@r2digisolutions/components 0.16.4 → 0.17.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.
|
@@ -134,25 +134,24 @@
|
|
|
134
134
|
|
|
135
135
|
<div
|
|
136
136
|
class={[
|
|
137
|
-
'
|
|
138
|
-
'h-[min(560px,70vh)] w-full min-w-[320px] max-w-[420px]',
|
|
137
|
+
'rounded-2xl border-border bg-surface-elevated shadow-xl flex h-[min(560px,70vh)] w-[min(420px,calc(100vw-2rem))] shrink-0 flex-col overflow-hidden border',
|
|
139
138
|
className
|
|
140
139
|
]}
|
|
141
140
|
role="complementary"
|
|
142
141
|
aria-label={title}
|
|
143
142
|
>
|
|
144
143
|
<!-- Header -->
|
|
145
|
-
<header class="
|
|
144
|
+
<header class="gap-2 border-border px-3 py-2.5 flex shrink-0 items-center border-b">
|
|
146
145
|
<span
|
|
147
|
-
class="
|
|
146
|
+
class="h-7 w-7 rounded-lg bg-brand-100 text-brand-600 dark:bg-brand-900/40 dark:text-brand-400 flex shrink-0 items-center justify-center"
|
|
148
147
|
aria-hidden="true"
|
|
149
148
|
>
|
|
150
149
|
<Sparkles size={15} strokeWidth={2} />
|
|
151
150
|
</span>
|
|
152
151
|
<div class="min-w-0 flex-1">
|
|
153
|
-
<p class="
|
|
152
|
+
<p class="text-sm font-semibold text-primary truncate">{title}</p>
|
|
154
153
|
{#if statusLabel}
|
|
155
|
-
<p class="
|
|
154
|
+
<p class="text-xs text-muted truncate">{statusLabel}</p>
|
|
156
155
|
{/if}
|
|
157
156
|
</div>
|
|
158
157
|
<IconButton variant="ghost" size="xs" label={newChatLabel} onclick={() => onnewchat?.()}>
|
|
@@ -164,22 +163,22 @@
|
|
|
164
163
|
</header>
|
|
165
164
|
|
|
166
165
|
<!-- Body -->
|
|
167
|
-
<div bind:this={scrollEl} class="min-h-0 flex-1 overflow-y-auto
|
|
166
|
+
<div bind:this={scrollEl} class="min-h-0 px-3 py-3 flex-1 overflow-y-auto">
|
|
168
167
|
{#if isEmpty}
|
|
169
|
-
<div class="flex flex-col items-center justify-center
|
|
168
|
+
<div class="gap-4 py-8 flex flex-col items-center justify-center text-center">
|
|
170
169
|
<span
|
|
171
|
-
class="
|
|
170
|
+
class="h-12 w-12 rounded-2xl bg-brand-50 text-brand-500 dark:bg-brand-950/30 dark:text-brand-400 flex items-center justify-center"
|
|
172
171
|
aria-hidden="true"
|
|
173
172
|
>
|
|
174
173
|
<Sparkles size={24} strokeWidth={1.5} />
|
|
175
174
|
</span>
|
|
176
175
|
<p class="text-sm text-muted">{emptyHint}</p>
|
|
177
176
|
{#if suggestions.length}
|
|
178
|
-
<div class="flex flex-wrap justify-center
|
|
177
|
+
<div class="gap-2 flex flex-wrap justify-center">
|
|
179
178
|
{#each suggestions as suggestion (suggestion)}
|
|
180
179
|
<button
|
|
181
180
|
type="button"
|
|
182
|
-
class="
|
|
181
|
+
class="border-border bg-surface px-3 py-1.5 text-xs text-secondary hover:border-brand-400 hover:text-brand-600 dark:hover:text-brand-400 rounded-full border transition-colors"
|
|
183
182
|
onclick={() => handleSuggestion(suggestion)}
|
|
184
183
|
>
|
|
185
184
|
{suggestion}
|
|
@@ -189,27 +188,27 @@
|
|
|
189
188
|
{/if}
|
|
190
189
|
</div>
|
|
191
190
|
{:else}
|
|
192
|
-
<div class="flex flex-col
|
|
191
|
+
<div class="gap-3 flex flex-col">
|
|
193
192
|
{#each messages as message (message.id)}
|
|
194
193
|
{#if message.role === 'user'}
|
|
195
194
|
<div class="flex justify-end">
|
|
196
195
|
<div
|
|
197
|
-
class="
|
|
196
|
+
class="rounded-2xl rounded-br-sm bg-brand-600 px-3.5 py-2.5 text-sm leading-relaxed text-white max-w-[80%]"
|
|
198
197
|
>
|
|
199
198
|
{message.content}
|
|
200
199
|
</div>
|
|
201
200
|
</div>
|
|
202
201
|
{:else}
|
|
203
|
-
<div class="flex flex-col
|
|
204
|
-
<div class="flex items-start
|
|
202
|
+
<div class="gap-1.5 flex flex-col">
|
|
203
|
+
<div class="gap-2 flex items-start">
|
|
205
204
|
<span
|
|
206
|
-
class="mt-0.5
|
|
205
|
+
class="mt-0.5 h-6 w-6 bg-brand-100 text-brand-600 dark:bg-brand-900/40 dark:text-brand-400 flex shrink-0 items-center justify-center rounded-full"
|
|
207
206
|
aria-hidden="true"
|
|
208
207
|
>
|
|
209
208
|
<Sparkles size={12} strokeWidth={2} />
|
|
210
209
|
</span>
|
|
211
210
|
<div
|
|
212
|
-
class="
|
|
211
|
+
class="rounded-2xl rounded-bl-sm bg-surface-overlay px-3.5 py-2.5 text-sm leading-relaxed text-primary max-w-[calc(100%-2rem)]"
|
|
213
212
|
>
|
|
214
213
|
{message.content}
|
|
215
214
|
</div>
|
|
@@ -224,15 +223,15 @@
|
|
|
224
223
|
{/each}
|
|
225
224
|
|
|
226
225
|
{#if loading && showLoadingBubble}
|
|
227
|
-
<div class="flex items-center
|
|
226
|
+
<div class="gap-2 flex items-center">
|
|
228
227
|
<span
|
|
229
|
-
class="
|
|
228
|
+
class="h-6 w-6 bg-brand-100 text-brand-600 dark:bg-brand-900/40 dark:text-brand-400 flex shrink-0 items-center justify-center rounded-full"
|
|
230
229
|
aria-hidden="true"
|
|
231
230
|
>
|
|
232
231
|
<Sparkles size={12} strokeWidth={2} />
|
|
233
232
|
</span>
|
|
234
233
|
<div
|
|
235
|
-
class="
|
|
234
|
+
class="gap-2 rounded-2xl rounded-bl-sm bg-surface-overlay px-3.5 py-2.5 flex items-center"
|
|
236
235
|
>
|
|
237
236
|
<LoaderCircle size={14} strokeWidth={2} class="animate-spin text-muted" />
|
|
238
237
|
<span class="text-xs text-muted">{loadingLabel}</span>
|
|
@@ -244,22 +243,22 @@
|
|
|
244
243
|
</div>
|
|
245
244
|
|
|
246
245
|
<!-- Footer -->
|
|
247
|
-
<footer class="
|
|
248
|
-
<div class="flex items-center
|
|
246
|
+
<footer class="border-border px-3 py-2.5 shrink-0 border-t">
|
|
247
|
+
<div class="gap-1.5 flex items-center">
|
|
249
248
|
<input
|
|
250
249
|
type="text"
|
|
251
250
|
bind:value={draft}
|
|
252
251
|
placeholder={listening ? statusLabel || placeholder : placeholder}
|
|
253
252
|
class={[
|
|
254
|
-
'h-9 min-w-0
|
|
255
|
-
listening ? 'border-red-400 ring-
|
|
253
|
+
'h-9 min-w-0 rounded-xl bg-surface px-3 text-sm text-primary placeholder:text-muted focus:border-brand-400 focus:ring-brand-500/20 flex-1 border transition-shadow outline-none focus:ring-2',
|
|
254
|
+
listening ? 'border-red-400 ring-red-500/20 ring-2' : 'border-border'
|
|
256
255
|
]}
|
|
257
256
|
disabled={loading}
|
|
258
257
|
onkeydown={handleKeydown}
|
|
259
258
|
aria-label={placeholder}
|
|
260
259
|
/>
|
|
261
260
|
|
|
262
|
-
<div class="flex shrink-0 items-center
|
|
261
|
+
<div class="gap-0.5 flex shrink-0 items-center">
|
|
263
262
|
{#if voiceEnabled}
|
|
264
263
|
<IconButton
|
|
265
264
|
variant="ghost"
|
|
@@ -33,6 +33,8 @@
|
|
|
33
33
|
loading?: boolean;
|
|
34
34
|
voiceEnabled?: boolean;
|
|
35
35
|
listening?: boolean;
|
|
36
|
+
/** When false, opening keeps the current query (voice dictation). */
|
|
37
|
+
resetQueryOnOpen?: boolean;
|
|
36
38
|
micLabel?: string;
|
|
37
39
|
stopMicLabel?: string;
|
|
38
40
|
class?: string;
|
|
@@ -51,6 +53,7 @@
|
|
|
51
53
|
loading = false,
|
|
52
54
|
voiceEnabled = false,
|
|
53
55
|
listening = false,
|
|
56
|
+
resetQueryOnOpen = true,
|
|
54
57
|
micLabel = 'Hablar',
|
|
55
58
|
stopMicLabel = 'Parar micrófono',
|
|
56
59
|
class: className = '',
|
|
@@ -141,9 +144,11 @@
|
|
|
141
144
|
$effect(() => {
|
|
142
145
|
if (!dialogEl) return;
|
|
143
146
|
if (open && !dialogEl.open) {
|
|
144
|
-
|
|
147
|
+
if (resetQueryOnOpen) {
|
|
148
|
+
query = '';
|
|
149
|
+
untrack(() => onquery?.(''));
|
|
150
|
+
}
|
|
145
151
|
activeIndex = Math.max(0, firstEnabledIndex());
|
|
146
|
-
untrack(() => onquery?.(''));
|
|
147
152
|
ignoreBackdropUntil = Date.now() + 400;
|
|
148
153
|
dialogEl.showModal();
|
|
149
154
|
} else if (!open && dialogEl.open) {
|
|
@@ -24,6 +24,8 @@ interface CommandPaletteProps {
|
|
|
24
24
|
loading?: boolean;
|
|
25
25
|
voiceEnabled?: boolean;
|
|
26
26
|
listening?: boolean;
|
|
27
|
+
/** When false, opening keeps the current query (voice dictation). */
|
|
28
|
+
resetQueryOnOpen?: boolean;
|
|
27
29
|
micLabel?: string;
|
|
28
30
|
stopMicLabel?: string;
|
|
29
31
|
class?: string;
|