@gradio/upload 0.3.0-beta.4 → 0.3.0-beta.6

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 CHANGED
@@ -1,5 +1,23 @@
1
1
  # @gradio/upload
2
2
 
3
+ ## 0.3.0-beta.6
4
+
5
+ ### Features
6
+
7
+ - [#6143](https://github.com/gradio-app/gradio/pull/6143) [`e4f7b4b40`](https://github.com/gradio-app/gradio/commit/e4f7b4b409323b01aa01b39e15ce6139e29aa073) - fix circular dependency with client + upload. Thanks [@pngwn](https://github.com/pngwn)!
8
+ - [#6136](https://github.com/gradio-app/gradio/pull/6136) [`667802a6c`](https://github.com/gradio-app/gradio/commit/667802a6cdbfb2ce454a3be5a78e0990b194548a) - JS Component Documentation. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
9
+ - [#6094](https://github.com/gradio-app/gradio/pull/6094) [`c476bd5a5`](https://github.com/gradio-app/gradio/commit/c476bd5a5b70836163b9c69bf4bfe068b17fbe13) - Image v4. Thanks [@pngwn](https://github.com/pngwn)!
10
+
11
+ ## 0.3.0-beta.5
12
+
13
+ ### Features
14
+
15
+ - [#6044](https://github.com/gradio-app/gradio/pull/6044) [`9053c95a1`](https://github.com/gradio-app/gradio/commit/9053c95a10de12aef572018ee37c71106d2da675) - Simplify File Component. Thanks [@freddyaboulton](https://github.com/freddyaboulton)!
16
+
17
+ ### Fixes
18
+
19
+ - [#6046](https://github.com/gradio-app/gradio/pull/6046) [`dbb7de5e0`](https://github.com/gradio-app/gradio/commit/dbb7de5e02c53fee05889d696d764d212cb96c74) - fix tests. Thanks [@pngwn](https://github.com/pngwn)!
20
+
3
21
  ## 0.3.0-beta.4
4
22
 
5
23
  ### Features
package/README.md ADDED
@@ -0,0 +1,83 @@
1
+ # `@gradio/upload`
2
+
3
+ ```html
4
+ <script>
5
+ import { Upload, ModifyUpload, normalise_file, get_fetchable_url_or_file, upload, prepare_files } from "@gradio/upload";
6
+ </script>
7
+ ```
8
+
9
+ Upload
10
+ ```javascript
11
+ export let filetype: string | null = null;
12
+ export let dragging = false;
13
+ export let boundedheight = true;
14
+ export let center = true;
15
+ export let flex = true;
16
+ export let file_count = "single";
17
+ export let disable_click = false;
18
+ export let root: string;
19
+ export let hidden = false;
20
+ ```
21
+
22
+ ModifyUpload
23
+ ```javascript
24
+ export let editable = false;
25
+ export let undoable = false;
26
+ export let absolute = true;
27
+ export let i18n: I18nFormatter;
28
+ ```
29
+
30
+ ```javascript
31
+ export function normalise_file(
32
+ file: FileData | null,
33
+ server_url: string,
34
+ proxy_url: string | null
35
+ ): FileData | null;
36
+
37
+ export function normalise_file(
38
+ file: FileData[] | null,
39
+ server_url: string,
40
+ proxy_url: string | null
41
+ ): FileData[] | null;
42
+
43
+ export function normalise_file(
44
+ file: FileData[] | FileData | null,
45
+ server_url: string, // root: string,
46
+ proxy_url: string | null // root_url: string | null
47
+ ): FileData[] | FileData | null;
48
+
49
+ export function normalise_file(
50
+ file: FileData[] | FileData | null,
51
+ server_url: string, // root: string,
52
+ proxy_url: string | null // root_url: string | null
53
+ ): FileData[] | FileData | null;
54
+
55
+ export function get_fetchable_url_or_file(
56
+ path: string | null,
57
+ server_url: string,
58
+ proxy_url: string | null
59
+ ): string
60
+
61
+ export async function upload(
62
+ file_data: FileData[],
63
+ root: string,
64
+ upload_fn: typeof upload_files = upload_files
65
+ ): Promise<(FileData | null)[] | null>
66
+
67
+ export async function prepare_files(
68
+ files: File[],
69
+ is_stream?: boolean
70
+ ): Promise<FileData[]> {
71
+ return files.map(
72
+ (f, i) =>
73
+ new FileData({
74
+ path: f.name,
75
+ orig_name: f.name,
76
+ blob: f,
77
+ size: f.size,
78
+ mime_type: f.type,
79
+ is_stream
80
+ })
81
+ );
82
+ }
83
+ ```
package/package.json CHANGED
@@ -1,17 +1,20 @@
1
1
  {
2
2
  "name": "@gradio/upload",
3
- "version": "0.3.0-beta.4",
3
+ "version": "0.3.0-beta.6",
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/atoms": "^0.2.0-beta.4",
11
- "@gradio/icons": "^0.2.0-beta.1",
12
- "@gradio/client": "^0.5.2",
13
- "@gradio/upload": "^0.3.0-beta.4",
14
- "@gradio/utils": "^0.2.0-beta.4"
10
+ "@gradio/atoms": "^0.2.0-beta.6",
11
+ "@gradio/icons": "^0.2.0-beta.3",
12
+ "@gradio/client": "^0.7.0-beta.1",
13
+ "@gradio/upload": "^0.3.0-beta.6",
14
+ "@gradio/utils": "^0.2.0-beta.6"
15
15
  },
16
- "main_changeset": true
16
+ "main_changeset": true,
17
+ "exports": {
18
+ ".": "./src/index.ts"
19
+ }
17
20
  }
@@ -11,9 +11,9 @@
11
11
  export let i18n: I18nFormatter;
12
12
 
13
13
  const dispatch = createEventDispatcher<{
14
- edit: never;
15
- clear: never;
16
- undo: never;
14
+ edit?: never;
15
+ clear?: never;
16
+ undo?: never;
17
17
  }>();
18
18
  </script>
19
19
 
package/src/Upload.svelte CHANGED
@@ -1,12 +1,8 @@
1
1
  <script lang="ts">
2
2
  import { createEventDispatcher, tick, getContext } from "svelte";
3
- import type { FileData } from "./types";
4
- import { blobToBase64, normalise_file } from "./utils";
5
- import { upload_files as default_upload_files } from "@gradio/client";
6
-
7
- const upload_files =
8
- getContext<typeof default_upload_files>("upload_files") ??
9
- default_upload_files;
3
+ import type { FileData } from "@gradio/client";
4
+ import { upload_files, upload, prepare_files } from "@gradio/client";
5
+ import { _ } from "svelte-i18n";
10
6
 
11
7
  export let filetype: string | null = null;
12
8
  export let dragging = false;
@@ -16,6 +12,10 @@
16
12
  export let file_count = "single";
17
13
  export let disable_click = false;
18
14
  export let root: string;
15
+ export let hidden = false;
16
+
17
+ // Needed for wasm support
18
+ const upload_fn = getContext<typeof upload_files>("upload_files");
19
19
 
20
20
  let hidden_upload: HTMLInputElement;
21
21
 
@@ -25,76 +25,74 @@
25
25
  dragging = !dragging;
26
26
  }
27
27
 
28
- function openFileUpload(): void {
28
+ export function open_file_upload(): void {
29
29
  if (disable_click) return;
30
30
  hidden_upload.value = "";
31
31
  hidden_upload.click();
32
32
  }
33
33
 
34
- async function handle_upload(file_data: FileData[]): Promise<void> {
34
+ async function handle_upload(
35
+ file_data: FileData[]
36
+ ): Promise<(FileData | null)[]> {
35
37
  await tick();
36
- let files = (Array.isArray(file_data) ? file_data : [file_data]).map(
37
- (file_data) => file_data.blob!
38
- );
39
-
40
- await upload_files(root, files).then(async (response) => {
41
- if (response.error) {
42
- (Array.isArray(file_data) ? file_data : [file_data]).forEach(
43
- async (file_data, i) => {
44
- file_data.data = await blobToBase64(file_data.blob!);
45
- file_data.blob = undefined;
46
- }
47
- );
48
- } else {
49
- (Array.isArray(file_data) ? file_data : [file_data]).forEach((f, i) => {
50
- if (response.files) {
51
- f.orig_name = f.name;
52
- f.name = response.files[i];
53
- f.is_file = true;
54
- f.blob = undefined;
55
- normalise_file(f, root, null);
56
- }
57
- });
58
- }
59
- });
60
- dispatch("load", file_count === "single" ? file_data[0] : file_data);
38
+ const _file_data = await upload(file_data, root, upload_fn);
39
+ dispatch("load", file_count === "single" ? _file_data?.[0] : _file_data);
40
+ return _file_data || [];
61
41
  }
62
42
 
63
- async function loadFiles(files: FileList): Promise<void> {
64
- let _files: File[] = Array.from(files);
43
+ export async function load_files(
44
+ files: File[] | Blob[]
45
+ ): Promise<(FileData | null)[] | void> {
65
46
  if (!files.length) {
66
47
  return;
67
48
  }
68
- if (file_count === "single") {
69
- _files = [files[0]];
70
- }
71
- var all_file_data: FileData[] = [];
72
- _files.forEach((f, i) => {
73
- all_file_data[i] = {
74
- name: f.name,
75
- size: f.size,
76
- data: "",
77
- blob: f
78
- };
79
- });
80
- await handle_upload(all_file_data);
49
+
50
+ let _files: File[] = files.map((f) => new File([f], f.name));
51
+
52
+ let file_data = await prepare_files(_files);
53
+ return await handle_upload(file_data);
81
54
  }
82
55
 
83
- async function loadFilesFromUpload(e: Event): Promise<void> {
56
+ async function load_files_from_upload(e: Event): Promise<void> {
84
57
  const target = e.target as HTMLInputElement;
85
-
86
58
  if (!target.files) return;
87
- await loadFiles(target.files);
59
+ await load_files(Array.from(target.files));
60
+ }
61
+
62
+ function is_valid_mimetype(
63
+ file_accept: string | null,
64
+ mime_type: string
65
+ ): boolean {
66
+ if (!file_accept) {
67
+ return true;
68
+ }
69
+ if (file_accept === "*") {
70
+ return true;
71
+ }
72
+ if (file_accept.endsWith("/*")) {
73
+ return mime_type.startsWith(file_accept.slice(0, -1));
74
+ }
75
+ return file_accept === mime_type;
88
76
  }
89
77
 
90
78
  async function loadFilesFromDrop(e: DragEvent): Promise<void> {
91
79
  dragging = false;
92
80
  if (!e.dataTransfer?.files) return;
93
- await loadFiles(e.dataTransfer.files);
81
+
82
+ const files_to_load = Array.from(e.dataTransfer.files).filter((f) => {
83
+ if (is_valid_mimetype(filetype, f.type)) {
84
+ return true;
85
+ }
86
+ dispatch("error", `Invalid file type only ${filetype} allowed.`);
87
+ return false;
88
+ });
89
+
90
+ await load_files(files_to_load);
94
91
  }
95
92
  </script>
96
93
 
97
94
  <button
95
+ class:hidden
98
96
  class:center
99
97
  class:boundedheight
100
98
  class:flex
@@ -105,7 +103,7 @@
105
103
  on:dragenter|preventDefault|stopPropagation
106
104
  on:dragleave|preventDefault|stopPropagation
107
105
  on:drop|preventDefault|stopPropagation
108
- on:click={openFileUpload}
106
+ on:click={open_file_upload}
109
107
  on:drop={loadFilesFromDrop}
110
108
  on:dragenter={updateDragging}
111
109
  on:dragleave={updateDragging}
@@ -114,7 +112,7 @@
114
112
  <input
115
113
  type="file"
116
114
  bind:this={hidden_upload}
117
- on:change={loadFilesFromUpload}
115
+ on:change={load_files_from_upload}
118
116
  accept={filetype}
119
117
  multiple={file_count === "multiple" || undefined}
120
118
  webkitdirectory={file_count === "directory" || undefined}
@@ -129,6 +127,12 @@
129
127
  height: var(--size-full);
130
128
  }
131
129
 
130
+ .hidden {
131
+ display: none;
132
+ height: 0;
133
+ position: absolute;
134
+ }
135
+
132
136
  .center {
133
137
  display: flex;
134
138
  justify-content: center;
package/src/index.ts CHANGED
@@ -1,8 +1,2 @@
1
1
  export { default as Upload } from "./Upload.svelte";
2
2
  export { default as ModifyUpload } from "./ModifyUpload.svelte";
3
- export type { FileData } from "./types";
4
- export {
5
- normalise_file,
6
- get_fetchable_url_or_file,
7
- blobToBase64
8
- } from "./utils";
package/src/types.ts DELETED
@@ -1,11 +0,0 @@
1
- export interface FileData {
2
- name: string;
3
- orig_name?: string;
4
- size?: number;
5
- data: string;
6
- blob?: File;
7
- is_file?: boolean;
8
- is_stream?: boolean;
9
- mime_type?: string;
10
- alt_text?: string;
11
- }
package/src/utils.ts DELETED
@@ -1,87 +0,0 @@
1
- import type { FileData } from "./types";
2
-
3
- export function normalise_file(
4
- file: string | FileData | null,
5
- root: string,
6
- root_url: string | null
7
- ): FileData | null;
8
-
9
- export function normalise_file(
10
- file: FileData[] | null,
11
- root: string,
12
- root_url: string | null
13
- ): FileData[] | null;
14
-
15
- export function normalise_file(
16
- file: FileData[] | FileData | null,
17
- root: string,
18
- root_url: string | null
19
- ): FileData[] | FileData | null;
20
-
21
- export function normalise_file(
22
- file: FileData[] | FileData | string | null,
23
- root: string,
24
- root_url: string | null
25
- ): FileData[] | FileData | null {
26
- if (file == null) return null;
27
- if (typeof file === "string") {
28
- return {
29
- name: "file_data",
30
- data: file
31
- };
32
- } else if (Array.isArray(file)) {
33
- const normalized_file: (FileData | null)[] = [];
34
-
35
- for (const x of file) {
36
- if (x === null) {
37
- normalized_file.push(null);
38
- } else {
39
- normalized_file.push(normalise_file(x, root, root_url));
40
- }
41
- }
42
-
43
- return normalized_file as FileData[];
44
- } else if (file.is_file) {
45
- file.data = get_fetchable_url_or_file(file.name, root, root_url);
46
- } else if (file.is_stream) {
47
- if (root_url == null) {
48
- file.data = root + "/stream/" + file.name;
49
- } else {
50
- file.data = "/proxy=" + root_url + "stream/" + file.name;
51
- }
52
- }
53
- return file;
54
- }
55
-
56
- function is_url(str: string): boolean {
57
- try {
58
- const url = new URL(str);
59
- return url.protocol === "http:" || url.protocol === "https:";
60
- } catch {
61
- return false;
62
- }
63
- }
64
-
65
- export function get_fetchable_url_or_file(
66
- path: string | null,
67
- root: string,
68
- root_url: string | null
69
- ): string {
70
- if (path == null) {
71
- return root_url ? `/proxy=${root_url}file=` : `${root}/file=`;
72
- }
73
- if (is_url(path)) {
74
- return path;
75
- }
76
- return root_url ? `/proxy=${root_url}file=${path}` : `${root}/file=${path}`;
77
- }
78
-
79
- export const blobToBase64 = (blob: File): Promise<string> => {
80
- const reader = new FileReader();
81
- reader.readAsDataURL(blob);
82
- return new Promise((resolve) => {
83
- reader.onloadend = (): void => {
84
- resolve(reader.result as string);
85
- };
86
- });
87
- };