@gradio/image 0.13.1 → 0.14.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 CHANGED
@@ -1,5 +1,19 @@
1
1
  # @gradio/image
2
2
 
3
+ ## 0.14.0
4
+
5
+ ### Features
6
+
7
+ - [#8964](https://github.com/gradio-app/gradio/pull/8964) [`bf6bbd9`](https://github.com/gradio-app/gradio/commit/bf6bbd971acddbf78f03bea431ed7d1e0003ccf9) - Add min/max-imize button to gr.Image and gr.Gallery. Thanks @hannahblair!
8
+
9
+ ### Dependency updates
10
+
11
+ - @gradio/atoms@0.7.9
12
+ - @gradio/statustracker@0.7.4
13
+ - @gradio/client@1.5.0
14
+ - @gradio/icons@0.7.0
15
+ - @gradio/upload@0.12.2
16
+
3
17
  ## 0.13.1
4
18
 
5
19
  ### Dependency updates
@@ -40,6 +40,27 @@
40
40
  }}
41
41
  />
42
42
 
43
+ <Story
44
+ name="static with label and download button"
45
+ args={{
46
+ value: {
47
+ path: "https://gradio-builds.s3.amazonaws.com/demo-files/ghepardo-primo-piano.jpg",
48
+ url: "https://gradio-builds.s3.amazonaws.com/demo-files/ghepardo-primo-piano.jpg",
49
+ orig_name: "cheetah.jpg"
50
+ },
51
+ show_label: true,
52
+ show_download_button: true
53
+ }}
54
+ play={async ({ canvasElement }) => {
55
+ const canvas = within(canvasElement);
56
+
57
+ const expand_btn = canvas.getByRole("button", {
58
+ name: "View in full screen"
59
+ });
60
+ await userEvent.click(expand_btn);
61
+ }}
62
+ />
63
+
43
64
  <Story
44
65
  name="static with no label or download button"
