@gradio/image 0.27.0 → 0.28.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.
- package/CHANGELOG.md +14 -0
- package/Example.svelte +9 -3
- package/Index.svelte +26 -49
- package/dist/Example.svelte +9 -3
- package/dist/Example.svelte.d.ts +4 -18
- package/dist/Index.svelte +26 -49
- package/dist/shared/Image.svelte +21 -4
- package/dist/shared/Image.svelte.d.ts +4 -19
- package/dist/shared/ImagePreview.svelte +39 -23
- package/dist/shared/ImagePreview.svelte.d.ts +10 -26
- package/dist/shared/ImageUploader.svelte +97 -63
- package/dist/shared/ImageUploader.svelte.d.ts +19 -42
- package/dist/shared/Webcam.svelte +63 -47
- package/dist/shared/Webcam.svelte.d.ts +11 -27
- package/dist/shared/WebcamPermissions.svelte +2 -5
- package/dist/shared/WebcamPermissions.svelte.d.ts +5 -19
- package/package.json +7 -7
- package/shared/Image.svelte +21 -4
- package/shared/ImagePreview.svelte +39 -23
- package/shared/ImageUploader.svelte +97 -63
- package/shared/Webcam.svelte +63 -47
- package/shared/WebcamPermissions.svelte +2 -5
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { tick, type Snippet } from "svelte";
|
|
3
3
|
import { BlockLabel, IconButtonWrapper, IconButton } from "@gradio/atoms";
|
|
4
4
|
import { Clear, Image as ImageIcon } from "@gradio/icons";
|
|
5
5
|
import { FullscreenButton } from "@gradio/atoms";
|
|
@@ -17,36 +17,80 @@
|
|
|
17
17
|
import Image from "./Image.svelte";
|
|
18
18
|
import type { Base64File, WebcamOptions } from "./types";
|
|
19
19
|
|
|
20
|
-
export let value: null | FileData | Base64File = null;
|
|
21
|
-
export let label: string | undefined = undefined;
|
|
22
|
-
export let show_label: boolean;
|
|
23
|
-
|
|
24
20
|
type source_type = "upload" | "webcam" | "clipboard" | "microphone" | null;
|
|
25
21
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
22
|
+
let {
|
|
23
|
+
value = $bindable<null | FileData | Base64File>(null),
|
|
24
|
+
label = undefined,
|
|
25
|
+
show_label,
|
|
26
|
+
sources = ["upload", "clipboard", "webcam"],
|
|
27
|
+
streaming = false,
|
|
28
|
+
pending = $bindable(false),
|
|
29
|
+
webcam_options,
|
|
30
|
+
selectable = false,
|
|
31
|
+
root,
|
|
32
|
+
i18n,
|
|
33
|
+
max_file_size = null,
|
|
34
|
+
upload,
|
|
35
|
+
stream_handler,
|
|
36
|
+
stream_every,
|
|
37
|
+
time_limit,
|
|
38
|
+
show_fullscreen_button = true,
|
|
39
|
+
stream_state = "closed",
|
|
40
|
+
upload_promise = $bindable<Promise<any> | null>(null),
|
|
41
|
+
onerror,
|
|
42
|
+
uploading = $bindable(false),
|
|
43
|
+
active_source = $bindable<source_type>(null),
|
|
44
|
+
fullscreen = $bindable(false),
|
|
45
|
+
dragging = $bindable(false),
|
|
46
|
+
onchange,
|
|
47
|
+
onstream,
|
|
48
|
+
onclear,
|
|
49
|
+
ondrag,
|
|
50
|
+
onupload,
|
|
51
|
+
onselect,
|
|
52
|
+
onfullscreen,
|
|
53
|
+
onclose_stream,
|
|
54
|
+
children
|
|
55
|
+
}: {
|
|
56
|
+
value?: null | FileData | Base64File;
|
|
57
|
+
label?: string;
|
|
58
|
+
show_label: boolean;
|
|
59
|
+
sources?: source_type[];
|
|
60
|
+
streaming?: boolean;
|
|
61
|
+
pending?: boolean;
|
|
62
|
+
webcam_options: WebcamOptions;
|
|
63
|
+
selectable?: boolean;
|
|
64
|
+
root: string;
|
|
65
|
+
i18n: I18nFormatter;
|
|
66
|
+
max_file_size?: number | null;
|
|
67
|
+
upload: Client["upload"];
|
|
68
|
+
stream_handler: Client["stream"];
|
|
69
|
+
stream_every: number;
|
|
70
|
+
time_limit: number;
|
|
71
|
+
show_fullscreen_button?: boolean;
|
|
72
|
+
stream_state?: "open" | "waiting" | "closed";
|
|
73
|
+
upload_promise?: Promise<any> | null;
|
|
74
|
+
onerror?: (error: string) => void;
|
|
75
|
+
uploading?: boolean;
|
|
76
|
+
active_source?: source_type;
|
|
77
|
+
fullscreen?: boolean;
|
|
78
|
+
dragging?: boolean;
|
|
79
|
+
onchange?: (value?: null | FileData | Base64File) => void;
|
|
80
|
+
onstream?: (value: ValueData) => void;
|
|
81
|
+
onclear?: () => void;
|
|
82
|
+
ondrag?: (dragging: boolean) => void;
|
|
83
|
+
onupload?: () => void;
|
|
84
|
+
onselect?: (value: SelectData) => void;
|
|
85
|
+
onfullscreen?: (fullscreen: boolean) => void;
|
|
86
|
+
onclose_stream?: () => void;
|
|
87
|
+
children?: Snippet;
|
|
88
|
+
} = $props();
|
|
42
89
|
|
|
43
90
|
let upload_input: Upload;
|
|
44
|
-
export let uploading = false;
|
|
45
|
-
export let active_source: source_type = null;
|
|
46
|
-
export let fullscreen = false;
|
|
47
91
|
|
|
48
|
-
let files
|
|
49
|
-
let upload_id
|
|
92
|
+
let files = $state<FileData[]>([]);
|
|
93
|
+
let upload_id = $state("");
|
|
50
94
|
|
|
51
95
|
async function handle_upload(detail: FileData): Promise<void> {
|
|
52
96
|
if (!streaming) {
|
|
@@ -62,14 +106,14 @@
|
|
|
62
106
|
}
|
|
63
107
|
|
|
64
108
|
await tick();
|
|
65
|
-
|
|
109
|
+
onupload?.();
|
|
66
110
|
}
|
|
67
111
|
}
|
|
68
112
|
|
|
69
113
|
function handle_clear(): void {
|
|
70
114
|
value = null;
|
|
71
|
-
|
|
72
|
-
|
|
115
|
+
onclear?.();
|
|
116
|
+
onchange?.(null);
|
|
73
117
|
}
|
|
74
118
|
|
|
75
119
|
function handle_remove_image_click(event: MouseEvent): void {
|
|
@@ -82,7 +126,7 @@
|
|
|
82
126
|
event: "change" | "stream" | "upload"
|
|
83
127
|
): Promise<void> {
|
|
84
128
|
if (event === "stream") {
|
|
85
|
-
|
|
129
|
+
onstream?.({
|
|
86
130
|
value: { url: img_blob } as Base64File,
|
|
87
131
|
is_value_data: true
|
|
88
132
|
});
|
|
@@ -105,39 +149,31 @@
|
|
|
105
149
|
if (event === "change" || event === "upload") {
|
|
106
150
|
value = f?.[0] || null;
|
|
107
151
|
await tick();
|
|
108
|
-
|
|
152
|
+
onchange?.();
|
|
109
153
|
}
|
|
110
154
|
pending = false;
|
|
111
155
|
}
|
|
112
156
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
drag: boolean;
|
|
121
|
-
upload?: never;
|
|
122
|
-
select: SelectData;
|
|
123
|
-
end_stream: never;
|
|
124
|
-
fullscreen: boolean;
|
|
125
|
-
}>();
|
|
126
|
-
|
|
127
|
-
export let dragging = false;
|
|
128
|
-
|
|
129
|
-
$: dispatch("drag", dragging);
|
|
157
|
+
let active_streaming = $derived(streaming && active_source === "webcam");
|
|
158
|
+
$effect(() => {
|
|
159
|
+
if (uploading && !active_streaming) value = null;
|
|
160
|
+
});
|
|
161
|
+
$effect(() => {
|
|
162
|
+
ondrag?.(dragging);
|
|
163
|
+
});
|
|
130
164
|
|
|
131
165
|
function handle_click(evt: MouseEvent): void {
|
|
132
166
|
let coordinates = get_coordinates_of_clicked_image(evt);
|
|
133
167
|
if (coordinates) {
|
|
134
|
-
|
|
168
|
+
onselect?.({ index: coordinates, value: null });
|
|
135
169
|
}
|
|
136
170
|
}
|
|
137
171
|
|
|
138
|
-
|
|
139
|
-
active_source
|
|
140
|
-
|
|
172
|
+
$effect(() => {
|
|
173
|
+
if (!active_source && sources) {
|
|
174
|
+
active_source = sources[0];
|
|
175
|
+
}
|
|
176
|
+
});
|
|
141
177
|
|
|
142
178
|
async function handle_select_source(
|
|
143
179
|
source: (typeof sources)[number]
|
|
@@ -189,7 +225,7 @@
|
|
|
189
225
|
{fullscreen}
|
|
190
226
|
onclick={(is_fullscreen) => {
|
|
191
227
|
fullscreen = is_fullscreen;
|
|
192
|
-
|
|
228
|
+
onfullscreen?.(is_fullscreen);
|
|
193
229
|
}}
|
|
194
230
|
/>
|
|
195
231
|
{/if}
|
|
@@ -205,8 +241,8 @@
|
|
|
205
241
|
class="upload-container"
|
|
206
242
|
class:reduced-height={sources.length > 1}
|
|
207
243
|
style:width={value ? "auto" : "100%"}
|
|
208
|
-
|
|
209
|
-
|
|
244
|
+
ondragover={on_drag_over}
|
|
245
|
+
ondrop={on_drop}
|
|
210
246
|
>
|
|
211
247
|
<Upload
|
|
212
248
|
bind:upload_promise
|
|
@@ -225,7 +261,7 @@
|
|
|
225
261
|
aria_label={i18n("image.drop_to_upload")}
|
|
226
262
|
>
|
|
227
263
|
{#if value === null}
|
|
228
|
-
|
|
264
|
+
{#if children}{@render children()}{/if}
|
|
229
265
|
{/if}
|
|
230
266
|
</Upload>
|
|
231
267
|
{#if active_source === "webcam" && !streaming && pending}
|
|
@@ -234,12 +270,10 @@
|
|
|
234
270
|
<Webcam
|
|
235
271
|
{root}
|
|
236
272
|
{value}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
on:upload={(e) => handle_save(e.detail, "upload")}
|
|
242
|
-
on:close_stream
|
|
273
|
+
oncapture={(detail) => handle_save(detail, "change")}
|
|
274
|
+
onstream={(detail) => handle_save(detail, "stream")}
|
|
275
|
+
{onerror}
|
|
276
|
+
{onclose_stream}
|
|
243
277
|
{stream_state}
|
|
244
278
|
mirror_webcam={webcam_options.mirror}
|
|
245
279
|
{stream_every}
|
|
@@ -254,7 +288,7 @@
|
|
|
254
288
|
{:else if value !== null && !streaming}
|
|
255
289
|
<!-- svelte-ignore a11y-click-events-have-key-events-->
|
|
256
290
|
<!-- svelte-ignore a11y-no-static-element-interactions-->
|
|
257
|
-
<div class:selectable class="image-frame"
|
|
291
|
+
<div class:selectable class="image-frame" onclick={handle_click}>
|
|
258
292
|
<Image src={value.url} restProps={{ alt: value.alt_text }} />
|
|
259
293
|
</div>
|
|
260
294
|
{/if}
|
|
@@ -1,29 +1,13 @@
|
|
|
1
|
+
import { type Snippet } from "svelte";
|
|
1
2
|
import { type SelectData, type I18nFormatter, type ValueData } from "@gradio/utils";
|
|
2
3
|
import { FileData, type Client } from "@gradio/client";
|
|
3
4
|
import type { Base64File, WebcamOptions } from "./types";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
$$bindings?: Bindings;
|
|
7
|
-
} & Exports;
|
|
8
|
-
(internal: unknown, props: Props & {
|
|
9
|
-
$$events?: Events;
|
|
10
|
-
$$slots?: Slots;
|
|
11
|
-
}): Exports & {
|
|
12
|
-
$set?: any;
|
|
13
|
-
$on?: any;
|
|
14
|
-
};
|
|
15
|
-
z_$$bindings?: Bindings;
|
|
16
|
-
}
|
|
17
|
-
type $$__sveltets_2_PropsWithChildren<Props, Slots> = Props & (Slots extends {
|
|
18
|
-
default: any;
|
|
19
|
-
} ? Props extends Record<string, never> ? any : {
|
|
20
|
-
children?: any;
|
|
21
|
-
} : {});
|
|
22
|
-
declare const ImageUploader: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWithChildren<{
|
|
5
|
+
type source_type = "upload" | "webcam" | "clipboard" | "microphone" | null;
|
|
6
|
+
type $$ComponentProps = {
|
|
23
7
|
value?: null | FileData | Base64File;
|
|
24
|
-
label?: string
|
|
8
|
+
label?: string;
|
|
25
9
|
show_label: boolean;
|
|
26
|
-
sources?:
|
|
10
|
+
sources?: source_type[];
|
|
27
11
|
streaming?: boolean;
|
|
28
12
|
pending?: boolean;
|
|
29
13
|
webcam_options: WebcamOptions;
|
|
@@ -38,28 +22,21 @@ declare const ImageUploader: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_P
|
|
|
38
22
|
show_fullscreen_button?: boolean;
|
|
39
23
|
stream_state?: "open" | "waiting" | "closed";
|
|
40
24
|
upload_promise?: Promise<any> | null;
|
|
41
|
-
onerror?: (
|
|
25
|
+
onerror?: (error: string) => void;
|
|
42
26
|
uploading?: boolean;
|
|
43
|
-
active_source?:
|
|
27
|
+
active_source?: source_type;
|
|
44
28
|
fullscreen?: boolean;
|
|
45
29
|
dragging?: boolean;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
fullscreen: CustomEvent<boolean>;
|
|
59
|
-
} & {
|
|
60
|
-
[evt: string]: CustomEvent<any>;
|
|
61
|
-
}, {
|
|
62
|
-
default: {};
|
|
63
|
-
}, {}, string>;
|
|
64
|
-
type ImageUploader = InstanceType<typeof ImageUploader>;
|
|
30
|
+
onchange?: (value?: null | FileData | Base64File) => void;
|
|
31
|
+
onstream?: (value: ValueData) => void;
|
|
32
|
+
onclear?: () => void;
|
|
33
|
+
ondrag?: (dragging: boolean) => void;
|
|
34
|
+
onupload?: () => void;
|
|
35
|
+
onselect?: (value: SelectData) => void;
|
|
36
|
+
onfullscreen?: (fullscreen: boolean) => void;
|
|
37
|
+
onclose_stream?: () => void;
|
|
38
|
+
children?: Snippet;
|
|
39
|
+
};
|
|
40
|
+
declare const ImageUploader: import("svelte").Component<$$ComponentProps, {}, "pending" | "value" | "active_source" | "fullscreen" | "uploading" | "dragging" | "upload_promise">;
|
|
41
|
+
type ImageUploader = ReturnType<typeof ImageUploader>;
|
|
65
42
|
export default ImageUploader;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { onDestroy, onMount } from "svelte";
|
|
3
3
|
import {
|
|
4
4
|
Camera,
|
|
5
5
|
Circle,
|
|
@@ -20,33 +20,51 @@
|
|
|
20
20
|
import type { Base64File } from "./types";
|
|
21
21
|
|
|
22
22
|
let video_source: HTMLVideoElement;
|
|
23
|
-
let available_video_devices
|
|
24
|
-
let selected_device
|
|
25
|
-
|
|
26
|
-
export let stream_state: "open" | "waiting" | "closed" = "closed";
|
|
23
|
+
let available_video_devices = $state<MediaDeviceInfo[]>([]);
|
|
24
|
+
let selected_device = $state<MediaDeviceInfo | null>(null);
|
|
27
25
|
|
|
28
26
|
let canvas: HTMLCanvasElement;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
27
|
+
let {
|
|
28
|
+
stream_state = "closed",
|
|
29
|
+
streaming = false,
|
|
30
|
+
pending = false,
|
|
31
|
+
root = "",
|
|
32
|
+
stream_every = 1,
|
|
33
|
+
mode = "image",
|
|
34
|
+
mirror_webcam,
|
|
35
|
+
include_audio,
|
|
36
|
+
webcam_constraints = null,
|
|
37
|
+
i18n,
|
|
38
|
+
upload,
|
|
39
|
+
value = null,
|
|
40
|
+
time_limit = null,
|
|
41
|
+
onstream,
|
|
42
|
+
oncapture,
|
|
43
|
+
onerror,
|
|
44
|
+
onstart_recording,
|
|
45
|
+
onstop_recording,
|
|
46
|
+
onclose_stream
|
|
47
|
+
}: {
|
|
48
|
+
stream_state?: "open" | "waiting" | "closed";
|
|
49
|
+
streaming?: boolean;
|
|
50
|
+
pending?: boolean;
|
|
51
|
+
root?: string;
|
|
52
|
+
stream_every?: number;
|
|
53
|
+
mode?: "image" | "video";
|
|
54
|
+
mirror_webcam: boolean;
|
|
55
|
+
include_audio: boolean;
|
|
56
|
+
webcam_constraints?: { [key: string]: any } | null;
|
|
57
|
+
i18n: I18nFormatter;
|
|
58
|
+
upload: Client["upload"];
|
|
59
|
+
value?: FileData | null | Base64File;
|
|
60
|
+
time_limit?: number | null;
|
|
61
|
+
onstream?: (value: Blob | string) => void;
|
|
62
|
+
oncapture?: (value: FileData | Blob | null) => void;
|
|
63
|
+
onerror?: (error: string) => void;
|
|
64
|
+
onstart_recording?: () => void;
|
|
65
|
+
onstop_recording?: () => void;
|
|
66
|
+
onclose_stream?: () => void;
|
|
67
|
+
} = $props();
|
|
50
68
|
|
|
51
69
|
onMount(() => {
|
|
52
70
|
canvas = document.createElement("canvas");
|
|
@@ -101,11 +119,11 @@
|
|
|
101
119
|
});
|
|
102
120
|
|
|
103
121
|
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
|
|
104
|
-
|
|
122
|
+
onerror?.(i18n("image.no_webcam_support"));
|
|
105
123
|
}
|
|
106
124
|
} catch (err) {
|
|
107
125
|
if (err instanceof DOMException && err.name == "NotAllowedError") {
|
|
108
|
-
|
|
126
|
+
onerror?.(i18n("image.allow_webcam_access"));
|
|
109
127
|
} else {
|
|
110
128
|
throw err;
|
|
111
129
|
}
|
|
@@ -139,13 +157,17 @@
|
|
|
139
157
|
}
|
|
140
158
|
if (streaming) {
|
|
141
159
|
const image_data = canvas.toDataURL("image/jpeg");
|
|
142
|
-
|
|
160
|
+
onstream?.(image_data);
|
|
143
161
|
return;
|
|
144
162
|
}
|
|
145
163
|
|
|
146
164
|
canvas.toBlob(
|
|
147
165
|
(blob) => {
|
|
148
|
-
|
|
166
|
+
if (streaming) {
|
|
167
|
+
onstream?.(blob as Blob);
|
|
168
|
+
} else {
|
|
169
|
+
oncapture?.(blob);
|
|
170
|
+
}
|
|
149
171
|
},
|
|
150
172
|
`image/${streaming ? "jpeg" : "png"}`,
|
|
151
173
|
0.8
|
|
@@ -153,7 +175,7 @@
|
|
|
153
175
|
}
|
|
154
176
|
}
|
|
155
177
|
|
|
156
|
-
let recording = false;
|
|
178
|
+
let recording = $state(false);
|
|
157
179
|
let recorded_blobs: BlobPart[] = [];
|
|
158
180
|
let stream: MediaStream;
|
|
159
181
|
let mimeType: string;
|
|
@@ -174,13 +196,13 @@
|
|
|
174
196
|
let val_ = (
|
|
175
197
|
(await upload(val, root))?.filter(Boolean) as FileData[]
|
|
176
198
|
)[0];
|
|
177
|
-
|
|
178
|
-
|
|
199
|
+
oncapture?.(val_);
|
|
200
|
+
onstop_recording?.();
|
|
179
201
|
}
|
|
180
202
|
};
|
|
181
203
|
ReaderObj.readAsDataURL(video_blob);
|
|
182
204
|
} else if (typeof MediaRecorder !== "undefined") {
|
|
183
|
-
|
|
205
|
+
onstart_recording?.();
|
|
184
206
|
recorded_blobs = [];
|
|
185
207
|
let validMimeTypes = ["video/webm", "video/mp4"];
|
|
186
208
|
for (let validMimeType of validMimeTypes) {
|
|
@@ -204,7 +226,7 @@
|
|
|
204
226
|
recording = !recording;
|
|
205
227
|
}
|
|
206
228
|
|
|
207
|
-
let webcam_accessed = false;
|
|
229
|
+
let webcam_accessed = $state(false);
|
|
208
230
|
|
|
209
231
|
function record_video_or_photo({
|
|
210
232
|
destroy
|
|
@@ -222,11 +244,11 @@
|
|
|
222
244
|
}
|
|
223
245
|
|
|
224
246
|
if (!recording && stream) {
|
|
225
|
-
|
|
247
|
+
onclose_stream?.();
|
|
226
248
|
}
|
|
227
249
|
}
|
|
228
250
|
|
|
229
|
-
let options_open = false;
|
|
251
|
+
let options_open = $state(false);
|
|
230
252
|
|
|
231
253
|
export function click_outside(node: Node, cb: any): any {
|
|
232
254
|
const handle_click = (event: MouseEvent): void => {
|
|
@@ -281,12 +303,12 @@
|
|
|
281
303
|
title="grant webcam access"
|
|
282
304
|
style="height: 100%"
|
|
283
305
|
>
|
|
284
|
-
<WebcamPermissions
|
|
306
|
+
<WebcamPermissions onclick={async () => access_webcam()} />
|
|
285
307
|
</div>
|
|
286
308
|
{:else}
|
|
287
309
|
<div class="button-wrap">
|
|
288
310
|
<button
|
|
289
|
-
|
|
311
|
+
onclick={() => record_video_or_photo()}
|
|
290
312
|
aria-label={mode === "image" ? "capture photo" : "start recording"}
|
|
291
313
|
>
|
|
292
314
|
{#if mode === "video" || streaming}
|
|
@@ -321,7 +343,7 @@
|
|
|
321
343
|
{#if !recording}
|
|
322
344
|
<button
|
|
323
345
|
class="icon"
|
|
324
|
-
|
|
346
|
+
onclick={() => (options_open = true)}
|
|
325
347
|
aria-label="select input source"
|
|
326
348
|
>
|
|
327
349
|
<DropdownArrow />
|
|
@@ -333,14 +355,8 @@
|
|
|
333
355
|
class="select-wrap"
|
|
334
356
|
aria-label="select source"
|
|
335
357
|
use:click_outside={handle_click_outside}
|
|
336
|
-
|
|
358
|
+
onchange={handle_device_change}
|
|
337
359
|
>
|
|
338
|
-
<!-- <button
|
|
339
|
-
class="inset-icon"
|
|
340
|
-
on:click|stopPropagation={() => (options_open = false)}
|
|
341
|
-
>
|
|
342
|
-
<DropdownArrow />
|
|
343
|
-
</button> -->
|
|
344
360
|
{#if available_video_devices.length === 0}
|
|
345
361
|
<option value="">{i18n("common.no_devices")}</option>
|
|
346
362
|
{:else}
|
|
@@ -1,20 +1,7 @@
|
|
|
1
1
|
import type { I18nFormatter } from "@gradio/utils";
|
|
2
2
|
import { type FileData, type Client } from "@gradio/client";
|
|
3
3
|
import type { Base64File } from "./types";
|
|
4
|
-
|
|
5
|
-
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
6
|
-
$$bindings?: Bindings;
|
|
7
|
-
} & Exports;
|
|
8
|
-
(internal: unknown, props: Props & {
|
|
9
|
-
$$events?: Events;
|
|
10
|
-
$$slots?: Slots;
|
|
11
|
-
}): Exports & {
|
|
12
|
-
$set?: any;
|
|
13
|
-
$on?: any;
|
|
14
|
-
};
|
|
15
|
-
z_$$bindings?: Bindings;
|
|
16
|
-
}
|
|
17
|
-
declare const Webcam: $$__sveltets_2_IsomorphicComponent<{
|
|
4
|
+
type $$ComponentProps = {
|
|
18
5
|
stream_state?: "open" | "waiting" | "closed";
|
|
19
6
|
streaming?: boolean;
|
|
20
7
|
pending?: boolean;
|
|
@@ -30,18 +17,15 @@ declare const Webcam: $$__sveltets_2_IsomorphicComponent<{
|
|
|
30
17
|
upload: Client["upload"];
|
|
31
18
|
value?: FileData | null | Base64File;
|
|
32
19
|
time_limit?: number | null;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
} & {
|
|
42
|
-
[evt: string]: CustomEvent<any>;
|
|
43
|
-
}, {}, {
|
|
20
|
+
onstream?: (value: Blob | string) => void;
|
|
21
|
+
oncapture?: (value: FileData | Blob | null) => void;
|
|
22
|
+
onerror?: (error: string) => void;
|
|
23
|
+
onstart_recording?: () => void;
|
|
24
|
+
onstop_recording?: () => void;
|
|
25
|
+
onclose_stream?: () => void;
|
|
26
|
+
};
|
|
27
|
+
declare const Webcam: import("svelte").Component<$$ComponentProps, {
|
|
44
28
|
click_outside: (node: Node, cb: any) => any;
|
|
45
|
-
},
|
|
46
|
-
type Webcam =
|
|
29
|
+
}, "">;
|
|
30
|
+
type Webcam = ReturnType<typeof Webcam>;
|
|
47
31
|
export default Webcam;
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { Webcam } from "@gradio/icons";
|
|
3
|
-
import { createEventDispatcher } from "svelte";
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
click: undefined;
|
|
7
|
-
}>();
|
|
4
|
+
let { onclick }: { onclick?: () => void } = $props();
|
|
8
5
|
</script>
|
|
9
6
|
|
|
10
|
-
<button style:height="100%"
|
|
7
|
+
<button style:height="100%" {onclick}>
|
|
11
8
|
<div class="wrap">
|
|
12
9
|
<span class="icon-wrap">
|
|
13
10
|
<Webcam />
|
|
@@ -1,20 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
$$events?: Events;
|
|
7
|
-
$$slots?: Slots;
|
|
8
|
-
}): Exports & {
|
|
9
|
-
$set?: any;
|
|
10
|
-
$on?: any;
|
|
11
|
-
};
|
|
12
|
-
z_$$bindings?: Bindings;
|
|
13
|
-
}
|
|
14
|
-
declare const WebcamPermissions: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
-
click: CustomEvent<undefined>;
|
|
16
|
-
} & {
|
|
17
|
-
[evt: string]: CustomEvent<any>;
|
|
18
|
-
}, {}, {}, string>;
|
|
19
|
-
type WebcamPermissions = InstanceType<typeof WebcamPermissions>;
|
|
1
|
+
type $$ComponentProps = {
|
|
2
|
+
onclick?: () => void;
|
|
3
|
+
};
|
|
4
|
+
declare const WebcamPermissions: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
5
|
+
type WebcamPermissions = ReturnType<typeof WebcamPermissions>;
|
|
20
6
|
export default WebcamPermissions;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gradio/image",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "Gradio UI packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "",
|
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
"cropperjs": "^2.0.1",
|
|
11
11
|
"lazy-brush": "^2.0.2",
|
|
12
12
|
"resize-observer-polyfill": "^1.5.1",
|
|
13
|
-
"@gradio/atoms": "^0.
|
|
14
|
-
"@gradio/
|
|
15
|
-
"@gradio/
|
|
16
|
-
"@gradio/
|
|
17
|
-
"@gradio/
|
|
18
|
-
"@gradio/
|
|
13
|
+
"@gradio/atoms": "^0.26.0",
|
|
14
|
+
"@gradio/statustracker": "^0.15.1",
|
|
15
|
+
"@gradio/client": "^2.3.1",
|
|
16
|
+
"@gradio/icons": "^0.16.0",
|
|
17
|
+
"@gradio/upload": "^0.18.1",
|
|
18
|
+
"@gradio/utils": "^0.13.0"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@gradio/preview": "^0.16.2"
|