@r2digisolutions/components 0.16.4 → 0.17.0
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,25 @@
|
|
|
134
134
|
|
|
135
135
|
<div
|
|
136
136
|
class={[
|
|
137
|
-
'
|
|
138
|
-
'h-[min(560px,70vh)] w-full
|
|
137
|
+
'rounded-2xl border-border bg-surface-elevated shadow-xl flex flex-col overflow-hidden border',
|
|
138
|
+
'h-[min(560px,70vh)] w-full max-w-[420px] min-w-[320px]',
|
|
139
139
|
className
|
|
140
140
|
]}
|
|
141
141
|
role="complementary"
|
|
142
142
|
aria-label={title}
|
|
143
143
|
>
|
|
144
144
|
<!-- Header -->
|
|
145
|
-
<header class="
|
|
145
|
+
<header class="gap-2 border-border px-3 py-2.5 flex shrink-0 items-center border-b">
|
|
146
146
|
<span
|
|
147
|
-
class="
|
|
147
|
+
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
148
|
aria-hidden="true"
|
|
149
149
|
>
|
|
150
150
|
<Sparkles size={15} strokeWidth={2} />
|
|
151
151
|
</span>
|
|
152
152
|
<div class="min-w-0 flex-1">
|
|
153
|
-
<p class="
|
|
153
|
+
<p class="text-sm font-semibold text-primary truncate">{title}</p>
|
|
154
154
|
{#if statusLabel}
|
|
155
|
-
<p class="
|
|
155
|
+
<p class="text-xs text-muted truncate">{statusLabel}</p>
|
|
156
156
|
{/if}
|
|
157
157
|
</div>
|
|
158
158
|
<IconButton variant="ghost" size="xs" label={newChatLabel} onclick={() => onnewchat?.()}>
|
|
@@ -164,22 +164,22 @@
|
|
|
164
164
|
</header>
|
|
165
165
|
|
|
166
166
|
<!-- Body -->
|
|
167
|
-
<div bind:this={scrollEl} class="min-h-0 flex-1 overflow-y-auto
|
|
167
|
+
<div bind:this={scrollEl} class="min-h-0 px-3 py-3 flex-1 overflow-y-auto">
|
|
168
168
|
{#if isEmpty}
|
|
169
|
-
<div class="flex flex-col items-center justify-center
|
|
169
|
+
<div class="gap-4 py-8 flex flex-col items-center justify-center text-center">
|
|
170
170
|
<span
|
|
171
|
-
class="
|
|
171
|
+
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
172
|
aria-hidden="true"
|
|
173
173
|
>
|
|
174
174
|
<Sparkles size={24} strokeWidth={1.5} />
|
|
175
175
|
</span>
|
|
176
176
|
<p class="text-sm text-muted">{emptyHint}</p>
|
|
177
177
|
{#if suggestions.length}
|
|
178
|
-
<div class="flex flex-wrap justify-center
|
|
178
|
+
<div class="gap-2 flex flex-wrap justify-center">
|
|
179
179
|
{#each suggestions as suggestion (suggestion)}
|
|
180
180
|
<button
|
|
181
181
|
type="button"
|
|
182
|
-
class="
|
|
182
|
+
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
183
|
onclick={() => handleSuggestion(suggestion)}
|
|
184
184
|
>
|
|
185
185
|
{suggestion}
|
|
@@ -189,27 +189,27 @@
|
|
|
189
189
|
{/if}
|
|
190
190
|
</div>
|
|
191
191
|
{:else}
|
|
192
|
-
<div class="flex flex-col
|
|
192
|
+
<div class="gap-3 flex flex-col">
|
|
193
193
|
{#each messages as message (message.id)}
|
|
194
194
|
{#if message.role === 'user'}
|
|
195
195
|
<div class="flex justify-end">
|
|
196
196
|
<div
|
|
197
|
-
class="
|
|
197
|
+
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
198
|
>
|
|
199
199
|
{message.content}
|
|
200
200
|
</div>
|
|
201
201
|
</div>
|
|
202
202
|
{:else}
|
|
203
|
-
<div class="flex flex-col
|
|
204
|
-
<div class="flex items-start
|
|
203
|
+
<div class="gap-1.5 flex flex-col">
|
|
204
|
+
<div class="gap-2 flex items-start">
|
|
205
205
|
<span
|
|
206
|
-
class="mt-0.5
|
|
206
|
+
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
207
|
aria-hidden="true"
|
|
208
208
|
>
|
|
209
209
|
<Sparkles size={12} strokeWidth={2} />
|
|
210
210
|
</span>
|
|
211
211
|
<div
|
|
212
|
-
class="
|
|
212
|
+
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
213
|
>
|
|
214
214
|
{message.content}
|
|
215
215
|
</div>
|
|
@@ -224,15 +224,15 @@
|
|
|
224
224
|
{/each}
|
|
225
225
|
|
|
226
226
|
{#if loading && showLoadingBubble}
|
|
227
|
-
<div class="flex items-center
|
|
227
|
+
<div class="gap-2 flex items-center">
|
|
228
228
|
<span
|
|
229
|
-
class="
|
|
229
|
+
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
230
|
aria-hidden="true"
|
|
231
231
|
>
|
|
232
232
|
<Sparkles size={12} strokeWidth={2} />
|
|
233
233
|
</span>
|
|
234
234
|
<div
|
|
235
|
-
class="
|
|
235
|
+
class="gap-2 rounded-2xl rounded-bl-sm bg-surface-overlay px-3.5 py-2.5 flex items-center"
|
|
236
236
|
>
|
|
237
237
|
<LoaderCircle size={14} strokeWidth={2} class="animate-spin text-muted" />
|
|
238
238
|
<span class="text-xs text-muted">{loadingLabel}</span>
|
|
@@ -244,22 +244,22 @@
|
|
|
244
244
|
</div>
|
|
245
245
|
|
|
246
246
|
<!-- Footer -->
|
|
247
|
-
<footer class="
|
|
248
|
-
<div class="flex items-center
|
|
247
|
+
<footer class="border-border px-3 py-2.5 shrink-0 border-t">
|
|
248
|
+
<div class="gap-1.5 flex items-center">
|
|
249
249
|
<input
|
|
250
250
|
type="text"
|
|
251
251
|
bind:value={draft}
|
|
252
252
|
placeholder={listening ? statusLabel || placeholder : placeholder}
|
|
253
253
|
class={[
|
|
254
|
-
'h-9 min-w-0
|
|
255
|
-
listening ? 'border-red-400 ring-
|
|
254
|
+
'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',
|
|
255
|
+
listening ? 'border-red-400 ring-red-500/20 ring-2' : 'border-border'
|
|
256
256
|
]}
|
|
257
257
|
disabled={loading}
|
|
258
258
|
onkeydown={handleKeydown}
|
|
259
259
|
aria-label={placeholder}
|
|
260
260
|
/>
|
|
261
261
|
|
|
262
|
-
<div class="flex shrink-0 items-center
|
|
262
|
+
<div class="gap-0.5 flex shrink-0 items-center">
|
|
263
263
|
{#if voiceEnabled}
|
|
264
264
|
<IconButton
|
|
265
265
|
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;
|