45
66
  args={{
package/Index.svelte CHANGED
@@ -51,6 +51,7 @@
51
51
  export let streaming: boolean;
52
52
  export let pending: boolean;
53
53
  export let mirror_webcam: boolean;
54
+ export let show_fullscreen_button: boolean;
54
55
 
55
56
  export let gradio: Gradio<{
56
57
  input: never;
@@ -114,6 +115,7 @@
114
115
  selectable={_selectable}
115
116
  {show_share_button}
116
117
  i18n={gradio.i18n}
118
+ {show_fullscreen_button}
117
119
  />
118
120
  </Block>
119
121
  {:else}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gradio/image",
3
- "version": "0.13.1",
3
+ "version": "0.14.0",
4
4
  "description": "Gradio UI packages",
5
5
  "type": "module",
6
6
  "author": "",
@@ -10,13 +10,13 @@
10
10
  "cropperjs": "^1.5.12",
11
11
  "lazy-brush": "^1.0.1",
12
12
  "resize-observer-polyfill": "^1.5.1",
13
- "@gradio/atoms": "^0.7.8",
14
- "@gradio/icons": "^0.6.1",
15
- "@gradio/statustracker": "^0.7.3",
16
- "@gradio/upload": "^0.12.1",
17
- "@gradio/client": "^1.4.0",
18
- "@gradio/wasm": "^0.12.0",
19
- "@gradio/utils": "^0.5.2"
13
+ "@gradio/atoms": "^0.7.9",
14
+ "@gradio/icons": "^0.7.0",
15
+ "@gradio/statustracker": "^0.7.4",
16
+ "@gradio/client": "^1.5.0",
17
+ "@gradio/upload": "^0.12.2",
18
+ "@gradio/utils": "^0.5.2",
19
+ "@gradio/wasm": "^0.12.0"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@gradio/preview": "^0.10.2"
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import { createEventDispatcher } from "svelte";
2
+ import { createEventDispatcher, onMount } from "svelte";
3
3
  import type { SelectData } from "@gradio/utils";
4
4
  import { uploadToHuggingFace } from "@gradio/utils";
5
5
  import { BlockLabel, Empty, IconButton, ShareButton } from "@gradio/atoms";
@@ -7,6 +7,7 @@
7
7
  import { get_coordinates_of_clicked_image } from "./utils";
8
8
  import Image from "./Image.svelte";
9
9
  import { DownloadLink } from "@gradio/wasm/svelte";
10
+ import { Maximize, Minimize } from "@gradio/icons";
10
11
 
11
12
  import { Image as ImageIcon } from "@gradio/icons";
12
13
  import { type FileData } from "@gradio/client";
@@ -19,6 +20,7 @@
19
20
  export let selectable = false;
20
21
  export let show_share_button = false;
21
22
  export let i18n: I18nFormatter;
23
+ export let show_fullscreen_button = true;
22
24
 
23
25
  const dispatch = createEventDispatcher<{
24
26
  change: string;
@@ -31,6 +33,24 @@
31
33
  dispatch("select", { index: coordinates, value: null });
32
34
  }
33
35
  };
36
+
37
+ let is_full_screen = false;
38
+ let image_container: HTMLElement;
39
+
40
+ onMount(() => {
41
+ document.addEventListener("fullscreenchange", () => {
42
+ is_full_screen = !!document.fullscreenElement;
43
+ });
44
+ });
45
+
46
+ const toggle_full_screen = async (): Promise<void> => {
47
+ if (!is_full_screen) {
48
+ await image_container.requestFullscreen();
49
+ } else {
50
+ await document.exitFullscreen();
51
+ is_full_screen = !is_full_screen;
52
+ }
53
+ };
34
54
  </script>
35
55
 
36
56
  <BlockLabel
@@ -41,36 +61,55 @@
41
61
  {#if value === null || !value.url}
42
62
  <Empty unpadded_box={true} size="large"><ImageIcon /></Empty>
43
63
  {:else}
44
- <div class="icon-buttons">
45
- {#if show_download_button}
46
- <DownloadLink href={value.url} download={value.orig_name || "image"}>
47
- <IconButton Icon={Download} label={i18n("common.download")} />
48
- </DownloadLink>
49
- {/if}
50
- {#if show_share_button}
51
- <ShareButton
52
- {i18n}
53
- on:share
54
- on:error
55
- formatter={async (value) => {
56
- if (!value) return "";
57
- let url = await uploadToHuggingFace(value, "url");
58
- return `<img src="${url}" />`;
59
- }}
60
- {value}
61
- />
62
- {/if}
63
- </div>
64
- <button on:click={handle_click}>
65
- <div class:selectable class="image-container">
66
- <Image src={value.url} alt="" loading="lazy" on:load />
64
+ <div class="image-container" bind:this={image_container}>
65
+ <div class="icon-buttons">
66
+ {#if !is_full_screen && show_fullscreen_button}
67
+ <IconButton
68
+ Icon={Maximize}
69
+ label={is_full_screen ? "Exit full screen" : "View in full screen"}
70
+ on:click={toggle_full_screen}
71
+ />
72
+ {/if}
73
+
74
+ {#if is_full_screen && show_fullscreen_button}
75
+ <IconButton
76
+ Icon={Minimize}
77
+ label={is_full_screen ? "Exit full screen" : "View in full screen"}
78
+ on:click={toggle_full_screen}
79
+ />
80
+ {/if}
81
+
82
+ {#if show_download_button}
83
+ <DownloadLink href={value.url} download={value.orig_name || "image"}>
84
+ <IconButton Icon={Download} label={i18n("common.download")} />
85
+ </DownloadLink>
86
+ {/if}
87
+ {#if show_share_button}
88
+ <ShareButton
89
+ {i18n}
90
+ on:share
91
+ on:error
92
+ formatter={async (value) => {
93
+ if (!value) return "";
94
+ let url = await uploadToHuggingFace(value, "url");
95
+ return `<img src="${url}" />`;
96
+ }}
97
+ {value}
98
+ />
99
+ {/if}
67
100
  </div>
68
- </button>
101
+ <button on:click={handle_click}>
102
+ <div class:selectable>
103
+ <Image src={value.url} alt="" loading="lazy" on:load />
104
+ </div>
105
+ </button>
106
+ </div>
69
107
  {/if}
70
108
 
71
109
  <style>
72
110
  .image-container {
73
111
  height: 100%;
112
+ position: relative;
74
113
  }
75
114
  .image-container :global(img),
76
115
  button {
@@ -79,6 +118,10 @@
79
118
  object-fit: contain;
80
119
  display: block;
81
120
  border-radius: var(--radius-lg);
121
+
122
+ display: flex;
123
+ align-items: center;
124
+ justify-content: center;
82
125
  }
83
126
 
84
127
  .selectable {
@@ -91,5 +134,24 @@
91
134
  top: 6px;
92
135
  right: 6px;
93
136
  gap: var(--size-1);
137
+ z-index: 1;
138
+ }
139
+
140
+ :global(.fullscreen-controls svg) {
141
+ position: relative;
142
+ top: 0px;
143
+ }
144
+
145
+ :global(.image-container:fullscreen) {
146
+ background-color: black;
147
+ display: flex;
148
+ justify-content: center;
149
+ align-items: center;
150
+ }
151
+
152
+ :global(.image-container:fullscreen img) {
153
+ max-width: 90vw;
154
+ max-height: 90vh;
155
+ object-fit: contain;
94
156
  }
95
157
  </style>