@gradio/image 0.23.2-dev.0 → 0.24.0-dev.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.
@@ -1,3 +1,5 @@
1
+ import type { LoadingStatus } from "@gradio/statustracker";
2
+ import type { FileData } from "@gradio/client";
1
3
  export interface Base64File {
2
4
  url: string;
3
5
  alt_text: string;
@@ -6,3 +8,31 @@ export interface WebcamOptions {
6
8
  mirror: boolean;
7
9
  constraints: MediaStreamConstraints;
8
10
  }
11
+ export interface ImageProps {
12
+ _selectable: boolean;
13
+ sources: ("clipboard" | "webcam" | "upload")[];
14
+ height: number;
15
+ width: number;
16
+ webcam_options: WebcamOptions;
17
+ value: FileData | null;
18
+ buttons: string[];
19
+ pending: boolean;
20
+ streaming: boolean;
21
+ stream_every: number;
22
+ input_ready: boolean;
23
+ placeholder: string;
24
+ watermark: FileData | null;
25
+ }
26
+ export interface ImageEvents {
27
+ clear: void;
28
+ change: any;
29
+ stream: any;
30
+ select: any;
31
+ upload: any;
32
+ input: any;
33
+ clear_status: LoadingStatus;
34
+ share: any;
35
+ error: any;
36
+ close_stream: void;
37
+ edit: void;
38
+ }
package/package.json CHANGED
@@ -1,24 +1,24 @@
1
1
  {
2
2
  "name": "@gradio/image",
3
- "version": "0.23.2-dev.0",
3
+ "version": "0.24.0-dev.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
- "cropperjs": "^1.5.12",
11
- "lazy-brush": "^1.0.1",
10
+ "cropperjs": "^2.0.1",
11
+ "lazy-brush": "^2.0.2",
12
12
  "resize-observer-polyfill": "^1.5.1",
13
- "@gradio/atoms": "^0.18.1",
14
- "@gradio/statustracker": "^0.11.1",
15
- "@gradio/icons": "^0.14.0",
16
- "@gradio/client": "^2.0.0-dev.0",
17
- "@gradio/utils": "^0.10.2",
18
- "@gradio/upload": "^0.17.2-dev.0"
13
+ "@gradio/atoms": "^0.19.0-dev.1",
14
+ "@gradio/client": "^2.0.0-dev.2",
15
+ "@gradio/statustracker": "^0.12.0-dev.1",
16
+ "@gradio/upload": "^0.17.2-dev.2",
17
+ "@gradio/utils": "^0.10.3-dev.0",
18
+ "@gradio/icons": "^0.15.0-dev.0"
19
19
  },
20
20
  "devDependencies": {
21
- "@gradio/preview": "^0.14.0"
21
+ "@gradio/preview": "^0.15.0-dev.0"
22
22
  },
23
23
  "main_changeset": true,
24
24
  "main": "./Index.svelte",
@@ -46,7 +46,7 @@
46
46
  }
47
47
  },
48
48
  "peerDependencies": {
49
- "svelte": "^4.0.0"
49
+ "svelte": "^5.43.4"
50
50
  },
