@happyvertical/smrt-chat 0.34.5 → 0.34.7
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/manifest.json +2 -2
- package/dist/smrt-knowledge.json +4 -4
- package/dist/svelte/components/agent/AgentChat.svelte +34 -49
- package/dist/svelte/components/agent/AgentChat.svelte.d.ts.map +1 -1
- package/dist/svelte/components/agent/AgentSelector.svelte +1 -0
- package/dist/svelte/components/agent/AgentSelector.svelte.d.ts.map +1 -1
- package/dist/svelte/components/agent/AgentSessionPanel.svelte +15 -16
- package/dist/svelte/components/agent/AgentSessionPanel.svelte.d.ts.map +1 -1
- package/dist/svelte/components/agent/ToolCallDisplay.svelte +1 -0
- package/dist/svelte/components/agent/ToolCallDisplay.svelte.d.ts.map +1 -1
- package/dist/svelte/components/dialogs/RoomCreateDialog.svelte +29 -94
- package/dist/svelte/components/dialogs/RoomCreateDialog.svelte.d.ts.map +1 -1
- package/dist/svelte/components/dialogs/SearchMessages.svelte +51 -36
- package/dist/svelte/components/dialogs/SearchMessages.svelte.d.ts.map +1 -1
- package/dist/svelte/components/layout/ChatLayout.svelte +1 -0
- package/dist/svelte/components/layout/ChatLayout.svelte.d.ts.map +1 -1
- package/dist/svelte/components/layout/MemberList.svelte +10 -15
- package/dist/svelte/components/layout/MemberList.svelte.d.ts.map +1 -1
- package/dist/svelte/components/layout/RoomHeader.svelte +13 -16
- package/dist/svelte/components/layout/RoomHeader.svelte.d.ts.map +1 -1
- package/dist/svelte/components/layout/RoomList.svelte +26 -17
- package/dist/svelte/components/layout/RoomList.svelte.d.ts.map +1 -1
- package/dist/svelte/components/messages/MessageInput.svelte +34 -48
- package/dist/svelte/components/messages/MessageInput.svelte.d.ts.map +1 -1
- package/dist/svelte/components/messages/MessageItem.svelte +52 -43
- package/dist/svelte/components/messages/MessageItem.svelte.d.ts.map +1 -1
- package/dist/svelte/components/messages/ThreadPanel.svelte +9 -9
- package/dist/svelte/components/messages/ThreadPanel.svelte.d.ts.map +1 -1
- package/dist/svelte/components/shared/FileUpload.svelte +23 -54
- package/dist/svelte/components/shared/FileUpload.svelte.d.ts.map +1 -1
- package/dist/svelte/components/shared/MentionAutocomplete.svelte +1 -0
- package/dist/svelte/components/shared/MentionAutocomplete.svelte.d.ts.map +1 -1
- package/dist/svelte/components/shared/ReactionPicker.svelte +15 -66
- package/dist/svelte/components/shared/ReactionPicker.svelte.d.ts.map +1 -1
- package/dist/svelte/components/tabs/ChatTab.svelte +20 -18
- package/dist/svelte/components/tabs/ChatTab.svelte.d.ts.map +1 -1
- package/dist/svelte/components/tabs/ChatTabList.svelte +13 -10
- package/dist/svelte/components/tabs/ChatTabList.svelte.d.ts.map +1 -1
- package/dist/svelte/components/tabs/MiniChat.svelte +21 -37
- package/dist/svelte/components/tabs/MiniChat.svelte.d.ts.map +1 -1
- package/dist/svelte/index.d.ts +1 -2
- package/dist/svelte/index.d.ts.map +1 -1
- package/dist/svelte/index.js +5 -4
- package/package.json +9 -8
- package/dist/svelte/components/shared/MessageBubble.svelte +0 -81
- package/dist/svelte/components/shared/MessageBubble.svelte.d.ts +0 -16
- package/dist/svelte/components/shared/MessageBubble.svelte.d.ts.map +0 -1
- package/dist/svelte/components/shared/TypingIndicator.svelte +0 -90
- package/dist/svelte/components/shared/TypingIndicator.svelte.d.ts +0 -12
- package/dist/svelte/components/shared/TypingIndicator.svelte.d.ts.map +0 -1
- package/dist/svelte/components/shared/__tests__/MessageBubble.test.js +0 -21
- package/dist/svelte/components/shared/__tests__/TypingIndicator.test.js +0 -27
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
* MessageInput - Chat message input bar
|
|
4
4
|
* Text area with send button. Shows reply preview when replying.
|
|
5
5
|
*/
|
|
6
|
+
import { Textarea } from '@happyvertical/smrt-ui/forms';
|
|
6
7
|
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
8
|
+
import { Button } from '@happyvertical/smrt-ui/ui';
|
|
7
9
|
import { M } from '../../i18n.messages.js';
|
|
8
10
|
|
|
9
11
|
const { t } = useI18n();
|
|
@@ -30,7 +32,9 @@ const {
|
|
|
30
32
|
}: Props = $props();
|
|
31
33
|
|
|
32
34
|
let content = $state('');
|
|
33
|
-
|
|
35
|
+
// Captured from the textarea's input event so auto-resize works without binding
|
|
36
|
+
// to the Textarea primitive's inner DOM node (the primitive doesn't expose it).
|
|
37
|
+
let textareaEl: HTMLTextAreaElement | undefined;
|
|
34
38
|
|
|
35
39
|
function handleSend() {
|
|
36
40
|
const trimmed = content.trim();
|
|
@@ -49,10 +53,11 @@ function handleKeydown(event: KeyboardEvent) {
|
|
|
49
53
|
}
|
|
50
54
|
}
|
|
51
55
|
|
|
52
|
-
function handleInput() {
|
|
53
|
-
|
|
54
|
-
textareaEl
|
|
55
|
-
|
|
56
|
+
function handleInput(event: Event) {
|
|
57
|
+
const el = event.currentTarget as HTMLTextAreaElement;
|
|
58
|
+
textareaEl = el;
|
|
59
|
+
el.style.height = 'auto';
|
|
60
|
+
el.style.height = `${Math.min(el.scrollHeight, 120)}px`;
|
|
56
61
|
}
|
|
57
62
|
</script>
|
|
58
63
|
|
|
@@ -64,31 +69,33 @@ function handleInput() {
|
|
|
64
69
|
<span class="message-input__reply-text">{replyTo.content}</span>
|
|
65
70
|
</div>
|
|
66
71
|
{#if oncancelreply}
|
|
67
|
-
<
|
|
72
|
+
<Button
|
|
73
|
+
variant="ghost"
|
|
74
|
+
size="sm"
|
|
68
75
|
class="message-input__reply-close"
|
|
69
76
|
type="button"
|
|
70
77
|
onclick={oncancelreply}
|
|
71
78
|
aria-label={t(M['chat.message_input.cancel_reply'])}
|
|
72
79
|
>
|
|
73
80
|
<svg viewBox="0 0 16 16" width="14" height="14"><path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" /></svg>
|
|
74
|
-
</
|
|
81
|
+
</Button>
|
|
75
82
|
{/if}
|
|
76
83
|
</div>
|
|
77
84
|
{/if}
|
|
78
85
|
|
|
79
86
|
<div class="message-input__bar">
|
|
80
|
-
<
|
|
81
|
-
bind:this={textareaEl}
|
|
87
|
+
<Textarea
|
|
82
88
|
bind:value={content}
|
|
83
89
|
class="message-input__textarea"
|
|
84
90
|
{placeholder}
|
|
85
91
|
{disabled}
|
|
86
|
-
rows=
|
|
92
|
+
rows={1}
|
|
87
93
|
onkeydown={handleKeydown}
|
|
88
94
|
oninput={handleInput}
|
|
89
95
|
aria-label={t(M['chat.message_input.input_label'])}
|
|
90
|
-
|
|
91
|
-
<
|
|
96
|
+
/>
|
|
97
|
+
<Button
|
|
98
|
+
variant="ghost"
|
|
92
99
|
class="message-input__send"
|
|
93
100
|
type="button"
|
|
94
101
|
onclick={handleSend}
|
|
@@ -105,7 +112,7 @@ function handleInput() {
|
|
|
105
112
|
stroke-linejoin="round"
|
|
106
113
|
/>
|
|
107
114
|
</svg>
|
|
108
|
-
</
|
|
115
|
+
</Button>
|
|
109
116
|
</div>
|
|
110
117
|
</div>
|
|
111
118
|
|
|
@@ -155,21 +162,18 @@ function handleInput() {
|
|
|
155
162
|
text-overflow: ellipsis;
|
|
156
163
|
}
|
|
157
164
|
|
|
158
|
-
.
|
|
159
|
-
|
|
160
|
-
align-items: center;
|
|
161
|
-
justify-content: center;
|
|
165
|
+
/* :global() pierces into the Button child's rendered <button> (see #1589). */
|
|
166
|
+
.message-input__reply :global(.message-input__reply-close) {
|
|
162
167
|
width: 24px;
|
|
163
168
|
height: 24px;
|
|
164
|
-
|
|
169
|
+
padding: 0;
|
|
165
170
|
border-radius: var(--smrt-radius-small, 0.25rem);
|
|
166
171
|
background: transparent;
|
|
167
172
|
color: var(--smrt-color-on-surface-variant, #43474e);
|
|
168
|
-
cursor: pointer;
|
|
169
173
|
flex-shrink: 0;
|
|
170
174
|
}
|
|
171
175
|
|
|
172
|
-
.message-input__reply-close:hover {
|
|
176
|
+
.message-input__reply :global(.message-input__reply-close:hover) {
|
|
173
177
|
background: var(--smrt-color-surface-container-high, #e1e3e8);
|
|
174
178
|
}
|
|
175
179
|
|
|
@@ -180,53 +184,35 @@ function handleInput() {
|
|
|
180
184
|
padding: var(--smrt-spacing-3, 0.75rem) var(--smrt-spacing-4, 1rem);
|
|
181
185
|
}
|
|
182
186
|
|
|
183
|
-
|
|
187
|
+
/* Layout/sizing for the Textarea primitive's rendered <textarea>; tokenised
|
|
188
|
+
border/focus/placeholder styling comes from the primitive. The height is
|
|
189
|
+
JS-driven (auto-resize), so resize is disabled and capped at max-height. */
|
|
190
|
+
:global(.message-input__textarea) {
|
|
184
191
|
flex: 1;
|
|
185
192
|
resize: none;
|
|
186
|
-
|
|
187
|
-
border-radius: var(--smrt-radius-medium, 0.5rem);
|
|
188
|
-
padding: var(--smrt-spacing-2, 0.375rem) var(--smrt-spacing-3, 0.75rem);
|
|
189
|
-
font-size: var(--smrt-typography-body-medium-size, 0.875rem);
|
|
190
|
-
font-family: inherit;
|
|
191
|
-
line-height: 1.4;
|
|
192
|
-
background: var(--smrt-color-surface-container-low, #f9fafb);
|
|
193
|
-
color: var(--smrt-color-on-surface, #1b1b1f);
|
|
193
|
+
min-height: auto;
|
|
194
194
|
max-height: 120px;
|
|
195
195
|
overflow-y: auto;
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
outline-offset: -1px;
|
|
201
|
-
border-color: transparent;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
.message-input__textarea::placeholder {
|
|
205
|
-
color: var(--smrt-color-outline, #74777f);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
.message-input__send {
|
|
209
|
-
display: flex;
|
|
210
|
-
align-items: center;
|
|
211
|
-
justify-content: center;
|
|
198
|
+
/* :global() pierces into the Button child's rendered <button> (see #1589). */
|
|
199
|
+
.message-input__bar :global(.message-input__send) {
|
|
212
200
|
width: 36px;
|
|
213
201
|
height: 36px;
|
|
214
|
-
|
|
202
|
+
padding: 0;
|
|
215
203
|
border-radius: var(--smrt-radius-full, 9999px);
|
|
216
204
|
background: var(--smrt-color-primary, #005ac1);
|
|
217
205
|
color: var(--smrt-color-on-primary, #ffffff);
|
|
218
|
-
cursor: pointer;
|
|
219
206
|
flex-shrink: 0;
|
|
220
207
|
transition: background var(--smrt-duration-short2, 150ms) var(--smrt-easing-standard, ease);
|
|
221
208
|
}
|
|
222
209
|
|
|
223
|
-
.message-input__send:hover:not(:disabled) {
|
|
210
|
+
.message-input__bar :global(.message-input__send:hover:not(:disabled)) {
|
|
224
211
|
background: color-mix(in srgb, var(--smrt-color-primary, #005ac1) 85%, var(--smrt-color-shadow, #000));
|
|
225
212
|
}
|
|
226
213
|
|
|
227
|
-
.message-input__send:disabled {
|
|
214
|
+
.message-input__bar :global(.message-input__send:disabled) {
|
|
228
215
|
background: var(--smrt-color-surface-container-high, #e1e3e8);
|
|
229
216
|
color: var(--smrt-color-outline, #74777f);
|
|
230
|
-
cursor: not-allowed;
|
|
231
217
|
}
|
|
232
218
|
</style>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageInput.svelte.d.ts","sourceRoot":"","sources":["../../../../src/svelte/components/messages/MessageInput.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MessageInput.svelte.d.ts","sourceRoot":"","sources":["../../../../src/svelte/components/messages/MessageInput.svelte.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,KAAK;IACpB,sCAAsC;IACtC,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wBAAwB;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,6CAA6C;IAC7C,OAAO,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACrE,4BAA4B;IAC5B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B;AA8ED,QAAA,MAAM,YAAY,2CAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
|
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
* Displays avatar, message bubble, reactions, reply preview, and tool call data.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { MessageBubble } from '@happyvertical/smrt-ui/chat';
|
|
7
8
|
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
9
|
+
import { Button } from '@happyvertical/smrt-ui/ui';
|
|
8
10
|
import { M } from '../../i18n.messages.js';
|
|
9
11
|
import type { ChatMessageData } from '../../types.js';
|
|
10
12
|
import Avatar from '../shared/Avatar.svelte';
|
|
11
|
-
import MessageBubble from '../shared/MessageBubble.svelte';
|
|
12
13
|
import ReactionPicker from '../shared/ReactionPicker.svelte';
|
|
13
14
|
|
|
14
15
|
const { t } = useI18n();
|
|
@@ -110,7 +111,7 @@ function handleEscape(event: KeyboardEvent) {
|
|
|
110
111
|
|
|
111
112
|
{#if message.messageType === 'system' || message.messageType === 'action'}
|
|
112
113
|
<div class="message-item message-item--system">
|
|
113
|
-
<MessageBubble content={message.content}
|
|
114
|
+
<MessageBubble content={message.content} own={false} variant="system" />
|
|
114
115
|
</div>
|
|
115
116
|
{:else}
|
|
116
117
|
<div
|
|
@@ -146,7 +147,7 @@ function handleEscape(event: KeyboardEvent) {
|
|
|
146
147
|
|
|
147
148
|
<MessageBubble
|
|
148
149
|
content={message.content}
|
|
149
|
-
{isOwn}
|
|
150
|
+
own={isOwn}
|
|
150
151
|
variant={bubbleVariant}
|
|
151
152
|
/>
|
|
152
153
|
|
|
@@ -172,16 +173,17 @@ function handleEscape(event: KeyboardEvent) {
|
|
|
172
173
|
{#if message.reactions.length > 0}
|
|
173
174
|
<div class="message-item__reactions">
|
|
174
175
|
{#each message.reactions as reaction}
|
|
175
|
-
<
|
|
176
|
-
|
|
177
|
-
|
|
176
|
+
<Button
|
|
177
|
+
variant="ghost"
|
|
178
|
+
size="sm"
|
|
179
|
+
class="message-item__reaction{reaction.reacted ? ' message-item__reaction--active' : ''}"
|
|
178
180
|
type="button"
|
|
179
181
|
onclick={() => onreact?.(message.id, reaction.emoji)}
|
|
180
182
|
aria-label="{reaction.emoji} {reaction.count}"
|
|
181
183
|
>
|
|
182
184
|
<span class="message-item__reaction-emoji">{reaction.emoji}</span>
|
|
183
185
|
<span class="message-item__reaction-count">{reaction.count}</span>
|
|
184
|
-
</
|
|
186
|
+
</Button>
|
|
185
187
|
{/each}
|
|
186
188
|
</div>
|
|
187
189
|
{/if}
|
|
@@ -195,7 +197,9 @@ function handleEscape(event: KeyboardEvent) {
|
|
|
195
197
|
</div>
|
|
196
198
|
|
|
197
199
|
{#if hasActions}
|
|
198
|
-
<
|
|
200
|
+
<Button
|
|
201
|
+
variant="ghost"
|
|
202
|
+
size="sm"
|
|
199
203
|
class="message-item__more-btn"
|
|
200
204
|
type="button"
|
|
201
205
|
onclick={openActions}
|
|
@@ -205,7 +209,7 @@ function handleEscape(event: KeyboardEvent) {
|
|
|
205
209
|
aria-controls={actionsId}
|
|
206
210
|
>
|
|
207
211
|
<svg viewBox="0 0 16 16" width="14" height="14" aria-hidden="true"><circle cx="3" cy="8" r="1.3" fill="currentColor" /><circle cx="8" cy="8" r="1.3" fill="currentColor" /><circle cx="13" cy="8" r="1.3" fill="currentColor" /></svg>
|
|
208
|
-
</
|
|
212
|
+
</Button>
|
|
209
213
|
{/if}
|
|
210
214
|
|
|
211
215
|
{#if showActions}
|
|
@@ -216,44 +220,52 @@ function handleEscape(event: KeyboardEvent) {
|
|
|
216
220
|
aria-label={t(M['chat.message_item.more_actions'])}
|
|
217
221
|
>
|
|
218
222
|
{#if onreact}
|
|
219
|
-
<
|
|
223
|
+
<Button
|
|
224
|
+
variant="ghost"
|
|
225
|
+
size="sm"
|
|
220
226
|
class="message-item__action-btn"
|
|
221
227
|
type="button"
|
|
222
228
|
onclick={toggleReactionPicker}
|
|
223
229
|
aria-label={t(M['chat.message_item.add_reaction'])}
|
|
224
230
|
>
|
|
225
231
|
<svg viewBox="0 0 16 16" width="14" height="14"><circle cx="8" cy="8" r="7" fill="none" stroke="currentColor" stroke-width="1.2" /><circle cx="5.5" cy="6.5" r="0.8" fill="currentColor" /><circle cx="10.5" cy="6.5" r="0.8" fill="currentColor" /><path d="M5.5 9.5c.5 1.2 1.5 1.8 2.5 1.8s2-.6 2.5-1.8" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" /></svg>
|
|
226
|
-
</
|
|
232
|
+
</Button>
|
|
227
233
|
{/if}
|
|
228
234
|
{#if onreply}
|
|
229
|
-
<
|
|
235
|
+
<Button
|
|
236
|
+
variant="ghost"
|
|
237
|
+
size="sm"
|
|
230
238
|
class="message-item__action-btn"
|
|
231
239
|
type="button"
|
|
232
240
|
onclick={() => onreply?.(message.id)}
|
|
233
241
|
aria-label={t(M['chat.message_item.reply'])}
|
|
234
242
|
>
|
|
235
243
|
<svg viewBox="0 0 16 16" width="14" height="14"><path d="M6 3L2 7l4 4" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" /><path d="M2 7h8c2.2 0 4 1.8 4 4v1" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" /></svg>
|
|
236
|
-
</
|
|
244
|
+
</Button>
|
|
237
245
|
{/if}
|
|
238
246
|
{#if isOwn && onedit}
|
|
239
|
-
<
|
|
247
|
+
<Button
|
|
248
|
+
variant="ghost"
|
|
249
|
+
size="sm"
|
|
240
250
|
class="message-item__action-btn"
|
|
241
251
|
type="button"
|
|
242
252
|
onclick={() => onedit?.(message.id)}
|
|
243
253
|
aria-label={t(M['chat.message_item.edit'])}
|
|
244
254
|
>
|
|
245
255
|
<svg viewBox="0 0 16 16" width="14" height="14"><path d="M11.5 1.5l3 3L5 14H2v-3z" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" /></svg>
|
|
246
|
-
</
|
|
256
|
+
</Button>
|
|
247
257
|
{/if}
|
|
248
258
|
{#if isOwn && ondelete}
|
|
249
|
-
<
|
|
259
|
+
<Button
|
|
260
|
+
variant="ghost"
|
|
261
|
+
size="sm"
|
|
250
262
|
class="message-item__action-btn"
|
|
251
263
|
type="button"
|
|
252
264
|
onclick={() => ondelete?.(message.id)}
|
|
253
265
|
aria-label={t(M['chat.message_item.delete'])}
|
|
254
266
|
>
|
|
255
267
|
<svg viewBox="0 0 16 16" width="14" height="14"><path d="M2 4h12M5.3 4V2.7A.7.7 0 016 2h4a.7.7 0 01.7.7V4m1.6 0v9.3a1.4 1.4 0 01-1.4 1.4H5.1a1.4 1.4 0 01-1.4-1.4V4" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" /></svg>
|
|
256
|
-
</
|
|
268
|
+
</Button>
|
|
257
269
|
{/if}
|
|
258
270
|
</div>
|
|
259
271
|
|
|
@@ -391,24 +403,22 @@ function handleEscape(event: KeyboardEvent) {
|
|
|
391
403
|
gap: var(--smrt-spacing-1, 0.25rem);
|
|
392
404
|
}
|
|
393
405
|
|
|
394
|
-
.
|
|
395
|
-
|
|
396
|
-
align-items: center;
|
|
406
|
+
/* :global() pierces into each Button's rendered <button> (see #1589). */
|
|
407
|
+
.message-item__reactions :global(.message-item__reaction) {
|
|
397
408
|
gap: var(--smrt-spacing-1, 4px);
|
|
398
409
|
padding: var(--smrt-spacing-1, 4px) var(--smrt-spacing-2, 8px);
|
|
399
410
|
border: 1px solid var(--smrt-color-outline-variant, #c4c6cf);
|
|
400
411
|
border-radius: var(--smrt-radius-full, 9999px);
|
|
401
412
|
background: var(--smrt-color-surface, #ffffff);
|
|
402
|
-
cursor: pointer;
|
|
403
413
|
font-size: var(--smrt-typography-label-medium-size, 0.75rem);
|
|
404
414
|
transition: background var(--smrt-duration-short2, 150ms) var(--smrt-easing-standard, ease);
|
|
405
415
|
}
|
|
406
416
|
|
|
407
|
-
.message-item__reaction:hover {
|
|
417
|
+
.message-item__reactions :global(.message-item__reaction:hover) {
|
|
408
418
|
background: var(--smrt-color-surface-container-high, #e1e3e8);
|
|
409
419
|
}
|
|
410
420
|
|
|
411
|
-
.message-item__reaction--active {
|
|
421
|
+
.message-item__reactions :global(.message-item__reaction--active) {
|
|
412
422
|
border-color: var(--smrt-color-primary, #005ac1);
|
|
413
423
|
background: var(--smrt-color-primary-container, #d6e3ff);
|
|
414
424
|
}
|
|
@@ -441,12 +451,11 @@ function handleEscape(event: KeyboardEvent) {
|
|
|
441
451
|
font-style: italic;
|
|
442
452
|
}
|
|
443
453
|
|
|
444
|
-
.
|
|
445
|
-
|
|
446
|
-
align-items: center;
|
|
447
|
-
justify-content: center;
|
|
454
|
+
/* :global() pierces into the Button child's rendered <button> (see #1589). */
|
|
455
|
+
.message-item :global(.message-item__more-btn) {
|
|
448
456
|
width: 26px;
|
|
449
457
|
height: 26px;
|
|
458
|
+
padding: 0;
|
|
450
459
|
position: absolute;
|
|
451
460
|
top: 0;
|
|
452
461
|
right: var(--smrt-spacing-4, 1rem);
|
|
@@ -454,12 +463,11 @@ function handleEscape(event: KeyboardEvent) {
|
|
|
454
463
|
border-radius: var(--smrt-radius-small, 0.25rem);
|
|
455
464
|
background: var(--smrt-color-surface, #ffffff);
|
|
456
465
|
color: var(--smrt-color-on-surface-variant, #43474e);
|
|
457
|
-
cursor: pointer;
|
|
458
466
|
opacity: 0;
|
|
459
467
|
transition: opacity var(--smrt-duration-short2, 150ms) var(--smrt-easing-standard, ease);
|
|
460
468
|
}
|
|
461
469
|
|
|
462
|
-
.message-item--own .message-item__more-btn {
|
|
470
|
+
.message-item--own :global(.message-item__more-btn) {
|
|
463
471
|
right: auto;
|
|
464
472
|
left: var(--smrt-spacing-4, 1rem);
|
|
465
473
|
}
|
|
@@ -467,19 +475,19 @@ function handleEscape(event: KeyboardEvent) {
|
|
|
467
475
|
/* Reveal the keyboard/touch affordance on hover OR when focus is inside the
|
|
468
476
|
row, so it is never strictly hover-only (a11y blocker, T2 #1391). Always
|
|
469
477
|
visible to coarse pointers (touch) which cannot hover. */
|
|
470
|
-
.message-item:hover .message-item__more-btn,
|
|
471
|
-
.message-item:focus-within .message-item__more-btn {
|
|
478
|
+
.message-item:hover :global(.message-item__more-btn),
|
|
479
|
+
.message-item:focus-within :global(.message-item__more-btn) {
|
|
472
480
|
opacity: 1;
|
|
473
481
|
}
|
|
474
482
|
|
|
475
|
-
.message-item__more-btn:focus-visible {
|
|
483
|
+
.message-item :global(.message-item__more-btn:focus-visible) {
|
|
476
484
|
opacity: 1;
|
|
477
485
|
outline: 2px solid var(--smrt-color-primary, #005ac1);
|
|
478
486
|
outline-offset: 1px;
|
|
479
487
|
}
|
|
480
488
|
|
|
481
489
|
@media (hover: none) {
|
|
482
|
-
.message-item__more-btn {
|
|
490
|
+
.message-item :global(.message-item__more-btn) {
|
|
483
491
|
opacity: 1;
|
|
484
492
|
}
|
|
485
493
|
}
|
|
@@ -504,21 +512,18 @@ function handleEscape(event: KeyboardEvent) {
|
|
|
504
512
|
left: var(--smrt-spacing-4, 1rem);
|
|
505
513
|
}
|
|
506
514
|
|
|
507
|
-
.
|
|
508
|
-
|
|
509
|
-
align-items: center;
|
|
510
|
-
justify-content: center;
|
|
515
|
+
/* :global() pierces into each Button's rendered <button> (see #1589). */
|
|
516
|
+
.message-item__actions :global(.message-item__action-btn) {
|
|
511
517
|
width: 26px;
|
|
512
518
|
height: 26px;
|
|
513
|
-
|
|
519
|
+
padding: 0;
|
|
514
520
|
border-radius: var(--smrt-radius-small, 0.25rem);
|
|
515
521
|
background: transparent;
|
|
516
522
|
color: var(--smrt-color-on-surface-variant, #43474e);
|
|
517
|
-
cursor: pointer;
|
|
518
523
|
transition: background var(--smrt-duration-short2, 150ms) var(--smrt-easing-standard, ease);
|
|
519
524
|
}
|
|
520
525
|
|
|
521
|
-
.message-item__action-btn:hover {
|
|
526
|
+
.message-item__actions :global(.message-item__action-btn:hover) {
|
|
522
527
|
background: var(--smrt-color-surface-container-high, #e1e3e8);
|
|
523
528
|
}
|
|
524
529
|
|
|
@@ -528,6 +533,10 @@ function handleEscape(event: KeyboardEvent) {
|
|
|
528
533
|
right: var(--smrt-spacing-4, 1rem);
|
|
529
534
|
z-index: 10;
|
|
530
535
|
transform: translateY(-100%);
|
|
536
|
+
/* The picker primitive supplies its own surface + radius; the popover
|
|
537
|
+
wrapper lifts it off the conversation with matching elevation. */
|
|
538
|
+
border-radius: var(--smrt-radius-large, 0.75rem);
|
|
539
|
+
box-shadow: var(--smrt-elevation-2, 0 2px 6px rgba(0, 0, 0, 0.15));
|
|
531
540
|
}
|
|
532
541
|
|
|
533
542
|
.message-item--own .message-item__picker-popover {
|
|
@@ -536,9 +545,9 @@ function handleEscape(event: KeyboardEvent) {
|
|
|
536
545
|
}
|
|
537
546
|
|
|
538
547
|
@media (prefers-reduced-motion: reduce) {
|
|
539
|
-
.message-item__more-btn,
|
|
540
|
-
.message-item__action-btn,
|
|
541
|
-
.message-item__reaction {
|
|
548
|
+
.message-item :global(.message-item__more-btn),
|
|
549
|
+
.message-item__actions :global(.message-item__action-btn),
|
|
550
|
+
.message-item__reactions :global(.message-item__reaction) {
|
|
542
551
|
transition: none;
|
|
543
552
|
}
|
|
544
553
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageItem.svelte.d.ts","sourceRoot":"","sources":["../../../../src/svelte/components/messages/MessageItem.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MessageItem.svelte.d.ts","sourceRoot":"","sources":["../../../../src/svelte/components/messages/MessageItem.svelte.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAKtD,MAAM,WAAW,KAAK;IACpB,6BAA6B;IAC7B,OAAO,EAAE,eAAe,CAAC;IACzB,wDAAwD;IACxD,KAAK,EAAE,OAAO,CAAC;IACf,qBAAqB;IACrB,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,qBAAqB;IACrB,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,oBAAoB;IACpB,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,sBAAsB;IACtB,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAwMD,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
8
|
+
import { Button } from '@happyvertical/smrt-ui/ui';
|
|
8
9
|
import { M } from '../../i18n.messages.js';
|
|
9
10
|
import type { ChatMessageData, ChatThreadData } from '../../types.js';
|
|
10
11
|
import MessageInput from './MessageInput.svelte';
|
|
@@ -47,7 +48,9 @@ const replyCount = $derived(
|
|
|
47
48
|
{#if thread.isResolved}
|
|
48
49
|
<span class="thread-panel__resolved">Resolved</span>
|
|
49
50
|
{/if}
|
|
50
|
-
<
|
|
51
|
+
<Button
|
|
52
|
+
variant="ghost"
|
|
53
|
+
size="sm"
|
|
51
54
|
class="thread-panel__close"
|
|
52
55
|
type="button"
|
|
53
56
|
onclick={onclose}
|
|
@@ -56,7 +59,7 @@ const replyCount = $derived(
|
|
|
56
59
|
<svg viewBox="0 0 16 16" width="16" height="16">
|
|
57
60
|
<path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
|
|
58
61
|
</svg>
|
|
59
|
-
</
|
|
62
|
+
</Button>
|
|
60
63
|
</header>
|
|
61
64
|
|
|
62
65
|
<div class="thread-panel__messages">
|
|
@@ -124,22 +127,19 @@ const replyCount = $derived(
|
|
|
124
127
|
flex-shrink: 0;
|
|
125
128
|
}
|
|
126
129
|
|
|
127
|
-
.
|
|
128
|
-
|
|
129
|
-
align-items: center;
|
|
130
|
-
justify-content: center;
|
|
130
|
+
/* :global() pierces into the Button child's rendered <button> (see #1589). */
|
|
131
|
+
.thread-panel__header :global(.thread-panel__close) {
|
|
131
132
|
width: 32px;
|
|
132
133
|
height: 32px;
|
|
133
|
-
|
|
134
|
+
padding: 0;
|
|
134
135
|
border-radius: var(--smrt-radius-small, 0.25rem);
|
|
135
136
|
background: transparent;
|
|
136
137
|
color: var(--smrt-color-on-surface-variant, #43474e);
|
|
137
|
-
cursor: pointer;
|
|
138
138
|
flex-shrink: 0;
|
|
139
139
|
transition: background var(--smrt-duration-short2, 150ms) var(--smrt-easing-standard, ease);
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
-
.thread-panel__close:hover {
|
|
142
|
+
.thread-panel__header :global(.thread-panel__close:hover) {
|
|
143
143
|
background: var(--smrt-color-surface-container-high, #e1e3e8);
|
|
144
144
|
}
|
|
145
145
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThreadPanel.svelte.d.ts","sourceRoot":"","sources":["../../../../src/svelte/components/messages/ThreadPanel.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ThreadPanel.svelte.d.ts","sourceRoot":"","sources":["../../../../src/svelte/components/messages/ThreadPanel.svelte.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAKtE,MAAM,WAAW,KAAK;IACpB,sBAAsB;IACtB,MAAM,EAAE,cAAc,CAAC;IACvB,6BAA6B;IAC7B,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,gCAAgC;IAChC,gBAAgB,EAAE,MAAM,CAAC;IACzB,iCAAiC;IACjC,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,6BAA6B;IAC7B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAuDD,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* Supports file type filtering and max size constraints.
|
|
6
6
|
*/
|
|
7
7
|
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
8
|
+
import { Button } from '@happyvertical/smrt-ui/ui';
|
|
8
9
|
import { M } from '../../i18n.js';
|
|
9
10
|
|
|
10
11
|
const { t } = useI18n();
|
|
@@ -116,7 +117,9 @@ function getFileIcon(type: string): string {
|
|
|
116
117
|
<span class="file-upload__file-name">{file.name}</span>
|
|
117
118
|
<span class="file-upload__file-size">{formatSize(file.size)}</span>
|
|
118
119
|
</div>
|
|
119
|
-
<
|
|
120
|
+
<Button
|
|
121
|
+
variant="ghost"
|
|
122
|
+
size="sm"
|
|
120
123
|
class="file-upload__file-remove"
|
|
121
124
|
type="button"
|
|
122
125
|
onclick={() => removePending(i)}
|
|
@@ -125,25 +128,27 @@ function getFileIcon(type: string): string {
|
|
|
125
128
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
|
126
129
|
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
|
|
127
130
|
</svg>
|
|
128
|
-
</
|
|
131
|
+
</Button>
|
|
129
132
|
</div>
|
|
130
133
|
{/each}
|
|
131
134
|
|
|
132
135
|
<div class="file-upload__preview-actions">
|
|
133
|
-
<
|
|
134
|
-
|
|
136
|
+
<Button
|
|
137
|
+
variant="primary"
|
|
138
|
+
size="sm"
|
|
135
139
|
type="button"
|
|
136
140
|
onclick={confirmUpload}
|
|
137
141
|
>
|
|
138
142
|
{t(M['chat.file_upload.upload_files'], { count: pendingFiles.length, plural: pendingFiles.length !== 1 ? 's' : '' })}
|
|
139
|
-
</
|
|
140
|
-
<
|
|
141
|
-
|
|
143
|
+
</Button>
|
|
144
|
+
<Button
|
|
145
|
+
variant="secondary"
|
|
146
|
+
size="sm"
|
|
142
147
|
type="button"
|
|
143
148
|
onclick={() => { pendingFiles = []; sizeError = ''; }}
|
|
144
149
|
>
|
|
145
150
|
Clear
|
|
146
|
-
</
|
|
151
|
+
</Button>
|
|
147
152
|
</div>
|
|
148
153
|
</div>
|
|
149
154
|
{/if}
|
|
@@ -164,6 +169,7 @@ function getFileIcon(type: string): string {
|
|
|
164
169
|
ondragleave={handleDragLeave}
|
|
165
170
|
>
|
|
166
171
|
<label class="file-upload__label">
|
|
172
|
+
<!-- raw-primitive-allow: visually-hidden native file input that backs a custom drag-and-drop zone; the base Input primitive renders a visible bordered control and cannot be the hidden picker behind this drop zone -->
|
|
167
173
|
<input
|
|
168
174
|
type="file"
|
|
169
175
|
class="file-upload__input"
|
|
@@ -302,22 +308,19 @@ function getFileIcon(type: string): string {
|
|
|
302
308
|
color: var(--smrt-color-outline, #74777f);
|
|
303
309
|
}
|
|
304
310
|
|
|
305
|
-
.
|
|
306
|
-
|
|
307
|
-
align-items: center;
|
|
308
|
-
justify-content: center;
|
|
311
|
+
/* :global() pierces into the Button child's rendered <button> (see #1589). */
|
|
312
|
+
.file-upload__file :global(.file-upload__file-remove) {
|
|
309
313
|
width: 24px;
|
|
310
314
|
height: 24px;
|
|
311
|
-
|
|
315
|
+
padding: 0;
|
|
312
316
|
background: none;
|
|
313
317
|
color: var(--smrt-color-on-surface-variant, #43474e);
|
|
314
|
-
cursor: pointer;
|
|
315
318
|
border-radius: var(--smrt-radius-full, 9999px);
|
|
316
319
|
flex-shrink: 0;
|
|
317
320
|
transition: background var(--smrt-duration-short2, 150ms);
|
|
318
321
|
}
|
|
319
322
|
|
|
320
|
-
.file-upload__file-remove:hover {
|
|
323
|
+
.file-upload__file :global(.file-upload__file-remove:hover) {
|
|
321
324
|
background: var(--smrt-color-error-container, #ffdad6);
|
|
322
325
|
color: var(--smrt-color-error, #ba1a1a);
|
|
323
326
|
}
|
|
@@ -328,41 +331,6 @@ function getFileIcon(type: string): string {
|
|
|
328
331
|
padding-top: var(--smrt-spacing-1, 4px);
|
|
329
332
|
}
|
|
330
333
|
|
|
331
|
-
.file-upload__confirm-btn {
|
|
332
|
-
padding: var(--smrt-spacing-2, 8px) var(--smrt-spacing-4, 16px);
|
|
333
|
-
border: none;
|
|
334
|
-
border-radius: var(--smrt-radius-full, 9999px);
|
|
335
|
-
background: var(--smrt-color-primary, #005ac1);
|
|
336
|
-
color: var(--smrt-color-on-primary, #ffffff);
|
|
337
|
-
font: var(--smrt-typography-label-large-font, 500 0.875rem/1.25 sans-serif);
|
|
338
|
-
cursor: pointer;
|
|
339
|
-
transition: opacity var(--smrt-duration-short2, 150ms);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
.file-upload__confirm-btn:hover {
|
|
343
|
-
opacity: 0.85;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
.file-upload__confirm-btn:focus-visible {
|
|
347
|
-
outline: 2px solid var(--smrt-color-primary, #005ac1);
|
|
348
|
-
outline-offset: 2px;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
.file-upload__clear-btn {
|
|
352
|
-
padding: var(--smrt-spacing-2, 8px) var(--smrt-spacing-4, 16px);
|
|
353
|
-
border: 1px solid var(--smrt-color-outline, #74777f);
|
|
354
|
-
border-radius: var(--smrt-radius-full, 9999px);
|
|
355
|
-
background: transparent;
|
|
356
|
-
color: var(--smrt-color-on-surface-variant, #43474e);
|
|
357
|
-
font: var(--smrt-typography-label-large-font, 500 0.875rem/1.25 sans-serif);
|
|
358
|
-
cursor: pointer;
|
|
359
|
-
transition: background var(--smrt-duration-short2, 150ms);
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
.file-upload__clear-btn:hover {
|
|
363
|
-
background: var(--smrt-color-surface-variant, #e1e2ec);
|
|
364
|
-
}
|
|
365
|
-
|
|
366
334
|
.file-upload__error {
|
|
367
335
|
padding: var(--smrt-spacing-2, 8px) var(--smrt-spacing-3, 12px);
|
|
368
336
|
border-radius: var(--smrt-radius-small, 4px);
|
|
@@ -372,10 +340,11 @@ function getFileIcon(type: string): string {
|
|
|
372
340
|
}
|
|
373
341
|
|
|
374
342
|
@media (prefers-reduced-motion: reduce) {
|
|
375
|
-
.file-upload__drop-zone
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
343
|
+
.file-upload__drop-zone {
|
|
344
|
+
transition: none;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
.file-upload__file :global(.file-upload__file-remove) {
|
|
379
348
|
transition: none;
|
|
380
349
|
}
|
|
381
350
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileUpload.svelte.d.ts","sourceRoot":"","sources":["../../../../src/svelte/components/shared/FileUpload.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FileUpload.svelte.d.ts","sourceRoot":"","sources":["../../../../src/svelte/components/shared/FileUpload.svelte.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,KAAK;IACpB,uCAAuC;IACvC,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;IACpC,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA2JD,QAAA,MAAM,UAAU,2CAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
|