@schlenkr/quassel 0.5.0 → 0.5.1
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/README.md +20 -12
- package/chat.css +34 -26
- package/index.js +52 -31
- package/index.js.map +2 -2
- package/options.d.ts +6 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Chat building blocks for React: a streaming transcript with thinking and tool st
|
|
|
4
4
|
actions, an input card with attachments and steering, and a small event contract that works
|
|
5
5
|
on the server as well. quassel is the chat of [RAgents](https://github.com/SchlenkR/RAgents),
|
|
6
6
|
published as a library. It ships a compiled stylesheet, so hosts need no Tailwind, and every
|
|
7
|
-
color, radius, font and font size is a `--qsl-*` variable,
|
|
7
|
+
color, radius, font and font size is a `--qsl-*` variable, with compact defaults for text and tool steps.
|
|
8
8
|
|
|
9
9
|

|
|
10
10
|
|
|
@@ -93,20 +93,28 @@ Any backend that emits the `@schlenkr/quassel/events` stream works with the same
|
|
|
93
93
|
|
|
94
94
|
## Text size
|
|
95
95
|
|
|
96
|
-
quassel
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
quassel starts at 13px with a line height of 1.5, a 10px message gap and a 3px dense
|
|
97
|
+
step gap. Tool rows and timestamps use 88% of the text size. Expanded tool groups have a
|
|
98
|
+
1px gap between rows; tool rows have 1px of vertical padding on each side.
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
.
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
Every size derives from one base, so nested elements never compound. Set `--qsl-font-size`
|
|
101
|
+
on a wrapper, or `appearance.fontSize`, to change it. Use `1em` to follow the host's font size.
|
|
102
|
+
`appearance` also offers `toolFontScale`, `toolGroupGap` and `toolRowPadding`.
|
|
103
|
+
|
|
104
|
+
User message backgrounds fill the available row by default while text keeps its width and
|
|
105
|
+
alignment. `bubbleOptions={{ userBackgroundFullWidth: false }}` restores a fitted background.
|
|
106
|
+
Timestamps sit beside messages by default; their size follows the tool text unless overridden:
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
<ChatMessages
|
|
110
|
+
messages={messages}
|
|
111
|
+
showTimestamps
|
|
112
|
+
timestampOptions={{ position: "above", fontScale: 0.88 }}
|
|
113
|
+
/>
|
|
104
114
|
```
|
|
105
115
|
|
|
106
|
-
`--qsl-
|
|
107
|
-
|
|
108
|
-
override sizes by hand; from 0.5.0 on that is no longer needed. Details in the
|
|
109
|
-
[guide](https://github.com/SchlenkR/quassel/blob/main/docs/guide.md#text-size).
|
|
116
|
+
`--qsl-text-trace`, `--qsl-timestamp-font-size` and the other `--qsl-text-*` variables override
|
|
117
|
+
individual sizes. The [guide](https://github.com/SchlenkR/quassel/blob/main/docs/guide.md#text-size) lists the full API.
|
|
110
118
|
|
|
111
119
|
## Development
|
|
112
120
|
|
package/chat.css
CHANGED
|
@@ -46,6 +46,9 @@
|
|
|
46
46
|
.qsl\:relative {
|
|
47
47
|
position: relative;
|
|
48
48
|
}
|
|
49
|
+
.qsl\:inset-0 {
|
|
50
|
+
inset: 0px;
|
|
51
|
+
}
|
|
49
52
|
.qsl\:inset-x-0 {
|
|
50
53
|
inset-inline: 0px;
|
|
51
54
|
}
|
|
@@ -112,11 +115,11 @@
|
|
|
112
115
|
.qsl\:mt-4 {
|
|
113
116
|
margin-top: calc(var(--qsl-spacing) * 4);
|
|
114
117
|
}
|
|
115
|
-
.qsl\:mt-\[var\(--qsl-chat-dense-message-gap\,
|
|
116
|
-
margin-top: var(--qsl-chat-dense-message-gap,
|
|
118
|
+
.qsl\:mt-\[var\(--qsl-chat-dense-message-gap\,3px\)\] {
|
|
119
|
+
margin-top: var(--qsl-chat-dense-message-gap,3px);
|
|
117
120
|
}
|
|
118
|
-
.qsl\:mt-\[var\(--qsl-chat-message-gap\,
|
|
119
|
-
margin-top: var(--qsl-chat-message-gap,
|
|
121
|
+
.qsl\:mt-\[var\(--qsl-chat-message-gap\,10px\)\] {
|
|
122
|
+
margin-top: var(--qsl-chat-message-gap,10px);
|
|
120
123
|
}
|
|
121
124
|
.qsl\:mb-0\.5 {
|
|
122
125
|
margin-bottom: calc(var(--qsl-spacing) * 0.5);
|
|
@@ -336,6 +339,9 @@
|
|
|
336
339
|
.qsl\:items-end {
|
|
337
340
|
align-items: flex-end;
|
|
338
341
|
}
|
|
342
|
+
.qsl\:items-stretch {
|
|
343
|
+
align-items: stretch;
|
|
344
|
+
}
|
|
339
345
|
.qsl\:justify-between {
|
|
340
346
|
justify-content: space-between;
|
|
341
347
|
}
|
|
@@ -354,9 +360,6 @@
|
|
|
354
360
|
.qsl\:gap-0 {
|
|
355
361
|
gap: 0px;
|
|
356
362
|
}
|
|
357
|
-
.qsl\:gap-0\.5 {
|
|
358
|
-
gap: calc(var(--qsl-spacing) * 0.5);
|
|
359
|
-
}
|
|
360
363
|
.qsl\:gap-1 {
|
|
361
364
|
gap: var(--qsl-spacing);
|
|
362
365
|
}
|
|
@@ -375,8 +378,11 @@
|
|
|
375
378
|
.qsl\:gap-\[5px\] {
|
|
376
379
|
gap: 5px;
|
|
377
380
|
}
|
|
378
|
-
.qsl\:gap-\[var\(--qsl-chat-dense-message-gap\,
|
|
379
|
-
gap: var(--qsl-chat-dense-message-gap,
|
|
381
|
+
.qsl\:gap-\[var\(--qsl-chat-dense-message-gap\,3px\)\] {
|
|
382
|
+
gap: var(--qsl-chat-dense-message-gap,3px);
|
|
383
|
+
}
|
|
384
|
+
.qsl\:gap-\[var\(--qsl-tool-group-gap\,1px\)\] {
|
|
385
|
+
gap: var(--qsl-tool-group-gap,1px);
|
|
380
386
|
}
|
|
381
387
|
:where(.qsl\:space-y-0 > :not(:last-child)) {
|
|
382
388
|
--tw-space-y-reverse: 0;
|
|
@@ -395,6 +401,9 @@
|
|
|
395
401
|
.qsl\:self-baseline {
|
|
396
402
|
align-self: baseline;
|
|
397
403
|
}
|
|
404
|
+
.qsl\:self-start {
|
|
405
|
+
align-self: flex-start;
|
|
406
|
+
}
|
|
398
407
|
.qsl\:overflow-auto {
|
|
399
408
|
overflow: auto;
|
|
400
409
|
}
|
|
@@ -530,8 +539,8 @@
|
|
|
530
539
|
.qsl\:bg-\[linear-gradient\(to_right\,var\(--qsl-scroll-cover\,var\(--qsl-background\)\)_50\%\,transparent\)_left\/20px_100\%_no-repeat_local\,linear-gradient\(to_left\,var\(--qsl-scroll-cover\,var\(--qsl-background\)\)_50\%\,transparent\)_right\/20px_100\%_no-repeat_local\,linear-gradient\(to_right\,\#00000047\,transparent\)_left\/14px_100\%_no-repeat_scroll\,linear-gradient\(to_left\,\#00000047\,transparent\)_right\/14px_100\%_no-repeat_scroll\] {
|
|
531
540
|
background-image: linear-gradient(to right,var(--qsl-scroll-cover,var(--qsl-background)) 50%,transparent) left/20px 100% no-repeat local,linear-gradient(to left,var(--qsl-scroll-cover,var(--qsl-background)) 50%,transparent) right/20px 100% no-repeat local,linear-gradient(to right,#00000047,transparent) left/14px 100% no-repeat scroll,linear-gradient(to left,#00000047,transparent) right/14px 100% no-repeat scroll;
|
|
532
541
|
}
|
|
533
|
-
.qsl\:\[mask-image\:linear-gradient\(to_bottom\,\#000_calc\(100\%_-_var\(--qsl-chat-message-gap\,
|
|
534
|
-
mask-image: linear-gradient(to bottom,#000 calc(100% - var(--qsl-chat-message-gap,
|
|
542
|
+
.qsl\:\[mask-image\:linear-gradient\(to_bottom\,\#000_calc\(100\%_-_var\(--qsl-chat-message-gap\,10px\)\)\,transparent\)\] {
|
|
543
|
+
mask-image: linear-gradient(to bottom,#000 calc(100% - var(--qsl-chat-message-gap,10px)),transparent);
|
|
535
544
|
}
|
|
536
545
|
.qsl\:\[mask-image\:linear-gradient\(to_bottom\,\#000_calc\(var\(--qsl-fade-edge\)_-_40px\)\,transparent_calc\(var\(--qsl-fade-edge\)_\+_16px\)\)\] {
|
|
537
546
|
mask-image: linear-gradient(to bottom,#000 calc(var(--qsl-fade-edge) - 40px),transparent calc(var(--qsl-fade-edge) + 16px));
|
|
@@ -608,6 +617,9 @@
|
|
|
608
617
|
.qsl\:py-\[3px\] {
|
|
609
618
|
padding-block: 3px;
|
|
610
619
|
}
|
|
620
|
+
.qsl\:py-\[var\(--qsl-tool-row-padding\,1px\)\] {
|
|
621
|
+
padding-block: var(--qsl-tool-row-padding,1px);
|
|
622
|
+
}
|
|
611
623
|
.qsl\:py-px {
|
|
612
624
|
padding-block: 1px;
|
|
613
625
|
}
|
|
@@ -635,8 +647,8 @@
|
|
|
635
647
|
.qsl\:pb-\[calc\(var\(--qsl-composer-height\,0px\)_\+_max\(3\.25em\,40px\)\)\] {
|
|
636
648
|
padding-bottom: calc(var(--qsl-composer-height,0px) + max(3.25em, 40px));
|
|
637
649
|
}
|
|
638
|
-
.qsl\:pb-\[var\(--qsl-chat-message-gap\,
|
|
639
|
-
padding-bottom: var(--qsl-chat-message-gap,
|
|
650
|
+
.qsl\:pb-\[var\(--qsl-chat-message-gap\,10px\)\] {
|
|
651
|
+
padding-bottom: var(--qsl-chat-message-gap,10px);
|
|
640
652
|
}
|
|
641
653
|
.qsl\:pl-1 {
|
|
642
654
|
padding-left: var(--qsl-spacing);
|
|
@@ -692,8 +704,11 @@
|
|
|
692
704
|
.qsl\:text-meta {
|
|
693
705
|
font-size: var(--qsl-text-meta, calc(var(--qsl-base) * 0.8));
|
|
694
706
|
}
|
|
707
|
+
.qsl\:text-timestamp {
|
|
708
|
+
font-size: var(--qsl-timestamp-font-size, var(--qsl-text-trace, calc(var(--qsl-base) * var(--qsl-tool-font-scale, 0.88))));
|
|
709
|
+
}
|
|
695
710
|
.qsl\:text-trace {
|
|
696
|
-
font-size: var(--qsl-text-trace, calc(var(--qsl-base) * 0.
|
|
711
|
+
font-size: var(--qsl-text-trace, calc(var(--qsl-base) * var(--qsl-tool-font-scale, 0.88)));
|
|
697
712
|
}
|
|
698
713
|
.qsl\:leading-\[1\.3\] {
|
|
699
714
|
--tw-leading: 1.3;
|
|
@@ -719,10 +734,6 @@
|
|
|
719
734
|
--tw-leading: var(--qsl-chat-line-height,1.5);
|
|
720
735
|
line-height: var(--qsl-chat-line-height,1.5);
|
|
721
736
|
}
|
|
722
|
-
.qsl\:leading-\[var\(--qsl-chat-line-height\,1\.625\)\] {
|
|
723
|
-
--tw-leading: var(--qsl-chat-line-height,1.625);
|
|
724
|
-
line-height: var(--qsl-chat-line-height,1.625);
|
|
725
|
-
}
|
|
726
737
|
.qsl\:leading-normal {
|
|
727
738
|
--tw-leading: var(--qsl-leading-normal);
|
|
728
739
|
line-height: var(--qsl-leading-normal);
|
|
@@ -925,8 +936,8 @@
|
|
|
925
936
|
.qsl\:\[--qsl-scroll-cover\:var\(--qsl-secondary\)\] {
|
|
926
937
|
--qsl-scroll-cover: var(--qsl-secondary);
|
|
927
938
|
}
|
|
928
|
-
.qsl\:\[-webkit-mask-image\:linear-gradient\(to_bottom\,\#000_calc\(100\%_-_var\(--qsl-chat-message-gap\,
|
|
929
|
-
-webkit-mask-image: linear-gradient(to bottom,#000 calc(100% - var(--qsl-chat-message-gap,
|
|
939
|
+
.qsl\:\[-webkit-mask-image\:linear-gradient\(to_bottom\,\#000_calc\(100\%_-_var\(--qsl-chat-message-gap\,10px\)\)\,transparent\)\] {
|
|
940
|
+
-webkit-mask-image: linear-gradient(to bottom,#000 calc(100% - var(--qsl-chat-message-gap,10px)),transparent);
|
|
930
941
|
}
|
|
931
942
|
.qsl\:\[-webkit-mask-image\:linear-gradient\(to_bottom\,\#000_calc\(var\(--qsl-fade-edge\)_-_40px\)\,transparent_calc\(var\(--qsl-fade-edge\)_\+_16px\)\)\] {
|
|
932
943
|
-webkit-mask-image: linear-gradient(to bottom,#000 calc(var(--qsl-fade-edge) - 40px),transparent calc(var(--qsl-fade-edge) + 16px));
|
|
@@ -1119,9 +1130,6 @@
|
|
|
1119
1130
|
:where([data-tone="material"]) .qsl\:in-data-\[tone\=material\]\:p-0 {
|
|
1120
1131
|
padding: 0px;
|
|
1121
1132
|
}
|
|
1122
|
-
:where([data-tone="material"]) .qsl\:in-data-\[tone\=material\]\:text-foreground {
|
|
1123
|
-
color: var(--qsl-foreground);
|
|
1124
|
-
}
|
|
1125
1133
|
:where([data-tone="on-color"]) .qsl\:in-data-\[tone\=on-color\]\:border-white\/35 {
|
|
1126
1134
|
border-color: var(--qsl-color-white);
|
|
1127
1135
|
@supports (color: color-mix(in lab, red, red)) {
|
|
@@ -1652,7 +1660,7 @@
|
|
|
1652
1660
|
@property --qsl-base {
|
|
1653
1661
|
syntax: "<length>";
|
|
1654
1662
|
inherits: true;
|
|
1655
|
-
initial-value:
|
|
1663
|
+
initial-value: 13px;
|
|
1656
1664
|
}
|
|
1657
1665
|
@layer theme {
|
|
1658
1666
|
:where(:root, :host, [data-theme="light"], [data-theme="system"]) {
|
|
@@ -1735,7 +1743,7 @@
|
|
|
1735
1743
|
font-family: var(--qsl-font);
|
|
1736
1744
|
font-feature-settings: normal;
|
|
1737
1745
|
font-variation-settings: normal;
|
|
1738
|
-
font-size: var(--qsl-font-size,
|
|
1746
|
+
font-size: var(--qsl-font-size, 13px);
|
|
1739
1747
|
--qsl-base: 1em;
|
|
1740
1748
|
color: var(--qsl-foreground);
|
|
1741
1749
|
-webkit-tap-highlight-color: transparent;
|
|
@@ -2018,7 +2026,7 @@
|
|
|
2018
2026
|
@layer properties {
|
|
2019
2027
|
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
|
|
2020
2028
|
:root, :host {
|
|
2021
|
-
--qsl-base:
|
|
2029
|
+
--qsl-base: 13px;
|
|
2022
2030
|
}
|
|
2023
2031
|
*, ::before, ::after, ::backdrop {
|
|
2024
2032
|
--tw-space-y-reverse: 0;
|
package/index.js
CHANGED
|
@@ -158,7 +158,7 @@ var defaultTexts = englishTexts;
|
|
|
158
158
|
|
|
159
159
|
// packages/quassel/src/ui/cn.ts
|
|
160
160
|
import { createCn } from "cn/config";
|
|
161
|
-
var cn = createCn({ prefix: "qsl", extend: { theme: { text: ["meta", "trace", "label", "chat"] } } });
|
|
161
|
+
var cn = createCn({ prefix: "qsl", extend: { theme: { text: ["meta", "trace", "timestamp", "label", "chat"] } } });
|
|
162
162
|
|
|
163
163
|
// packages/quassel/src/ChatMessages.tsx
|
|
164
164
|
import { useCallback as useCallback2, useContext as useContext3, useEffect as useEffect3, useLayoutEffect, useMemo as useMemo3, useRef as useRef3, useState as useState4 } from "react";
|
|
@@ -933,10 +933,14 @@ import { CheckIcon as CheckIcon4, ChevronDownIcon, ChevronRightIcon, ChevronUpIc
|
|
|
933
933
|
// packages/quassel/src/options.ts
|
|
934
934
|
var cssLength = (value) => typeof value === "number" ? `${value}px` : value;
|
|
935
935
|
var appearanceStyle = (appearance) => ({
|
|
936
|
+
"--qsl-font-size": cssLength(appearance?.fontSize),
|
|
936
937
|
"--qsl-chat-font-size": cssLength(appearance?.fontSize),
|
|
937
938
|
"--qsl-chat-line-height": appearance?.lineHeight,
|
|
938
939
|
"--qsl-chat-message-gap": cssLength(appearance?.messageGap),
|
|
939
|
-
"--qsl-chat-dense-message-gap": cssLength(appearance?.denseMessageGap)
|
|
940
|
+
"--qsl-chat-dense-message-gap": cssLength(appearance?.denseMessageGap),
|
|
941
|
+
"--qsl-tool-font-scale": appearance?.toolFontScale,
|
|
942
|
+
"--qsl-tool-group-gap": cssLength(appearance?.toolGroupGap),
|
|
943
|
+
"--qsl-tool-row-padding": cssLength(appearance?.toolRowPadding)
|
|
940
944
|
});
|
|
941
945
|
|
|
942
946
|
// packages/quassel/src/timestamps.ts
|
|
@@ -1159,10 +1163,10 @@ function announce(text) {
|
|
|
1159
1163
|
|
|
1160
1164
|
// packages/quassel/src/ChatMessages.tsx
|
|
1161
1165
|
import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1162
|
-
var stepClasses = "qsl:mt-[var(--qsl-chat-message-gap,
|
|
1163
|
-
var denseStepClasses = "qsl:mt-[var(--qsl-chat-dense-message-gap,
|
|
1164
|
-
var traceClasses = "qsl:flex qsl:w-full qsl:gap-2 qsl:pl-6 qsl:text-left qsl:text-trace qsl:leading-[1.375] qsl:text-muted-foreground";
|
|
1165
|
-
var traceButtonClasses = "qsl:cursor-pointer qsl:rounded-md qsl:
|
|
1166
|
+
var stepClasses = "qsl:mt-[var(--qsl-chat-message-gap,10px)]";
|
|
1167
|
+
var denseStepClasses = "qsl:mt-[var(--qsl-chat-dense-message-gap,3px)]";
|
|
1168
|
+
var traceClasses = "qsl:flex qsl:w-full qsl:gap-2 qsl:py-[var(--qsl-tool-row-padding,1px)] qsl:pl-6 qsl:text-left qsl:text-trace qsl:leading-[1.375] qsl:text-muted-foreground";
|
|
1169
|
+
var traceButtonClasses = "qsl:cursor-pointer qsl:rounded-md qsl:pr-2 qsl:transition-colors qsl:hover:bg-secondary qsl:hover:text-foreground qsl:focus-visible:bg-secondary qsl:focus-visible:text-foreground qsl:focus-visible:outline-none";
|
|
1166
1170
|
var traceIconClasses = "qsl:mt-0.5 qsl:flex-none qsl:opacity-60";
|
|
1167
1171
|
var traceErrorIconClasses = "qsl:mt-0.5 qsl:flex-none qsl:text-destructive qsl:opacity-100";
|
|
1168
1172
|
var traceLineClasses = "qsl:min-w-0 qsl:self-baseline qsl:[overflow-wrap:anywhere]";
|
|
@@ -1181,7 +1185,7 @@ var chipClasses = cn(
|
|
|
1181
1185
|
var chipInteractiveClasses = "qsl:cursor-pointer qsl:hover:border-border qsl:hover:bg-secondary qsl:hover:text-foreground qsl:focus-visible:border-border qsl:focus-visible:bg-secondary qsl:focus-visible:text-foreground qsl:focus-visible:outline-none qsl:data-[state=done]:hover:opacity-100 qsl:data-[state=done]:focus-visible:opacity-100";
|
|
1182
1186
|
var collapseAtBottomFrom = 11;
|
|
1183
1187
|
var maxAnnouncementsAtOnce = 2;
|
|
1184
|
-
var bubbleBodyClasses = "qsl:relative qsl:max-w-[86%] qsl:px-3 qsl:py-2 qsl:leading-[var(--qsl-chat-line-height,1.
|
|
1188
|
+
var bubbleBodyClasses = "qsl:relative qsl:max-w-[86%] qsl:px-3 qsl:py-2 qsl:leading-[var(--qsl-chat-line-height,1.5)] qsl:[overflow-wrap:anywhere] qsl:@max-[620px]/chat:max-w-full";
|
|
1185
1189
|
function isStep(message) {
|
|
1186
1190
|
return !!message && (message.role === "thinking" || message.role === "tool");
|
|
1187
1191
|
}
|
|
@@ -1337,13 +1341,22 @@ function ChatMessages({
|
|
|
1337
1341
|
[selected, detailMode, running2, dock]
|
|
1338
1342
|
);
|
|
1339
1343
|
const openActions = dock ? messages.filter(isOpenAction) : [];
|
|
1340
|
-
const withTime = (content, key, at, dense = false) => showTimestamps ? /* @__PURE__ */ jsxs6(
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1344
|
+
const withTime = (content, key, at, dense = false) => showTimestamps ? /* @__PURE__ */ jsxs6(
|
|
1345
|
+
"div",
|
|
1346
|
+
{
|
|
1347
|
+
className: cn("qsl:flex", timestampOptions?.position === "above" ? "qsl:flex-col qsl:items-stretch qsl:gap-1" : "qsl:items-baseline qsl:gap-2", dense ? denseStepClasses : stepClasses),
|
|
1348
|
+
"data-chat": "timestamped",
|
|
1349
|
+
"data-timestamp-position": timestampOptions?.position ?? "aside",
|
|
1350
|
+
children: [
|
|
1351
|
+
/* @__PURE__ */ jsx13("time", { dateTime: messageDate(at)?.toISOString(), className: cn(
|
|
1352
|
+
"qsl:flex-none qsl:text-timestamp qsl:leading-[1.375] qsl:tabular-nums qsl:text-muted-foreground qsl:opacity-85",
|
|
1353
|
+
timestampOptions?.position === "above" ? "qsl:self-start" : timestampOptions?.format && timestampOptions.format !== "time" ? "qsl:w-[clamp(60px,20%,120px)]" : "qsl:min-w-[5ch] qsl:whitespace-nowrap"
|
|
1354
|
+
), children: messageDate(at) ? timestampLabel(messageDate(at), timestampOptions, now) : "" }),
|
|
1355
|
+
/* @__PURE__ */ jsx13("div", { className: "qsl:min-w-0 qsl:flex-1 qsl:[&>*:first-child]:mt-0", children: content })
|
|
1356
|
+
]
|
|
1357
|
+
},
|
|
1358
|
+
`time-${key}`
|
|
1359
|
+
) : content;
|
|
1347
1360
|
const chipMode = detailMode === "current" || detailMode === "chips" || detailMode === "icons";
|
|
1348
1361
|
const elapsedAfter = running2 && toolElapsedThreshold !== false ? toolElapsedThreshold : void 0;
|
|
1349
1362
|
const groupMode = detailMode === "grouped";
|
|
@@ -1439,7 +1452,8 @@ function ChatMessages({
|
|
|
1439
1452
|
const transcript = /* @__PURE__ */ jsxs6("div", { className: cn("qsl:@container/chat qsl:relative qsl:flex qsl:min-h-0 qsl:flex-1 qsl:flex-col", className), "data-quassel": "", style: {
|
|
1440
1453
|
...appearanceStyle(appearance),
|
|
1441
1454
|
"--qsl-chat-content-max-width": typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth,
|
|
1442
|
-
"--qsl-chat-horizontal-padding": typeof horizontalPadding === "number" ? `${horizontalPadding}px` : horizontalPadding
|
|
1455
|
+
"--qsl-chat-horizontal-padding": typeof horizontalPadding === "number" ? `${horizontalPadding}px` : horizontalPadding,
|
|
1456
|
+
"--qsl-timestamp-font-size": timestampOptions?.fontScale === void 0 ? void 0 : `calc(var(--qsl-base) * ${timestampOptions.fontScale})`
|
|
1443
1457
|
}, children: [
|
|
1444
1458
|
/* @__PURE__ */ jsx13(
|
|
1445
1459
|
"div",
|
|
@@ -1505,7 +1519,7 @@ function ChatMessages({
|
|
|
1505
1519
|
}
|
|
1506
1520
|
}, children: /* @__PURE__ */ jsx13(ChevronDownIcon, {}) }) }),
|
|
1507
1521
|
dock && openActions.length > 0 && createPortal(
|
|
1508
|
-
/* @__PURE__ */ jsx13("div", { className: "qsl:flex qsl:flex-col qsl:gap-[var(--qsl-chat-dense-message-gap,
|
|
1522
|
+
/* @__PURE__ */ jsx13("div", { className: "qsl:flex qsl:flex-col qsl:gap-[var(--qsl-chat-dense-message-gap,3px)] qsl:text-chat qsl:text-foreground", style: appearanceStyle(appearance), children: openActions.map((message) => /* @__PURE__ */ jsx13("div", { children: /* @__PURE__ */ jsx13(ActionContent, { action: message.action, onDismissAction, renderAction, text: message.text, texts: allTexts }) }, message.key)) }),
|
|
1509
1523
|
dock
|
|
1510
1524
|
)
|
|
1511
1525
|
] });
|
|
@@ -1604,7 +1618,7 @@ function StepGroup({
|
|
|
1604
1618
|
] })
|
|
1605
1619
|
] });
|
|
1606
1620
|
if (!groupExpandable) {
|
|
1607
|
-
return /* @__PURE__ */ jsx13("div", { className: stepClasses, "data-step": "group", children: /* @__PURE__ */ jsx13("div", { className: cn(traceClasses, "qsl:items-center qsl:
|
|
1621
|
+
return /* @__PURE__ */ jsx13("div", { className: stepClasses, "data-step": "group", children: /* @__PURE__ */ jsx13("div", { className: cn(traceClasses, "qsl:items-center qsl:pr-2 qsl:pl-1", active && "qsl:animate-fade-pulse qsl:motion-reduce:animate-none"), children: summary }) });
|
|
1608
1622
|
}
|
|
1609
1623
|
return /* @__PURE__ */ jsxs6("div", { className: stepClasses, "data-step": "group", children: [
|
|
1610
1624
|
/* @__PURE__ */ jsxs6(
|
|
@@ -1621,7 +1635,7 @@ function StepGroup({
|
|
|
1621
1635
|
]
|
|
1622
1636
|
}
|
|
1623
1637
|
),
|
|
1624
|
-
open && /* @__PURE__ */ jsx13("div", { className: "qsl:mt-0.5 qsl:flex qsl:flex-col qsl:gap-
|
|
1638
|
+
open && /* @__PURE__ */ jsx13("div", { className: "qsl:mt-0.5 qsl:flex qsl:flex-col qsl:gap-[var(--qsl-tool-group-gap,1px)] qsl:pl-3", children: messages.map((message) => /* @__PURE__ */ jsx13(TraceLine, { className: "qsl:pl-3", elapsedAfter, expandable, message, texts, toolArgumentsText }, message.key)) }),
|
|
1625
1639
|
open && messages.length >= collapseAtBottomFrom && /* @__PURE__ */ jsxs6(
|
|
1626
1640
|
"button",
|
|
1627
1641
|
{
|
|
@@ -1766,23 +1780,30 @@ function Bubble({
|
|
|
1766
1780
|
/* @__PURE__ */ jsx13(MessageActions, { message, options: messageActions, texts })
|
|
1767
1781
|
] });
|
|
1768
1782
|
const cursor = message.role === "assistant" && message.textCursor ? JSON.stringify(message.textCursor) : void 0;
|
|
1769
|
-
if (!useBubble) return /* @__PURE__ */ jsx13("div", { "data-chat-text-cursor": cursor, className: cn(stepSpacing, "qsl:group qsl:relative qsl:w-full qsl:leading-[var(--qsl-chat-line-height,1.
|
|
1770
|
-
|
|
1783
|
+
if (!useBubble) return /* @__PURE__ */ jsx13("div", { "data-chat-text-cursor": cursor, className: cn(stepSpacing, "qsl:group qsl:relative qsl:w-full qsl:leading-[var(--qsl-chat-line-height,1.5)] qsl:text-foreground"), "data-message": "answer", children: content });
|
|
1784
|
+
const fullBackground = message.role === "user" && bubbleOptions?.userBackgroundFullWidth !== false;
|
|
1785
|
+
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";
|
|
1786
|
+
return /* @__PURE__ */ jsxs6(
|
|
1771
1787
|
"div",
|
|
1772
1788
|
{
|
|
1773
1789
|
"data-chat-text-cursor": cursor,
|
|
1774
|
-
className: cn(stepSpacing, "qsl:flex", side === "end" ? "qsl:justify-end" : "qsl:justify-start"),
|
|
1790
|
+
className: cn(stepSpacing, "qsl:relative qsl:flex", side === "end" ? "qsl:justify-end" : "qsl:justify-start"),
|
|
1775
1791
|
"data-message": message.role === "user" && !message.bubble && variant === "default" ? "user" : "bubble",
|
|
1776
1792
|
"data-side": side,
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
{
|
|
1780
|
-
|
|
1781
|
-
"
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1793
|
+
"data-background-width": fullBackground ? "full" : "content",
|
|
1794
|
+
children: [
|
|
1795
|
+
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 } }),
|
|
1796
|
+
/* @__PURE__ */ jsx13(
|
|
1797
|
+
"div",
|
|
1798
|
+
{
|
|
1799
|
+
className: cn(bubbleBodyClasses, "qsl:group", !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)]"),
|
|
1800
|
+
"data-chat": "bubble-content",
|
|
1801
|
+
"data-tone": message.bubble ? "on-color" : void 0,
|
|
1802
|
+
style: { background: fullBackground ? void 0 : message.bubble?.color, maxWidth: bubbleOptions?.maxWidth },
|
|
1803
|
+
children: content
|
|
1804
|
+
}
|
|
1805
|
+
)
|
|
1806
|
+
]
|
|
1786
1807
|
}
|
|
1787
1808
|
);
|
|
1788
1809
|
}
|
|
@@ -1884,7 +1905,7 @@ function ChatPanel({
|
|
|
1884
1905
|
/* @__PURE__ */ jsx14("div", { children: /* @__PURE__ */ jsx14(
|
|
1885
1906
|
"div",
|
|
1886
1907
|
{
|
|
1887
|
-
className: "qsl:-mx-[16px] qsl:max-h-[calc(var(--qsl-panel-height,100dvh)_/_2)] qsl:overflow-y-auto qsl:overscroll-contain qsl:px-[16px] qsl:pb-[var(--qsl-chat-message-gap,
|
|
1908
|
+
className: "qsl:-mx-[16px] qsl:max-h-[calc(var(--qsl-panel-height,100dvh)_/_2)] qsl:overflow-y-auto qsl:overscroll-contain qsl:px-[16px] qsl:pb-[var(--qsl-chat-message-gap,10px)] qsl:[-webkit-mask-image:linear-gradient(to_bottom,#000_calc(100%_-_var(--qsl-chat-message-gap,10px)),transparent)] qsl:[mask-image:linear-gradient(to_bottom,#000_calc(100%_-_var(--qsl-chat-message-gap,10px)),transparent)] qsl:empty:hidden",
|
|
1888
1909
|
"data-chat": "actions",
|
|
1889
1910
|
ref: setDock
|
|
1890
1911
|
}
|