@gradio/file 0.11.3 → 0.12.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 +20 -0
- package/File.stories.svelte +28 -11
- package/Index.svelte +2 -0
- package/dist/Index.svelte +2 -0
- package/dist/Index.svelte.d.ts +4 -0
- package/dist/shared/FilePreview.svelte +96 -2
- package/dist/shared/FilePreview.svelte.d.ts +3 -1
- package/dist/shared/FileUpload.svelte +3 -0
- package/dist/shared/FileUpload.svelte.d.ts +1 -0
- package/package.json +8 -8
- package/shared/FilePreview.svelte +110 -3
- package/shared/FileUpload.svelte +3 -0
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
# @gradio/file
|
2
2
|
|
3
|
+
## 0.12.0
|
4
|
+
|
5
|
+
### Features
|
6
|
+
|
7
|
+
- [#10210](https://github.com/gradio-app/gradio/pull/10210) [`13a83e5`](https://github.com/gradio-app/gradio/commit/13a83e5001e29594990d61569887cb8562744964) - Allow reordering files in gr.File. Thanks @hannahblair!
|
8
|
+
|
9
|
+
### Fixes
|
10
|
+
|
11
|
+
- [#10209](https://github.com/gradio-app/gradio/pull/10209) [`2700d18`](https://github.com/gradio-app/gradio/commit/2700d1898bc8eeb3fd9f65ce77be17c2614a388f) - Ensure the `height` param in `gr.File` works as expected. Thanks @hannahblair!
|
12
|
+
|
13
|
+
### Dependency updates
|
14
|
+
|
15
|
+
- @gradio/atoms@0.13.0
|
16
|
+
- @gradio/utils@0.10.0
|
17
|
+
- @gradio/upload@0.14.4
|
18
|
+
- @gradio/client@1.9.0
|
19
|
+
- @gradio/icons@0.9.0
|
20
|
+
- @gradio/statustracker@0.10.0
|
21
|
+
- @gradio/wasm@0.16.0
|
22
|
+
|
3
23
|
## 0.11.3
|
4
24
|
|
5
25
|
### Dependency updates
|
package/File.stories.svelte
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
<script>
|
2
2
|
import { Meta, Template, Story } from "@storybook/addon-svelte-csf";
|
3
|
-
import
|
3
|
+
import File from "./Index.svelte";
|
4
4
|
</script>
|
5
5
|
|
6
6
|
<Meta
|
7
7
|
title="Components/File"
|
8
|
-
component={
|
8
|
+
component={File}
|
9
9
|
argTypes={{
|
10
10
|
value: {
|
11
11
|
control: "text",
|
@@ -17,7 +17,7 @@
|
|
17
17
|
/>
|
18
18
|
|
19
19
|
<Template let:args>
|
20
|
-
<
|
20
|
+
<File {...args} />
|
21
21
|
</Template>
|
22
22
|
|
23
23
|
<Story
|
@@ -34,14 +34,31 @@
|
|
34
34
|
}}
|
35
35
|
/>
|
36
36
|
<Story
|
37
|
-
name="Multiple files, with height set to 150px"
|
37
|
+
name="Multiple files, with height set to 150px and reordering enabled"
|
38
38
|
args={{
|
39
|
-
value:
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
39
|
+
value: [
|
40
|
+
{
|
41
|
+
path: "cheetah.jpg",
|
42
|
+
orig_name: "cheetah.jpgz",
|
43
|
+
url: "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png",
|
44
|
+
size: 10000
|
45
|
+
},
|
46
|
+
{
|
47
|
+
path: "cheetah.jpgs",
|
48
|
+
orig_name: "cheetah.jpg",
|
49
|
+
url: "https://gradio-builds.s3.amazonaws.com/demo-files/ghepardo-primo-piano.jpg",
|
50
|
+
size: 10000
|
51
|
+
}
|
52
|
+
],
|
53
|
+
height: 150,
|
54
|
+
allow_reordering: true
|
55
|
+
}}
|
56
|
+
/>
|
57
|
+
<Story
|
58
|
+
name="File upload with height set to 400px"
|
59
|
+
args={{
|
60
|
+
interactive: true,
|
61
|
+
value: null,
|
62
|
+
height: 400
|
46
63
|
}}
|
47
64
|
/>
|
package/Index.svelte
CHANGED
@@ -46,6 +46,7 @@
|
|
46
46
|
export let file_count: "single" | "multiple" | "directory";
|
47
47
|
export let file_types: string[] = ["file"];
|
48
48
|
export let input_ready: boolean;
|
49
|
+
export let allow_reordering = false;
|
49
50
|
let uploading = false;
|
50
51
|
$: input_ready = !uploading;
|
51
52
|
|
@@ -103,6 +104,7 @@
|
|
103
104
|
selectable={_selectable}
|
104
105
|
{root}
|
105
106
|
{height}
|
107
|
+
{allow_reordering}
|
106
108
|
bind:uploading
|
107
109
|
max_file_size={gradio.max_file_size}
|
108
110
|
on:change={({ detail }) => {
|
package/dist/Index.svelte
CHANGED
@@ -28,6 +28,7 @@ export let gradio;
|
|
28
28
|
export let file_count;
|
29
29
|
export let file_types = ["file"];
|
30
30
|
export let input_ready;
|
31
|
+
export let allow_reordering = false;
|
31
32
|
let uploading = false;
|
32
33
|
$:
|
33
34
|
input_ready = !uploading;
|
@@ -85,6 +86,7 @@ let pending_upload = false;
|
|
85
86
|
selectable={_selectable}
|
86
87
|
{root}
|
87
88
|
{height}
|
89
|
+
{allow_reordering}
|
88
90
|
bind:uploading
|
89
91
|
max_file_size={gradio.max_file_size}
|
90
92
|
on:change={({ detail }) => {
|
package/dist/Index.svelte.d.ts
CHANGED
@@ -35,6 +35,7 @@ declare const __propDef: {
|
|
35
35
|
file_count: "single" | "multiple" | "directory";
|
36
36
|
file_types?: string[] | undefined;
|
37
37
|
input_ready: boolean;
|
38
|
+
allow_reordering?: boolean | undefined;
|
38
39
|
};
|
39
40
|
events: {
|
40
41
|
[evt: string]: CustomEvent<any>;
|
@@ -117,4 +118,7 @@ export default class Index extends SvelteComponent<IndexProps, IndexEvents, Inde
|
|
117
118
|
get input_ready(): boolean;
|
118
119
|
/**accessor*/
|
119
120
|
set input_ready(_: boolean);
|
121
|
+
get allow_reordering(): boolean | undefined;
|
122
|
+
/**accessor*/
|
123
|
+
set allow_reordering(_: boolean | undefined);
|
120
124
|
}
|
@@ -6,6 +6,51 @@ export let value;
|
|
6
6
|
export let selectable = false;
|
7
7
|
export let height = void 0;
|
8
8
|
export let i18n;
|
9
|
+
export let allow_reordering = false;
|
10
|
+
let dragging_index = null;
|
11
|
+
let drop_target_index = null;
|
12
|
+
function handle_drag_start(event, index) {
|
13
|
+
dragging_index = index;
|
14
|
+
if (event.dataTransfer) {
|
15
|
+
event.dataTransfer.effectAllowed = "move";
|
16
|
+
event.dataTransfer.setData("text/plain", index.toString());
|
17
|
+
}
|
18
|
+
}
|
19
|
+
function handle_drag_over(event, index) {
|
20
|
+
event.preventDefault();
|
21
|
+
if (index === normalized_files.length - 1) {
|
22
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
23
|
+
const midY = rect.top + rect.height / 2;
|
24
|
+
drop_target_index = event.clientY > midY ? normalized_files.length : index;
|
25
|
+
} else {
|
26
|
+
drop_target_index = index;
|
27
|
+
}
|
28
|
+
if (event.dataTransfer) {
|
29
|
+
event.dataTransfer.dropEffect = "move";
|
30
|
+
}
|
31
|
+
}
|
32
|
+
function handle_drag_end(event) {
|
33
|
+
if (!event.dataTransfer?.dropEffect || event.dataTransfer.dropEffect === "none") {
|
34
|
+
dragging_index = null;
|
35
|
+
drop_target_index = null;
|
36
|
+
}
|
37
|
+
}
|
38
|
+
function handle_drop(event, index) {
|
39
|
+
event.preventDefault();
|
40
|
+
if (dragging_index === null || dragging_index === index)
|
41
|
+
return;
|
42
|
+
const files = Array.isArray(value) ? [...value] : [value];
|
43
|
+
const [removed] = files.splice(dragging_index, 1);
|
44
|
+
files.splice(
|
45
|
+
drop_target_index === normalized_files.length ? normalized_files.length : index,
|
46
|
+
0,
|
47
|
+
removed
|
48
|
+
);
|
49
|
+
const new_value = Array.isArray(value) ? files : files[0];
|
50
|
+
dispatch("change", new_value);
|
51
|
+
dragging_index = null;
|
52
|
+
drop_target_index = null;
|
53
|
+
}
|
9
54
|
function split_filename(filename) {
|
10
55
|
const last_dot = filename.lastIndexOf(".");
|
11
56
|
if (last_dot === -1) {
|
@@ -45,19 +90,42 @@ const is_browser = typeof window !== "undefined";
|
|
45
90
|
|
46
91
|
<div
|
47
92
|
class="file-preview-holder"
|
48
|
-
style
|
93
|
+
style:max-height={height
|
94
|
+
? typeof height === "number"
|
95
|
+
? height + "px"
|
96
|
+
: height
|
97
|
+
: "auto"}
|
49
98
|
>
|
50
99
|
<table class="file-preview">
|
51
100
|
<tbody>
|
52
|
-
{#each normalized_files as file, i (file)}
|
101
|
+
{#each normalized_files as file, i (file.url)}
|
53
102
|
<tr
|
54
103
|
class="file"
|
55
104
|
class:selectable
|
105
|
+
class:dragging={dragging_index === i}
|
106
|
+
class:drop-target={drop_target_index === i ||
|
107
|
+
(i === normalized_files.length - 1 &&
|
108
|
+
drop_target_index === normalized_files.length)}
|
109
|
+
data-drop-target={drop_target_index === normalized_files.length &&
|
110
|
+
i === normalized_files.length - 1
|
111
|
+
? "after"
|
112
|
+
: drop_target_index === i + 1
|
113
|
+
? "after"
|
114
|
+
: "before"}
|
115
|
+
draggable={allow_reordering && normalized_files.length > 1}
|
56
116
|
on:click={(event) => {
|
57
117
|
handle_row_click(event, i);
|
58
118
|
}}
|
119
|
+
on:dragstart={(event) => handle_drag_start(event, i)}
|
120
|
+
on:dragenter|preventDefault
|
121
|
+
on:dragover={(event) => handle_drag_over(event, i)}
|
122
|
+
on:drop={(event) => handle_drop(event, i)}
|
123
|
+
on:dragend={handle_drag_end}
|
59
124
|
>
|
60
125
|
<td class="filename" aria-label={file.orig_name}>
|
126
|
+
{#if allow_reordering && normalized_files.length > 1}
|
127
|
+
<span class="drag-handle">⋮⋮</span>
|
128
|
+
{/if}
|
61
129
|
<span class="stem">{file.filename_stem}</span>
|
62
130
|
<span class="ext">{file.filename_ext}</span>
|
63
131
|
</td>
|
@@ -183,4 +251,30 @@ const is_browser = typeof window !== "undefined";
|
|
183
251
|
tbody > tr:nth-child(odd) {
|
184
252
|
background: var(--table-odd-background-fill);
|
185
253
|
}
|
254
|
+
|
255
|
+
.drag-handle {
|
256
|
+
cursor: grab;
|
257
|
+
color: var(--body-text-color-subdued);
|
258
|
+
padding-right: var(--size-2);
|
259
|
+
user-select: none;
|
260
|
+
}
|
261
|
+
|
262
|
+
.dragging {
|
263
|
+
opacity: 0.5;
|
264
|
+
cursor: grabbing;
|
265
|
+
}
|
266
|
+
|
267
|
+
.drop-target {
|
268
|
+
border-top: 2px solid var(--color-accent);
|
269
|
+
}
|
270
|
+
|
271
|
+
tr:last-child.drop-target[data-drop-target="before"] {
|
272
|
+
border-top: 2px solid var(--color-accent);
|
273
|
+
border-bottom: none;
|
274
|
+
}
|
275
|
+
|
276
|
+
tr:last-child.drop-target[data-drop-target="after"] {
|
277
|
+
border-top: none;
|
278
|
+
border-bottom: 2px solid var(--color-accent);
|
279
|
+
}
|
186
280
|
</style>
|
@@ -5,10 +5,12 @@ declare const __propDef: {
|
|
5
5
|
props: {
|
6
6
|
value: FileData | FileData[];
|
7
7
|
selectable?: boolean | undefined;
|
8
|
-
height?: number | undefined;
|
8
|
+
height?: number | string | undefined;
|
9
9
|
i18n: I18nFormatter;
|
10
|
+
allow_reordering?: boolean | undefined;
|
10
11
|
};
|
11
12
|
events: {
|
13
|
+
dragenter: DragEvent;
|
12
14
|
select: CustomEvent<SelectData>;
|
13
15
|
change: CustomEvent<any>;
|
14
16
|
delete: CustomEvent<FileData>;
|
@@ -16,6 +16,7 @@ export let max_file_size = null;
|
|
16
16
|
export let upload;
|
17
17
|
export let stream_handler;
|
18
18
|
export let uploading = false;
|
19
|
+
export let allow_reordering = false;
|
19
20
|
async function handle_upload({
|
20
21
|
detail
|
21
22
|
}) {
|
@@ -81,6 +82,7 @@ $:
|
|
81
82
|
{height}
|
82
83
|
on:change
|
83
84
|
on:delete
|
85
|
+
{allow_reordering}
|
84
86
|
/>
|
85
87
|
{:else}
|
86
88
|
<Upload
|
@@ -94,6 +96,7 @@ $:
|
|
94
96
|
on:error
|
95
97
|
{stream_handler}
|
96
98
|
{upload}
|
99
|
+
{height}
|
97
100
|
>
|
98
101
|
<slot />
|
99
102
|
</Upload>
|
package/package.json
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
{
|
2
2
|
"name": "@gradio/file",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.12.0",
|
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/client": "^1.
|
12
|
-
"@gradio/
|
13
|
-
"@gradio/
|
14
|
-
"@gradio/
|
15
|
-
"@gradio/
|
16
|
-
"@gradio/
|
10
|
+
"@gradio/atoms": "^0.13.0",
|
11
|
+
"@gradio/client": "^1.9.0",
|
12
|
+
"@gradio/icons": "^0.9.0",
|
13
|
+
"@gradio/statustracker": "^0.10.0",
|
14
|
+
"@gradio/utils": "^0.10.0",
|
15
|
+
"@gradio/upload": "^0.14.4",
|
16
|
+
"@gradio/wasm": "^0.16.0"
|
17
17
|
},
|
18
18
|
"devDependencies": {
|
19
19
|
"@gradio/preview": "^0.13.0"
|
@@ -13,8 +13,66 @@
|
|
13
13
|
}>();
|
14
14
|
export let value: FileData | FileData[];
|
15
15
|
export let selectable = false;
|
16
|
-
export let height: number | undefined = undefined;
|
16
|
+
export let height: number | string | undefined = undefined;
|
17
17
|
export let i18n: I18nFormatter;
|
18
|
+
export let allow_reordering = false;
|
19
|
+
|
20
|
+
let dragging_index: number | null = null;
|
21
|
+
let drop_target_index: number | null = null;
|
22
|
+
|
23
|
+
function handle_drag_start(event: DragEvent, index: number): void {
|
24
|
+
dragging_index = index;
|
25
|
+
if (event.dataTransfer) {
|
26
|
+
event.dataTransfer.effectAllowed = "move";
|
27
|
+
event.dataTransfer.setData("text/plain", index.toString());
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
function handle_drag_over(event: DragEvent, index: number): void {
|
32
|
+
event.preventDefault();
|
33
|
+
if (index === normalized_files.length - 1) {
|
34
|
+
const rect = (event.currentTarget as HTMLElement).getBoundingClientRect();
|
35
|
+
const midY = rect.top + rect.height / 2;
|
36
|
+
drop_target_index =
|
37
|
+
event.clientY > midY ? normalized_files.length : index;
|
38
|
+
} else {
|
39
|
+
drop_target_index = index;
|
40
|
+
}
|
41
|
+
if (event.dataTransfer) {
|
42
|
+
event.dataTransfer.dropEffect = "move";
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
function handle_drag_end(event: DragEvent): void {
|
47
|
+
if (
|
48
|
+
!event.dataTransfer?.dropEffect ||
|
49
|
+
event.dataTransfer.dropEffect === "none"
|
50
|
+
) {
|
51
|
+
dragging_index = null;
|
52
|
+
drop_target_index = null;
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
function handle_drop(event: DragEvent, index: number): void {
|
57
|
+
event.preventDefault();
|
58
|
+
if (dragging_index === null || dragging_index === index) return;
|
59
|
+
|
60
|
+
const files = Array.isArray(value) ? [...value] : [value];
|
61
|
+
const [removed] = files.splice(dragging_index, 1);
|
62
|
+
files.splice(
|
63
|
+
drop_target_index === normalized_files.length
|
64
|
+
? normalized_files.length
|
65
|
+
: index,
|
66
|
+
0,
|
67
|
+
removed
|
68
|
+
);
|
69
|
+
|
70
|
+
const new_value = Array.isArray(value) ? files : files[0];
|
71
|
+
dispatch("change", new_value);
|
72
|
+
|
73
|
+
dragging_index = null;
|
74
|
+
drop_target_index = null;
|
75
|
+
}
|
18
76
|
|
19
77
|
function split_filename(filename: string): [string, string] {
|
20
78
|
const last_dot = filename.lastIndexOf(".");
|
@@ -66,19 +124,42 @@
|
|
66
124
|
|
67
125
|
<div
|
68
126
|
class="file-preview-holder"
|
69
|
-
style
|
127
|
+
style:max-height={height
|
128
|
+
? typeof height === "number"
|
129
|
+
? height + "px"
|
130
|
+
: height
|
131
|
+
: "auto"}
|
70
132
|
>
|
71
133
|
<table class="file-preview">
|
72
134
|
<tbody>
|
73
|
-
{#each normalized_files as file, i (file)}
|
135
|
+
{#each normalized_files as file, i (file.url)}
|
74
136
|
<tr
|
75
137
|
class="file"
|
76
138
|
class:selectable
|
139
|
+
class:dragging={dragging_index === i}
|
140
|
+
class:drop-target={drop_target_index === i ||
|
141
|
+
(i === normalized_files.length - 1 &&
|
142
|
+
drop_target_index === normalized_files.length)}
|
143
|
+
data-drop-target={drop_target_index === normalized_files.length &&
|
144
|
+
i === normalized_files.length - 1
|
145
|
+
? "after"
|
146
|
+
: drop_target_index === i + 1
|
147
|
+
? "after"
|
148
|
+
: "before"}
|
149
|
+
draggable={allow_reordering && normalized_files.length > 1}
|
77
150
|
on:click={(event) => {
|
78
151
|
handle_row_click(event, i);
|
79
152
|
}}
|
153
|
+
on:dragstart={(event) => handle_drag_start(event, i)}
|
154
|
+
on:dragenter|preventDefault
|
155
|
+
on:dragover={(event) => handle_drag_over(event, i)}
|
156
|
+
on:drop={(event) => handle_drop(event, i)}
|
157
|
+
on:dragend={handle_drag_end}
|
80
158
|
>
|
81
159
|
<td class="filename" aria-label={file.orig_name}>
|
160
|
+
{#if allow_reordering && normalized_files.length > 1}
|
161
|
+
<span class="drag-handle">⋮⋮</span>
|
162
|
+
{/if}
|
82
163
|
<span class="stem">{file.filename_stem}</span>
|
83
164
|
<span class="ext">{file.filename_ext}</span>
|
84
165
|
</td>
|
@@ -204,4 +285,30 @@
|
|
204
285
|
tbody > tr:nth-child(odd) {
|
205
286
|
background: var(--table-odd-background-fill);
|
206
287
|
}
|
288
|
+
|
289
|
+
.drag-handle {
|
290
|
+
cursor: grab;
|
291
|
+
color: var(--body-text-color-subdued);
|
292
|
+
padding-right: var(--size-2);
|
293
|
+
user-select: none;
|
294
|
+
}
|
295
|
+
|
296
|
+
.dragging {
|
297
|
+
opacity: 0.5;
|
298
|
+
cursor: grabbing;
|
299
|
+
}
|
300
|
+
|
301
|
+
.drop-target {
|
302
|
+
border-top: 2px solid var(--color-accent);
|
303
|
+
}
|
304
|
+
|
305
|
+
tr:last-child.drop-target[data-drop-target="before"] {
|
306
|
+
border-top: 2px solid var(--color-accent);
|
307
|
+
border-bottom: none;
|
308
|
+
}
|
309
|
+
|
310
|
+
tr:last-child.drop-target[data-drop-target="after"] {
|
311
|
+
border-top: none;
|
312
|
+
border-bottom: 2px solid var(--color-accent);
|
313
|
+
}
|
207
314
|
</style>
|
package/shared/FileUpload.svelte
CHANGED
@@ -22,6 +22,7 @@
|
|
22
22
|
export let upload: Client["upload"];
|
23
23
|
export let stream_handler: Client["stream"];
|
24
24
|
export let uploading = false;
|
25
|
+
export let allow_reordering = false;
|
25
26
|
|
26
27
|
async function handle_upload({
|
27
28
|
detail
|
@@ -97,6 +98,7 @@
|
|
97
98
|
{height}
|
98
99
|
on:change
|
99
100
|
on:delete
|
101
|
+
{allow_reordering}
|
100
102
|
/>
|
101
103
|
{:else}
|
102
104
|
<Upload
|
@@ -110,6 +112,7 @@
|
|
110
112
|
on:error
|
111
113
|
{stream_handler}
|
112
114
|
{upload}
|
115
|
+
{height}
|
113
116
|
>
|
114
117
|
<slot />
|
115
118
|
</Upload>
|