@smartspace/chat-ui 1.14.0-main.f7a280f → 1.14.2-main.10a17d6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.js +268 -20
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { createPortal } from 'react-dom';
|
|
|
7
7
|
import { useQuery, queryOptions, useQueryClient, useMutation, skipToken } from '@tanstack/react-query';
|
|
8
8
|
import { toast } from 'sonner';
|
|
9
9
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
10
|
-
import { Editor, rootCtx, defaultValueCtx, editorViewOptionsCtx, editorViewCtx, serializerCtx, SchemaReady, nodeViewCtx, markViewCtx, schemaCtx, prosePluginsCtx, nodesCtx } from '@milkdown/core';
|
|
10
|
+
import { Editor, rootCtx, defaultValueCtx, editorViewOptionsCtx, editorViewCtx, serializerCtx, parserCtx, SchemaReady, nodeViewCtx, markViewCtx, schemaCtx, prosePluginsCtx, nodesCtx } from '@milkdown/core';
|
|
11
11
|
import { history } from '@milkdown/kit/plugin/history';
|
|
12
12
|
import { clipboard } from '@milkdown/plugin-clipboard';
|
|
13
13
|
import { listenerCtx, listener } from '@milkdown/plugin-listener';
|
|
@@ -424,6 +424,29 @@ var fileTag = $node("fileTag", () => ({
|
|
|
424
424
|
var MAX_IFRAME_HEIGHT = 5e3;
|
|
425
425
|
var HEIGHT_MESSAGE = "ss-html-preview-height";
|
|
426
426
|
var ERROR_MESSAGE = "ss-html-preview-error";
|
|
427
|
+
var SNAPSHOT_REQUEST = "ss-html-preview-snapshot";
|
|
428
|
+
var SNAPSHOT_RESULT = "ss-html-preview-snapshot-result";
|
|
429
|
+
var SS_MARKDOWN_CLIPBOARD_TYPE = "web text/markdown";
|
|
430
|
+
var MARKDOWN_MARKER_PREFIX = "<!--ss-md:";
|
|
431
|
+
var MARKDOWN_MARKER_SUFFIX = "-->";
|
|
432
|
+
var MARKDOWN_MARKER_RE = /<!--ss-md:([A-Za-z0-9+/=]+)-->/;
|
|
433
|
+
function encodeMarkdownMarker(markdown) {
|
|
434
|
+
try {
|
|
435
|
+
const b64 = btoa(unescape(encodeURIComponent(markdown)));
|
|
436
|
+
return `${MARKDOWN_MARKER_PREFIX}${b64}${MARKDOWN_MARKER_SUFFIX}`;
|
|
437
|
+
} catch {
|
|
438
|
+
return "";
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
function extractMarkdownMarker(html4) {
|
|
442
|
+
const match = html4.match(MARKDOWN_MARKER_RE);
|
|
443
|
+
if (!match) return null;
|
|
444
|
+
try {
|
|
445
|
+
return decodeURIComponent(escape(atob(match[1])));
|
|
446
|
+
} catch {
|
|
447
|
+
return null;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
427
450
|
var HEIGHT_REPORTER_SCRIPT = `
|
|
428
451
|
<script>(function(){
|
|
429
452
|
try {
|
|
@@ -448,6 +471,48 @@ var HEIGHT_REPORTER_SCRIPT = `
|
|
|
448
471
|
window.addEventListener('unhandledrejection', function(ev){
|
|
449
472
|
reportError(ev && ev.reason && ev.reason.message);
|
|
450
473
|
});
|
|
474
|
+
// Snapshot responder. The parent can't read this sandboxed (no
|
|
475
|
+
// allow-same-origin) document, so when it asks for a snapshot we rasterize
|
|
476
|
+
// our own <canvas> elements via toDataURL and post just the PNG strings
|
|
477
|
+
// back out \u2014 strings cross the sandbox boundary fine. Used by the message
|
|
478
|
+
// "smart copy" so client-side charts (Chart.js etc.) paste into Word as
|
|
479
|
+
// images instead of dead <canvas>/<script> source.
|
|
480
|
+
window.addEventListener('message', function(ev){
|
|
481
|
+
var d = ev && ev.data;
|
|
482
|
+
if (!d || d.type !== ${JSON.stringify(SNAPSHOT_REQUEST)}) return;
|
|
483
|
+
var images = [];
|
|
484
|
+
try {
|
|
485
|
+
var canvases = document.querySelectorAll('canvas');
|
|
486
|
+
for (var i = 0; i < canvases.length; i++) {
|
|
487
|
+
var c = canvases[i];
|
|
488
|
+
// Skip zero-area canvases (off-screen / not yet drawn).
|
|
489
|
+
if (!c.width || !c.height) continue;
|
|
490
|
+
try {
|
|
491
|
+
var rect = c.getBoundingClientRect();
|
|
492
|
+
images.push({
|
|
493
|
+
dataUrl: c.toDataURL('image/png'),
|
|
494
|
+
width: c.width,
|
|
495
|
+
height: c.height,
|
|
496
|
+
// On-screen CSS size, independent of devicePixelRatio scaling, so
|
|
497
|
+
// the pasted <img> renders at the chart's intended size rather than
|
|
498
|
+
// 2x on a retina display. Falls back to the pixel size.
|
|
499
|
+
cssWidth: Math.round(rect.width) || c.width,
|
|
500
|
+
cssHeight: Math.round(rect.height) || c.height
|
|
501
|
+
});
|
|
502
|
+
} catch (e) {
|
|
503
|
+
// Tainted canvas (cross-origin image drawn without CORS) \u2014 skip it;
|
|
504
|
+
// the host falls back to inlining the static HTML source.
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
} catch (e) {}
|
|
508
|
+
try {
|
|
509
|
+
parent.postMessage({
|
|
510
|
+
type: ${JSON.stringify(SNAPSHOT_RESULT)},
|
|
511
|
+
id: d.id,
|
|
512
|
+
images: images
|
|
513
|
+
}, '*');
|
|
514
|
+
} catch (e) {}
|
|
515
|
+
});
|
|
451
516
|
var lastSent = -1;
|
|
452
517
|
function send(){
|
|
453
518
|
try {
|
|
@@ -533,6 +598,38 @@ async function copyText(text6) {
|
|
|
533
598
|
return false;
|
|
534
599
|
}
|
|
535
600
|
}
|
|
601
|
+
var snapshotSeq = 0;
|
|
602
|
+
function snapshotIframe(iframe, timeoutMs = 1500) {
|
|
603
|
+
return new Promise((resolve) => {
|
|
604
|
+
const win = iframe.contentWindow;
|
|
605
|
+
if (!win || typeof window === "undefined") {
|
|
606
|
+
resolve([]);
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
const id = `snap-${++snapshotSeq}`;
|
|
610
|
+
let settled = false;
|
|
611
|
+
const finish = (images) => {
|
|
612
|
+
if (settled) return;
|
|
613
|
+
settled = true;
|
|
614
|
+
window.removeEventListener("message", onMessage);
|
|
615
|
+
clearTimeout(timer);
|
|
616
|
+
resolve(images);
|
|
617
|
+
};
|
|
618
|
+
const onMessage = (event) => {
|
|
619
|
+
if (event.source !== win) return;
|
|
620
|
+
const data = event.data;
|
|
621
|
+
if (!data || data.type !== SNAPSHOT_RESULT || data.id !== id) return;
|
|
622
|
+
finish(Array.isArray(data.images) ? data.images : []);
|
|
623
|
+
};
|
|
624
|
+
const timer = setTimeout(() => finish([]), timeoutMs);
|
|
625
|
+
window.addEventListener("message", onMessage);
|
|
626
|
+
try {
|
|
627
|
+
win.postMessage({ type: SNAPSHOT_REQUEST, id }, "*");
|
|
628
|
+
} catch {
|
|
629
|
+
finish([]);
|
|
630
|
+
}
|
|
631
|
+
});
|
|
632
|
+
}
|
|
536
633
|
|
|
537
634
|
// src/shared/markdown/extensions/htmlPreview.ts
|
|
538
635
|
var PREVIEW_LANGUAGES = /* @__PURE__ */ new Set(["html"]);
|
|
@@ -982,6 +1079,7 @@ function EditorInner({
|
|
|
982
1079
|
const [_isDragging, setIsDragging] = useState(false);
|
|
983
1080
|
const viewRef = useRef(null);
|
|
984
1081
|
const serializerRef = useRef(null);
|
|
1082
|
+
const parserRef = useRef(null);
|
|
985
1083
|
function guessImageExt(mime) {
|
|
986
1084
|
const t = (mime || "").toLowerCase();
|
|
987
1085
|
if (t === "image/jpeg") return "jpg";
|
|
@@ -1100,6 +1198,10 @@ function EditorInner({
|
|
|
1100
1198
|
serializerRef.current = anyCtx.get(serializerCtx);
|
|
1101
1199
|
} catch {
|
|
1102
1200
|
}
|
|
1201
|
+
try {
|
|
1202
|
+
parserRef.current = anyCtx.get(parserCtx);
|
|
1203
|
+
} catch {
|
|
1204
|
+
}
|
|
1103
1205
|
const handle2 = () => {
|
|
1104
1206
|
try {
|
|
1105
1207
|
if (enableMentions) updateMentionFromView();
|
|
@@ -1189,6 +1291,19 @@ function EditorInner({
|
|
|
1189
1291
|
const tr = view.state.tr.replaceWith(from, to, node2);
|
|
1190
1292
|
view.dispatch(tr.scrollIntoView());
|
|
1191
1293
|
}
|
|
1294
|
+
function insertMarkdownAtSelection(view, markdown) {
|
|
1295
|
+
const parser = parserRef.current;
|
|
1296
|
+
if (!parser) return false;
|
|
1297
|
+
try {
|
|
1298
|
+
const doc = parser(markdown);
|
|
1299
|
+
if (!doc) return false;
|
|
1300
|
+
const slice = new Slice(doc.content, 0, 0);
|
|
1301
|
+
view.dispatch(view.state.tr.replaceSelection(slice).scrollIntoView());
|
|
1302
|
+
return true;
|
|
1303
|
+
} catch {
|
|
1304
|
+
return false;
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1192
1307
|
async function insertUploadedFilesIntoEditor(files) {
|
|
1193
1308
|
const view = viewRef.current;
|
|
1194
1309
|
if (!isEditable || !view) return false;
|
|
@@ -1461,6 +1576,17 @@ function EditorInner({
|
|
|
1461
1576
|
},
|
|
1462
1577
|
onPasteCapture: (e) => {
|
|
1463
1578
|
try {
|
|
1579
|
+
const view = viewRef.current;
|
|
1580
|
+
if (isEditable && view) {
|
|
1581
|
+
const ssMarkdown = extractMarkdownMarker(
|
|
1582
|
+
e.clipboardData?.getData("text/html") ?? ""
|
|
1583
|
+
) ?? e.clipboardData?.getData(SS_MARKDOWN_CLIPBOARD_TYPE);
|
|
1584
|
+
if (ssMarkdown && insertMarkdownAtSelection(view, ssMarkdown)) {
|
|
1585
|
+
e.preventDefault();
|
|
1586
|
+
e.stopPropagation();
|
|
1587
|
+
return;
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1464
1590
|
const items = e.clipboardData?.items;
|
|
1465
1591
|
if (!items) return;
|
|
1466
1592
|
const imageFiles = [];
|
|
@@ -18720,17 +18846,29 @@ function CodeBlock({ language, source }) {
|
|
|
18720
18846
|
/* @__PURE__ */ jsx("pre", { ...language ? { "data-language": language } : {}, children: /* @__PURE__ */ jsx("code", { className: codeClass, children: source }) })
|
|
18721
18847
|
] });
|
|
18722
18848
|
}
|
|
18849
|
+
var STREAM_SETTLE_MS = 250;
|
|
18723
18850
|
function HtmlPreview({ source }) {
|
|
18724
18851
|
const [showingPreview, setShowingPreview] = useState(true);
|
|
18725
18852
|
const [copyLabel, setCopyLabel] = useState(
|
|
18726
18853
|
"Copy"
|
|
18727
18854
|
);
|
|
18728
18855
|
const [iframeHeight, setIframeHeight] = useState(null);
|
|
18856
|
+
const [settledSource, setSettledSource] = useState(source);
|
|
18857
|
+
const [measured, setMeasured] = useState(false);
|
|
18858
|
+
const loading = showingPreview && (source !== settledSource || !measured);
|
|
18729
18859
|
const iframeRef = useRef(null);
|
|
18730
18860
|
const rafIdRef = useRef(null);
|
|
18731
18861
|
const pendingHeightRef = useRef(null);
|
|
18732
18862
|
const copyResetTimerRef = useRef(null);
|
|
18733
|
-
const srcdoc = injectHeightReporter(
|
|
18863
|
+
const srcdoc = injectHeightReporter(settledSource);
|
|
18864
|
+
useEffect(() => {
|
|
18865
|
+
if (source === settledSource) return;
|
|
18866
|
+
const id = setTimeout(() => setSettledSource(source), STREAM_SETTLE_MS);
|
|
18867
|
+
return () => clearTimeout(id);
|
|
18868
|
+
}, [source, settledSource]);
|
|
18869
|
+
useEffect(() => {
|
|
18870
|
+
setMeasured(false);
|
|
18871
|
+
}, [settledSource]);
|
|
18734
18872
|
useEffect(() => {
|
|
18735
18873
|
ensureGlobalListener();
|
|
18736
18874
|
}, []);
|
|
@@ -18745,6 +18883,7 @@ function HtmlPreview({ source }) {
|
|
|
18745
18883
|
pendingHeightRef.current = null;
|
|
18746
18884
|
if (next2 <= 0) return;
|
|
18747
18885
|
setIframeHeight(next2);
|
|
18886
|
+
setMeasured(true);
|
|
18748
18887
|
};
|
|
18749
18888
|
const scheduleHeight = (height) => {
|
|
18750
18889
|
pendingHeightRef.current = height;
|
|
@@ -18836,19 +18975,35 @@ function HtmlPreview({ source }) {
|
|
|
18836
18975
|
)
|
|
18837
18976
|
] })
|
|
18838
18977
|
] }),
|
|
18839
|
-
/* @__PURE__ */
|
|
18840
|
-
"
|
|
18978
|
+
/* @__PURE__ */ jsxs(
|
|
18979
|
+
"div",
|
|
18841
18980
|
{
|
|
18842
|
-
|
|
18843
|
-
className: "ss-code-block__iframe",
|
|
18844
|
-
sandbox: "allow-scripts",
|
|
18845
|
-
loading: "lazy",
|
|
18846
|
-
title: "HTML preview",
|
|
18847
|
-
srcDoc: srcdoc,
|
|
18981
|
+
className: "ss-code-block__preview",
|
|
18848
18982
|
style: {
|
|
18849
18983
|
display: showingPreview ? "block" : "none",
|
|
18850
|
-
...
|
|
18851
|
-
}
|
|
18984
|
+
...loading ? { minHeight: 180 } : {}
|
|
18985
|
+
},
|
|
18986
|
+
children: [
|
|
18987
|
+
loading && /* @__PURE__ */ jsxs("div", { className: "ss-code-block__loading", children: [
|
|
18988
|
+
/* @__PURE__ */ jsx("div", { className: "ss-code-block__spinner" }),
|
|
18989
|
+
/* @__PURE__ */ jsx("span", { children: "Rendering preview\u2026" })
|
|
18990
|
+
] }),
|
|
18991
|
+
/* @__PURE__ */ jsx(
|
|
18992
|
+
"iframe",
|
|
18993
|
+
{
|
|
18994
|
+
ref: iframeRef,
|
|
18995
|
+
className: "ss-code-block__iframe",
|
|
18996
|
+
sandbox: "allow-scripts",
|
|
18997
|
+
loading: "lazy",
|
|
18998
|
+
title: "HTML preview",
|
|
18999
|
+
srcDoc: srcdoc,
|
|
19000
|
+
style: {
|
|
19001
|
+
opacity: loading ? 0 : 1,
|
|
19002
|
+
...loading ? { position: "absolute", inset: 0, height: "100%" } : iframeHeight != null ? { height: `${iframeHeight}px` } : {}
|
|
19003
|
+
}
|
|
19004
|
+
}
|
|
19005
|
+
)
|
|
19006
|
+
]
|
|
18852
19007
|
}
|
|
18853
19008
|
),
|
|
18854
19009
|
/* @__PURE__ */ jsx(
|
|
@@ -19287,23 +19442,115 @@ function getUserPhotoUrl(userId) {
|
|
|
19287
19442
|
if (!base2) return void 0;
|
|
19288
19443
|
return `${base2}/users/${userId}/photo`;
|
|
19289
19444
|
}
|
|
19445
|
+
|
|
19446
|
+
// src/messages/smartCopy.ts
|
|
19447
|
+
async function copyMessageRich(container, markdown) {
|
|
19448
|
+
try {
|
|
19449
|
+
const canRichWrite = typeof ClipboardItem !== "undefined" && !!navigator.clipboard?.write;
|
|
19450
|
+
if (!canRichWrite) return copyText(markdown);
|
|
19451
|
+
const { html: html4, images } = await buildHtmlPayload(container);
|
|
19452
|
+
const htmlWithMarker = `${html4}${encodeMarkdownMarker(markdown)}`;
|
|
19453
|
+
const parts = {
|
|
19454
|
+
"text/html": new Blob([htmlWithMarker], { type: "text/html" }),
|
|
19455
|
+
"text/plain": new Blob([markdown], { type: "text/plain" })
|
|
19456
|
+
};
|
|
19457
|
+
if (images.length === 1) {
|
|
19458
|
+
const pngBlob = await dataUrlToBlob(images[0].dataUrl);
|
|
19459
|
+
if (pngBlob) parts["image/png"] = pngBlob;
|
|
19460
|
+
}
|
|
19461
|
+
const withCustom = {
|
|
19462
|
+
...parts,
|
|
19463
|
+
[SS_MARKDOWN_CLIPBOARD_TYPE]: new Blob([markdown], {
|
|
19464
|
+
type: SS_MARKDOWN_CLIPBOARD_TYPE
|
|
19465
|
+
})
|
|
19466
|
+
};
|
|
19467
|
+
if (await tryWrite(withCustom)) return true;
|
|
19468
|
+
if (await tryWrite(parts)) return true;
|
|
19469
|
+
return copyText(markdown);
|
|
19470
|
+
} catch {
|
|
19471
|
+
return copyText(markdown);
|
|
19472
|
+
}
|
|
19473
|
+
}
|
|
19474
|
+
async function tryWrite(parts) {
|
|
19475
|
+
try {
|
|
19476
|
+
await navigator.clipboard.write([new ClipboardItem(parts)]);
|
|
19477
|
+
return true;
|
|
19478
|
+
} catch {
|
|
19479
|
+
return false;
|
|
19480
|
+
}
|
|
19481
|
+
}
|
|
19482
|
+
async function buildHtmlPayload(container) {
|
|
19483
|
+
const liveBlocks = Array.from(
|
|
19484
|
+
container.querySelectorAll(".ss-code-block--previewable")
|
|
19485
|
+
);
|
|
19486
|
+
const snapshots = await Promise.all(
|
|
19487
|
+
liveBlocks.map((block) => {
|
|
19488
|
+
const iframe = block.querySelector("iframe");
|
|
19489
|
+
return iframe ? snapshotIframe(iframe) : Promise.resolve([]);
|
|
19490
|
+
})
|
|
19491
|
+
);
|
|
19492
|
+
const clone = container.cloneNode(true);
|
|
19493
|
+
const cloneBlocks = Array.from(
|
|
19494
|
+
clone.querySelectorAll(".ss-code-block--previewable")
|
|
19495
|
+
);
|
|
19496
|
+
const allImages = [];
|
|
19497
|
+
cloneBlocks.forEach((block, i) => {
|
|
19498
|
+
const images = snapshots[i] ?? [];
|
|
19499
|
+
if (images.length > 0) {
|
|
19500
|
+
allImages.push(...images);
|
|
19501
|
+
const frag = block.ownerDocument.createElement("div");
|
|
19502
|
+
for (const img of images) {
|
|
19503
|
+
const el = block.ownerDocument.createElement("img");
|
|
19504
|
+
el.src = img.dataUrl;
|
|
19505
|
+
el.setAttribute("width", String(img.cssWidth));
|
|
19506
|
+
el.setAttribute("height", String(img.cssHeight));
|
|
19507
|
+
el.style.maxWidth = "100%";
|
|
19508
|
+
frag.appendChild(el);
|
|
19509
|
+
}
|
|
19510
|
+
block.replaceWith(frag);
|
|
19511
|
+
} else {
|
|
19512
|
+
const source = block.querySelector("code")?.textContent ?? "";
|
|
19513
|
+
const div = block.ownerDocument.createElement("div");
|
|
19514
|
+
div.innerHTML = stripScripts(source);
|
|
19515
|
+
block.replaceWith(div);
|
|
19516
|
+
}
|
|
19517
|
+
});
|
|
19518
|
+
clone.querySelectorAll(
|
|
19519
|
+
"iframe, button, .ss-code-block__header, .ss-code-block__copy, .ss-code-block__toggle"
|
|
19520
|
+
).forEach((el) => el.remove());
|
|
19521
|
+
const html4 = `<meta charset="utf-8">${clone.innerHTML}`;
|
|
19522
|
+
return { html: html4, images: allImages };
|
|
19523
|
+
}
|
|
19524
|
+
function stripScripts(html4) {
|
|
19525
|
+
return html4.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, "");
|
|
19526
|
+
}
|
|
19527
|
+
async function dataUrlToBlob(dataUrl) {
|
|
19528
|
+
try {
|
|
19529
|
+
const res = await fetch(dataUrl);
|
|
19530
|
+
return await res.blob();
|
|
19531
|
+
} catch {
|
|
19532
|
+
return null;
|
|
19533
|
+
}
|
|
19534
|
+
}
|
|
19290
19535
|
var RESET_DELAY = 1e3;
|
|
19291
19536
|
function ChatMessageCopyButton({
|
|
19292
|
-
content
|
|
19537
|
+
content,
|
|
19538
|
+
contentRef
|
|
19293
19539
|
}) {
|
|
19294
19540
|
const [state, setState] = useState("idle" /* IDLE */);
|
|
19295
19541
|
const handleCopy = async () => {
|
|
19296
19542
|
if (!content) return;
|
|
19297
19543
|
const textToCopy = content.filter((item) => !!item.text).map((item) => item.text).join("\n");
|
|
19298
19544
|
if (!textToCopy) return;
|
|
19299
|
-
|
|
19300
|
-
|
|
19545
|
+
const container = contentRef?.current;
|
|
19546
|
+
const ok3 = container ? await copyMessageRich(container, textToCopy) : await copyText(textToCopy);
|
|
19547
|
+
if (ok3) {
|
|
19301
19548
|
setState("success" /* SUCCESS */);
|
|
19302
19549
|
setTimeout(() => {
|
|
19303
19550
|
setState("idle" /* IDLE */);
|
|
19304
19551
|
}, RESET_DELAY);
|
|
19305
|
-
}
|
|
19306
|
-
console.error("Failed to copy
|
|
19552
|
+
} else {
|
|
19553
|
+
console.error("Failed to copy message content");
|
|
19307
19554
|
}
|
|
19308
19555
|
};
|
|
19309
19556
|
const getIcon = () => {
|
|
@@ -19591,6 +19838,7 @@ var MessageBubble = (props) => {
|
|
|
19591
19838
|
} = props;
|
|
19592
19839
|
const [responseFormData, setResponseFormData] = useState(userInput);
|
|
19593
19840
|
const [responseFormValid, setResponseFormValid] = useState(false);
|
|
19841
|
+
const contentRef = useRef(null);
|
|
19594
19842
|
const isBotResponse = type === "Output" /* OUTPUT */;
|
|
19595
19843
|
const showForm = userOutput;
|
|
19596
19844
|
useEffect(() => {
|
|
@@ -19628,12 +19876,12 @@ var MessageBubble = (props) => {
|
|
|
19628
19876
|
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: createdAt ? parseDateTime(createdAt, "Do MMMM YYYY, h:mm a") : "" })
|
|
19629
19877
|
] })
|
|
19630
19878
|
] }),
|
|
19631
|
-
/* @__PURE__ */ jsx(ChatMessageCopyButton, { content })
|
|
19879
|
+
/* @__PURE__ */ jsx(ChatMessageCopyButton, { content, contentRef })
|
|
19632
19880
|
]
|
|
19633
19881
|
}
|
|
19634
19882
|
),
|
|
19635
19883
|
/* @__PURE__ */ jsxs("div", { className: cn(isBotResponse ? "p-4" : "px-4 py-2"), children: [
|
|
19636
|
-
contentIsList && content?.map(
|
|
19884
|
+
/* @__PURE__ */ jsx("div", { ref: contentRef, children: contentIsList && content?.map(
|
|
19637
19885
|
(item, i) => item.text ? /* @__PURE__ */ jsx(
|
|
19638
19886
|
"div",
|
|
19639
19887
|
{
|
|
@@ -19642,7 +19890,7 @@ var MessageBubble = (props) => {
|
|
|
19642
19890
|
},
|
|
19643
19891
|
`content-${i}`
|
|
19644
19892
|
) : item.image ? /* @__PURE__ */ jsx("div", { className: "mb-3 last:mb-0", children: /* @__PURE__ */ jsx(ChatMessageImage, { image: item.image }) }, `image-${i}`) : null
|
|
19645
|
-
),
|
|
19893
|
+
) }),
|
|
19646
19894
|
files.length > 0 && /* @__PURE__ */ jsxs("div", { className: "ss-chat-message__attachments mt-4 space-y-2", children: [
|
|
19647
19895
|
/* @__PURE__ */ jsx("h4", { className: "text-xs font-semibold text-muted-foreground mb-1", children: "Attachments" }),
|
|
19648
19896
|
files.map((file, idx) => {
|