@r2digisolutions/components 0.16.3 → 0.16.4

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.
@@ -30,6 +30,8 @@
30
30
  draft?: string;
31
31
  loading?: boolean;
32
32
  loadingLabel?: string;
33
+ /** When false, input stays disabled via `loading` but the spinner bubble is hidden (parent paints status in a message). */
34
+ showLoadingBubble?: boolean;
33
35
  error?: string | null;
34
36
  voiceEnabled?: boolean;
35
37
  voiceOutput?: boolean;
@@ -63,6 +65,7 @@
63
65
  draft = $bindable(''),
64
66
  loading = false,
65
67
  loadingLabel = 'Procesando…',
68
+ showLoadingBubble = true,
66
69
  error = null,
67
70
  voiceEnabled = true,
68
71
  voiceOutput = $bindable(true),
@@ -220,7 +223,7 @@
220
223
  {/if}
221
224
  {/each}
222
225
 
223
- {#if loading}
226
+ {#if loading && showLoadingBubble}
224
227
  <div class="flex items-center gap-2">
225
228
  <span
226
229
  class="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-brand-100 text-brand-600 dark:bg-brand-900/40 dark:text-brand-400"
@@ -236,14 +239,6 @@
236
239
  </div>
237
240
  </div>
238
241
  {/if}
239
-
240
- {#if error}
241
- <div
242
- class="rounded-xl border border-red-200 bg-red-50 px-3 py-2 text-xs text-red-600 dark:border-red-800/40 dark:bg-red-950/20 dark:text-red-400"
243
- >
244
- {error}
245
- </div>
246
- {/if}
247
242
  </div>
248
243
  {/if}
249
244
  </div>
@@ -254,8 +249,11 @@
254
249
  <input
255
250
  type="text"
256
251
  bind:value={draft}
257
- {placeholder}
258
- class="h-9 min-w-0 flex-1 rounded-xl border border-border bg-surface px-3 text-sm text-primary outline-none transition-shadow placeholder:text-muted focus:border-brand-400 focus:ring-2 focus:ring-brand-500/20"
252
+ placeholder={listening ? statusLabel || placeholder : placeholder}
253
+ class={[
254
+ 'h-9 min-w-0 flex-1 rounded-xl border bg-surface px-3 text-sm text-primary outline-none transition-shadow placeholder:text-muted focus:border-brand-400 focus:ring-2 focus:ring-brand-500/20',
255
+ listening ? 'border-red-400 ring-2 ring-red-500/20' : 'border-border'
256
+ ]}
259
257
  disabled={loading}
260
258
  onkeydown={handleKeydown}
261
259
  aria-label={placeholder}
@@ -302,6 +300,10 @@
302
300
  </div>
303
301
  </div>
304
302
 
303
+ {#if error}
304
+ <p class="mt-1.5 px-1 text-xs text-red-600 dark:text-red-400">{error}</p>
305
+ {/if}
306
+
305
307
  {#if footerExtra}
306
308
  {@render footerExtra()}
307
309
  {/if}
@@ -15,6 +15,8 @@ interface AssistantChatProps {
15
15
  draft?: string;
16
16
  loading?: boolean;
17
17
  loadingLabel?: string;
18
+ /** When false, input stays disabled via `loading` but the spinner bubble is hidden (parent paints status in a message). */
19
+ showLoadingBubble?: boolean;
18
20
  error?: string | null;
19
21
  voiceEnabled?: boolean;
20
22
  voiceOutput?: boolean;
@@ -2,7 +2,9 @@
2
2
  import type { Component } from 'svelte';
3
3
  import { untrack } from 'svelte';
4
4
  import Kbd from '../../atoms/Kbd/Kbd.svelte';
5
+ import IconButton from '../../atoms/IconButton/IconButton.svelte';
5
6
  import { i18n } from '../../../utils/i18n.svelte';
7
+ import { Mic, MicOff } from '@lucide/svelte';
6
8
 
7
9
  export type CommandIcon = Component<{
8
10
  class?: string;
@@ -24,29 +26,39 @@
24
26
 
25
27
  interface CommandPaletteProps {
26
28
  open?: boolean;
29
+ query?: string;
27
30
  items?: CommandItem[];
28
31
  placeholder?: string;
29
32
  emptyLabel?: string;
30
33
  loading?: boolean;
34
+ voiceEnabled?: boolean;
35
+ listening?: boolean;
36
+ micLabel?: string;
37
+ stopMicLabel?: string;
31
38
  class?: string;
32
39
  onselect?: (item: CommandItem) => void;
33
40
  onclose?: () => void;
34
41
  onquery?: (query: string) => void;
42
+ onmicclick?: () => void;
35
43
  }
36
44
 
37
45
  let {
38
46
  open = $bindable(false),
47
+ query = $bindable(''),
39
48
  items = [],
40
49
  placeholder,
41
50
  emptyLabel,
42
51
  loading = false,
52
+ voiceEnabled = false,
53
+ listening = false,
54
+ micLabel = 'Hablar',
55
+ stopMicLabel = 'Parar micrófono',
43
56
  class: className = '',
44
57
  onselect,
45
58
  onclose,
46
- onquery
59
+ onquery,
60
+ onmicclick
47
61
  }: CommandPaletteProps = $props();
48
-
49
- let query = $state('');
50
62
  let activeIndex = $state(0);
51
63
  let dialogEl = $state<HTMLDialogElement | null>(null);
52
64
  let listEl = $state<HTMLDivElement | null>(null);
@@ -232,6 +244,25 @@
232
244
  oninput={onInput}
233
245
  onkeydown={onKeydown}
234
246
  />
247
+ {#if voiceEnabled}
248
+ <IconButton
249
+ variant="ghost"
250
+ size="xs"
251
+ label={listening ? stopMicLabel : micLabel}
252
+ aria-pressed={listening}
253
+ onclick={(e) => {
254
+ e.stopPropagation();
255
+ onmicclick?.();
256
+ }}
257
+ class={listening ? 'text-red-500 hover:text-red-600' : 'text-muted'}
258
+ >
259
+ {#if listening}
260
+ <MicOff size={16} strokeWidth={2} />
261
+ {:else}
262
+ <Mic size={16} strokeWidth={2} />
263
+ {/if}
264
+ </IconButton>
265
+ {/if}
235
266
  {#if loading}
236
267
  <span
237
268
  class="h-4 w-4 animate-spin border-border border-t-brand-500 shrink-0 rounded-full border-2"
@@ -17,15 +17,21 @@ export interface CommandItem {
17
17
  }
18
18
  interface CommandPaletteProps {
19
19
  open?: boolean;
20
+ query?: string;
20
21
  items?: CommandItem[];
21
22
  placeholder?: string;
22
23
  emptyLabel?: string;
23
24
  loading?: boolean;
25
+ voiceEnabled?: boolean;
26
+ listening?: boolean;
27
+ micLabel?: string;
28
+ stopMicLabel?: string;
24
29
  class?: string;
25
30
  onselect?: (item: CommandItem) => void;
26
31
  onclose?: () => void;
27
32
  onquery?: (query: string) => void;
33
+ onmicclick?: () => void;
28
34
  }
29
- declare const CommandPalette: Component<CommandPaletteProps, {}, "open">;
35
+ declare const CommandPalette: Component<CommandPaletteProps, {}, "open" | "query">;
30
36
  type CommandPalette = ReturnType<typeof CommandPalette>;
31
37
  export default CommandPalette;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@r2digisolutions/components",
3
- "version": "0.16.3",
3
+ "version": "0.16.4",
4
4
  "private": false,
5
5
  "description": "R2DigiSolutions Svelte 5 component library — Atomic Design, Tailwind 4, Light/Dark mode",
6
6
  "license": "MIT",