@gradio/multimodaltextbox 0.11.0-dev.2 → 0.11.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.
- package/CHANGELOG.md +37 -0
- package/Index.svelte +3 -3
- package/MultimodalTextbox.test.ts +20 -21
- package/README.md +1 -1
- package/dist/Index.svelte +3 -3
- package/dist/shared/MultimodalTextbox.svelte +218 -56
- package/package.json +11 -11
- package/shared/MultimodalTextbox.svelte +218 -56
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
# @gradio/multimodaltextbox
|
|
2
2
|
|
|
3
|
+
## 0.11.1
|
|
4
|
+
|
|
5
|
+
### Dependency updates
|
|
6
|
+
|
|
7
|
+
- @gradio/audio@0.21.0
|
|
8
|
+
- @gradio/video@0.18.0
|
|
9
|
+
|
|
10
|
+
## 0.11.0
|
|
11
|
+
|
|
12
|
+
### Dependency updates
|
|
13
|
+
|
|
14
|
+
- @gradio/utils@0.10.4
|
|
15
|
+
|
|
16
|
+
## 0.11.0
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
- [#11908](https://github.com/gradio-app/gradio/pull/11908) [`029034f`](https://github.com/gradio-app/gradio/commit/029034f7853ea018d110efe9b7e2ef7d1407091c) - remove_placeholder_type_here
|
|
21
|
+
- [#11908](https://github.com/gradio-app/gradio/pull/11908) [`029034f`](https://github.com/gradio-app/gradio/commit/029034f7853ea018d110efe9b7e2ef7d1407091c) - Clear Error statuses
|
|
22
|
+
- [#11908](https://github.com/gradio-app/gradio/pull/11908) [`029034f`](https://github.com/gradio-app/gradio/commit/029034f7853ea018d110efe9b7e2ef7d1407091c) - Improve gr.MultimodalTextbox in mobile
|
|
23
|
+
- [#11908](https://github.com/gradio-app/gradio/pull/11908) [`029034f`](https://github.com/gradio-app/gradio/commit/029034f7853ea018d110efe9b7e2ef7d1407091c) - Add minimal recording UI to gr.MultimodalTextbox
|
|
24
|
+
- [#11908](https://github.com/gradio-app/gradio/pull/11908) [`029034f`](https://github.com/gradio-app/gradio/commit/029034f7853ea018d110efe9b7e2ef7d1407091c) - Add back default values for labels
|
|
25
|
+
- [#11908](https://github.com/gradio-app/gradio/pull/11908) [`029034f`](https://github.com/gradio-app/gradio/commit/029034f7853ea018d110efe9b7e2ef7d1407091c) - Unit test fixes
|
|
26
|
+
- [#12438](https://github.com/gradio-app/gradio/pull/12438) [`25ffc03`](https://github.com/gradio-app/gradio/commit/25ffc0398f8feb43d817c02b2ab970c16de6d797) - Svelte5 migration and bugfix
|
|
27
|
+
|
|
28
|
+
### Dependencies
|
|
29
|
+
|
|
30
|
+
- @gradio/atoms@0.19.0
|
|
31
|
+
- @gradio/icons@0.15.0
|
|
32
|
+
- @gradio/statustracker@0.12.0
|
|
33
|
+
- @gradio/utils@0.10.3
|
|
34
|
+
- @gradio/upload@0.17.2
|
|
35
|
+
- @gradio/image@0.24.0
|
|
36
|
+
- @gradio/video@0.17.0
|
|
37
|
+
- @gradio/client@2.0.0
|
|
38
|
+
- @gradio/audio@0.20.0
|
|
39
|
+
|
|
3
40
|
## 0.11.0-dev.2
|
|
4
41
|
|
|
5
42
|
### Dependency updates
|
package/Index.svelte
CHANGED
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
|
|
40
40
|
const value = $derived(gradio.props.value || { text: "", files: [] });
|
|
41
41
|
|
|
42
|
-
let dragging
|
|
43
|
-
let active_source
|
|
42
|
+
let dragging = $state<boolean>(false);
|
|
43
|
+
let active_source = $state<"microphone" | null>(null);
|
|
44
44
|
|
|
45
45
|
let color_accent = "darkorange";
|
|
46
46
|
|
|
@@ -127,7 +127,7 @@
|
|
|
127
127
|
autoscroll={gradio.shared.autoscroll}
|
|
128
128
|
i18n={gradio.i18n}
|
|
129
129
|
{...gradio.shared.loading_status}
|
|
130
|
-
|
|
130
|
+
on_clear_status={() =>
|
|
131
131
|
gradio.dispatch("clear_status", gradio.shared.loading_status)}
|
|
132
132
|
/>
|
|
133
133
|
{/if}
|
|
@@ -28,7 +28,8 @@ describe("MultimodalTextbox", () => {
|
|
|
28
28
|
value: { text: "hello world", files: [] },
|
|
29
29
|
label: "Textbox",
|
|
30
30
|
interactive: false,
|
|
31
|
-
root: ""
|
|
31
|
+
root: "",
|
|
32
|
+
sources: []
|
|
32
33
|
});
|
|
33
34
|
|
|
34
35
|
const item: HTMLInputElement = getByDisplayValue(
|
|
@@ -38,19 +39,17 @@ describe("MultimodalTextbox", () => {
|
|
|
38
39
|
});
|
|
39
40
|
|
|
40
41
|
test("changing the text should update the value", async () => {
|
|
41
|
-
const {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
);
|
|
42
|
+
const { getByDisplayValue, listen } = await render(MultimodalTextbox, {
|
|
43
|
+
show_label: true,
|
|
44
|
+
max_lines: 10,
|
|
45
|
+
loading_status,
|
|
46
|
+
lines: 1,
|
|
47
|
+
value: { text: "hi ", files: [] },
|
|
48
|
+
label: "MultimodalTextbox",
|
|
49
|
+
interactive: true,
|
|
50
|
+
root: "",
|
|
51
|
+
sources: []
|
|
52
|
+
});
|
|
54
53
|
|
|
55
54
|
const item: HTMLInputElement = getByDisplayValue("hi") as HTMLInputElement;
|
|
56
55
|
|
|
@@ -60,14 +59,13 @@ describe("MultimodalTextbox", () => {
|
|
|
60
59
|
await event.keyboard("some text");
|
|
61
60
|
|
|
62
61
|
assert.equal(item.value, "hi some text");
|
|
63
|
-
assert.equal(component.value.text, "hi some text");
|
|
64
62
|
assert.equal(mock.callCount, 9);
|
|
65
63
|
assert.equal(mock.calls[8][0].detail.data.text, "hi some text");
|
|
66
64
|
assert.equal(mock.calls[8][0].detail.data.files.length, 0);
|
|
67
65
|
});
|
|
68
66
|
|
|
69
67
|
test("submitting should clear mic_audio", async () => {
|
|
70
|
-
const {
|
|
68
|
+
const { getByTestId, listen } = await render(MultimodalTextbox, {
|
|
71
69
|
show_label: true,
|
|
72
70
|
max_lines: 10,
|
|
73
71
|
loading_status,
|
|
@@ -76,12 +74,13 @@ describe("MultimodalTextbox", () => {
|
|
|
76
74
|
label: "MultimodalTextbox",
|
|
77
75
|
interactive: true,
|
|
78
76
|
root: "",
|
|
79
|
-
sources: ["microphone"]
|
|
77
|
+
sources: ["microphone"],
|
|
78
|
+
submit_btn: true
|
|
80
79
|
});
|
|
81
80
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
await
|
|
85
|
-
assert.equal(
|
|
81
|
+
const mock = listen("submit");
|
|
82
|
+
const submitButton = getByTestId("submit-button");
|
|
83
|
+
await event.click(submitButton);
|
|
84
|
+
assert.equal(mock.callCount, 1);
|
|
86
85
|
});
|
|
87
86
|
});
|
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ BaseMultimodalTextbox
|
|
|
11
11
|
export let value = "";
|
|
12
12
|
export let value_is_output = false;
|
|
13
13
|
export let lines = 1;
|
|
14
|
-
export let placeholder = "
|
|
14
|
+
export let placeholder = "";
|
|
15
15
|
export let label: string;
|
|
16
16
|
export let info: string | undefined = undefined;
|
|
17
17
|
export let disabled = false;
|
package/dist/Index.svelte
CHANGED
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
|
|
40
40
|
const value = $derived(gradio.props.value || { text: "", files: [] });
|
|
41
41
|
|
|
42
|
-
let dragging
|
|
43
|
-
let active_source
|
|
42
|
+
let dragging = $state<boolean>(false);
|
|
43
|
+
let active_source = $state<"microphone" | null>(null);
|
|
44
44
|
|
|
45
45
|
let color_accent = "darkorange";
|
|
46
46
|
|
|
@@ -127,7 +127,7 @@
|
|
|
127
127
|
autoscroll={gradio.shared.autoscroll}
|
|
128
128
|
i18n={gradio.i18n}
|
|
129
129
|
{...gradio.shared.loading_status}
|
|
130
|
-
|
|
130
|
+
on_clear_status={() =>
|
|
131
131
|
gradio.dispatch("clear_status", gradio.shared.loading_status)}
|
|
132
132
|
/>
|
|
133
133
|
{/if}
|
|
@@ -21,10 +21,15 @@
|
|
|
21
21
|
Video,
|
|
22
22
|
ArrowUp,
|
|
23
23
|
Square,
|
|
24
|
-
Microphone
|
|
24
|
+
Microphone,
|
|
25
|
+
Check
|
|
25
26
|
} from "@gradio/icons";
|
|
26
27
|
import type { SelectData } from "@gradio/utils";
|
|
27
28
|
import { BaseInteractiveAudio as InteractiveAudio } from "@gradio/audio";
|
|
29
|
+
import {
|
|
30
|
+
MinimalAudioPlayer,
|
|
31
|
+
MinimalAudioRecorder
|
|
32
|
+
} from "@gradio/audio/shared";
|
|
28
33
|
import type { InputHTMLAttributes } from "./types";
|
|
29
34
|
|
|
30
35
|
export let value: { text: string; files: FileData[] } = {
|
|
@@ -35,7 +40,7 @@
|
|
|
35
40
|
export let value_is_output = false;
|
|
36
41
|
export let lines = 1;
|
|
37
42
|
export let i18n: I18nFormatter;
|
|
38
|
-
export let placeholder = "
|
|
43
|
+
export let placeholder = "";
|
|
39
44
|
export let disabled = false;
|
|
40
45
|
export let label: string;
|
|
41
46
|
export let info: string | undefined = undefined;
|
|
@@ -181,10 +186,10 @@
|
|
|
181
186
|
max_lines >= 1
|
|
182
187
|
) {
|
|
183
188
|
e.preventDefault();
|
|
189
|
+
add_mic_audio_to_files();
|
|
190
|
+
active_source = null;
|
|
184
191
|
await tick();
|
|
185
192
|
dispatch("submit");
|
|
186
|
-
active_source = null;
|
|
187
|
-
add_mic_audio_to_files();
|
|
188
193
|
}
|
|
189
194
|
}
|
|
190
195
|
|
|
@@ -241,13 +246,14 @@
|
|
|
241
246
|
value.files.push(mic_audio);
|
|
242
247
|
value = value;
|
|
243
248
|
mic_audio = null;
|
|
249
|
+
dispatch("change", value);
|
|
244
250
|
}
|
|
245
251
|
}
|
|
246
252
|
|
|
247
253
|
function handle_submit(): void {
|
|
248
|
-
dispatch("submit");
|
|
249
|
-
active_source = null;
|
|
250
254
|
add_mic_audio_to_files();
|
|
255
|
+
active_source = null;
|
|
256
|
+
dispatch("submit");
|
|
251
257
|
}
|
|
252
258
|
|
|
253
259
|
async function handle_paste(event: ClipboardEvent): Promise<void> {
|
|
@@ -343,36 +349,70 @@
|
|
|
343
349
|
<BlockTitle {show_label} {info} {rtl}>{label}</BlockTitle>
|
|
344
350
|
<div class="input-container">
|
|
345
351
|
{#if sources && sources.includes("microphone") && active_source === "microphone"}
|
|
346
|
-
<
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
352
|
+
<div class="recording-overlay" class:has-audio={mic_audio !== null}>
|
|
353
|
+
{#if !mic_audio}
|
|
354
|
+
<div class="recording-content">
|
|
355
|
+
<MinimalAudioRecorder
|
|
356
|
+
label={label || "Audio"}
|
|
357
|
+
{waveform_settings}
|
|
358
|
+
{recording}
|
|
359
|
+
{upload}
|
|
360
|
+
{root}
|
|
361
|
+
{max_file_size}
|
|
362
|
+
bind:upload_promise
|
|
363
|
+
on:change={({ detail }) => {
|
|
364
|
+
mic_audio = detail;
|
|
365
|
+
}}
|
|
366
|
+
on:stop_recording={() => {
|
|
367
|
+
recording = false;
|
|
368
|
+
dispatch("stop_recording");
|
|
369
|
+
}}
|
|
370
|
+
on:clear={() => {
|
|
371
|
+
active_source = null;
|
|
372
|
+
recording = false;
|
|
373
|
+
mic_audio = null;
|
|
374
|
+
}}
|
|
375
|
+
on:error={({ detail }) => {
|
|
376
|
+
active_source = null;
|
|
377
|
+
recording = false;
|
|
378
|
+
mic_audio = null;
|
|
379
|
+
}}
|
|
380
|
+
/>
|
|
381
|
+
</div>
|
|
382
|
+
{:else}
|
|
383
|
+
<div class="recording-content">
|
|
384
|
+
<MinimalAudioPlayer
|
|
385
|
+
value={mic_audio}
|
|
386
|
+
label={label || "Audio"}
|
|
387
|
+
loop={false}
|
|
388
|
+
/>
|
|
389
|
+
<div class="action-buttons">
|
|
390
|
+
<button
|
|
391
|
+
class="confirm-button"
|
|
392
|
+
on:click={() => {
|
|
393
|
+
add_mic_audio_to_files();
|
|
394
|
+
active_source = null;
|
|
395
|
+
recording = false;
|
|
396
|
+
}}
|
|
397
|
+
aria-label="Attach audio"
|
|
398
|
+
>
|
|
399
|
+
<Check />
|
|
400
|
+
</button>
|
|
401
|
+
<button
|
|
402
|
+
class="cancel-button"
|
|
403
|
+
on:click={() => {
|
|
404
|
+
active_source = null;
|
|
405
|
+
recording = false;
|
|
406
|
+
mic_audio = null;
|
|
407
|
+
}}
|
|
408
|
+
aria-label="Clear audio"
|
|
409
|
+
>
|
|
410
|
+
<Clear />
|
|
411
|
+
</button>
|
|
412
|
+
</div>
|
|
413
|
+
</div>
|
|
414
|
+
{/if}
|
|
415
|
+
</div>
|
|
376
416
|
{/if}
|
|
377
417
|
{#if show_upload}
|
|
378
418
|
<Upload
|
|
@@ -407,7 +447,7 @@
|
|
|
407
447
|
{#if show_upload}
|
|
408
448
|
<button
|
|
409
449
|
data-testid="upload-button"
|
|
410
|
-
class="upload-button
|
|
450
|
+
class="upload-button thumbnail-add"
|
|
411
451
|
{disabled}
|
|
412
452
|
on:click={handle_upload_click}
|
|
413
453
|
aria-label="Upload a file"
|
|
@@ -492,9 +532,15 @@
|
|
|
492
532
|
class="microphone-button"
|
|
493
533
|
class:recording
|
|
494
534
|
{disabled}
|
|
495
|
-
on:click={() => {
|
|
496
|
-
active_source
|
|
497
|
-
active_source
|
|
535
|
+
on:click={async () => {
|
|
536
|
+
if (active_source !== "microphone") {
|
|
537
|
+
active_source = "microphone";
|
|
538
|
+
await tick();
|
|
539
|
+
recording = true;
|
|
540
|
+
} else {
|
|
541
|
+
active_source = null;
|
|
542
|
+
recording = false;
|
|
543
|
+
}
|
|
498
544
|
}}
|
|
499
545
|
aria-label="Record audio"
|
|
500
546
|
>
|
|
@@ -505,6 +551,7 @@
|
|
|
505
551
|
{#if submit_btn}
|
|
506
552
|
<button
|
|
507
553
|
class="submit-button"
|
|
554
|
+
data-testid="submit-button"
|
|
508
555
|
class:padded-button={submit_btn !== true}
|
|
509
556
|
{disabled}
|
|
510
557
|
on:click={handle_submit}
|
|
@@ -626,7 +673,6 @@
|
|
|
626
673
|
display: flex;
|
|
627
674
|
justify-content: center;
|
|
628
675
|
align-items: center;
|
|
629
|
-
border: var(--size-px) solid var(--border-color-primary);
|
|
630
676
|
border-radius: var(--radius-md);
|
|
631
677
|
background: var(--background-fill-secondary);
|
|
632
678
|
width: var(--size-full);
|
|
@@ -712,7 +758,6 @@
|
|
|
712
758
|
transform: scaleX(-1);
|
|
713
759
|
}
|
|
714
760
|
|
|
715
|
-
.mobile-thumbnail-add,
|
|
716
761
|
.microphone-button {
|
|
717
762
|
color: var(--body-text-color);
|
|
718
763
|
cursor: pointer;
|
|
@@ -722,14 +767,33 @@
|
|
|
722
767
|
align-items: center;
|
|
723
768
|
flex-shrink: 0;
|
|
724
769
|
border-radius: var(--radius-md);
|
|
725
|
-
transition:
|
|
726
|
-
background 0.2s var(--easing-standard),
|
|
727
|
-
border-color 0.2s var(--easing-standard);
|
|
728
770
|
}
|
|
729
771
|
|
|
730
|
-
.
|
|
772
|
+
.thumbnail-add {
|
|
773
|
+
background: var(--button-secondary-background-fill);
|
|
774
|
+
cursor: pointer;
|
|
775
|
+
display: flex;
|
|
776
|
+
justify-content: center;
|
|
777
|
+
align-items: center;
|
|
778
|
+
flex-shrink: 0;
|
|
731
779
|
width: var(--size-10);
|
|
732
780
|
height: var(--size-10);
|
|
781
|
+
border-radius: var(--radius-md);
|
|
782
|
+
z-index: var(--layer-1);
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
.thumbnail-add:hover:not(:disabled) {
|
|
786
|
+
background: var(--button-secondary-background-fill-hover);
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
.thumbnail-add:disabled {
|
|
790
|
+
opacity: 0.5;
|
|
791
|
+
cursor: not-allowed;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
.thumbnail-add :global(svg) {
|
|
795
|
+
width: var(--size-5);
|
|
796
|
+
height: var(--size-5);
|
|
733
797
|
}
|
|
734
798
|
|
|
735
799
|
.microphone-button {
|
|
@@ -737,19 +801,15 @@
|
|
|
737
801
|
height: var(--size-9);
|
|
738
802
|
}
|
|
739
803
|
|
|
740
|
-
.mobile-thumbnail-add:hover:not(:disabled),
|
|
741
804
|
.microphone-button:hover:not(:disabled) {
|
|
742
|
-
background: var(--button-secondary-background-fill
|
|
743
|
-
border-color: var(--border-color-primary);
|
|
805
|
+
background: var(--button-secondary-background-fill);
|
|
744
806
|
}
|
|
745
807
|
|
|
746
|
-
.mobile-thumbnail-add:disabled,
|
|
747
808
|
.microphone-button:disabled {
|
|
748
809
|
opacity: 0.5;
|
|
749
810
|
cursor: not-allowed;
|
|
750
811
|
}
|
|
751
812
|
|
|
752
|
-
.mobile-thumbnail-add :global(svg),
|
|
753
813
|
.microphone-button :global(svg) {
|
|
754
814
|
width: var(--size-5);
|
|
755
815
|
height: var(--size-5);
|
|
@@ -757,7 +817,6 @@
|
|
|
757
817
|
|
|
758
818
|
.submit-button,
|
|
759
819
|
.stop-button {
|
|
760
|
-
border: var(--size-px) solid var(--border-color-primary);
|
|
761
820
|
background: var(--button-secondary-background-fill);
|
|
762
821
|
cursor: pointer;
|
|
763
822
|
display: flex;
|
|
@@ -768,9 +827,6 @@
|
|
|
768
827
|
height: var(--size-9);
|
|
769
828
|
border-radius: var(--radius-md);
|
|
770
829
|
z-index: var(--layer-1);
|
|
771
|
-
transition:
|
|
772
|
-
background 0.2s var(--easing-standard),
|
|
773
|
-
border-color 0.2s var(--easing-standard);
|
|
774
830
|
}
|
|
775
831
|
|
|
776
832
|
.submit-button:hover:not(:disabled),
|
|
@@ -820,6 +876,112 @@
|
|
|
820
876
|
}
|
|
821
877
|
}
|
|
822
878
|
|
|
879
|
+
.recording-overlay {
|
|
880
|
+
position: absolute;
|
|
881
|
+
top: 0;
|
|
882
|
+
left: 0;
|
|
883
|
+
right: 0;
|
|
884
|
+
bottom: 0;
|
|
885
|
+
background: var(--block-background-fill);
|
|
886
|
+
border-radius: var(--radius-xl);
|
|
887
|
+
display: flex;
|
|
888
|
+
align-items: center;
|
|
889
|
+
justify-content: center;
|
|
890
|
+
z-index: var(--layer-5);
|
|
891
|
+
padding: var(--spacing-lg);
|
|
892
|
+
backdrop-filter: blur(8px);
|
|
893
|
+
animation: fadeIn 0.2s var(--easing-standard);
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
@keyframes fadeIn {
|
|
897
|
+
from {
|
|
898
|
+
opacity: 0;
|
|
899
|
+
}
|
|
900
|
+
to {
|
|
901
|
+
opacity: 1;
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
.recording-content {
|
|
906
|
+
display: flex;
|
|
907
|
+
align-items: center;
|
|
908
|
+
gap: var(--spacing-lg);
|
|
909
|
+
width: 100%;
|
|
910
|
+
max-width: 700px;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
.recording-content :global(.minimal-audio-recorder),
|
|
914
|
+
.recording-content :global(.minimal-audio-player) {
|
|
915
|
+
flex: 1;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
.action-buttons {
|
|
919
|
+
display: flex;
|
|
920
|
+
align-items: center;
|
|
921
|
+
gap: var(--spacing-sm);
|
|
922
|
+
flex-shrink: 0;
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
.stop-button,
|
|
926
|
+
.confirm-button,
|
|
927
|
+
.cancel-button {
|
|
928
|
+
display: flex;
|
|
929
|
+
align-items: center;
|
|
930
|
+
justify-content: center;
|
|
931
|
+
width: var(--size-9);
|
|
932
|
+
height: var(--size-9);
|
|
933
|
+
padding: 0;
|
|
934
|
+
border-radius: var(--radius-md);
|
|
935
|
+
cursor: pointer;
|
|
936
|
+
flex-shrink: 0;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
.stop-button {
|
|
940
|
+
background: var(--button-secondary-background-fill);
|
|
941
|
+
border-color: var(--border-color-primary);
|
|
942
|
+
color: var(--error-500);
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
.stop-button:hover {
|
|
946
|
+
background: var(--button-secondary-background-fill-hover);
|
|
947
|
+
color: var(--error-600);
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
.stop-button:active {
|
|
951
|
+
transform: scale(0.95);
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
.confirm-button {
|
|
955
|
+
background: var(--button-primary-background-fill);
|
|
956
|
+
border-color: var(--button-primary-border-color);
|
|
957
|
+
color: white;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
.confirm-button:hover {
|
|
961
|
+
background: var(--button-primary-background-fill-hover);
|
|
962
|
+
color: var(--button-primary-text-color-hover);
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
.confirm-button:active {
|
|
966
|
+
transform: scale(0.95);
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
.cancel-button {
|
|
970
|
+
background: var(--button-secondary-background-fill);
|
|
971
|
+
color: var(--body-text-color);
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
.cancel-button:hover {
|
|
975
|
+
background: var(--button-secondary-background-fill-hover);
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
.stop-button :global(svg),
|
|
979
|
+
.confirm-button :global(svg),
|
|
980
|
+
.cancel-button :global(svg) {
|
|
981
|
+
width: var(--size-5);
|
|
982
|
+
height: var(--size-5);
|
|
983
|
+
}
|
|
984
|
+
|
|
823
985
|
@media (max-width: 768px) {
|
|
824
986
|
.input-wrapper {
|
|
825
987
|
padding: var(--spacing-xs);
|
|
@@ -831,7 +993,7 @@
|
|
|
831
993
|
}
|
|
832
994
|
|
|
833
995
|
.thumbnail-small,
|
|
834
|
-
.
|
|
996
|
+
.thumbnail-add {
|
|
835
997
|
width: var(--size-9);
|
|
836
998
|
height: var(--size-9);
|
|
837
999
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gradio/multimodaltextbox",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "Gradio UI packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "",
|
|
@@ -22,18 +22,18 @@
|
|
|
22
22
|
"./package.json": "./package.json"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@gradio/atoms": "^0.19.0
|
|
26
|
-
"@gradio/icons": "^0.15.0
|
|
27
|
-
"@gradio/
|
|
28
|
-
"@gradio/
|
|
29
|
-
"@gradio/
|
|
30
|
-
"@gradio/
|
|
31
|
-
"@gradio/
|
|
32
|
-
"@gradio/client": "^2.0.0
|
|
33
|
-
"@gradio/audio": "^0.
|
|
25
|
+
"@gradio/atoms": "^0.19.0",
|
|
26
|
+
"@gradio/icons": "^0.15.0",
|
|
27
|
+
"@gradio/statustracker": "^0.12.0",
|
|
28
|
+
"@gradio/utils": "^0.10.4",
|
|
29
|
+
"@gradio/upload": "^0.17.2",
|
|
30
|
+
"@gradio/video": "^0.18.0",
|
|
31
|
+
"@gradio/image": "^0.24.0",
|
|
32
|
+
"@gradio/client": "^2.0.0",
|
|
33
|
+
"@gradio/audio": "^0.21.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@gradio/preview": "^0.15.
|
|
36
|
+
"@gradio/preview": "^0.15.1"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"svelte": "^5.43.4"
|
|
@@ -21,10 +21,15 @@
|
|
|
21
21
|
Video,
|
|
22
22
|
ArrowUp,
|
|
23
23
|
Square,
|
|
24
|
-
Microphone
|
|
24
|
+
Microphone,
|
|
25
|
+
Check
|
|
25
26
|
} from "@gradio/icons";
|
|
26
27
|
import type { SelectData } from "@gradio/utils";
|
|
27
28
|
import { BaseInteractiveAudio as InteractiveAudio } from "@gradio/audio";
|
|
29
|
+
import {
|
|
30
|
+
MinimalAudioPlayer,
|
|
31
|
+
MinimalAudioRecorder
|
|
32
|
+
} from "@gradio/audio/shared";
|
|
28
33
|
import type { InputHTMLAttributes } from "./types";
|
|
29
34
|
|
|
30
35
|
export let value: { text: string; files: FileData[] } = {
|
|
@@ -35,7 +40,7 @@
|
|
|
35
40
|
export let value_is_output = false;
|
|
36
41
|
export let lines = 1;
|
|
37
42
|
export let i18n: I18nFormatter;
|
|
38
|
-
export let placeholder = "
|
|
43
|
+
export let placeholder = "";
|
|
39
44
|
export let disabled = false;
|
|
40
45
|
export let label: string;
|
|
41
46
|
export let info: string | undefined = undefined;
|
|
@@ -181,10 +186,10 @@
|
|
|
181
186
|
max_lines >= 1
|
|
182
187
|
) {
|
|
183
188
|
e.preventDefault();
|
|
189
|
+
add_mic_audio_to_files();
|
|
190
|
+
active_source = null;
|
|
184
191
|
await tick();
|
|
185
192
|
dispatch("submit");
|
|
186
|
-
active_source = null;
|
|
187
|
-
add_mic_audio_to_files();
|
|
188
193
|
}
|
|
189
194
|
}
|
|
190
195
|
|
|
@@ -241,13 +246,14 @@
|
|
|
241
246
|
value.files.push(mic_audio);
|
|
242
247
|
value = value;
|
|
243
248
|
mic_audio = null;
|
|
249
|
+
dispatch("change", value);
|
|
244
250
|
}
|
|
245
251
|
}
|
|
246
252
|
|
|
247
253
|
function handle_submit(): void {
|
|
248
|
-
dispatch("submit");
|
|
249
|
-
active_source = null;
|
|
250
254
|
add_mic_audio_to_files();
|
|
255
|
+
active_source = null;
|
|
256
|
+
dispatch("submit");
|
|
251
257
|
}
|
|
252
258
|
|
|
253
259
|
async function handle_paste(event: ClipboardEvent): Promise<void> {
|
|
@@ -343,36 +349,70 @@
|
|
|
343
349
|
<BlockTitle {show_label} {info} {rtl}>{label}</BlockTitle>
|
|
344
350
|
<div class="input-container">
|
|
345
351
|
{#if sources && sources.includes("microphone") && active_source === "microphone"}
|
|
346
|
-
<
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
352
|
+
<div class="recording-overlay" class:has-audio={mic_audio !== null}>
|
|
353
|
+
{#if !mic_audio}
|
|
354
|
+
<div class="recording-content">
|
|
355
|
+
<MinimalAudioRecorder
|
|
356
|
+
label={label || "Audio"}
|
|
357
|
+
{waveform_settings}
|
|
358
|
+
{recording}
|
|
359
|
+
{upload}
|
|
360
|
+
{root}
|
|
361
|
+
{max_file_size}
|
|
362
|
+
bind:upload_promise
|
|
363
|
+
on:change={({ detail }) => {
|
|
364
|
+
mic_audio = detail;
|
|
365
|
+
}}
|
|
366
|
+
on:stop_recording={() => {
|
|
367
|
+
recording = false;
|
|
368
|
+
dispatch("stop_recording");
|
|
369
|
+
}}
|
|
370
|
+
on:clear={() => {
|
|
371
|
+
active_source = null;
|
|
372
|
+
recording = false;
|
|
373
|
+
mic_audio = null;
|
|
374
|
+
}}
|
|
375
|
+
on:error={({ detail }) => {
|
|
376
|
+
active_source = null;
|
|
377
|
+
recording = false;
|
|
378
|
+
mic_audio = null;
|
|
379
|
+
}}
|
|
380
|
+
/>
|
|
381
|
+
</div>
|
|
382
|
+
{:else}
|
|
383
|
+
<div class="recording-content">
|
|
384
|
+
<MinimalAudioPlayer
|
|
385
|
+
value={mic_audio}
|
|
386
|
+
label={label || "Audio"}
|
|
387
|
+
loop={false}
|
|
388
|
+
/>
|
|
389
|
+
<div class="action-buttons">
|
|
390
|
+
<button
|
|
391
|
+
class="confirm-button"
|
|
392
|
+
on:click={() => {
|
|
393
|
+
add_mic_audio_to_files();
|
|
394
|
+
active_source = null;
|
|
395
|
+
recording = false;
|
|
396
|
+
}}
|
|
397
|
+
aria-label="Attach audio"
|
|
398
|
+
>
|
|
399
|
+
<Check />
|
|
400
|
+
</button>
|
|
401
|
+
<button
|
|
402
|
+
class="cancel-button"
|
|
403
|
+
on:click={() => {
|
|
404
|
+
active_source = null;
|
|
405
|
+
recording = false;
|
|
406
|
+
mic_audio = null;
|
|
407
|
+
}}
|
|
408
|
+
aria-label="Clear audio"
|
|
409
|
+
>
|
|
410
|
+
<Clear />
|
|
411
|
+
</button>
|
|
412
|
+
</div>
|
|
413
|
+
</div>
|
|
414
|
+
{/if}
|
|
415
|
+
</div>
|
|
376
416
|
{/if}
|
|
377
417
|
{#if show_upload}
|
|
378
418
|
<Upload
|
|
@@ -407,7 +447,7 @@
|
|
|
407
447
|
{#if show_upload}
|
|
408
448
|
<button
|
|
409
449
|
data-testid="upload-button"
|
|
410
|
-
class="upload-button
|
|
450
|
+
class="upload-button thumbnail-add"
|
|
411
451
|
{disabled}
|
|
412
452
|
on:click={handle_upload_click}
|
|
413
453
|
aria-label="Upload a file"
|
|
@@ -492,9 +532,15 @@
|
|
|
492
532
|
class="microphone-button"
|
|
493
533
|
class:recording
|
|
494
534
|
{disabled}
|
|
495
|
-
on:click={() => {
|
|
496
|
-
active_source
|
|
497
|
-
active_source
|
|
535
|
+
on:click={async () => {
|
|
536
|
+
if (active_source !== "microphone") {
|
|
537
|
+
active_source = "microphone";
|
|
538
|
+
await tick();
|
|
539
|
+
recording = true;
|
|
540
|
+
} else {
|
|
541
|
+
active_source = null;
|
|
542
|
+
recording = false;
|
|
543
|
+
}
|
|
498
544
|
}}
|
|
499
545
|
aria-label="Record audio"
|
|
500
546
|
>
|
|
@@ -505,6 +551,7 @@
|
|
|
505
551
|
{#if submit_btn}
|
|
506
552
|
<button
|
|
507
553
|
class="submit-button"
|
|
554
|
+
data-testid="submit-button"
|
|
508
555
|
class:padded-button={submit_btn !== true}
|
|
509
556
|
{disabled}
|
|
510
557
|
on:click={handle_submit}
|
|
@@ -626,7 +673,6 @@
|
|
|
626
673
|
display: flex;
|
|
627
674
|
justify-content: center;
|
|
628
675
|
align-items: center;
|
|
629
|
-
border: var(--size-px) solid var(--border-color-primary);
|
|
630
676
|
border-radius: var(--radius-md);
|
|
631
677
|
background: var(--background-fill-secondary);
|
|
632
678
|
width: var(--size-full);
|
|
@@ -712,7 +758,6 @@
|
|
|
712
758
|
transform: scaleX(-1);
|
|
713
759
|
}
|
|
714
760
|
|
|
715
|
-
.mobile-thumbnail-add,
|
|
716
761
|
.microphone-button {
|
|
717
762
|
color: var(--body-text-color);
|
|
718
763
|
cursor: pointer;
|
|
@@ -722,14 +767,33 @@
|
|
|
722
767
|
align-items: center;
|
|
723
768
|
flex-shrink: 0;
|
|
724
769
|
border-radius: var(--radius-md);
|
|
725
|
-
transition:
|
|
726
|
-
background 0.2s var(--easing-standard),
|
|
727
|
-
border-color 0.2s var(--easing-standard);
|
|
728
770
|
}
|
|
729
771
|
|
|
730
|
-
.
|
|
772
|
+
.thumbnail-add {
|
|
773
|
+
background: var(--button-secondary-background-fill);
|
|
774
|
+
cursor: pointer;
|
|
775
|
+
display: flex;
|
|
776
|
+
justify-content: center;
|
|
777
|
+
align-items: center;
|
|
778
|
+
flex-shrink: 0;
|
|
731
779
|
width: var(--size-10);
|
|
732
780
|
height: var(--size-10);
|
|
781
|
+
border-radius: var(--radius-md);
|
|
782
|
+
z-index: var(--layer-1);
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
.thumbnail-add:hover:not(:disabled) {
|
|
786
|
+
background: var(--button-secondary-background-fill-hover);
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
.thumbnail-add:disabled {
|
|
790
|
+
opacity: 0.5;
|
|
791
|
+
cursor: not-allowed;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
.thumbnail-add :global(svg) {
|
|
795
|
+
width: var(--size-5);
|
|
796
|
+
height: var(--size-5);
|
|
733
797
|
}
|
|
734
798
|
|
|
735
799
|
.microphone-button {
|
|
@@ -737,19 +801,15 @@
|
|
|
737
801
|
height: var(--size-9);
|
|
738
802
|
}
|
|
739
803
|
|
|
740
|
-
.mobile-thumbnail-add:hover:not(:disabled),
|
|
741
804
|
.microphone-button:hover:not(:disabled) {
|
|
742
|
-
background: var(--button-secondary-background-fill
|
|
743
|
-
border-color: var(--border-color-primary);
|
|
805
|
+
background: var(--button-secondary-background-fill);
|
|
744
806
|
}
|
|
745
807
|
|
|
746
|
-
.mobile-thumbnail-add:disabled,
|
|
747
808
|
.microphone-button:disabled {
|
|
748
809
|
opacity: 0.5;
|
|
749
810
|
cursor: not-allowed;
|
|
750
811
|
}
|
|
751
812
|
|
|
752
|
-
.mobile-thumbnail-add :global(svg),
|
|
753
813
|
.microphone-button :global(svg) {
|
|
754
814
|
width: var(--size-5);
|
|
755
815
|
height: var(--size-5);
|
|
@@ -757,7 +817,6 @@
|
|
|
757
817
|
|
|
758
818
|
.submit-button,
|
|
759
819
|
.stop-button {
|
|
760
|
-
border: var(--size-px) solid var(--border-color-primary);
|
|
761
820
|
background: var(--button-secondary-background-fill);
|
|
762
821
|
cursor: pointer;
|
|
763
822
|
display: flex;
|
|
@@ -768,9 +827,6 @@
|
|
|
768
827
|
height: var(--size-9);
|
|
769
828
|
border-radius: var(--radius-md);
|
|
770
829
|
z-index: var(--layer-1);
|
|
771
|
-
transition:
|
|
772
|
-
background 0.2s var(--easing-standard),
|
|
773
|
-
border-color 0.2s var(--easing-standard);
|
|
774
830
|
}
|
|
775
831
|
|
|
776
832
|
.submit-button:hover:not(:disabled),
|
|
@@ -820,6 +876,112 @@
|
|
|
820
876
|
}
|
|
821
877
|
}
|
|
822
878
|
|
|
879
|
+
.recording-overlay {
|
|
880
|
+
position: absolute;
|
|
881
|
+
top: 0;
|
|
882
|
+
left: 0;
|
|
883
|
+
right: 0;
|
|
884
|
+
bottom: 0;
|
|
885
|
+
background: var(--block-background-fill);
|
|
886
|
+
border-radius: var(--radius-xl);
|
|
887
|
+
display: flex;
|
|
888
|
+
align-items: center;
|
|
889
|
+
justify-content: center;
|
|
890
|
+
z-index: var(--layer-5);
|
|
891
|
+
padding: var(--spacing-lg);
|
|
892
|
+
backdrop-filter: blur(8px);
|
|
893
|
+
animation: fadeIn 0.2s var(--easing-standard);
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
@keyframes fadeIn {
|
|
897
|
+
from {
|
|
898
|
+
opacity: 0;
|
|
899
|
+
}
|
|
900
|
+
to {
|
|
901
|
+
opacity: 1;
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
.recording-content {
|
|
906
|
+
display: flex;
|
|
907
|
+
align-items: center;
|
|
908
|
+
gap: var(--spacing-lg);
|
|
909
|
+
width: 100%;
|
|
910
|
+
max-width: 700px;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
.recording-content :global(.minimal-audio-recorder),
|
|
914
|
+
.recording-content :global(.minimal-audio-player) {
|
|
915
|
+
flex: 1;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
.action-buttons {
|
|
919
|
+
display: flex;
|
|
920
|
+
align-items: center;
|
|
921
|
+
gap: var(--spacing-sm);
|
|
922
|
+
flex-shrink: 0;
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
.stop-button,
|
|
926
|
+
.confirm-button,
|
|
927
|
+
.cancel-button {
|
|
928
|
+
display: flex;
|
|
929
|
+
align-items: center;
|
|
930
|
+
justify-content: center;
|
|
931
|
+
width: var(--size-9);
|
|
932
|
+
height: var(--size-9);
|
|
933
|
+
padding: 0;
|
|
934
|
+
border-radius: var(--radius-md);
|
|
935
|
+
cursor: pointer;
|
|
936
|
+
flex-shrink: 0;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
.stop-button {
|
|
940
|
+
background: var(--button-secondary-background-fill);
|
|
941
|
+
border-color: var(--border-color-primary);
|
|
942
|
+
color: var(--error-500);
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
.stop-button:hover {
|
|
946
|
+
background: var(--button-secondary-background-fill-hover);
|
|
947
|
+
color: var(--error-600);
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
.stop-button:active {
|
|
951
|
+
transform: scale(0.95);
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
.confirm-button {
|
|
955
|
+
background: var(--button-primary-background-fill);
|
|
956
|
+
border-color: var(--button-primary-border-color);
|
|
957
|
+
color: white;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
.confirm-button:hover {
|
|
961
|
+
background: var(--button-primary-background-fill-hover);
|
|
962
|
+
color: var(--button-primary-text-color-hover);
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
.confirm-button:active {
|
|
966
|
+
transform: scale(0.95);
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
.cancel-button {
|
|
970
|
+
background: var(--button-secondary-background-fill);
|
|
971
|
+
color: var(--body-text-color);
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
.cancel-button:hover {
|
|
975
|
+
background: var(--button-secondary-background-fill-hover);
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
.stop-button :global(svg),
|
|
979
|
+
.confirm-button :global(svg),
|
|
980
|
+
.cancel-button :global(svg) {
|
|
981
|
+
width: var(--size-5);
|
|
982
|
+
height: var(--size-5);
|
|
983
|
+
}
|
|
984
|
+
|
|
823
985
|
@media (max-width: 768px) {
|
|
824
986
|
.input-wrapper {
|
|
825
987
|
padding: var(--spacing-xs);
|
|
@@ -831,7 +993,7 @@
|
|
|
831
993
|
}
|
|
832
994
|
|
|
833
995
|
.thumbnail-small,
|
|
834
|
-
.
|
|
996
|
+
.thumbnail-add {
|
|
835
997
|
width: var(--size-9);
|
|
836
998
|
height: var(--size-9);
|
|
837
999
|
}
|