@r2digisolutions/components 0.16.2 → 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.
- package/dist/components/atoms/Input/Input.svelte +65 -28
- package/dist/components/atoms/Input/Input.svelte.d.ts +3 -0
- package/dist/components/molecules/FormField/FormField.svelte +7 -1
- package/dist/components/molecules/FormField/FormField.svelte.d.ts +2 -0
- package/dist/components/molecules/FormPasswordInput/FormPasswordInput.svelte +7 -1
- package/dist/components/molecules/FormPasswordInput/FormPasswordInput.svelte.d.ts +2 -0
- package/dist/components/molecules/PasswordInput/PasswordInput.svelte +7 -1
- package/dist/components/molecules/PasswordInput/PasswordInput.svelte.d.ts +2 -0
- package/dist/components/organisms/AssistantChat/AssistantChat.svelte +16 -12
- package/dist/components/organisms/AssistantChat/AssistantChat.svelte.d.ts +3 -0
- package/dist/components/organisms/CommandPalette/CommandPalette.svelte +34 -3
- package/dist/components/organisms/CommandPalette/CommandPalette.svelte.d.ts +7 -1
- package/package.json +1 -1
|
@@ -31,6 +31,9 @@
|
|
|
31
31
|
onfocus?: (e: FocusEvent) => void;
|
|
32
32
|
onblur?: (e: FocusEvent) => void;
|
|
33
33
|
onkeydown?: (e: KeyboardEvent) => void;
|
|
34
|
+
autocomplete?: string;
|
|
35
|
+
/** Native form value only (no Svelte bind). Needed for login + autofill. */
|
|
36
|
+
uncontrolled?: boolean;
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
let {
|
|
@@ -58,7 +61,9 @@
|
|
|
58
61
|
onchange,
|
|
59
62
|
onfocus,
|
|
60
63
|
onblur,
|
|
61
|
-
onkeydown
|
|
64
|
+
onkeydown,
|
|
65
|
+
autocomplete,
|
|
66
|
+
uncontrolled = false
|
|
62
67
|
}: InputProps = $props();
|
|
63
68
|
|
|
64
69
|
let autoId = $state<string | undefined>(undefined);
|
|
@@ -67,7 +72,9 @@
|
|
|
67
72
|
});
|
|
68
73
|
const inputId = $derived(id ?? autoId);
|
|
69
74
|
const helperId = $derived(inputId ? `${inputId}-helper` : undefined);
|
|
70
|
-
const hasClear = $derived(
|
|
75
|
+
const hasClear = $derived(
|
|
76
|
+
!uncontrolled && clearable && value.length > 0 && !disabled && !readonly
|
|
77
|
+
);
|
|
71
78
|
|
|
72
79
|
const wrapperSizeClasses: Record<InputSize, string> = {
|
|
73
80
|
sm: 'h-8 text-sm',
|
|
@@ -137,32 +144,62 @@
|
|
|
137
144
|
</span>
|
|
138
145
|
{/if}
|
|
139
146
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
'
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
147
|
+
{#if uncontrolled}
|
|
148
|
+
<input
|
|
149
|
+
id={inputId}
|
|
150
|
+
{name}
|
|
151
|
+
{type}
|
|
152
|
+
{placeholder}
|
|
153
|
+
{disabled}
|
|
154
|
+
{readonly}
|
|
155
|
+
{required}
|
|
156
|
+
{autofocus}
|
|
157
|
+
{min}
|
|
158
|
+
{max}
|
|
159
|
+
{step}
|
|
160
|
+
{autocomplete}
|
|
161
|
+
aria-describedby={helperText ? helperId : undefined}
|
|
162
|
+
aria-invalid={status === 'error'}
|
|
163
|
+
class={[
|
|
164
|
+
'min-w-0 text-primary placeholder:text-muted h-full flex-1 self-stretch bg-transparent outline-none disabled:cursor-not-allowed',
|
|
165
|
+
type === 'search' &&
|
|
166
|
+
'[&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none'
|
|
167
|
+
]}
|
|
168
|
+
{oninput}
|
|
169
|
+
{onchange}
|
|
170
|
+
{onfocus}
|
|
171
|
+
{onblur}
|
|
172
|
+
{onkeydown}
|
|
173
|
+
/>
|
|
174
|
+
{:else}
|
|
175
|
+
<input
|
|
176
|
+
id={inputId}
|
|
177
|
+
{name}
|
|
178
|
+
{type}
|
|
179
|
+
{placeholder}
|
|
180
|
+
{disabled}
|
|
181
|
+
{readonly}
|
|
182
|
+
{required}
|
|
183
|
+
{autofocus}
|
|
184
|
+
{min}
|
|
185
|
+
{max}
|
|
186
|
+
{step}
|
|
187
|
+
{autocomplete}
|
|
188
|
+
bind:value
|
|
189
|
+
aria-describedby={helperText ? helperId : undefined}
|
|
190
|
+
aria-invalid={status === 'error'}
|
|
191
|
+
class={[
|
|
192
|
+
'min-w-0 text-primary placeholder:text-muted h-full flex-1 self-stretch bg-transparent outline-none disabled:cursor-not-allowed',
|
|
193
|
+
type === 'search' &&
|
|
194
|
+
'[&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none'
|
|
195
|
+
]}
|
|
196
|
+
{oninput}
|
|
197
|
+
{onchange}
|
|
198
|
+
{onfocus}
|
|
199
|
+
{onblur}
|
|
200
|
+
{onkeydown}
|
|
201
|
+
/>
|
|
202
|
+
{/if}
|
|
166
203
|
</label>
|
|
167
204
|
|
|
168
205
|
{#if hasClear}
|
|
@@ -27,6 +27,9 @@ interface InputProps {
|
|
|
27
27
|
onfocus?: (e: FocusEvent) => void;
|
|
28
28
|
onblur?: (e: FocusEvent) => void;
|
|
29
29
|
onkeydown?: (e: KeyboardEvent) => void;
|
|
30
|
+
autocomplete?: string;
|
|
31
|
+
/** Native form value only (no Svelte bind). Needed for login + autofill. */
|
|
32
|
+
uncontrolled?: boolean;
|
|
30
33
|
}
|
|
31
34
|
declare const Input: import("svelte").Component<InputProps, {}, "value">;
|
|
32
35
|
type Input = ReturnType<typeof Input>;
|
|
@@ -71,6 +71,8 @@
|
|
|
71
71
|
/** Absorbed if a Kit `.as()` object is spread by mistake. */
|
|
72
72
|
defaultValue?: unknown;
|
|
73
73
|
'aria-invalid'?: boolean | 'true' | 'false';
|
|
74
|
+
autocomplete?: string;
|
|
75
|
+
uncontrolled?: boolean;
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
let {
|
|
@@ -97,7 +99,9 @@
|
|
|
97
99
|
oninput,
|
|
98
100
|
onchange,
|
|
99
101
|
defaultValue: _kitDefaultValue = undefined,
|
|
100
|
-
'aria-invalid': _ariaInvalid = undefined
|
|
102
|
+
'aria-invalid': _ariaInvalid = undefined,
|
|
103
|
+
autocomplete,
|
|
104
|
+
uncontrolled = false
|
|
101
105
|
}: FormFieldProps = $props();
|
|
102
106
|
|
|
103
107
|
const form = getFormContext();
|
|
@@ -186,6 +190,8 @@
|
|
|
186
190
|
{onchange}
|
|
187
191
|
status={resolved.status}
|
|
188
192
|
helperText={resolved.helperText}
|
|
193
|
+
{autocomplete}
|
|
194
|
+
{uncontrolled}
|
|
189
195
|
bind:value
|
|
190
196
|
/>
|
|
191
197
|
{/if}
|
|
@@ -60,6 +60,8 @@ interface FormFieldProps {
|
|
|
60
60
|
/** Absorbed if a Kit `.as()` object is spread by mistake. */
|
|
61
61
|
defaultValue?: unknown;
|
|
62
62
|
'aria-invalid'?: boolean | 'true' | 'false';
|
|
63
|
+
autocomplete?: string;
|
|
64
|
+
uncontrolled?: boolean;
|
|
63
65
|
}
|
|
64
66
|
declare const FormField: import("svelte").Component<FormFieldProps, {}, "value">;
|
|
65
67
|
type FormField = ReturnType<typeof FormField>;
|
|
@@ -32,6 +32,8 @@
|
|
|
32
32
|
defaultValue?: unknown;
|
|
33
33
|
type?: string;
|
|
34
34
|
'aria-invalid'?: boolean | 'true' | 'false';
|
|
35
|
+
autocomplete?: string;
|
|
36
|
+
uncontrolled?: boolean;
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
let {
|
|
@@ -53,7 +55,9 @@
|
|
|
53
55
|
onchange,
|
|
54
56
|
defaultValue: _kitDefaultValue = undefined,
|
|
55
57
|
type: _kitType = undefined,
|
|
56
|
-
'aria-invalid': _ariaInvalid = undefined
|
|
58
|
+
'aria-invalid': _ariaInvalid = undefined,
|
|
59
|
+
autocomplete,
|
|
60
|
+
uncontrolled = false
|
|
57
61
|
}: FormPasswordInputProps = $props();
|
|
58
62
|
|
|
59
63
|
const form = getFormContext();
|
|
@@ -111,6 +115,8 @@
|
|
|
111
115
|
helperText={resolved.helperText}
|
|
112
116
|
oninput={handleInput}
|
|
113
117
|
{onchange}
|
|
118
|
+
{autocomplete}
|
|
119
|
+
{uncontrolled}
|
|
114
120
|
bind:value
|
|
115
121
|
/>
|
|
116
122
|
</div>
|
|
@@ -22,6 +22,8 @@ interface FormPasswordInputProps {
|
|
|
22
22
|
defaultValue?: unknown;
|
|
23
23
|
type?: string;
|
|
24
24
|
'aria-invalid'?: boolean | 'true' | 'false';
|
|
25
|
+
autocomplete?: string;
|
|
26
|
+
uncontrolled?: boolean;
|
|
25
27
|
}
|
|
26
28
|
declare const FormPasswordInput: import("svelte").Component<FormPasswordInputProps, {}, "value">;
|
|
27
29
|
type FormPasswordInput = ReturnType<typeof FormPasswordInput>;
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
class?: string;
|
|
16
16
|
oninput?: (e: Event) => void;
|
|
17
17
|
onchange?: (e: Event) => void;
|
|
18
|
+
autocomplete?: string;
|
|
19
|
+
uncontrolled?: boolean;
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
let {
|
|
@@ -30,7 +32,9 @@
|
|
|
30
32
|
status = 'default',
|
|
31
33
|
class: className = '',
|
|
32
34
|
oninput,
|
|
33
|
-
onchange
|
|
35
|
+
onchange,
|
|
36
|
+
autocomplete,
|
|
37
|
+
uncontrolled = false
|
|
34
38
|
}: PasswordInputProps = $props();
|
|
35
39
|
|
|
36
40
|
let visible = $state(false);
|
|
@@ -48,6 +52,8 @@
|
|
|
48
52
|
{size}
|
|
49
53
|
{status}
|
|
50
54
|
type={visible ? 'text' : 'password'}
|
|
55
|
+
{autocomplete}
|
|
56
|
+
{uncontrolled}
|
|
51
57
|
bind:value
|
|
52
58
|
{oninput}
|
|
53
59
|
{onchange}
|
|
@@ -12,6 +12,8 @@ interface PasswordInputProps {
|
|
|
12
12
|
class?: string;
|
|
13
13
|
oninput?: (e: Event) => void;
|
|
14
14
|
onchange?: (e: Event) => void;
|
|
15
|
+
autocomplete?: string;
|
|
16
|
+
uncontrolled?: boolean;
|
|
15
17
|
}
|
|
16
18
|
declare const PasswordInput: import("svelte").Component<PasswordInputProps, {}, "value">;
|
|
17
19
|
type PasswordInput = ReturnType<typeof PasswordInput>;
|
|
@@ -29,6 +29,9 @@
|
|
|
29
29
|
messages?: AssistantMessage[];
|
|
30
30
|
draft?: string;
|
|
31
31
|
loading?: boolean;
|
|
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;
|
|
32
35
|
error?: string | null;
|
|
33
36
|
voiceEnabled?: boolean;
|
|
34
37
|
voiceOutput?: boolean;
|
|
@@ -61,6 +64,8 @@
|
|
|
61
64
|
messages = [],
|
|
62
65
|
draft = $bindable(''),
|
|
63
66
|
loading = false,
|
|
67
|
+
loadingLabel = 'Procesando…',
|
|
68
|
+
showLoadingBubble = true,
|
|
64
69
|
error = null,
|
|
65
70
|
voiceEnabled = true,
|
|
66
71
|
voiceOutput = $bindable(true),
|
|
@@ -218,7 +223,7 @@
|
|
|
218
223
|
{/if}
|
|
219
224
|
{/each}
|
|
220
225
|
|
|
221
|
-
{#if loading}
|
|
226
|
+
{#if loading && showLoadingBubble}
|
|
222
227
|
<div class="flex items-center gap-2">
|
|
223
228
|
<span
|
|
224
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"
|
|
@@ -230,18 +235,10 @@
|
|
|
230
235
|
class="flex items-center gap-2 rounded-2xl rounded-bl-sm bg-surface-overlay px-3.5 py-2.5"
|
|
231
236
|
>
|
|
232
237
|
<LoaderCircle size={14} strokeWidth={2} class="animate-spin text-muted" />
|
|
233
|
-
<span class="text-xs text-muted">
|
|
238
|
+
<span class="text-xs text-muted">{loadingLabel}</span>
|
|
234
239
|
</div>
|
|
235
240
|
</div>
|
|
236
241
|
{/if}
|
|
237
|
-
|
|
238
|
-
{#if error}
|
|
239
|
-
<div
|
|
240
|
-
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"
|
|
241
|
-
>
|
|
242
|
-
{error}
|
|
243
|
-
</div>
|
|
244
|
-
{/if}
|
|
245
242
|
</div>
|
|
246
243
|
{/if}
|
|
247
244
|
</div>
|
|
@@ -252,8 +249,11 @@
|
|
|
252
249
|
<input
|
|
253
250
|
type="text"
|
|
254
251
|
bind:value={draft}
|
|
255
|
-
{placeholder}
|
|
256
|
-
class=
|
|
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
|
+
]}
|
|
257
257
|
disabled={loading}
|
|
258
258
|
onkeydown={handleKeydown}
|
|
259
259
|
aria-label={placeholder}
|
|
@@ -300,6 +300,10 @@
|
|
|
300
300
|
</div>
|
|
301
301
|
</div>
|
|
302
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
|
+
|
|
303
307
|
{#if footerExtra}
|
|
304
308
|
{@render footerExtra()}
|
|
305
309
|
{/if}
|
|
@@ -14,6 +14,9 @@ interface AssistantChatProps {
|
|
|
14
14
|
messages?: AssistantMessage[];
|
|
15
15
|
draft?: string;
|
|
16
16
|
loading?: boolean;
|
|
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;
|
|
17
20
|
error?: string | null;
|
|
18
21
|
voiceEnabled?: boolean;
|
|
19
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;
|