@gradio/file 0.14.0 → 0.14.2
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 +33 -0
- package/Example.svelte +9 -3
- package/File.stories.svelte +32 -29
- package/FileUpload.stories.svelte +37 -25
- package/Index.svelte +11 -10
- package/dist/Example.svelte +9 -3
- package/dist/Example.svelte.d.ts +5 -19
- package/dist/Index.svelte +11 -10
- package/dist/shared/FilePreview.svelte +53 -39
- package/dist/shared/FilePreview.svelte.d.ts +8 -24
- package/dist/shared/FileUpload.svelte +67 -47
- package/dist/shared/FileUpload.svelte.d.ts +29 -30
- package/dist/types.d.ts +1 -1
- package/package.json +9 -9
- package/shared/FilePreview.svelte +53 -39
- package/shared/FileUpload.svelte +67 -47
- package/types.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# @gradio/file
|
|
2
2
|
|
|
3
|
+
## 0.14.2
|
|
4
|
+
|
|
5
|
+
### Dependency updates
|
|
6
|
+
|
|
7
|
+
- @gradio/atoms@0.21.0
|
|
8
|
+
- @gradio/client@2.0.4
|
|
9
|
+
- @gradio/statustracker@0.12.3
|
|
10
|
+
- @gradio/upload@0.17.5
|
|
11
|
+
|
|
12
|
+
## 0.14.1
|
|
13
|
+
|
|
14
|
+
### Fixes
|
|
15
|
+
|
|
16
|
+
- [#12800](https://github.com/gradio-app/gradio/pull/12800) [`7a1c321`](https://github.com/gradio-app/gradio/commit/7a1c321b6546ba05a353488f5133e8262c4a8a39) - Bump svelte/kit for security reasons. Thanks @freddyaboulton!
|
|
17
|
+
- [#12698](https://github.com/gradio-app/gradio/pull/12698) [`db86165`](https://github.com/gradio-app/gradio/commit/db86165535386991701ea89b2083ef5e60cd23e8) - Migrates gr.File. Thanks @aliabid94!
|
|
18
|
+
- [#12779](https://github.com/gradio-app/gradio/pull/12779) [`ea2d3e9`](https://github.com/gradio-app/gradio/commit/ea2d3e985a8b42d188e551f517c5825c00790628) - Migrate Audio + Upload + Atoms to Svelte 5. Thanks @dawoodkhan82!
|
|
19
|
+
|
|
20
|
+
### Dependency updates
|
|
21
|
+
|
|
22
|
+
- @gradio/statustracker@0.12.2
|
|
23
|
+
- @gradio/atoms@0.20.1
|
|
24
|
+
- @gradio/utils@0.11.2
|
|
25
|
+
- @gradio/icons@0.15.1
|
|
26
|
+
- @gradio/upload@0.17.4
|
|
27
|
+
- @gradio/client@2.0.3
|
|
28
|
+
|
|
29
|
+
## 0.14.0
|
|
30
|
+
|
|
31
|
+
### Dependency updates
|
|
32
|
+
|
|
33
|
+
- @gradio/utils@0.11.1
|
|
34
|
+
- @gradio/client@2.0.2
|
|
35
|
+
|
|
3
36
|
## 0.14.0
|
|
4
37
|
|
|
5
38
|
### Features
|
package/Example.svelte
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { FileData } from "@gradio/client";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
let {
|
|
5
|
+
value,
|
|
6
|
+
type,
|
|
7
|
+
selected = false
|
|
8
|
+
}: {
|
|
9
|
+
value: FileData | null;
|
|
10
|
+
type: "gallery" | "table";
|
|
11
|
+
selected: boolean;
|
|
12
|
+
} = $props();
|
|
7
13
|
</script>
|
|
8
14
|
|
|
9
15
|
<div
|
package/File.stories.svelte
CHANGED
|
@@ -1,64 +1,67 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import {
|
|
1
|
+
<script module>
|
|
2
|
+
import { defineMeta } from "@storybook/addon-svelte-csf";
|
|
3
3
|
import File from "./Index.svelte";
|
|
4
|
-
|
|
4
|
+
import { wrapProps } from "../storybook/wrapProps";
|
|
5
|
+
|
|
6
|
+
const cheetah = "/cheetah.jpg";
|
|
7
|
+
const bus = "/bus.png";
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
const { Story } = defineMeta({
|
|
10
|
+
title: "Components/File",
|
|
11
|
+
component: File,
|
|
12
|
+
argTypes: {
|
|
13
|
+
value: {
|
|
14
|
+
control: "text",
|
|
15
|
+
description: "The URL or filepath (or list of URLs or filepaths)",
|
|
16
|
+
name: "value",
|
|
17
|
+
value: []
|
|
18
|
+
}
|
|
15
19
|
}
|
|
16
|
-
}
|
|
17
|
-
|
|
20
|
+
});
|
|
21
|
+
</script>
|
|
18
22
|
|
|
19
|
-
|
|
20
|
-
<File {...args} />
|
|
21
|
-
|
|
23
|
+
{#snippet template(args)}
|
|
24
|
+
<File {...wrapProps(args)} />
|
|
25
|
+
{/snippet}
|
|
22
26
|
|
|
23
27
|
<Story
|
|
24
28
|
name="Single File"
|
|
25
29
|
args={{
|
|
26
30
|
value: [
|
|
27
31
|
{
|
|
28
|
-
path:
|
|
32
|
+
path: cheetah,
|
|
29
33
|
orig_name: "cheetah.jpg",
|
|
30
|
-
url:
|
|
34
|
+
url: cheetah,
|
|
31
35
|
size: 10000
|
|
32
36
|
}
|
|
33
37
|
]
|
|
34
38
|
}}
|
|
39
|
+
{template}
|
|
35
40
|
/>
|
|
36
41
|
<Story
|
|
37
42
|
name="Multiple files, with height set to 150px and reordering enabled"
|
|
38
43
|
args={{
|
|
39
44
|
value: [
|
|
40
45
|
{
|
|
41
|
-
path:
|
|
42
|
-
orig_name: "
|
|
43
|
-
url:
|
|
46
|
+
path: bus,
|
|
47
|
+
orig_name: "bus.png",
|
|
48
|
+
url: bus,
|
|
44
49
|
size: 10000
|
|
45
50
|
},
|
|
46
51
|
{
|
|
47
|
-
path:
|
|
52
|
+
path: cheetah,
|
|
48
53
|
orig_name: "cheetah.jpg",
|
|
49
|
-
url:
|
|
54
|
+
url: cheetah,
|
|
50
55
|
size: 10000
|
|
51
56
|
}
|
|
52
57
|
],
|
|
53
58
|
height: 150,
|
|
54
59
|
allow_reordering: true
|
|
55
60
|
}}
|
|
61
|
+
{template}
|
|
56
62
|
/>
|
|
57
63
|
<Story
|
|
58
64
|
name="File upload with height set to 400px"
|
|
59
|
-
args={{
|
|
60
|
-
|
|
61
|
-
value: null,
|
|
62
|
-
height: 400
|
|
63
|
-
}}
|
|
65
|
+
args={{ interactive: true, value: null, height: 400 }}
|
|
66
|
+
{template}
|
|
64
67
|
/>
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
<script
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import { get } from "svelte/store";
|
|
1
|
+
<script module>
|
|
2
|
+
import { defineMeta } from "@storybook/addon-svelte-csf";
|
|
3
|
+
import File from "./Index.svelte";
|
|
4
|
+
import { wrapProps } from "../storybook/wrapProps";
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
const cheetah = "/cheetah.jpg";
|
|
7
|
+
const lion = "/lion.jpg";
|
|
8
|
+
|
|
9
|
+
const { Story } = defineMeta({
|
|
8
10
|
title: "Components/FileUpload",
|
|
9
|
-
component:
|
|
11
|
+
component: File,
|
|
10
12
|
argTypes: {
|
|
11
13
|
value: {
|
|
12
14
|
control: "text",
|
|
@@ -22,43 +24,53 @@
|
|
|
22
24
|
value: "single"
|
|
23
25
|
}
|
|
24
26
|
}
|
|
25
|
-
};
|
|
27
|
+
});
|
|
26
28
|
</script>
|
|
27
29
|
|
|
28
|
-
|
|
29
|
-
<
|
|
30
|
-
|
|
30
|
+
{#snippet template(args)}
|
|
31
|
+
<File {...wrapProps(args)} />
|
|
32
|
+
{/snippet}
|
|
31
33
|
|
|
32
34
|
<Story
|
|
33
35
|
name="Single File"
|
|
34
36
|
args={{
|
|
35
37
|
value: [
|
|
36
38
|
{
|
|
37
|
-
path:
|
|
39
|
+
path: cheetah,
|
|
38
40
|
orig_name: "cheetah.jpg",
|
|
39
|
-
url:
|
|
41
|
+
url: cheetah,
|
|
40
42
|
size: 10000
|
|
41
43
|
}
|
|
42
44
|
],
|
|
43
|
-
file_count: "single"
|
|
45
|
+
file_count: "single",
|
|
46
|
+
interactive: true
|
|
44
47
|
}}
|
|
48
|
+
{template}
|
|
45
49
|
/>
|
|
46
50
|
<Story
|
|
47
51
|
name="Multiple files"
|
|
48
52
|
args={{
|
|
49
|
-
value:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
value: [
|
|
54
|
+
{
|
|
55
|
+
path: cheetah,
|
|
56
|
+
orig_name: "cheetah.jpg",
|
|
57
|
+
url: cheetah,
|
|
58
|
+
size: 10000
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
path: lion,
|
|
62
|
+
orig_name: "lion.jpg",
|
|
63
|
+
url: lion,
|
|
64
|
+
size: 10000
|
|
65
|
+
}
|
|
66
|
+
],
|
|
67
|
+
file_count: "multiple",
|
|
68
|
+
interactive: true
|
|
56
69
|
}}
|
|
70
|
+
{template}
|
|
57
71
|
/>
|
|
58
72
|
<Story
|
|
59
73
|
name="No value"
|
|
60
|
-
args={{
|
|
61
|
-
|
|
62
|
-
file_count: "multiple"
|
|
63
|
-
}}
|
|
74
|
+
args={{ value: null, file_count: "multiple", interactive: true }}
|
|
75
|
+
{template}
|
|
64
76
|
/>
|
package/Index.svelte
CHANGED
|
@@ -13,11 +13,12 @@
|
|
|
13
13
|
import FileUpload from "./shared/FileUpload.svelte";
|
|
14
14
|
import { Block, UploadText } from "@gradio/atoms";
|
|
15
15
|
import type { FileEvents, FileProps } from "./types";
|
|
16
|
+
import type { SelectData } from "@gradio/utils";
|
|
16
17
|
import { StatusTracker } from "@gradio/statustracker";
|
|
17
18
|
import { tick } from "svelte";
|
|
18
19
|
|
|
19
20
|
const props = $props();
|
|
20
|
-
let upload_promise = $state<Promise<any
|
|
21
|
+
let upload_promise = $state<Promise<any> | null>(null);
|
|
21
22
|
|
|
22
23
|
let dragging = $state(false);
|
|
23
24
|
let pending_upload = $state(false);
|
|
@@ -94,7 +95,7 @@
|
|
|
94
95
|
file_count={gradio.props.file_count}
|
|
95
96
|
file_types={gradio.props.file_types}
|
|
96
97
|
selectable={gradio.props._selectable}
|
|
97
|
-
height={gradio.props.height}
|
|
98
|
+
height={gradio.props.height ?? undefined}
|
|
98
99
|
root={gradio.shared.root}
|
|
99
100
|
allow_reordering={gradio.props.allow_reordering}
|
|
100
101
|
max_file_size={gradio.shared.max_file_size}
|
|
@@ -102,19 +103,19 @@
|
|
|
102
103
|
on_custom_button_click={(id) => {
|
|
103
104
|
gradio.dispatch("custom_button_click", { id });
|
|
104
105
|
}}
|
|
105
|
-
|
|
106
|
+
onchange={(detail) => {
|
|
106
107
|
gradio.props.value = detail;
|
|
107
108
|
}}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
109
|
+
ondrag={(detail) => (dragging = detail)}
|
|
110
|
+
onclear={() => gradio.dispatch("clear")}
|
|
111
|
+
onselect={(detail: SelectData) => gradio.dispatch("select", detail)}
|
|
112
|
+
onupload={() => gradio.dispatch("upload")}
|
|
113
|
+
onerror={(error) => {
|
|
113
114
|
gradio.shared.loading_status = gradio.shared.loading_status || {};
|
|
114
115
|
gradio.shared.loading_status.status = "error";
|
|
115
|
-
gradio.dispatch("error",
|
|
116
|
+
gradio.dispatch("error", error);
|
|
116
117
|
}}
|
|
117
|
-
|
|
118
|
+
ondelete={(detail) => {
|
|
118
119
|
gradio.dispatch("delete", detail);
|
|
119
120
|
}}
|
|
120
121
|
i18n={gradio.i18n}
|
package/dist/Example.svelte
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { FileData } from "@gradio/client";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
let {
|
|
5
|
+
value,
|
|
6
|
+
type,
|
|
7
|
+
selected = false
|
|
8
|
+
}: {
|
|
9
|
+
value: FileData | null;
|
|
10
|
+
type: "gallery" | "table";
|
|
11
|
+
selected: boolean;
|
|
12
|
+
} = $props();
|
|
7
13
|
</script>
|
|
8
14
|
|
|
9
15
|
<div
|
package/dist/Example.svelte.d.ts
CHANGED
|
@@ -1,23 +1,9 @@
|
|
|
1
1
|
import type { FileData } from "@gradio/client";
|
|
2
|
-
|
|
3
|
-
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
|
-
$$bindings?: Bindings;
|
|
5
|
-
} & Exports;
|
|
6
|
-
(internal: unknown, props: Props & {
|
|
7
|
-
$$events?: Events;
|
|
8
|
-
$$slots?: Slots;
|
|
9
|
-
}): Exports & {
|
|
10
|
-
$set?: any;
|
|
11
|
-
$on?: any;
|
|
12
|
-
};
|
|
13
|
-
z_$$bindings?: Bindings;
|
|
14
|
-
}
|
|
15
|
-
declare const Example: $$__sveltets_2_IsomorphicComponent<{
|
|
2
|
+
type $$ComponentProps = {
|
|
16
3
|
value: FileData | null;
|
|
17
4
|
type: "gallery" | "table";
|
|
18
|
-
selected
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
type Example = InstanceType<typeof Example>;
|
|
5
|
+
selected: boolean;
|
|
6
|
+
};
|
|
7
|
+
declare const Example: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
|
+
type Example = ReturnType<typeof Example>;
|
|
23
9
|
export default Example;
|
package/dist/Index.svelte
CHANGED
|
@@ -13,11 +13,12 @@
|
|
|
13
13
|
import FileUpload from "./shared/FileUpload.svelte";
|
|
14
14
|
import { Block, UploadText } from "@gradio/atoms";
|
|
15
15
|
import type { FileEvents, FileProps } from "./types";
|
|
16
|
+
import type { SelectData } from "@gradio/utils";
|
|
16
17
|
import { StatusTracker } from "@gradio/statustracker";
|
|
17
18
|
import { tick } from "svelte";
|
|
18
19
|
|
|
19
20
|
const props = $props();
|
|
20
|
-
let upload_promise = $state<Promise<any
|
|
21
|
+
let upload_promise = $state<Promise<any> | null>(null);
|
|
21
22
|
|
|
22
23
|
let dragging = $state(false);
|
|
23
24
|
let pending_upload = $state(false);
|
|
@@ -94,7 +95,7 @@
|
|
|
94
95
|
file_count={gradio.props.file_count}
|
|
95
96
|
file_types={gradio.props.file_types}
|
|
96
97
|
selectable={gradio.props._selectable}
|
|
97
|
-
height={gradio.props.height}
|
|
98
|
+
height={gradio.props.height ?? undefined}
|
|
98
99
|
root={gradio.shared.root}
|
|
99
100
|
allow_reordering={gradio.props.allow_reordering}
|
|
100
101
|
max_file_size={gradio.shared.max_file_size}
|
|
@@ -102,19 +103,19 @@
|
|
|
102
103
|
on_custom_button_click={(id) => {
|
|
103
104
|
gradio.dispatch("custom_button_click", { id });
|
|
104
105
|
}}
|
|
105
|
-
|
|
106
|
+
onchange={(detail) => {
|
|
106
107
|
gradio.props.value = detail;
|
|
107
108
|
}}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
109
|
+
ondrag={(detail) => (dragging = detail)}
|
|
110
|
+
onclear={() => gradio.dispatch("clear")}
|
|
111
|
+
onselect={(detail: SelectData) => gradio.dispatch("select", detail)}
|
|
112
|
+
onupload={() => gradio.dispatch("upload")}
|
|
113
|
+
onerror={(error) => {
|
|
113
114
|
gradio.shared.loading_status = gradio.shared.loading_status || {};
|
|
114
115
|
gradio.shared.loading_status.status = "error";
|
|
115
|
-
gradio.dispatch("error",
|
|
116
|
+
gradio.dispatch("error", error);
|
|
116
117
|
}}
|
|
117
|
-
|
|
118
|
+
ondelete={(detail) => {
|
|
118
119
|
gradio.dispatch("delete", detail);
|
|
119
120
|
}}
|
|
120
121
|
i18n={gradio.i18n}
|
|
@@ -1,24 +1,33 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { FileData } from "@gradio/client";
|
|
3
3
|
import { prettyBytes } from "./utils";
|
|
4
|
-
import { createEventDispatcher } from "svelte";
|
|
5
4
|
import type { I18nFormatter, SelectData } from "@gradio/utils";
|
|
6
5
|
import { DownloadLink } from "@gradio/atoms";
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
7
|
+
let {
|
|
8
|
+
value,
|
|
9
|
+
selectable = false,
|
|
10
|
+
height = undefined,
|
|
11
|
+
i18n,
|
|
12
|
+
allow_reordering = false,
|
|
13
|
+
onselect,
|
|
14
|
+
onchange,
|
|
15
|
+
ondelete,
|
|
16
|
+
ondownload
|
|
17
|
+
}: {
|
|
18
|
+
value: FileData | FileData[];
|
|
19
|
+
selectable?: boolean;
|
|
20
|
+
height?: number | string | undefined;
|
|
21
|
+
i18n: I18nFormatter;
|
|
22
|
+
allow_reordering?: boolean;
|
|
23
|
+
onselect?: (event_data: SelectData) => void;
|
|
24
|
+
onchange?: (event_data: FileData[] | FileData) => void;
|
|
25
|
+
ondelete?: (event_data: FileData) => void;
|
|
26
|
+
ondownload?: (event_data: FileData) => void;
|
|
27
|
+
} = $props();
|
|
28
|
+
|
|
29
|
+
let dragging_index: number | null = $state(null);
|
|
30
|
+
let drop_target_index: number | null = $state(null);
|
|
22
31
|
|
|
23
32
|
function handle_drag_start(event: DragEvent, index: number): void {
|
|
24
33
|
dragging_index = index;
|
|
@@ -68,7 +77,7 @@
|
|
|
68
77
|
);
|
|
69
78
|
|
|
70
79
|
const new_value = Array.isArray(value) ? files : files[0];
|
|
71
|
-
|
|
80
|
+
onchange?.(new_value);
|
|
72
81
|
|
|
73
82
|
dragging_index = null;
|
|
74
83
|
drop_target_index = null;
|
|
@@ -82,14 +91,18 @@
|
|
|
82
91
|
return [filename.slice(0, last_dot), filename.slice(last_dot)];
|
|
83
92
|
}
|
|
84
93
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
94
|
+
let normalized_files = $derived(
|
|
95
|
+
(Array.isArray(value) ? value : [value]).map((file) => {
|
|
96
|
+
const [filename_stem, filename_ext] = split_filename(
|
|
97
|
+
file.orig_name ?? ""
|
|
98
|
+
);
|
|
99
|
+
return {
|
|
100
|
+
...file,
|
|
101
|
+
filename_stem,
|
|
102
|
+
filename_ext
|
|
103
|
+
};
|
|
104
|
+
})
|
|
105
|
+
);
|
|
93
106
|
|
|
94
107
|
function handle_row_click(
|
|
95
108
|
event: MouseEvent & { currentTarget: HTMLTableRowElement },
|
|
@@ -103,20 +116,21 @@
|
|
|
103
116
|
event.composedPath().includes(tr.firstElementChild)); // Or if the click is on the name column
|
|
104
117
|
|
|
105
118
|
if (should_select) {
|
|
106
|
-
|
|
119
|
+
onselect?.({ value: normalized_files[index].orig_name, index });
|
|
107
120
|
}
|
|
108
121
|
}
|
|
109
122
|
|
|
110
123
|
function remove_file(index: number): void {
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
124
|
+
const files = Array.isArray(value) ? [...value] : [value];
|
|
125
|
+
const removed = files.splice(index, 1);
|
|
126
|
+
const new_value = Array.isArray(value) ? files : files[0];
|
|
127
|
+
value = new_value;
|
|
128
|
+
ondelete?.(removed[0]);
|
|
129
|
+
onchange?.(new_value);
|
|
116
130
|
}
|
|
117
131
|
|
|
118
132
|
function handle_download(file: FileData): void {
|
|
119
|
-
|
|
133
|
+
ondownload?.(file);
|
|
120
134
|
}
|
|
121
135
|
|
|
122
136
|
const is_browser = typeof window !== "undefined";
|
|
@@ -147,14 +161,14 @@
|
|
|
147
161
|
? "after"
|
|
148
162
|
: "before"}
|
|
149
163
|
draggable={allow_reordering && normalized_files.length > 1}
|
|
150
|
-
|
|
164
|
+
onclick={(event) => {
|
|
151
165
|
handle_row_click(event, i);
|
|
152
166
|
}}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
167
|
+
ondragstart={(event) => handle_drag_start(event, i)}
|
|
168
|
+
ondragenter={(event) => event.preventDefault()}
|
|
169
|
+
ondragover={(event) => handle_drag_over(event, i)}
|
|
170
|
+
ondrop={(event) => handle_drop(event, i)}
|
|
171
|
+
ondragend={handle_drag_end}
|
|
158
172
|
>
|
|
159
173
|
<td class="filename" aria-label={file.orig_name}>
|
|
160
174
|
{#if allow_reordering && normalized_files.length > 1}
|
|
@@ -187,10 +201,10 @@
|
|
|
187
201
|
<button
|
|
188
202
|
class="label-clear-button"
|
|
189
203
|
aria-label="Remove this file"
|
|
190
|
-
|
|
204
|
+
onclick={() => {
|
|
191
205
|
remove_file(i);
|
|
192
206
|
}}
|
|
193
|
-
|
|
207
|
+
onkeydown={(event) => {
|
|
194
208
|
if (event.key === "Enter") {
|
|
195
209
|
remove_file(i);
|
|
196
210
|
}
|
|
@@ -1,32 +1,16 @@
|
|
|
1
1
|
import type { FileData } from "@gradio/client";
|
|
2
2
|
import type { I18nFormatter, SelectData } from "@gradio/utils";
|
|
3
|
-
|
|
4
|
-
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
5
|
-
$$bindings?: Bindings;
|
|
6
|
-
} & Exports;
|
|
7
|
-
(internal: unknown, props: Props & {
|
|
8
|
-
$$events?: Events;
|
|
9
|
-
$$slots?: Slots;
|
|
10
|
-
}): Exports & {
|
|
11
|
-
$set?: any;
|
|
12
|
-
$on?: any;
|
|
13
|
-
};
|
|
14
|
-
z_$$bindings?: Bindings;
|
|
15
|
-
}
|
|
16
|
-
declare const FilePreview: $$__sveltets_2_IsomorphicComponent<{
|
|
3
|
+
type $$ComponentProps = {
|
|
17
4
|
value: FileData | FileData[];
|
|
18
5
|
selectable?: boolean;
|
|
19
6
|
height?: number | string | undefined;
|
|
20
7
|
i18n: I18nFormatter;
|
|
21
8
|
allow_reordering?: boolean;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
[evt: string]: CustomEvent<any>;
|
|
30
|
-
}, {}, {}, string>;
|
|
31
|
-
type FilePreview = InstanceType<typeof FilePreview>;
|
|
9
|
+
onselect?: (event_data: SelectData) => void;
|
|
10
|
+
onchange?: (event_data: FileData[] | FileData) => void;
|
|
11
|
+
ondelete?: (event_data: FileData) => void;
|
|
12
|
+
ondownload?: (event_data: FileData) => void;
|
|
13
|
+
};
|
|
14
|
+
declare const FilePreview: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
15
|
+
type FilePreview = ReturnType<typeof FilePreview>;
|
|
32
16
|
export default FilePreview;
|
|
@@ -1,36 +1,67 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { tick } from "svelte";
|
|
3
3
|
import { Upload, ModifyUpload } from "@gradio/upload";
|
|
4
4
|
import type { FileData, Client } from "@gradio/client";
|
|
5
5
|
import { BlockLabel, IconButtonWrapper, IconButton } from "@gradio/atoms";
|
|
6
6
|
import { File, Clear, Upload as UploadIcon } from "@gradio/icons";
|
|
7
7
|
|
|
8
8
|
import FilePreview from "./FilePreview.svelte";
|
|
9
|
-
import type { I18nFormatter } from "@gradio/utils";
|
|
9
|
+
import type { I18nFormatter, SelectData } from "@gradio/utils";
|
|
10
10
|
import type { CustomButton as CustomButtonType } from "@gradio/utils";
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
let {
|
|
13
|
+
value = $bindable<null | FileData | FileData[]>(),
|
|
14
|
+
label,
|
|
15
|
+
show_label = true,
|
|
16
|
+
file_count = "single",
|
|
17
|
+
file_types = null,
|
|
18
|
+
selectable = false,
|
|
19
|
+
root,
|
|
20
|
+
height = undefined,
|
|
21
|
+
i18n,
|
|
22
|
+
max_file_size = null,
|
|
23
|
+
upload,
|
|
24
|
+
stream_handler,
|
|
25
|
+
uploading = $bindable(false),
|
|
26
|
+
allow_reordering = false,
|
|
27
|
+
upload_promise = $bindable<Promise<(FileData | null)[]> | null>(),
|
|
28
|
+
buttons = null,
|
|
29
|
+
on_custom_button_click = null,
|
|
30
|
+
onchange,
|
|
31
|
+
onclear,
|
|
32
|
+
ondrag,
|
|
33
|
+
onupload,
|
|
34
|
+
onerror,
|
|
35
|
+
ondelete,
|
|
36
|
+
onselect
|
|
37
|
+
}: {
|
|
38
|
+
value: null | FileData | FileData[];
|
|
39
|
+
label: string;
|
|
40
|
+
show_label?: boolean;
|
|
41
|
+
file_count: "single" | "multiple" | "directory";
|
|
42
|
+
file_types: string[] | null;
|
|
43
|
+
selectable?: boolean;
|
|
44
|
+
root: string;
|
|
45
|
+
height?: number | undefined;
|
|
46
|
+
i18n: I18nFormatter;
|
|
47
|
+
max_file_size: number | null;
|
|
48
|
+
upload: Client["upload"];
|
|
49
|
+
stream_handler: Client["stream"];
|
|
50
|
+
uploading?: boolean;
|
|
51
|
+
allow_reordering?: boolean;
|
|
52
|
+
upload_promise?: Promise<(FileData | null)[]> | null;
|
|
53
|
+
buttons?: (string | CustomButtonType)[] | null;
|
|
54
|
+
on_custom_button_click?: ((id: number) => void) | null;
|
|
55
|
+
onchange?: (event_data: FileData[] | FileData | null) => void;
|
|
56
|
+
onclear?: () => void;
|
|
57
|
+
ondrag?: (dragging: boolean) => void;
|
|
58
|
+
onupload?: (event_data: FileData[] | FileData) => void;
|
|
59
|
+
onerror?: (error: string) => void;
|
|
60
|
+
ondelete?: (event_data: FileData) => void;
|
|
61
|
+
onselect?: (event_data: SelectData) => void;
|
|
62
|
+
} = $props();
|
|
13
63
|
|
|
14
|
-
|
|
15
|
-
export let show_label = true;
|
|
16
|
-
export let file_count: "single" | "multiple" | "directory" = "single";
|
|
17
|
-
export let file_types: string[] | null = null;
|
|
18
|
-
export let selectable = false;
|
|
19
|
-
export let root: string;
|
|
20
|
-
export let height: number | undefined = undefined;
|
|
21
|
-
export let i18n: I18nFormatter;
|
|
22
|
-
export let max_file_size: number | null = null;
|
|
23
|
-
export let upload: Client["upload"];
|
|
24
|
-
export let stream_handler: Client["stream"];
|
|
25
|
-
export let uploading = false;
|
|
26
|
-
export let allow_reordering = false;
|
|
27
|
-
export let upload_promise: Promise<(FileData | null)[]> | null = null;
|
|
28
|
-
export let buttons: (string | CustomButtonType)[] | null = null;
|
|
29
|
-
export let on_custom_button_click: ((id: number) => void) | null = null;
|
|
30
|
-
|
|
31
|
-
async function handle_upload({
|
|
32
|
-
detail
|
|
33
|
-
}: CustomEvent<FileData | FileData[]>): Promise<void> {
|
|
64
|
+
async function handle_upload(detail: FileData | FileData[]): Promise<void> {
|
|
34
65
|
if (Array.isArray(value)) {
|
|
35
66
|
value = [...value, ...(Array.isArray(detail) ? detail : [detail])];
|
|
36
67
|
} else if (value) {
|
|
@@ -39,27 +70,17 @@
|
|
|
39
70
|
value = detail;
|
|
40
71
|
}
|
|
41
72
|
await tick();
|
|
42
|
-
|
|
43
|
-
|
|
73
|
+
onchange?.(value);
|
|
74
|
+
onupload?.(value);
|
|
44
75
|
}
|
|
45
76
|
|
|
46
77
|
function handle_clear(): void {
|
|
47
78
|
value = null;
|
|
48
|
-
|
|
49
|
-
|
|
79
|
+
onchange?.(null);
|
|
80
|
+
onclear?.();
|
|
50
81
|
}
|
|
51
82
|
|
|
52
|
-
|
|
53
|
-
change: FileData[] | FileData | null;
|
|
54
|
-
clear: undefined;
|
|
55
|
-
drag: boolean;
|
|
56
|
-
upload: FileData[] | FileData;
|
|
57
|
-
load: FileData[] | FileData;
|
|
58
|
-
error: string;
|
|
59
|
-
}>();
|
|
60
|
-
|
|
61
|
-
let dragging = false;
|
|
62
|
-
$: dispatch("drag", dragging);
|
|
83
|
+
let dragging = $state(false);
|
|
63
84
|
</script>
|
|
64
85
|
|
|
65
86
|
{#if show_label && buttons && buttons.length > 0}
|
|
@@ -74,14 +95,14 @@
|
|
|
74
95
|
<Upload
|
|
75
96
|
bind:upload_promise
|
|
76
97
|
icon_upload={true}
|
|
77
|
-
|
|
98
|
+
onload={handle_upload}
|
|
78
99
|
filetype={file_types}
|
|
79
100
|
{file_count}
|
|
80
101
|
{max_file_size}
|
|
81
102
|
{root}
|
|
82
103
|
bind:dragging
|
|
83
104
|
bind:uploading
|
|
84
|
-
|
|
105
|
+
{onerror}
|
|
85
106
|
{stream_handler}
|
|
86
107
|
{upload}
|
|
87
108
|
/>
|
|
@@ -90,8 +111,7 @@
|
|
|
90
111
|
<IconButton
|
|
91
112
|
Icon={Clear}
|
|
92
113
|
label={i18n("common.clear")}
|
|
93
|
-
|
|
94
|
-
dispatch("clear");
|
|
114
|
+
onclick={(event) => {
|
|
95
115
|
event.stopPropagation();
|
|
96
116
|
handle_clear();
|
|
97
117
|
}}
|
|
@@ -100,25 +120,25 @@
|
|
|
100
120
|
|
|
101
121
|
<FilePreview
|
|
102
122
|
{i18n}
|
|
103
|
-
|
|
123
|
+
{onselect}
|
|
104
124
|
{selectable}
|
|
105
125
|
{value}
|
|
106
126
|
{height}
|
|
107
|
-
|
|
108
|
-
|
|
127
|
+
{onchange}
|
|
128
|
+
{ondelete}
|
|
109
129
|
{allow_reordering}
|
|
110
130
|
/>
|
|
111
131
|
{:else}
|
|
112
132
|
<Upload
|
|
113
133
|
bind:upload_promise
|
|
114
|
-
|
|
134
|
+
onload={handle_upload}
|
|
115
135
|
filetype={file_types}
|
|
116
136
|
{file_count}
|
|
117
137
|
{max_file_size}
|
|
118
138
|
{root}
|
|
119
139
|
bind:dragging
|
|
120
140
|
bind:uploading
|
|
121
|
-
|
|
141
|
+
{onerror}
|
|
122
142
|
{stream_handler}
|
|
123
143
|
{upload}
|
|
124
144
|
{height}
|
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
import type { FileData, Client } from "@gradio/client";
|
|
2
|
-
import type { I18nFormatter } from "@gradio/utils";
|
|
2
|
+
import type { I18nFormatter, SelectData } from "@gradio/utils";
|
|
3
3
|
import type { CustomButton as CustomButtonType } from "@gradio/utils";
|
|
4
|
+
type $$ComponentProps = {
|
|
5
|
+
value: null | FileData | FileData[];
|
|
6
|
+
label: string;
|
|
7
|
+
show_label?: boolean;
|
|
8
|
+
file_count: "single" | "multiple" | "directory";
|
|
9
|
+
file_types: string[] | null;
|
|
10
|
+
selectable?: boolean;
|
|
11
|
+
root: string;
|
|
12
|
+
height?: number | undefined;
|
|
13
|
+
i18n: I18nFormatter;
|
|
14
|
+
max_file_size: number | null;
|
|
15
|
+
upload: Client["upload"];
|
|
16
|
+
stream_handler: Client["stream"];
|
|
17
|
+
uploading?: boolean;
|
|
18
|
+
allow_reordering?: boolean;
|
|
19
|
+
upload_promise?: Promise<(FileData | null)[]> | null;
|
|
20
|
+
buttons?: (string | CustomButtonType)[] | null;
|
|
21
|
+
on_custom_button_click?: ((id: number) => void) | null;
|
|
22
|
+
onchange?: (event_data: FileData[] | FileData | null) => void;
|
|
23
|
+
onclear?: () => void;
|
|
24
|
+
ondrag?: (dragging: boolean) => void;
|
|
25
|
+
onupload?: (event_data: FileData[] | FileData) => void;
|
|
26
|
+
onerror?: (error: string) => void;
|
|
27
|
+
ondelete?: (event_data: FileData) => void;
|
|
28
|
+
onselect?: (event_data: SelectData) => void;
|
|
29
|
+
};
|
|
4
30
|
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
5
31
|
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
6
32
|
$$bindings?: Bindings;
|
|
@@ -19,39 +45,12 @@ type $$__sveltets_2_PropsWithChildren<Props, Slots> = Props & (Slots extends {
|
|
|
19
45
|
} ? Props extends Record<string, never> ? any : {
|
|
20
46
|
children?: any;
|
|
21
47
|
} : {});
|
|
22
|
-
declare const FileUpload: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWithChildren
|
|
23
|
-
value: null | FileData | FileData[];
|
|
24
|
-
label: string;
|
|
25
|
-
show_label?: boolean;
|
|
26
|
-
file_count?: "single" | "multiple" | "directory";
|
|
27
|
-
file_types?: string[] | null;
|
|
28
|
-
selectable?: boolean;
|
|
29
|
-
root: string;
|
|
30
|
-
height?: number | undefined;
|
|
31
|
-
i18n: I18nFormatter;
|
|
32
|
-
max_file_size?: number | null;
|
|
33
|
-
upload: Client["upload"];
|
|
34
|
-
stream_handler: Client["stream"];
|
|
35
|
-
uploading?: boolean;
|
|
36
|
-
allow_reordering?: boolean;
|
|
37
|
-
upload_promise?: Promise<(FileData | null)[]> | null;
|
|
38
|
-
buttons?: (string | CustomButtonType)[] | null;
|
|
39
|
-
on_custom_button_click?: ((id: number) => void) | null;
|
|
40
|
-
}, {
|
|
48
|
+
declare const FileUpload: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWithChildren<$$ComponentProps, {
|
|
41
49
|
default: {};
|
|
42
50
|
}>, {
|
|
43
|
-
error: CustomEvent<any>;
|
|
44
|
-
select: CustomEvent<import("@gradio/utils").SelectData>;
|
|
45
|
-
change: CustomEvent<any>;
|
|
46
|
-
delete: CustomEvent<FileData>;
|
|
47
|
-
clear: CustomEvent<undefined>;
|
|
48
|
-
drag: CustomEvent<boolean>;
|
|
49
|
-
upload: CustomEvent<FileData | FileData[]>;
|
|
50
|
-
load: CustomEvent<FileData | FileData[]>;
|
|
51
|
-
} & {
|
|
52
51
|
[evt: string]: CustomEvent<any>;
|
|
53
52
|
}, {
|
|
54
53
|
default: {};
|
|
55
|
-
}, {},
|
|
54
|
+
}, {}, "value" | "uploading" | "upload_promise">;
|
|
56
55
|
type FileUpload = InstanceType<typeof FileUpload>;
|
|
57
56
|
export default FileUpload;
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gradio/file",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.2",
|
|
4
4
|
"description": "Gradio UI packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "",
|
|
7
7
|
"license": "ISC",
|
|
8
8
|
"private": false,
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@gradio/atoms": "^0.
|
|
11
|
-
"@gradio/
|
|
12
|
-
"@gradio/
|
|
13
|
-
"@gradio/
|
|
14
|
-
"@gradio/
|
|
15
|
-
"@gradio/
|
|
10
|
+
"@gradio/atoms": "^0.21.0",
|
|
11
|
+
"@gradio/icons": "^0.15.1",
|
|
12
|
+
"@gradio/client": "^2.0.4",
|
|
13
|
+
"@gradio/statustracker": "^0.12.3",
|
|
14
|
+
"@gradio/utils": "^0.11.2",
|
|
15
|
+
"@gradio/upload": "^0.17.5"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@gradio/preview": "^0.15.
|
|
18
|
+
"@gradio/preview": "^0.15.2"
|
|
19
19
|
},
|
|
20
20
|
"main": "./Index.svelte",
|
|
21
21
|
"main_changeset": true,
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"./package.json": "./package.json"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"svelte": "^5.
|
|
36
|
+
"svelte": "^5.48.0"
|
|
37
37
|
},
|
|
38
38
|
"repository": {
|
|
39
39
|
"type": "git",
|
|
@@ -1,24 +1,33 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { FileData } from "@gradio/client";
|
|
3
3
|
import { prettyBytes } from "./utils";
|
|
4
|
-
import { createEventDispatcher } from "svelte";
|
|
5
4
|
import type { I18nFormatter, SelectData } from "@gradio/utils";
|
|
6
5
|
import { DownloadLink } from "@gradio/atoms";
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
7
|
+
let {
|
|
8
|
+
value,
|
|
9
|
+
selectable = false,
|
|
10
|
+
height = undefined,
|
|
11
|
+
i18n,
|
|
12
|
+
allow_reordering = false,
|
|
13
|
+
onselect,
|
|
14
|
+
onchange,
|
|
15
|
+
ondelete,
|
|
16
|
+
ondownload
|
|
17
|
+
}: {
|
|
18
|
+
value: FileData | FileData[];
|
|
19
|
+
selectable?: boolean;
|
|
20
|
+
height?: number | string | undefined;
|
|
21
|
+
i18n: I18nFormatter;
|
|
22
|
+
allow_reordering?: boolean;
|
|
23
|
+
onselect?: (event_data: SelectData) => void;
|
|
24
|
+
onchange?: (event_data: FileData[] | FileData) => void;
|
|
25
|
+
ondelete?: (event_data: FileData) => void;
|
|
26
|
+
ondownload?: (event_data: FileData) => void;
|
|
27
|
+
} = $props();
|
|
28
|
+
|
|
29
|
+
let dragging_index: number | null = $state(null);
|
|
30
|
+
let drop_target_index: number | null = $state(null);
|
|
22
31
|
|
|
23
32
|
function handle_drag_start(event: DragEvent, index: number): void {
|
|
24
33
|
dragging_index = index;
|
|
@@ -68,7 +77,7 @@
|
|
|
68
77
|
);
|
|
69
78
|
|
|
70
79
|
const new_value = Array.isArray(value) ? files : files[0];
|
|
71
|
-
|
|
80
|
+
onchange?.(new_value);
|
|
72
81
|
|
|
73
82
|
dragging_index = null;
|
|
74
83
|
drop_target_index = null;
|
|
@@ -82,14 +91,18 @@
|
|
|
82
91
|
return [filename.slice(0, last_dot), filename.slice(last_dot)];
|
|
83
92
|
}
|
|
84
93
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
94
|
+
let normalized_files = $derived(
|
|
95
|
+
(Array.isArray(value) ? value : [value]).map((file) => {
|
|
96
|
+
const [filename_stem, filename_ext] = split_filename(
|
|
97
|
+
file.orig_name ?? ""
|
|
98
|
+
);
|
|
99
|
+
return {
|
|
100
|
+
...file,
|
|
101
|
+
filename_stem,
|
|
102
|
+
filename_ext
|
|
103
|
+
};
|
|
104
|
+
})
|
|
105
|
+
);
|
|
93
106
|
|
|
94
107
|
function handle_row_click(
|
|
95
108
|
event: MouseEvent & { currentTarget: HTMLTableRowElement },
|
|
@@ -103,20 +116,21 @@
|
|
|
103
116
|
event.composedPath().includes(tr.firstElementChild)); // Or if the click is on the name column
|
|
104
117
|
|
|
105
118
|
if (should_select) {
|
|
106
|
-
|
|
119
|
+
onselect?.({ value: normalized_files[index].orig_name, index });
|
|
107
120
|
}
|
|
108
121
|
}
|
|
109
122
|
|
|
110
123
|
function remove_file(index: number): void {
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
124
|
+
const files = Array.isArray(value) ? [...value] : [value];
|
|
125
|
+
const removed = files.splice(index, 1);
|
|
126
|
+
const new_value = Array.isArray(value) ? files : files[0];
|
|
127
|
+
value = new_value;
|
|
128
|
+
ondelete?.(removed[0]);
|
|
129
|
+
onchange?.(new_value);
|
|
116
130
|
}
|
|
117
131
|
|
|
118
132
|
function handle_download(file: FileData): void {
|
|
119
|
-
|
|
133
|
+
ondownload?.(file);
|
|
120
134
|
}
|
|
121
135
|
|
|
122
136
|
const is_browser = typeof window !== "undefined";
|
|
@@ -147,14 +161,14 @@
|
|
|
147
161
|
? "after"
|
|
148
162
|
: "before"}
|
|
149
163
|
draggable={allow_reordering && normalized_files.length > 1}
|
|
150
|
-
|
|
164
|
+
onclick={(event) => {
|
|
151
165
|
handle_row_click(event, i);
|
|
152
166
|
}}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
167
|
+
ondragstart={(event) => handle_drag_start(event, i)}
|
|
168
|
+
ondragenter={(event) => event.preventDefault()}
|
|
169
|
+
ondragover={(event) => handle_drag_over(event, i)}
|
|
170
|
+
ondrop={(event) => handle_drop(event, i)}
|
|
171
|
+
ondragend={handle_drag_end}
|
|
158
172
|
>
|
|
159
173
|
<td class="filename" aria-label={file.orig_name}>
|
|
160
174
|
{#if allow_reordering && normalized_files.length > 1}
|
|
@@ -187,10 +201,10 @@
|
|
|
187
201
|
<button
|
|
188
202
|
class="label-clear-button"
|
|
189
203
|
aria-label="Remove this file"
|
|
190
|
-
|
|
204
|
+
onclick={() => {
|
|
191
205
|
remove_file(i);
|
|
192
206
|
}}
|
|
193
|
-
|
|
207
|
+
onkeydown={(event) => {
|
|
194
208
|
if (event.key === "Enter") {
|
|
195
209
|
remove_file(i);
|
|
196
210
|
}
|
package/shared/FileUpload.svelte
CHANGED
|
@@ -1,36 +1,67 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { tick } from "svelte";
|
|
3
3
|
import { Upload, ModifyUpload } from "@gradio/upload";
|
|
4
4
|
import type { FileData, Client } from "@gradio/client";
|
|
5
5
|
import { BlockLabel, IconButtonWrapper, IconButton } from "@gradio/atoms";
|
|
6
6
|
import { File, Clear, Upload as UploadIcon } from "@gradio/icons";
|
|
7
7
|
|
|
8
8
|
import FilePreview from "./FilePreview.svelte";
|
|
9
|
-
import type { I18nFormatter } from "@gradio/utils";
|
|
9
|
+
import type { I18nFormatter, SelectData } from "@gradio/utils";
|
|
10
10
|
import type { CustomButton as CustomButtonType } from "@gradio/utils";
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
let {
|
|
13
|
+
value = $bindable<null | FileData | FileData[]>(),
|
|
14
|
+
label,
|
|
15
|
+
show_label = true,
|
|
16
|
+
file_count = "single",
|
|
17
|
+
file_types = null,
|
|
18
|
+
selectable = false,
|
|
19
|
+
root,
|
|
20
|
+
height = undefined,
|
|
21
|
+
i18n,
|
|
22
|
+
max_file_size = null,
|
|
23
|
+
upload,
|
|
24
|
+
stream_handler,
|
|
25
|
+
uploading = $bindable(false),
|
|
26
|
+
allow_reordering = false,
|
|
27
|
+
upload_promise = $bindable<Promise<(FileData | null)[]> | null>(),
|
|
28
|
+
buttons = null,
|
|
29
|
+
on_custom_button_click = null,
|
|
30
|
+
onchange,
|
|
31
|
+
onclear,
|
|
32
|
+
ondrag,
|
|
33
|
+
onupload,
|
|
34
|
+
onerror,
|
|
35
|
+
ondelete,
|
|
36
|
+
onselect
|
|
37
|
+
}: {
|
|
38
|
+
value: null | FileData | FileData[];
|
|
39
|
+
label: string;
|
|
40
|
+
show_label?: boolean;
|
|
41
|
+
file_count: "single" | "multiple" | "directory";
|
|
42
|
+
file_types: string[] | null;
|
|
43
|
+
selectable?: boolean;
|
|
44
|
+
root: string;
|
|
45
|
+
height?: number | undefined;
|
|
46
|
+
i18n: I18nFormatter;
|
|
47
|
+
max_file_size: number | null;
|
|
48
|
+
upload: Client["upload"];
|
|
49
|
+
stream_handler: Client["stream"];
|
|
50
|
+
uploading?: boolean;
|
|
51
|
+
allow_reordering?: boolean;
|
|
52
|
+
upload_promise?: Promise<(FileData | null)[]> | null;
|
|
53
|
+
buttons?: (string | CustomButtonType)[] | null;
|
|
54
|
+
on_custom_button_click?: ((id: number) => void) | null;
|
|
55
|
+
onchange?: (event_data: FileData[] | FileData | null) => void;
|
|
56
|
+
onclear?: () => void;
|
|
57
|
+
ondrag?: (dragging: boolean) => void;
|
|
58
|
+
onupload?: (event_data: FileData[] | FileData) => void;
|
|
59
|
+
onerror?: (error: string) => void;
|
|
60
|
+
ondelete?: (event_data: FileData) => void;
|
|
61
|
+
onselect?: (event_data: SelectData) => void;
|
|
62
|
+
} = $props();
|
|
13
63
|
|
|
14
|
-
|
|
15
|
-
export let show_label = true;
|
|
16
|
-
export let file_count: "single" | "multiple" | "directory" = "single";
|
|
17
|
-
export let file_types: string[] | null = null;
|
|
18
|
-
export let selectable = false;
|
|
19
|
-
export let root: string;
|
|
20
|
-
export let height: number | undefined = undefined;
|
|
21
|
-
export let i18n: I18nFormatter;
|
|
22
|
-
export let max_file_size: number | null = null;
|
|
23
|
-
export let upload: Client["upload"];
|
|
24
|
-
export let stream_handler: Client["stream"];
|
|
25
|
-
export let uploading = false;
|
|
26
|
-
export let allow_reordering = false;
|
|
27
|
-
export let upload_promise: Promise<(FileData | null)[]> | null = null;
|
|
28
|
-
export let buttons: (string | CustomButtonType)[] | null = null;
|
|
29
|
-
export let on_custom_button_click: ((id: number) => void) | null = null;
|
|
30
|
-
|
|
31
|
-
async function handle_upload({
|
|
32
|
-
detail
|
|
33
|
-
}: CustomEvent<FileData | FileData[]>): Promise<void> {
|
|
64
|
+
async function handle_upload(detail: FileData | FileData[]): Promise<void> {
|
|
34
65
|
if (Array.isArray(value)) {
|
|
35
66
|
value = [...value, ...(Array.isArray(detail) ? detail : [detail])];
|
|
36
67
|
} else if (value) {
|
|
@@ -39,27 +70,17 @@
|
|
|
39
70
|
value = detail;
|
|
40
71
|
}
|
|
41
72
|
await tick();
|
|
42
|
-
|
|
43
|
-
|
|
73
|
+
onchange?.(value);
|
|
74
|
+
onupload?.(value);
|
|
44
75
|
}
|
|
45
76
|
|
|
46
77
|
function handle_clear(): void {
|
|
47
78
|
value = null;
|
|
48
|
-
|
|
49
|
-
|
|
79
|
+
onchange?.(null);
|
|
80
|
+
onclear?.();
|
|
50
81
|
}
|
|
51
82
|
|
|
52
|
-
|
|
53
|
-
change: FileData[] | FileData | null;
|
|
54
|
-
clear: undefined;
|
|
55
|
-
drag: boolean;
|
|
56
|
-
upload: FileData[] | FileData;
|
|
57
|
-
load: FileData[] | FileData;
|
|
58
|
-
error: string;
|
|
59
|
-
}>();
|
|
60
|
-
|
|
61
|
-
let dragging = false;
|
|
62
|
-
$: dispatch("drag", dragging);
|
|
83
|
+
let dragging = $state(false);
|
|
63
84
|
</script>
|
|
64
85
|
|
|
65
86
|
{#if show_label && buttons && buttons.length > 0}
|
|
@@ -74,14 +95,14 @@
|
|
|
74
95
|
<Upload
|
|
75
96
|
bind:upload_promise
|
|
76
97
|
icon_upload={true}
|
|
77
|
-
|
|
98
|
+
onload={handle_upload}
|
|
78
99
|
filetype={file_types}
|
|
79
100
|
{file_count}
|
|
80
101
|
{max_file_size}
|
|
81
102
|
{root}
|
|
82
103
|
bind:dragging
|
|
83
104
|
bind:uploading
|
|
84
|
-
|
|
105
|
+
{onerror}
|
|
85
106
|
{stream_handler}
|
|
86
107
|
{upload}
|
|
87
108
|
/>
|
|
@@ -90,8 +111,7 @@
|
|
|
90
111
|
<IconButton
|
|
91
112
|
Icon={Clear}
|
|
92
113
|
label={i18n("common.clear")}
|
|
93
|
-
|
|
94
|
-
dispatch("clear");
|
|
114
|
+
onclick={(event) => {
|
|
95
115
|
event.stopPropagation();
|
|
96
116
|
handle_clear();
|
|
97
117
|
}}
|
|
@@ -100,25 +120,25 @@
|
|
|
100
120
|
|
|
101
121
|
<FilePreview
|
|
102
122
|
{i18n}
|
|
103
|
-
|
|
123
|
+
{onselect}
|
|
104
124
|
{selectable}
|
|
105
125
|
{value}
|
|
106
126
|
{height}
|
|
107
|
-
|
|
108
|
-
|
|
127
|
+
{onchange}
|
|
128
|
+
{ondelete}
|
|
109
129
|
{allow_reordering}
|
|
110
130
|
/>
|
|
111
131
|
{:else}
|
|
112
132
|
<Upload
|
|
113
133
|
bind:upload_promise
|
|
114
|
-
|
|
134
|
+
onload={handle_upload}
|
|
115
135
|
filetype={file_types}
|
|
116
136
|
{file_count}
|
|
117
137
|
{max_file_size}
|
|
118
138
|
{root}
|
|
119
139
|
bind:dragging
|
|
120
140
|
bind:uploading
|
|
121
|
-
|
|
141
|
+
{onerror}
|
|
122
142
|
{stream_handler}
|
|
123
143
|
{upload}
|
|
124
144
|
{height}
|