@gradio/upload 0.12.3 → 0.12.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/CHANGELOG.md +14 -0
- package/dist/src/ModifyUpload.svelte +62 -0
- package/dist/src/ModifyUpload.svelte.d.ts +25 -0
- package/dist/src/Upload.svelte +298 -0
- package/dist/src/Upload.svelte.d.ts +51 -0
- package/dist/src/UploadProgress.svelte +172 -0
- package/dist/src/UploadProgress.svelte.d.ts +22 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +2 -0
- package/package.json +14 -7
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# @gradio/upload
|
2
2
|
|
3
|
+
## 0.12.4
|
4
|
+
|
5
|
+
### Fixes
|
6
|
+
|
7
|
+
- [#9163](https://github.com/gradio-app/gradio/pull/9163) [`2b6cbf2`](https://github.com/gradio-app/gradio/commit/2b6cbf25908e42cf027324e54ef2cc0baad11a91) - fix exports and generate types. Thanks @pngwn!
|
8
|
+
|
9
|
+
### Dependency updates
|
10
|
+
|
11
|
+
- @gradio/utils@0.6.1
|
12
|
+
- @gradio/atoms@0.8.1
|
13
|
+
- @gradio/icons@0.7.2
|
14
|
+
- @gradio/wasm@0.13.1
|
15
|
+
- @gradio/client@1.5.2
|
16
|
+
|
3
17
|
## 0.12.3
|
4
18
|
|
5
19
|
### Features
|
@@ -0,0 +1,62 @@
|
|
1
|
+
<script>import { IconButton } from "@gradio/atoms";
|
2
|
+
import { Edit, Clear, Undo, Download } from "@gradio/icons";
|
3
|
+
import { DownloadLink } from "@gradio/wasm/svelte";
|
4
|
+
import { createEventDispatcher } from "svelte";
|
5
|
+
export let editable = false;
|
6
|
+
export let undoable = false;
|
7
|
+
export let download = null;
|
8
|
+
export let absolute = true;
|
9
|
+
export let i18n;
|
10
|
+
const dispatch = createEventDispatcher();
|
11
|
+
</script>
|
12
|
+
|
13
|
+
<div
|
14
|
+
class:not-absolute={!absolute}
|
15
|
+
style:position={absolute ? "absolute" : "static"}
|
16
|
+
>
|
17
|
+
{#if editable}
|
18
|
+
<IconButton
|
19
|
+
Icon={Edit}
|
20
|
+
label={i18n("common.edit")}
|
21
|
+
on:click={() => dispatch("edit")}
|
22
|
+
/>
|
23
|
+
{/if}
|
24
|
+
|
25
|
+
{#if undoable}
|
26
|
+
<IconButton
|
27
|
+
Icon={Undo}
|
28
|
+
label={i18n("common.undo")}
|
29
|
+
on:click={() => dispatch("undo")}
|
30
|
+
/>
|
31
|
+
{/if}
|
32
|
+
|
33
|
+
{#if download}
|
34
|
+
<DownloadLink href={download} download>
|
35
|
+
<IconButton Icon={Download} label={i18n("common.download")} />
|
36
|
+
</DownloadLink>
|
37
|
+
{/if}
|
38
|
+
|
39
|
+
<IconButton
|
40
|
+
Icon={Clear}
|
41
|
+
label={i18n("common.clear")}
|
42
|
+
on:click={(event) => {
|
43
|
+
dispatch("clear");
|
44
|
+
event.stopPropagation();
|
45
|
+
}}
|
46
|
+
/>
|
47
|
+
</div>
|
48
|
+
|
49
|
+
<style>
|
50
|
+
div {
|
51
|
+
display: flex;
|
52
|
+
top: var(--size-2);
|
53
|
+
right: var(--size-2);
|
54
|
+
justify-content: flex-end;
|
55
|
+
gap: var(--spacing-sm);
|
56
|
+
z-index: var(--layer-1);
|
57
|
+
}
|
58
|
+
|
59
|
+
.not-absolute {
|
60
|
+
margin: var(--size-1);
|
61
|
+
}
|
62
|
+
</style>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
2
|
+
import type { I18nFormatter } from "@gradio/utils";
|
3
|
+
declare const __propDef: {
|
4
|
+
props: {
|
5
|
+
editable?: boolean | undefined;
|
6
|
+
undoable?: boolean | undefined;
|
7
|
+
download?: (string | null) | undefined;
|
8
|
+
absolute?: boolean | undefined;
|
9
|
+
i18n: I18nFormatter;
|
10
|
+
};
|
11
|
+
events: {
|
12
|
+
edit?: CustomEvent<undefined> | undefined;
|
13
|
+
clear?: CustomEvent<undefined> | undefined;
|
14
|
+
undo?: CustomEvent<undefined> | undefined;
|
15
|
+
} & {
|
16
|
+
[evt: string]: CustomEvent<any>;
|
17
|
+
};
|
18
|
+
slots: {};
|
19
|
+
};
|
20
|
+
export type ModifyUploadProps = typeof __propDef.props;
|
21
|
+
export type ModifyUploadEvents = typeof __propDef.events;
|
22
|
+
export type ModifyUploadSlots = typeof __propDef.slots;
|
23
|
+
export default class ModifyUpload extends SvelteComponent<ModifyUploadProps, ModifyUploadEvents, ModifyUploadSlots> {
|
24
|
+
}
|
25
|
+
export {};
|
@@ -0,0 +1,298 @@
|
|
1
|
+
<script>import { createEventDispatcher, tick, getContext } from "svelte";
|
2
|
+
import { prepare_files } from "@gradio/client";
|
3
|
+
import { _ } from "svelte-i18n";
|
4
|
+
import UploadProgress from "./UploadProgress.svelte";
|
5
|
+
export let filetype = null;
|
6
|
+
export let dragging = false;
|
7
|
+
export let boundedheight = true;
|
8
|
+
export let center = true;
|
9
|
+
export let flex = true;
|
10
|
+
export let file_count = "single";
|
11
|
+
export let disable_click = false;
|
12
|
+
export let root;
|
13
|
+
export let hidden = false;
|
14
|
+
export let format = "file";
|
15
|
+
export let uploading = false;
|
16
|
+
export let hidden_upload = null;
|
17
|
+
export let show_progress = true;
|
18
|
+
export let max_file_size = null;
|
19
|
+
export let upload;
|
20
|
+
export let stream_handler;
|
21
|
+
let upload_id;
|
22
|
+
let file_data;
|
23
|
+
let accept_file_types;
|
24
|
+
let use_post_upload_validation = null;
|
25
|
+
const get_ios = () => {
|
26
|
+
if (typeof navigator !== "undefined") {
|
27
|
+
const userAgent = navigator.userAgent.toLowerCase();
|
28
|
+
return userAgent.indexOf("iphone") > -1 || userAgent.indexOf("ipad") > -1;
|
29
|
+
}
|
30
|
+
return false;
|
31
|
+
};
|
32
|
+
$:
|
33
|
+
ios = get_ios();
|
34
|
+
const dispatch = createEventDispatcher();
|
35
|
+
const validFileTypes = ["image", "video", "audio", "text", "file"];
|
36
|
+
const process_file_type = (type) => {
|
37
|
+
if (ios && type.startsWith(".")) {
|
38
|
+
use_post_upload_validation = true;
|
39
|
+
return type;
|
40
|
+
}
|
41
|
+
if (ios && type.includes("file/*")) {
|
42
|
+
return "*";
|
43
|
+
}
|
44
|
+
if (type.startsWith(".") || type.endsWith("/*")) {
|
45
|
+
return type;
|
46
|
+
}
|
47
|
+
if (validFileTypes.includes(type)) {
|
48
|
+
return type + "/*";
|
49
|
+
}
|
50
|
+
return "." + type;
|
51
|
+
};
|
52
|
+
$:
|
53
|
+
if (filetype == null) {
|
54
|
+
accept_file_types = null;
|
55
|
+
} else if (typeof filetype === "string") {
|
56
|
+
accept_file_types = process_file_type(filetype);
|
57
|
+
} else if (ios && filetype.includes("file/*")) {
|
58
|
+
accept_file_types = "*";
|
59
|
+
} else {
|
60
|
+
filetype = filetype.map(process_file_type);
|
61
|
+
accept_file_types = filetype.join(", ");
|
62
|
+
}
|
63
|
+
function updateDragging() {
|
64
|
+
dragging = !dragging;
|
65
|
+
}
|
66
|
+
export function paste_clipboard() {
|
67
|
+
navigator.clipboard.read().then(async (items) => {
|
68
|
+
for (let i = 0; i < items.length; i++) {
|
69
|
+
const type = items[i].types.find((t) => t.startsWith("image/"));
|
70
|
+
if (type) {
|
71
|
+
items[i].getType(type).then(async (blob) => {
|
72
|
+
const file = new File(
|
73
|
+
[blob],
|
74
|
+
`clipboard.${type.replace("image/", "")}`
|
75
|
+
);
|
76
|
+
await load_files([file]);
|
77
|
+
});
|
78
|
+
break;
|
79
|
+
}
|
80
|
+
}
|
81
|
+
});
|
82
|
+
}
|
83
|
+
export function open_file_upload() {
|
84
|
+
if (disable_click)
|
85
|
+
return;
|
86
|
+
if (hidden_upload) {
|
87
|
+
hidden_upload.value = "";
|
88
|
+
hidden_upload.click();
|
89
|
+
}
|
90
|
+
}
|
91
|
+
async function handle_upload(file_data2) {
|
92
|
+
await tick();
|
93
|
+
upload_id = Math.random().toString(36).substring(2, 15);
|
94
|
+
uploading = true;
|
95
|
+
try {
|
96
|
+
const _file_data = await upload(
|
97
|
+
file_data2,
|
98
|
+
root,
|
99
|
+
upload_id,
|
100
|
+
max_file_size ?? Infinity
|
101
|
+
);
|
102
|
+
dispatch("load", file_count === "single" ? _file_data?.[0] : _file_data);
|
103
|
+
uploading = false;
|
104
|
+
return _file_data || [];
|
105
|
+
} catch (e) {
|
106
|
+
dispatch("error", e.message);
|
107
|
+
uploading = false;
|
108
|
+
return [];
|
109
|
+
}
|
110
|
+
}
|
111
|
+
export async function load_files(files) {
|
112
|
+
if (!files.length) {
|
113
|
+
return;
|
114
|
+
}
|
115
|
+
let _files = files.map(
|
116
|
+
(f) => new File([f], f instanceof File ? f.name : "file", { type: f.type })
|
117
|
+
);
|
118
|
+
if (ios && use_post_upload_validation) {
|
119
|
+
_files = _files.filter((file) => {
|
120
|
+
if (is_valid_file(file)) {
|
121
|
+
return true;
|
122
|
+
}
|
123
|
+
dispatch(
|
124
|
+
"error",
|
125
|
+
`Invalid file type: ${file.name}. Only ${filetype} allowed.`
|
126
|
+
);
|
127
|
+
return false;
|
128
|
+
});
|
129
|
+
if (_files.length === 0) {
|
130
|
+
return [];
|
131
|
+
}
|
132
|
+
}
|
133
|
+
file_data = await prepare_files(_files);
|
134
|
+
return await handle_upload(file_data);
|
135
|
+
}
|
136
|
+
function is_valid_file(file) {
|
137
|
+
if (!filetype)
|
138
|
+
return true;
|
139
|
+
const allowed_types = Array.isArray(filetype) ? filetype : [filetype];
|
140
|
+
return allowed_types.some((type) => {
|
141
|
+
const processed_type = process_file_type(type);
|
142
|
+
if (processed_type.startsWith(".")) {
|
143
|
+
return file.name.toLowerCase().endsWith(processed_type.toLowerCase());
|
144
|
+
}
|
145
|
+
if (processed_type === "*") {
|
146
|
+
return true;
|
147
|
+
}
|
148
|
+
if (processed_type.endsWith("/*")) {
|
149
|
+
const [category] = processed_type.split("/");
|
150
|
+
return file.type.startsWith(category + "/");
|
151
|
+
}
|
152
|
+
return file.type === processed_type;
|
153
|
+
});
|
154
|
+
}
|
155
|
+
async function load_files_from_upload(e) {
|
156
|
+
const target = e.target;
|
157
|
+
if (!target.files)
|
158
|
+
return;
|
159
|
+
if (format != "blob") {
|
160
|
+
await load_files(Array.from(target.files));
|
161
|
+
} else {
|
162
|
+
if (file_count === "single") {
|
163
|
+
dispatch("load", target.files[0]);
|
164
|
+
return;
|
165
|
+
}
|
166
|
+
dispatch("load", target.files);
|
167
|
+
}
|
168
|
+
}
|
169
|
+
function is_valid_mimetype(file_accept, uploaded_file_extension, uploaded_file_type) {
|
170
|
+
if (!file_accept || file_accept === "*" || file_accept === "file/*" || Array.isArray(file_accept) && file_accept.some((accept) => accept === "*" || accept === "file/*")) {
|
171
|
+
return true;
|
172
|
+
}
|
173
|
+
let acceptArray;
|
174
|
+
if (typeof file_accept === "string") {
|
175
|
+
acceptArray = file_accept.split(",").map((s) => s.trim());
|
176
|
+
} else if (Array.isArray(file_accept)) {
|
177
|
+
acceptArray = file_accept;
|
178
|
+
} else {
|
179
|
+
return false;
|
180
|
+
}
|
181
|
+
return acceptArray.includes(uploaded_file_extension) || acceptArray.some((type) => {
|
182
|
+
const [category] = type.split("/").map((s) => s.trim());
|
183
|
+
return type.endsWith("/*") && uploaded_file_type.startsWith(category + "/");
|
184
|
+
});
|
185
|
+
}
|
186
|
+
async function loadFilesFromDrop(e) {
|
187
|
+
dragging = false;
|
188
|
+
if (!e.dataTransfer?.files)
|
189
|
+
return;
|
190
|
+
const files_to_load = Array.from(e.dataTransfer.files).filter((file) => {
|
191
|
+
const file_extension = "." + file.name.split(".").pop();
|
192
|
+
if (file_extension && is_valid_mimetype(accept_file_types, file_extension, file.type)) {
|
193
|
+
return true;
|
194
|
+
}
|
195
|
+
if (file_extension && Array.isArray(filetype) ? filetype.includes(file_extension) : file_extension === filetype) {
|
196
|
+
return true;
|
197
|
+
}
|
198
|
+
dispatch("error", `Invalid file type only ${filetype} allowed.`);
|
199
|
+
return false;
|
200
|
+
});
|
201
|
+
if (format != "blob") {
|
202
|
+
await load_files(files_to_load);
|
203
|
+
} else {
|
204
|
+
if (file_count === "single") {
|
205
|
+
dispatch("load", files_to_load[0]);
|
206
|
+
return;
|
207
|
+
}
|
208
|
+
dispatch("load", files_to_load);
|
209
|
+
}
|
210
|
+
}
|
211
|
+
</script>
|
212
|
+
|
213
|
+
{#if filetype === "clipboard"}
|
214
|
+
<button
|
215
|
+
class:hidden
|
216
|
+
class:center
|
217
|
+
class:boundedheight
|
218
|
+
class:flex
|
219
|
+
style:height="100%"
|
220
|
+
tabindex={hidden ? -1 : 0}
|
221
|
+
on:click={paste_clipboard}
|
222
|
+
>
|
223
|
+
<slot />
|
224
|
+
</button>
|
225
|
+
{:else if uploading && show_progress}
|
226
|
+
{#if !hidden}
|
227
|
+
<UploadProgress {root} {upload_id} files={file_data} {stream_handler} />
|
228
|
+
{/if}
|
229
|
+
{:else}
|
230
|
+
<button
|
231
|
+
class:hidden
|
232
|
+
class:center
|
233
|
+
class:boundedheight
|
234
|
+
class:flex
|
235
|
+
class:disable_click
|
236
|
+
style:height="100%"
|
237
|
+
tabindex={hidden ? -1 : 0}
|
238
|
+
on:drag|preventDefault|stopPropagation
|
239
|
+
on:dragstart|preventDefault|stopPropagation
|
240
|
+
on:dragend|preventDefault|stopPropagation
|
241
|
+
on:dragover|preventDefault|stopPropagation
|
242
|
+
on:dragenter|preventDefault|stopPropagation
|
243
|
+
on:dragleave|preventDefault|stopPropagation
|
244
|
+
on:drop|preventDefault|stopPropagation
|
245
|
+
on:click={open_file_upload}
|
246
|
+
on:drop={loadFilesFromDrop}
|
247
|
+
on:dragenter={updateDragging}
|
248
|
+
on:dragleave={updateDragging}
|
249
|
+
>
|
250
|
+
<slot />
|
251
|
+
<input
|
252
|
+
aria-label="file upload"
|
253
|
+
data-testid="file-upload"
|
254
|
+
type="file"
|
255
|
+
bind:this={hidden_upload}
|
256
|
+
on:change={load_files_from_upload}
|
257
|
+
accept={accept_file_types || undefined}
|
258
|
+
multiple={file_count === "multiple" || undefined}
|
259
|
+
webkitdirectory={file_count === "directory" || undefined}
|
260
|
+
mozdirectory={file_count === "directory" || undefined}
|
261
|
+
/>
|
262
|
+
</button>
|
263
|
+
{/if}
|
264
|
+
|
265
|
+
<style>
|
266
|
+
button {
|
267
|
+
cursor: pointer;
|
268
|
+
width: var(--size-full);
|
269
|
+
}
|
270
|
+
|
271
|
+
.hidden {
|
272
|
+
display: none;
|
273
|
+
position: absolute;
|
274
|
+
flex-grow: 0;
|
275
|
+
}
|
276
|
+
|
277
|
+
.hidden :global(svg) {
|
278
|
+
display: none;
|
279
|
+
}
|
280
|
+
|
281
|
+
.center {
|
282
|
+
display: flex;
|
283
|
+
justify-content: center;
|
284
|
+
}
|
285
|
+
.flex {
|
286
|
+
display: flex;
|
287
|
+
flex-direction: column;
|
288
|
+
justify-content: center;
|
289
|
+
align-items: center;
|
290
|
+
}
|
291
|
+
.disable_click {
|
292
|
+
cursor: default;
|
293
|
+
}
|
294
|
+
|
295
|
+
input {
|
296
|
+
display: none;
|
297
|
+
}
|
298
|
+
</style>
|
@@ -0,0 +1,51 @@
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
2
|
+
import type { FileData } from "@gradio/client";
|
3
|
+
import { type Client } from "@gradio/client";
|
4
|
+
declare const __propDef: {
|
5
|
+
props: {
|
6
|
+
filetype?: (string | string[] | null) | undefined;
|
7
|
+
dragging?: boolean | undefined;
|
8
|
+
boundedheight?: boolean | undefined;
|
9
|
+
center?: boolean | undefined;
|
10
|
+
flex?: boolean | undefined;
|
11
|
+
file_count?: ("single" | "multiple" | "directory") | undefined;
|
12
|
+
disable_click?: boolean | undefined;
|
13
|
+
root: string;
|
14
|
+
hidden?: boolean | undefined;
|
15
|
+
format?: ("blob" | "file") | undefined;
|
16
|
+
uploading?: boolean | undefined;
|
17
|
+
hidden_upload?: (HTMLInputElement | null) | undefined;
|
18
|
+
show_progress?: boolean | undefined;
|
19
|
+
max_file_size?: (number | null) | undefined;
|
20
|
+
upload: Client["upload"];
|
21
|
+
stream_handler: Client["stream"];
|
22
|
+
paste_clipboard?: (() => void) | undefined;
|
23
|
+
open_file_upload?: (() => void) | undefined;
|
24
|
+
load_files?: ((files: File[] | Blob[]) => Promise<(FileData | null)[] | void>) | undefined;
|
25
|
+
};
|
26
|
+
events: {
|
27
|
+
drag: DragEvent;
|
28
|
+
dragstart: DragEvent;
|
29
|
+
dragend: DragEvent;
|
30
|
+
dragover: DragEvent;
|
31
|
+
dragenter: DragEvent;
|
32
|
+
dragleave: DragEvent;
|
33
|
+
drop: DragEvent;
|
34
|
+
load: CustomEvent<any>;
|
35
|
+
error: CustomEvent<any>;
|
36
|
+
} & {
|
37
|
+
[evt: string]: CustomEvent<any>;
|
38
|
+
};
|
39
|
+
slots: {
|
40
|
+
default: {};
|
41
|
+
};
|
42
|
+
};
|
43
|
+
export type UploadProps = typeof __propDef.props;
|
44
|
+
export type UploadEvents = typeof __propDef.events;
|
45
|
+
export type UploadSlots = typeof __propDef.slots;
|
46
|
+
export default class Upload extends SvelteComponent<UploadProps, UploadEvents, UploadSlots> {
|
47
|
+
get paste_clipboard(): () => void;
|
48
|
+
get open_file_upload(): () => void;
|
49
|
+
get load_files(): (files: File[] | Blob[]) => Promise<(FileData | null)[] | void>;
|
50
|
+
}
|
51
|
+
export {};
|
@@ -0,0 +1,172 @@
|
|
1
|
+
<script>import { FileData } from "@gradio/client";
|
2
|
+
import { onMount, createEventDispatcher, onDestroy } from "svelte";
|
3
|
+
export let upload_id;
|
4
|
+
export let root;
|
5
|
+
export let files;
|
6
|
+
export let stream_handler;
|
7
|
+
let stream;
|
8
|
+
let progress = false;
|
9
|
+
let current_file_upload;
|
10
|
+
let file_to_display;
|
11
|
+
let files_with_progress = files.map((file) => {
|
12
|
+
return {
|
13
|
+
...file,
|
14
|
+
progress: 0
|
15
|
+
};
|
16
|
+
});
|
17
|
+
const dispatch = createEventDispatcher();
|
18
|
+
function handleProgress(filename, chunk_size) {
|
19
|
+
files_with_progress = files_with_progress.map((file) => {
|
20
|
+
if (file.orig_name === filename) {
|
21
|
+
file.progress += chunk_size;
|
22
|
+
}
|
23
|
+
return file;
|
24
|
+
});
|
25
|
+
}
|
26
|
+
function getProgress(file) {
|
27
|
+
return file.progress * 100 / (file.size || 0) || 0;
|
28
|
+
}
|
29
|
+
onMount(async () => {
|
30
|
+
stream = await stream_handler(
|
31
|
+
new URL(`${root}/upload_progress?upload_id=${upload_id}`)
|
32
|
+
);
|
33
|
+
if (stream == null) {
|
34
|
+
throw new Error("Event source is not defined");
|
35
|
+
}
|
36
|
+
stream.onmessage = async function(event) {
|
37
|
+
const _data = JSON.parse(event.data);
|
38
|
+
if (!progress)
|
39
|
+
progress = true;
|
40
|
+
if (_data.msg === "done") {
|
41
|
+
stream?.close();
|
42
|
+
dispatch("done");
|
43
|
+
} else {
|
44
|
+
current_file_upload = _data;
|
45
|
+
handleProgress(_data.orig_name, _data.chunk_size);
|
46
|
+
}
|
47
|
+
};
|
48
|
+
});
|
49
|
+
onDestroy(() => {
|
50
|
+
if (stream != null || stream != void 0)
|
51
|
+
stream.close();
|
52
|
+
});
|
53
|
+
function calculateTotalProgress(files2) {
|
54
|
+
let totalProgress = 0;
|
55
|
+
files2.forEach((file) => {
|
56
|
+
totalProgress += getProgress(file);
|
57
|
+
});
|
58
|
+
document.documentElement.style.setProperty(
|
59
|
+
"--upload-progress-width",
|
60
|
+
(totalProgress / files2.length).toFixed(2) + "%"
|
61
|
+
);
|
62
|
+
return totalProgress / files2.length;
|
63
|
+
}
|
64
|
+
$:
|
65
|
+
calculateTotalProgress(files_with_progress);
|
66
|
+
$:
|
67
|
+
file_to_display = current_file_upload || files_with_progress[0];
|
68
|
+
</script>
|
69
|
+
|
70
|
+
<div class="wrap" class:progress>
|
71
|
+
<span class="uploading"
|
72
|
+
>Uploading {files_with_progress.length}
|
73
|
+
{files_with_progress.length > 1 ? "files" : "file"}...</span
|
74
|
+
>
|
75
|
+
|
76
|
+
{#if file_to_display}
|
77
|
+
<div class="file">
|
78
|
+
<span>
|
79
|
+
<div class="progress-bar">
|
80
|
+
<progress
|
81
|
+
style="visibility:hidden;height:0;width:0;"
|
82
|
+
value={getProgress(file_to_display)}
|
83
|
+
max="100">{getProgress(file_to_display)}</progress
|
84
|
+
>
|
85
|
+
</div>
|
86
|
+
</span>
|
87
|
+
<span class="file-name">
|
88
|
+
{file_to_display.orig_name}
|
89
|
+
</span>
|
90
|
+
</div>
|
91
|
+
{/if}
|
92
|
+
</div>
|
93
|
+
|
94
|
+
<style>
|
95
|
+
.wrap {
|
96
|
+
overflow-y: auto;
|
97
|
+
transition: opacity 0.5s ease-in-out;
|
98
|
+
background: var(--block-background-fill);
|
99
|
+
position: relative;
|
100
|
+
display: flex;
|
101
|
+
flex-direction: column;
|
102
|
+
align-items: center;
|
103
|
+
justify-content: center;
|
104
|
+
min-height: var(--size-40);
|
105
|
+
width: var(--size-full);
|
106
|
+
}
|
107
|
+
|
108
|
+
.wrap::after {
|
109
|
+
content: "";
|
110
|
+
position: absolute;
|
111
|
+
top: 0;
|
112
|
+
left: 0;
|
113
|
+
width: var(--upload-progress-width);
|
114
|
+
height: 100%;
|
115
|
+
transition: all 0.5s ease-in-out;
|
116
|
+
z-index: 1;
|
117
|
+
}
|
118
|
+
|
119
|
+
.uploading {
|
120
|
+
font-size: var(--text-lg);
|
121
|
+
font-family: var(--font);
|
122
|
+
z-index: 2;
|
123
|
+
}
|
124
|
+
|
125
|
+
.file-name {
|
126
|
+
margin: var(--spacing-md);
|
127
|
+
font-size: var(--text-lg);
|
128
|
+
color: var(--body-text-color-subdued);
|
129
|
+
}
|
130
|
+
|
131
|
+
.file {
|
132
|
+
font-size: var(--text-md);
|
133
|
+
z-index: 2;
|
134
|
+
display: flex;
|
135
|
+
align-items: center;
|
136
|
+
}
|
137
|
+
|
138
|
+
.file progress {
|
139
|
+
display: inline;
|
140
|
+
height: var(--size-1);
|
141
|
+
width: 100%;
|
142
|
+
transition: all 0.5s ease-in-out;
|
143
|
+
color: var(--color-accent);
|
144
|
+
border: none;
|
145
|
+
}
|
146
|
+
|
147
|
+
.file progress[value]::-webkit-progress-value {
|
148
|
+
background-color: var(--color-accent);
|
149
|
+
border-radius: 20px;
|
150
|
+
}
|
151
|
+
|
152
|
+
.file progress[value]::-webkit-progress-bar {
|
153
|
+
background-color: var(--border-color-accent);
|
154
|
+
border-radius: 20px;
|
155
|
+
}
|
156
|
+
|
157
|
+
.progress-bar {
|
158
|
+
width: 14px;
|
159
|
+
height: 14px;
|
160
|
+
border-radius: 50%;
|
161
|
+
background: radial-gradient(
|
162
|
+
closest-side,
|
163
|
+
var(--block-background-fill) 64%,
|
164
|
+
transparent 53% 100%
|
165
|
+
),
|
166
|
+
conic-gradient(
|
167
|
+
var(--color-accent) var(--upload-progress-width),
|
168
|
+
var(--border-color-accent) 0
|
169
|
+
);
|
170
|
+
transition: all 0.5s ease-in-out;
|
171
|
+
}
|
172
|
+
</style>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
2
|
+
import { FileData, type Client } from "@gradio/client";
|
3
|
+
declare const __propDef: {
|
4
|
+
props: {
|
5
|
+
upload_id: string;
|
6
|
+
root: string;
|
7
|
+
files: FileData[];
|
8
|
+
stream_handler: Client["stream"];
|
9
|
+
};
|
10
|
+
events: {
|
11
|
+
done: CustomEvent<any>;
|
12
|
+
} & {
|
13
|
+
[evt: string]: CustomEvent<any>;
|
14
|
+
};
|
15
|
+
slots: {};
|
16
|
+
};
|
17
|
+
export type UploadProgressProps = typeof __propDef.props;
|
18
|
+
export type UploadProgressEvents = typeof __propDef.events;
|
19
|
+
export type UploadProgressSlots = typeof __propDef.slots;
|
20
|
+
export default class UploadProgress extends SvelteComponent<UploadProgressProps, UploadProgressEvents, UploadProgressSlots> {
|
21
|
+
}
|
22
|
+
export {};
|
package/package.json
CHANGED
@@ -1,21 +1,28 @@
|
|
1
1
|
{
|
2
2
|
"name": "@gradio/upload",
|
3
|
-
"version": "0.12.
|
3
|
+
"version": "0.12.4",
|
4
4
|
"description": "Gradio UI packages",
|
5
5
|
"type": "module",
|
6
6
|
"main": "src/index.ts",
|
7
7
|
"author": "",
|
8
8
|
"license": "ISC",
|
9
9
|
"dependencies": {
|
10
|
-
"@gradio/
|
11
|
-
"@gradio/
|
12
|
-
"@gradio/
|
13
|
-
"@gradio/
|
14
|
-
"@gradio/
|
10
|
+
"@gradio/client": "^1.5.2",
|
11
|
+
"@gradio/utils": "^0.6.1",
|
12
|
+
"@gradio/wasm": "^0.13.1",
|
13
|
+
"@gradio/atoms": "^0.8.1",
|
14
|
+
"@gradio/icons": "^0.7.2"
|
15
15
|
},
|
16
16
|
"main_changeset": true,
|
17
17
|
"exports": {
|
18
|
-
".":
|
18
|
+
".": {
|
19
|
+
"gradio": "./src/index.ts",
|
20
|
+
"svelte": "./dist/src/index.js",
|
21
|
+
"types": "./dist/src/index.d.ts"
|
22
|
+
}
|
23
|
+
},
|
24
|
+
"peerDependencies": {
|
25
|
+
"svelte": "^4.0.0"
|
19
26
|
},
|
20
27
|
"repository": {
|
21
28
|
"type": "git",
|