51
51
  "repository": {
52
52
  "type": "git",
@@ -1,16 +1,25 @@
1
1
  <script lang="ts">
2
- import type { HTMLImgAttributes } from "svelte/elements";
3
-
4
- interface Props extends HTMLImgAttributes {
5
- "data-testid"?: string;
6
- }
7
- type $$Props = Props;
8
-
9
- export let src: HTMLImgAttributes["src"] = undefined;
2
+ let {
3
+ src,
4
+ restProps,
5
+ data_testid,
6
+ class_names
7
+ }: {
8
+ src: string;
9
+ restProps: object;
10
+ data_testid: string;
11
+ class_names: string[];
12
+ } = $props();
10
13
  </script>
11
14
 
12
15
  <!-- svelte-ignore a11y-missing-attribute -->
13
- <img {src} {...$$restProps} on:load />
16
+ <img
17
+ {src}
18
+ class={(class_names || []).join(" ")}
19
+ data-testid={data_testid}
20
+ {...restProps}
21
+ on:load
22
+ />
14
23
 
15
24
  <style>
16
25
  img {
@@ -26,6 +26,7 @@
26
26
  export let i18n: I18nFormatter;
27
27
  export let display_icon_button_wrapper_top_corner = false;
28
28
  export let fullscreen = false;
29
+ export let show_button_background = true;
29
30
 
30
31
  const dispatch = createEventDispatcher<{
31
32
  change: string;
@@ -48,12 +49,13 @@
48
49
  Icon={ImageIcon}
49
50
  label={!show_label ? "" : label || i18n("image.image")}
50
51
  />
51
- {#if value === null || !value.url}
52
+ {#if value == null || !value?.url}
52
53
  <Empty unpadded_box={true} size="large"><ImageIcon /></Empty>
53
54
  {:else}
54
55
  <div class="image-container" bind:this={image_container}>
55
56
  <IconButtonWrapper
56
57
  display_top_corner={display_icon_button_wrapper_top_corner}
58
+ show_background={show_button_background}
57
59
  >
58
60
  {#if buttons === null ? true : buttons.includes("fullscreen")}
59
61
  <FullscreenButton {fullscreen} on:fullscreen />
@@ -80,7 +82,11 @@
80
82
  </IconButtonWrapper>
81
83
  <button on:click={handle_click}>
82
84
  <div class:selectable class="image-frame">
83
- <Image src={value.url} alt="" loading="lazy" on:load />
85
+ <Image
86
+ src={value.url}
87
+ restProps={{ loading: "lazy", alt: "" }}
88
+ on:load
89
+ />
84
90
  </div>
85
91
  </button>
86
92
  </div>
@@ -34,10 +34,10 @@
34
34
  export let upload: Client["upload"];
35
35
  export let stream_handler: Client["stream"];
36
36
  export let stream_every: number;
37
-
38
- export let modify_stream: (state: "open" | "closed" | "waiting") => void;
39
- export let set_time_limit: (arg0: number) => void;
37
+ export let time_limit: number;
40
38
  export let show_fullscreen_button = true;
39
+ export let stream_state: "open" | "waiting" | "closed" = "closed";
40
+ export let upload_promise: Promise<any> | null = null;
41
41
 
42
42
  let upload_input: Upload;
43
43
  export let uploading = false;
@@ -82,6 +82,7 @@
82
82
  img_blob: Blob | any,
83
83
  event: "change" | "stream" | "upload"
84
84
  ): Promise<void> {
85
+ console.log("handle_save", { event, img_blob });
85
86
  if (event === "stream") {
86
87
  dispatch("stream", {
87
88
  value: { url: img_blob } as Base64File,
@@ -103,6 +104,7 @@
103
104
  ];
104
105
  pending = true;
105
106
  const f = await upload_input.load_files([f_], upload_id);
107
+ console.log("uploaded file", f);
106
108
  if (event === "change" || event === "upload") {
107
109
  value = f?.[0] || null;
108
110
  await tick();
@@ -203,6 +205,7 @@
203
205
  on:drop={on_drop}
204
206
  >
205
207
  <Upload
208
+ bind:upload_promise
206
209
  hidden={value !== null || active_source === "webcam"}
207
210
  bind:this={upload_input}
208
211
  bind:uploading
@@ -233,6 +236,7 @@
233
236
  on:drag
234
237
  on:upload={(e) => handle_save(e.detail, "upload")}
235
238
  on:close_stream
239
+ {stream_state}
236
240
  mirror_webcam={webcam_options.mirror}
237
241
  {stream_every}
238
242
  {streaming}
@@ -240,15 +244,14 @@
240
244
  include_audio={false}
241
245
  {i18n}
242
246
  {upload}
243
- bind:modify_stream
244
- bind:set_time_limit
247
+ {time_limit}
245
248
  webcam_constraints={webcam_options.constraints}
246
249
  />
247
250
  {:else if value !== null && !streaming}
248
251
  <!-- svelte-ignore a11y-click-events-have-key-events-->
249
252
  <!-- svelte-ignore a11y-no-static-element-interactions-->
250
253
  <div class:selectable class="image-frame" on:click={handle_click}>
251
- <Image src={value.url} alt={value.alt_text} />
254
+ <Image src={value.url} restProps={{ alt: value.alt_text }} />
252
255
  </div>
253
256
  {/if}
254
257
  </div>
@@ -22,26 +22,8 @@
22
22
  let video_source: HTMLVideoElement;
23
23
  let available_video_devices: MediaDeviceInfo[] = [];
24
24
  let selected_device: MediaDeviceInfo | null = null;
25
- let time_limit: number | null = null;
26
- let stream_state: "open" | "waiting" | "closed" = "closed";
27
-
28
- export const modify_stream: (state: "open" | "closed" | "waiting") => void = (
29
- state: "open" | "closed" | "waiting"
30
- ) => {
31
- if (state === "closed") {
32
- time_limit = null;
33
- stream_state = "closed";
34
- value = null;
35
- } else if (state === "waiting") {
36
- stream_state = "waiting";
37
- } else {
38
- stream_state = "open";
39
- }
40
- };
41
25
 
42
- export const set_time_limit = (time: number): void => {
43
- if (recording) time_limit = time;
44
- };
26
+ export let stream_state: "open" | "waiting" | "closed" = "closed";
45
27
 
46
28
  let canvas: HTMLCanvasElement;
47
29
  export let streaming = false;
@@ -56,7 +38,7 @@
56
38
  export let i18n: I18nFormatter;
57
39
  export let upload: Client["upload"];
58
40
  export let value: FileData | null | Base64File = null;
59
-
41
+ export let time_limit: number | null = null;
60
42
  const dispatch = createEventDispatcher<{
61
43
  stream: Blob | string;
62
44
  capture: FileData | Blob | null;
@@ -131,12 +113,13 @@
131
113
  }
132
114
 
133
115
  function take_picture(): void {
134
- var context = canvas.getContext("2d")!;
135
116
  if (
136
117
  (!streaming || (streaming && recording)) &&
137
118
  video_source.videoWidth &&
138
119
  video_source.videoHeight
139
120
  ) {
121
+ console.log("Taking picture from webcam");
122
+ var context = canvas.getContext("2d")!;
140
123
  canvas.width = video_source.videoWidth;
141
124
  canvas.height = video_source.videoHeight;
142
125
  context.drawImage(
@@ -241,13 +224,6 @@
241
224
 
242
225
  if (!recording && stream) {
243
226
  dispatch("close_stream");
244
- stream.getTracks().forEach((track) => track.stop());
245
- video_source.srcObject = null;
246
- webcam_accessed = false;
247
- window.setTimeout(() => {
248
- value = null;
249
- }, 500);
250
- value = null;
251
227
  }
252
228
  }
253
229
 
@@ -360,12 +336,12 @@
360
336
  use:click_outside={handle_click_outside}
361
337
  on:change={handle_device_change}
362
338
  >
363
- <button
339
+ <!-- <button
364
340
  class="inset-icon"
365
341
  on:click|stopPropagation={() => (options_open = false)}
366
342
  >
367
343
  <DropdownArrow />
368
- </button>
344
+ </button> -->
369
345
  {#if available_video_devices.length === 0}
370
346
  <option value="">{i18n("common.no_devices")}</option>
371
347
  {:else}
package/shared/types.ts CHANGED
@@ -1,3 +1,6 @@
1
+ import type { LoadingStatus } from "@gradio/statustracker";
2
+ import type { FileData } from "@gradio/client";
3
+
1
4
  export interface Base64File {
2
5
  url: string;
3
6
  alt_text: string;
@@ -7,3 +10,33 @@ export interface WebcamOptions {
7
10
  mirror: boolean;
8
11
  constraints: MediaStreamConstraints;
9
12
  }
13
+
14
+ export interface ImageProps {
15
+ _selectable: boolean;
16
+ sources: ("clipboard" | "webcam" | "upload")[];
17
+ height: number;
18
+ width: number;
19
+ webcam_options: WebcamOptions;
20
+ value: FileData | null;
21
+ buttons: string[];
22
+ pending: boolean;
23
+ streaming: boolean;
24
+ stream_every: number;
25
+ input_ready: boolean;
26
+ placeholder: string;
27
+ watermark: FileData | null;
28
+ }
29
+
30
+ export interface ImageEvents {
31
+ clear: void;
32
+ change: any;
33
+ stream: any;
34
+ select: any;
35
+ upload: any;
36
+ input: any;
37
+ clear_status: LoadingStatus;
38
+ share: any;
39
+ error: any;
40
+ close_stream: void;
41
+ edit: void;
42
+ }