@schlenkr/quassel 0.5.4 → 0.5.6
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/MessageActions.d.ts +5 -2
- package/chat.css +26 -12
- package/index.d.ts +1 -1
- package/index.js +78 -44
- package/index.js.map +2 -2
- package/options.d.ts +1 -0
- package/package.json +1 -1
- package/texts.d.ts +1 -0
- package/useChatAction.d.ts +1 -0
package/MessageActions.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { type RefObject } from "react";
|
|
1
2
|
import type { MessageActionsOptions } from "./options";
|
|
2
|
-
import type
|
|
3
|
+
import { type ChatTexts } from "./texts";
|
|
3
4
|
import type { Message } from "./types";
|
|
4
|
-
export declare function MessageActions({ message, options, texts }: {
|
|
5
|
+
export declare function MessageActions({ message, options, texts, contentRef, side }: {
|
|
5
6
|
message: Message;
|
|
6
7
|
options?: MessageActionsOptions;
|
|
7
8
|
texts: ChatTexts;
|
|
9
|
+
contentRef?: RefObject<HTMLElement | null>;
|
|
10
|
+
side?: "start" | "end";
|
|
8
11
|
}): import("react").JSX.Element;
|
package/chat.css
CHANGED
|
@@ -79,9 +79,6 @@
|
|
|
79
79
|
.qsl\:z-10 {
|
|
80
80
|
z-index: 10;
|
|
81
81
|
}
|
|
82
|
-
.qsl\:z-\[1\] {
|
|
83
|
-
z-index: 1;
|
|
84
|
-
}
|
|
85
82
|
.qsl\:z-\[5\] {
|
|
86
83
|
z-index: 5;
|
|
87
84
|
}
|
|
@@ -170,6 +167,10 @@
|
|
|
170
167
|
width: calc(var(--qsl-spacing) * 4);
|
|
171
168
|
height: calc(var(--qsl-spacing) * 4);
|
|
172
169
|
}
|
|
170
|
+
.qsl\:size-5 {
|
|
171
|
+
width: calc(var(--qsl-spacing) * 5);
|
|
172
|
+
height: calc(var(--qsl-spacing) * 5);
|
|
173
|
+
}
|
|
173
174
|
.qsl\:size-6 {
|
|
174
175
|
width: calc(var(--qsl-spacing) * 6);
|
|
175
176
|
height: calc(var(--qsl-spacing) * 6);
|
|
@@ -186,6 +187,9 @@
|
|
|
186
187
|
width: calc(var(--qsl-spacing) * 9);
|
|
187
188
|
height: calc(var(--qsl-spacing) * 9);
|
|
188
189
|
}
|
|
190
|
+
.qsl\:h-5 {
|
|
191
|
+
height: calc(var(--qsl-spacing) * 5);
|
|
192
|
+
}
|
|
189
193
|
.qsl\:h-6 {
|
|
190
194
|
height: calc(var(--qsl-spacing) * 6);
|
|
191
195
|
}
|
|
@@ -395,6 +399,9 @@
|
|
|
395
399
|
.qsl\:gap-0 {
|
|
396
400
|
gap: 0px;
|
|
397
401
|
}
|
|
402
|
+
.qsl\:gap-0\.5 {
|
|
403
|
+
gap: calc(var(--qsl-spacing) * 0.5);
|
|
404
|
+
}
|
|
398
405
|
.qsl\:gap-1 {
|
|
399
406
|
gap: var(--qsl-spacing);
|
|
400
407
|
}
|
|
@@ -890,13 +897,6 @@
|
|
|
890
897
|
.qsl\:opacity-100 {
|
|
891
898
|
opacity: 100%;
|
|
892
899
|
}
|
|
893
|
-
.qsl\:shadow-\[0_2px_6px_color-mix\(in_srgb\,var\(--qsl-foreground\)_15\%\,transparent\)\] {
|
|
894
|
-
--tw-shadow: 0 2px 6px var(--tw-shadow-color, var(--qsl-foreground));
|
|
895
|
-
@supports (color: color-mix(in lab, red, red)) {
|
|
896
|
-
--tw-shadow: 0 2px 6px var(--tw-shadow-color, color-mix(in srgb,var(--qsl-foreground) 15%,transparent));
|
|
897
|
-
}
|
|
898
|
-
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
899
|
-
}
|
|
900
900
|
.qsl\:shadow-bar {
|
|
901
901
|
--tw-shadow: var(--qsl-bar-shadow);
|
|
902
902
|
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
@@ -951,6 +951,11 @@
|
|
|
951
951
|
transition-timing-function: var(--tw-ease, var(--qsl-default-transition-timing-function));
|
|
952
952
|
transition-duration: var(--tw-duration, var(--qsl-default-transition-duration));
|
|
953
953
|
}
|
|
954
|
+
.qsl\:transition-opacity {
|
|
955
|
+
transition-property: opacity;
|
|
956
|
+
transition-timing-function: var(--tw-ease, var(--qsl-default-transition-timing-function));
|
|
957
|
+
transition-duration: var(--tw-duration, var(--qsl-default-transition-duration));
|
|
958
|
+
}
|
|
954
959
|
.qsl\:transition-transform {
|
|
955
960
|
transition-property: transform, translate, scale, rotate;
|
|
956
961
|
transition-timing-function: var(--tw-ease, var(--qsl-default-transition-timing-function));
|
|
@@ -1000,10 +1005,13 @@
|
|
|
1000
1005
|
max-width: var(--qsl-chat-content-max-width,none);
|
|
1001
1006
|
}
|
|
1002
1007
|
@media (hover: hover) {
|
|
1003
|
-
.qsl\:group-hover\:pointer-events-auto:is(:where(.qsl\:group):hover *) {
|
|
1008
|
+
.qsl\:group-hover\/message\:pointer-events-auto:is(:where(.qsl\:group\/message):hover *) {
|
|
1004
1009
|
pointer-events: auto;
|
|
1005
1010
|
}
|
|
1006
|
-
.qsl\:group-hover\:opacity-
|
|
1011
|
+
.qsl\:group-hover\/message\:opacity-70:is(:where(.qsl\:group\/message):hover *) {
|
|
1012
|
+
opacity: 70%;
|
|
1013
|
+
}
|
|
1014
|
+
.qsl\:group-hover\/message\:opacity-100:is(:where(.qsl\:group\/message):hover *) {
|
|
1007
1015
|
opacity: 100%;
|
|
1008
1016
|
}
|
|
1009
1017
|
}
|
|
@@ -1031,6 +1039,9 @@
|
|
|
1031
1039
|
.qsl\:focus-within\:border-primary:focus-within {
|
|
1032
1040
|
border-color: var(--qsl-primary);
|
|
1033
1041
|
}
|
|
1042
|
+
.qsl\:focus-within\:opacity-70:focus-within {
|
|
1043
|
+
opacity: 70%;
|
|
1044
|
+
}
|
|
1034
1045
|
.qsl\:focus-within\:opacity-100:focus-within {
|
|
1035
1046
|
opacity: 100%;
|
|
1036
1047
|
}
|
|
@@ -1604,6 +1615,9 @@
|
|
|
1604
1615
|
.qsl\:\[\@media\(hover\:none\)\]\:pointer-events-auto {
|
|
1605
1616
|
pointer-events: auto;
|
|
1606
1617
|
}
|
|
1618
|
+
.qsl\:\[\@media\(hover\:none\)\]\:opacity-70 {
|
|
1619
|
+
opacity: 70%;
|
|
1620
|
+
}
|
|
1607
1621
|
.qsl\:\[\@media\(hover\:none\)\]\:opacity-100 {
|
|
1608
1622
|
opacity: 100%;
|
|
1609
1623
|
}
|
package/index.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export { PendingActionCard } from "./PendingActionCard";
|
|
|
14
14
|
export { StepPopover } from "./StepPopover";
|
|
15
15
|
export { WorkingScenes, type WorkingScenesProps } from "./WorkingScenes";
|
|
16
16
|
export { announce } from "./announce";
|
|
17
|
-
export { useChatAction, copyChatText } from "./useChatAction";
|
|
17
|
+
export { useChatAction, copyChatText, copyChatHtml } from "./useChatAction";
|
|
18
18
|
export { createChatScroll } from "./chat-scroll";
|
|
19
19
|
export { ChatSendContext, createChatSendScope, type ChatSendScope } from "./ChatSendContext";
|
|
20
20
|
export { messageDate, timestampDay, timestampLabel } from "./timestamps";
|
package/index.js
CHANGED
|
@@ -57,7 +57,8 @@ var englishTexts = {
|
|
|
57
57
|
showLatestExchange: "Show latest reply between inputs",
|
|
58
58
|
showTimestamps: "Show timestamps",
|
|
59
59
|
hideTimestamps: "Hide timestamps",
|
|
60
|
-
copyMessage: "Copy
|
|
60
|
+
copyMessage: "Copy as Markdown",
|
|
61
|
+
copyFormatted: "Copy with formatting",
|
|
61
62
|
editMessage: "Edit message",
|
|
62
63
|
retryMessage: "Request answer again",
|
|
63
64
|
copyCode: "Copy code",
|
|
@@ -126,7 +127,8 @@ var germanTexts = {
|
|
|
126
127
|
showLatestExchange: "Letzte Antwort zwischen den Eingaben anzeigen",
|
|
127
128
|
showTimestamps: "Zeitstempel anzeigen",
|
|
128
129
|
hideTimestamps: "Zeitstempel ausblenden",
|
|
129
|
-
copyMessage: "
|
|
130
|
+
copyMessage: "Als Markdown kopieren",
|
|
131
|
+
copyFormatted: "Mit Formatierung kopieren",
|
|
130
132
|
editMessage: "Nachricht bearbeiten",
|
|
131
133
|
retryMessage: "Antwort erneut anfordern",
|
|
132
134
|
copyCode: "Code kopieren",
|
|
@@ -175,6 +177,8 @@ function createChatScroll(onFollowChange = () => {
|
|
|
175
177
|
}, getThreshold = () => defaultJumpToEndThreshold) {
|
|
176
178
|
const atEnd = (viewport) => viewport.scrollHeight - viewport.clientHeight - viewport.scrollTop <= getThreshold();
|
|
177
179
|
let following = true;
|
|
180
|
+
let held = false;
|
|
181
|
+
let heldTop = 0;
|
|
178
182
|
let lastTop = 0;
|
|
179
183
|
let lastHeight = 0;
|
|
180
184
|
let lastClientHeight = 0;
|
|
@@ -185,6 +189,7 @@ function createChatScroll(onFollowChange = () => {
|
|
|
185
189
|
lastClientHeight = viewport.clientHeight;
|
|
186
190
|
};
|
|
187
191
|
const follow = (value) => {
|
|
192
|
+
if (value) held = false;
|
|
188
193
|
if (following === value) return;
|
|
189
194
|
following = value;
|
|
190
195
|
onFollowChange(value);
|
|
@@ -192,19 +197,23 @@ function createChatScroll(onFollowChange = () => {
|
|
|
192
197
|
const layout = (viewport, dragging = false) => {
|
|
193
198
|
if (viewport.clientHeight <= 0) return;
|
|
194
199
|
if (movedUp(viewport, dragging) && !atEnd(viewport)) follow(false);
|
|
195
|
-
if (atEnd(viewport)) follow(true);
|
|
200
|
+
if (viewport.scrollHeight <= viewport.clientHeight || atEnd(viewport) && !held) follow(true);
|
|
196
201
|
if (following) viewport.scrollTop = Math.max(0, viewport.scrollHeight - viewport.clientHeight);
|
|
197
202
|
remember(viewport);
|
|
198
203
|
};
|
|
199
204
|
return {
|
|
200
205
|
layout,
|
|
201
206
|
pause(viewport) {
|
|
202
|
-
if (viewport.clientHeight
|
|
207
|
+
if (viewport.clientHeight <= 0 || viewport.scrollHeight <= viewport.clientHeight) return;
|
|
208
|
+
follow(false);
|
|
209
|
+
held = true;
|
|
210
|
+
heldTop = viewport.scrollTop;
|
|
203
211
|
},
|
|
204
212
|
scroll(viewport, dragging = false) {
|
|
205
213
|
if (viewport.clientHeight <= 0) return;
|
|
206
|
-
if (atEnd(viewport)) follow(true);
|
|
214
|
+
if (atEnd(viewport) && (!held || viewport.scrollTop > heldTop)) follow(true);
|
|
207
215
|
else if (movedUp(viewport, dragging) && !atEnd(viewport)) follow(false);
|
|
216
|
+
heldTop = viewport.scrollTop;
|
|
208
217
|
remember(viewport);
|
|
209
218
|
},
|
|
210
219
|
jump(viewport) {
|
|
@@ -456,6 +465,15 @@ async function copyChatText(text, unavailable) {
|
|
|
456
465
|
if (!navigator.clipboard) throw new Error(unavailable);
|
|
457
466
|
await navigator.clipboard.writeText(text);
|
|
458
467
|
}
|
|
468
|
+
async function copyChatHtml(element, text, unavailable) {
|
|
469
|
+
if (!navigator.clipboard) throw new Error(unavailable);
|
|
470
|
+
if (typeof ClipboardItem === "undefined" || !navigator.clipboard.write) return navigator.clipboard.writeText(text);
|
|
471
|
+
const clone = element.cloneNode(true);
|
|
472
|
+
clone.querySelectorAll("button").forEach((button) => button.remove());
|
|
473
|
+
clone.querySelectorAll("[class]").forEach((node) => node.removeAttribute("class"));
|
|
474
|
+
const blob = (content, type) => new Blob([content], { type });
|
|
475
|
+
await navigator.clipboard.write([new ClipboardItem({ "text/html": blob(clone.innerHTML, "text/html"), "text/plain": blob(markdownPlainText(text), "text/plain") })]);
|
|
476
|
+
}
|
|
459
477
|
|
|
460
478
|
// packages/quassel/src/Markdown.tsx
|
|
461
479
|
import { jsx as jsx8, jsxs } from "react/jsx-runtime";
|
|
@@ -1041,37 +1059,46 @@ function useElapsed(start) {
|
|
|
1041
1059
|
}
|
|
1042
1060
|
|
|
1043
1061
|
// packages/quassel/src/MessageActions.tsx
|
|
1044
|
-
import { CheckIcon as CheckIcon3, CopyIcon as CopyIcon2, PencilIcon, RotateCcwIcon } from "lucide-react";
|
|
1062
|
+
import { CheckIcon as CheckIcon3, ClipboardTypeIcon, CopyIcon as CopyIcon2, PencilIcon, RotateCcwIcon } from "lucide-react";
|
|
1045
1063
|
import { useState as useState3 } from "react";
|
|
1046
1064
|
import { Fragment, jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1047
1065
|
var actionClasses = cn(
|
|
1048
|
-
"qsl:
|
|
1049
|
-
"qsl:
|
|
1050
|
-
"qsl:
|
|
1051
|
-
"qsl:[@media(hover:none)]:pointer-events-auto qsl:[@media(hover:none)]:opacity-100"
|
|
1066
|
+
"qsl:mt-0.5 qsl:flex qsl:h-5 qsl:items-center qsl:gap-0.5 qsl:text-muted-foreground qsl:opacity-0 qsl:transition-opacity",
|
|
1067
|
+
"qsl:pointer-events-none qsl:group-hover/message:pointer-events-auto qsl:focus-within:pointer-events-auto",
|
|
1068
|
+
"qsl:[@media(hover:none)]:pointer-events-auto"
|
|
1052
1069
|
);
|
|
1053
|
-
|
|
1070
|
+
var visibleClasses = "qsl:group-hover/message:opacity-100 qsl:focus-within:opacity-100 qsl:[@media(hover:none)]:opacity-100";
|
|
1071
|
+
var lightClasses = "qsl:group-hover/message:opacity-70 qsl:focus-within:opacity-70 qsl:[@media(hover:none)]:opacity-70";
|
|
1072
|
+
function MessageActions({ message, options, texts, contentRef, side = message.role === "user" ? "end" : "start" }) {
|
|
1054
1073
|
const action = useChatAction();
|
|
1055
1074
|
const { Button: Button2 } = useQuasselComponents();
|
|
1056
1075
|
const [lastAction, setLastAction] = useState3();
|
|
1057
|
-
const
|
|
1076
|
+
const enabled = (option, fallback) => typeof option === "function" ? option(message) : option ?? fallback;
|
|
1077
|
+
const copy = enabled(options?.copy, message.role === "user" || message.role === "assistant") && !!message.text.trim();
|
|
1078
|
+
const copyFormatted = copy && !!contentRef && enabled(options?.copyFormatted, message.role === "assistant");
|
|
1058
1079
|
const actions = [
|
|
1059
|
-
...copy
|
|
1080
|
+
...copy ? [{ id: "copy", label: texts.copyMessage, icon: /* @__PURE__ */ jsx12(CopyIcon2, {}), onClick: () => copyChatText(message.text, texts.clipboardUnavailable) }] : [],
|
|
1081
|
+
...copyFormatted ? [{
|
|
1082
|
+
id: "copy-formatted",
|
|
1083
|
+
label: texts.copyFormatted ?? defaultTexts.copyFormatted,
|
|
1084
|
+
icon: /* @__PURE__ */ jsx12(ClipboardTypeIcon, {}),
|
|
1085
|
+
onClick: () => contentRef.current ? copyChatHtml(contentRef.current, message.text, texts.clipboardUnavailable) : copyChatText(message.text, texts.clipboardUnavailable)
|
|
1086
|
+
}] : [],
|
|
1060
1087
|
...options?.edit && message.role === "user" ? [{ id: "edit", label: texts.editMessage, icon: /* @__PURE__ */ jsx12(PencilIcon, {}), onClick: options.edit }] : [],
|
|
1061
1088
|
...options?.retry && message.role === "assistant" ? [{ id: "retry", label: texts.retryMessage, icon: /* @__PURE__ */ jsx12(RotateCcwIcon, {}), onClick: options.retry }] : [],
|
|
1062
1089
|
...options?.custom?.(message) ?? []
|
|
1063
1090
|
];
|
|
1064
1091
|
return /* @__PURE__ */ jsxs5(Fragment, { children: [
|
|
1065
|
-
actions.length > 0 && /* @__PURE__ */ jsx12("div", { className: actionClasses, children: actions.map((item) => {
|
|
1066
|
-
const copied =
|
|
1092
|
+
actions.length > 0 && /* @__PURE__ */ jsx12("div", { className: cn(actionClasses, message.role === "user" ? visibleClasses : lightClasses, side === "end" && "qsl:justify-end"), "data-chat": "message-actions", children: actions.map((item) => {
|
|
1093
|
+
const copied = ["copy", "copy-formatted"].includes(item.id) && lastAction === item.id && action.status === "done";
|
|
1067
1094
|
const label = copied ? texts.copied : item.label;
|
|
1068
1095
|
return /* @__PURE__ */ jsx12(
|
|
1069
1096
|
Button2,
|
|
1070
1097
|
{
|
|
1071
1098
|
"aria-label": label,
|
|
1072
|
-
className: "qsl:text-inherit",
|
|
1099
|
+
className: cn("qsl:text-inherit", item.icon && "qsl:size-5"),
|
|
1073
1100
|
disabled: item.disabled || action.status === "pending",
|
|
1074
|
-
size: item.icon ? "icon-
|
|
1101
|
+
size: item.icon ? "icon-xs" : "xs",
|
|
1075
1102
|
title: label,
|
|
1076
1103
|
variant: "ghost",
|
|
1077
1104
|
onClick: () => {
|
|
@@ -1731,6 +1758,7 @@ function Bubble({
|
|
|
1731
1758
|
messageActions
|
|
1732
1759
|
}) {
|
|
1733
1760
|
const stepSpacing = dense ? denseStepClasses : stepClasses;
|
|
1761
|
+
const textRef = useRef3(null);
|
|
1734
1762
|
if (message.role === "thinking" || message.role === "tool" && message.tool) {
|
|
1735
1763
|
if (detailMode === "compact") {
|
|
1736
1764
|
return /* @__PURE__ */ jsx13(TraceLine, { className: stepSpacing, elapsedAfter, expandable, message, texts, toolArgumentsText });
|
|
@@ -1777,38 +1805,43 @@ function Bubble({
|
|
|
1777
1805
|
"qsl:mb-[5px] qsl:table qsl:text-label qsl:leading-[1.45] qsl:font-semibold",
|
|
1778
1806
|
useBubble && message.bubble && "qsl:rounded-full qsl:border qsl:border-white/30 qsl:bg-black/15 qsl:px-[7px] qsl:py-px qsl:tracking-[0.02em]"
|
|
1779
1807
|
), "data-chat": "sender", children: sender }),
|
|
1780
|
-
/* @__PURE__ */ jsx13(Markdown, { text: message.text, streaming: message.role === "assistant" && !message.closed }),
|
|
1808
|
+
/* @__PURE__ */ jsx13("div", { "data-chat": "message-text", ref: textRef, children: /* @__PURE__ */ jsx13(Markdown, { text: message.text, streaming: message.role === "assistant" && !message.closed }) }),
|
|
1781
1809
|
/* @__PURE__ */ jsx13(MessageAttachments, { message, texts }),
|
|
1782
|
-
message.steered && /* @__PURE__ */ jsx13("small", { className: "qsl:mt-1 qsl:block qsl:text-label qsl:leading-[1.45] qsl:opacity-70", "data-chat": "steered", children: texts.steered })
|
|
1783
|
-
/* @__PURE__ */ jsx13(MessageActions, { message, options: messageActions, texts })
|
|
1810
|
+
message.steered && /* @__PURE__ */ jsx13("small", { className: "qsl:mt-1 qsl:block qsl:text-label qsl:leading-[1.45] qsl:opacity-70", "data-chat": "steered", children: texts.steered })
|
|
1784
1811
|
] });
|
|
1785
1812
|
const cursor = message.role === "assistant" && message.textCursor ? JSON.stringify(message.textCursor) : void 0;
|
|
1786
|
-
if (!useBubble) return /* @__PURE__ */
|
|
1813
|
+
if (!useBubble) return /* @__PURE__ */ jsxs6("div", { "data-chat-text-cursor": cursor, className: cn(stepSpacing, "qsl:group/message qsl:relative qsl:w-full qsl:leading-[var(--qsl-chat-line-height,1.65)] qsl:text-foreground"), "data-message": "answer", children: [
|
|
1814
|
+
content,
|
|
1815
|
+
/* @__PURE__ */ jsx13(MessageActions, { contentRef: textRef, message, options: messageActions, side, texts })
|
|
1816
|
+
] });
|
|
1787
1817
|
const fullBackground = message.role === "user" && bubbleOptions?.userBackgroundFullWidth !== false;
|
|
1788
1818
|
const surfaceClasses = message.bubble ? "qsl:rounded-lg" : "qsl:rounded-[var(--qsl-bubble-radius,10px_10px_4px_10px)] qsl:border qsl:border-border qsl:bg-secondary qsl:in-data-[tone=material]:rounded-[var(--qsl-bubble-radius,9px)] qsl:in-data-[tone=material]:border-glass-edge/20 qsl:in-data-[tone=material]:bg-primary/15";
|
|
1789
|
-
return /* @__PURE__ */ jsxs6(
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1819
|
+
return /* @__PURE__ */ jsxs6("div", { className: cn(stepSpacing, "qsl:group/message"), children: [
|
|
1820
|
+
/* @__PURE__ */ jsxs6(
|
|
1821
|
+
"div",
|
|
1822
|
+
{
|
|
1823
|
+
"data-chat-text-cursor": cursor,
|
|
1824
|
+
className: cn("qsl:relative qsl:flex", side === "end" ? "qsl:justify-end" : "qsl:justify-start"),
|
|
1825
|
+
"data-message": message.role === "user" && !message.bubble && variant === "default" ? "user" : "bubble",
|
|
1826
|
+
"data-side": side,
|
|
1827
|
+
"data-background-width": fullBackground ? "full" : "content",
|
|
1828
|
+
children: [
|
|
1829
|
+
fullBackground && /* @__PURE__ */ jsx13("div", { "aria-hidden": "true", className: cn("qsl:pointer-events-none qsl:absolute qsl:inset-0", surfaceClasses), "data-chat": "bubble-background", style: { background: message.bubble?.color } }),
|
|
1830
|
+
/* @__PURE__ */ jsx13(
|
|
1831
|
+
"div",
|
|
1832
|
+
{
|
|
1833
|
+
className: cn(bubbleBodyClasses, !fullBackground && surfaceClasses, fullBackground && !message.bubble && "qsl:border qsl:border-transparent", message.bubble ? "qsl:text-white qsl:[--qsl-scroll-cover:var(--qsl-primary)]" : "qsl:text-foreground qsl:[--qsl-scroll-cover:var(--qsl-secondary)]"),
|
|
1834
|
+
"data-chat": "bubble-content",
|
|
1835
|
+
"data-tone": message.bubble ? "on-color" : void 0,
|
|
1836
|
+
style: { background: fullBackground ? void 0 : message.bubble?.color, maxWidth: bubbleOptions?.maxWidth },
|
|
1837
|
+
children: content
|
|
1838
|
+
}
|
|
1839
|
+
)
|
|
1840
|
+
]
|
|
1841
|
+
}
|
|
1842
|
+
),
|
|
1843
|
+
/* @__PURE__ */ jsx13(MessageActions, { contentRef: textRef, message, options: messageActions, side, texts })
|
|
1844
|
+
] });
|
|
1812
1845
|
}
|
|
1813
1846
|
function ActionContent({
|
|
1814
1847
|
action,
|
|
@@ -2602,6 +2635,7 @@ export {
|
|
|
2602
2635
|
attachmentDownloadUrl,
|
|
2603
2636
|
attachmentMediaType,
|
|
2604
2637
|
compactToolLine,
|
|
2638
|
+
copyChatHtml,
|
|
2605
2639
|
copyChatText,
|
|
2606
2640
|
createChatScroll,
|
|
2607
2641
|
createChatSendScope,
|