@gradio/imageslider 0.7.0 → 0.8.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,47 @@
1
1
  # @gradio/imageslider
2
2
 
3
+ ## 0.8.0
4
+
5
+ ### Features
6
+
7
+ - [#13862](https://github.com/gradio-app/gradio/pull/13862) [`3353446`](https://github.com/gradio-app/gradio/commit/3353446616a56838e7e3cb3477fcd02664a0db40) - Expose live camera and slider position to event handlers. Thanks @abidlabs!/n `camera_position` on `gr.Model3D` and `slider_position` on `gr.ImageSlider` now follow the user, so a function whose parameter is annotated with the component reads the view that is actually on screen. Both can still be set from the backend to move the camera or the divider./n Also fixes, in the same area:/n - `camera_position` is applied on load for `display_mode="point_cloud"` and `display_mode="wireframe"`, not only for `"solid"`./n - `camera_position` is applied to interactive (uploadable) `gr.Model3D`, and `slider_position` to interactive `gr.ImageSlider`; both previously ignored it./n - `pan_speed` is passed through to the `gr.Model3D` viewer; it was silently stuck at its default./n - A Model3D camera observer was added on every camera update without ever being removed; exactly one is now registered, and it is cleaned up with the component.
8
+
9
+ ### Dependency updates
10
+
11
+ - @gradio/utils@0.14.2
12
+ - @gradio/client@2.7.0
13
+
14
+ ## 0.7.1
15
+
16
+ ### Dependency updates
17
+
18
+ - @gradio/client@2.6.0
19
+ - @gradio/atoms@0.26.2
20
+ - @gradio/utils@0.14.1
21
+ - @gradio/upload@0.18.3
22
+
23
+ ## 0.7.1
24
+
25
+ ### Dependency updates
26
+
27
+ - @gradio/client@2.5.1
28
+
29
+ ## 0.7.1
30
+
31
+ ### Dependency updates
32
+
33
+ - @gradio/client@2.5.0
34
+
35
+ ## 0.7.1
36
+
37
+ ### Dependency updates
38
+
39
+ - @gradio/client@2.4.0
40
+ - @gradio/utils@0.14.0
41
+ - @gradio/atoms@0.26.1
42
+ - @gradio/statustracker@0.15.2
43
+ - @gradio/upload@0.18.2
44
+
3
45
  ## 0.7.0
4
46
 
5
47
  ### Features
@@ -0,0 +1,57 @@
1
+ <script module>
2
+ import { defineMeta } from "@storybook/addon-svelte-csf";
3
+ import { userEvent, within } from "storybook/test";
4
+ import ImageSlider from "./Index.svelte";
5
+ import { allModes } from "../storybook/modes";
6
+ import { wrapProps } from "../storybook/wrapProps";
7
+
8
+ const cheetah = "/cheetah.jpg";
9
+ const lion = "/lion.jpg";
10
+ const fileData = (url, name) => ({
11
+ path: url,
12
+ url,
13
+ orig_name: name,
14
+ size: null,
15
+ mime_type: "image/jpeg",
16
+ is_stream: false,
17
+ meta: { _type: "gradio.FileData" }
18
+ });
19
+
20
+ const { Story } = defineMeta({
21
+ title: "Components/Image Slider",
22
+ component: ImageSlider,
23
+ parameters: {
24
+ chromatic: {
25
+ modes: {
26
+ desktop: allModes["desktop"],
27
+ mobile: allModes["mobile"]
28
+ }
29
+ }
30
+ }
31
+ });
32
+ </script>
33
+
34
+ <Story
35
+ name="Mobile fullscreen"
36
+ args={{
37
+ value: [fileData(cheetah, "cheetah.jpg"), fileData(lion, "lion.jpg")],
38
+ interactive: false,
39
+ show_label: true,
40
+ label: "Fullscreen comparison",
41
+ buttons: ["fullscreen"],
42
+ slider_position: 50,
43
+ upload_count: 2,
44
+ slider_color: "#ff8c00",
45
+ max_height: 500
46
+ }}
47
+ play={async ({ canvasElement }) => {
48
+ const canvas = within(canvasElement);
49
+ await userEvent.click(canvas.getByRole("button", { name: "Fullscreen" }));
50
+ }}
51
+ >
52
+ {#snippet template(args)}
53
+ <div style="width: 360px; height: 440px; position: relative;">
54
+ <ImageSlider {...wrapProps(args)} />
55
+ </div>
56
+ {/snippet}
57
+ </Story>
@@ -521,6 +521,21 @@ describe("Events: clear", () => {
521
521
  expect(clear).toHaveBeenCalledTimes(1);
522
522
  });
523
523
 
524
+ test("clearing keeps the configured slider_position", async () => {
525
+ // One image keeps the component on the uploader branch, which is where the
526
+ // X lives while a slider is still waiting for its second image.
527
+ const { get_data, getByLabelText } = await render(ImageSlider, {
528
+ ...default_props,
529
+ interactive: true,
530
+ slider_position: 30,
531
+ value: [img_a, null]
532
+ });
533
+
534
+ await fireEvent.click(getByLabelText("Remove Image"));
535
+
536
+ expect((await get_data()).slider_position).toBe(30);
537
+ });
538
+
524
539
  test("value is [null, null] after clicking Remove Image", async () => {
525
540
  const { get_data, getByLabelText } = await render(ImageSlider, {
526
541
  ...default_props,
package/Index.svelte CHANGED
@@ -1,5 +1,3 @@
1
- <svelte:options accessors={true} />
2
-
3
1
  <script lang="ts">
4
2
  import { tick } from "svelte";
5
3
  import type { ImageSliderProps, ImageSliderEvents } from "./types";
@@ -39,6 +37,16 @@
39
37
  Math.max(0, Math.min(100, gradio.props.slider_position)) / 100
40
38
  );
41
39
 
40
+ function handle_slider_position(position: number): void {
41
+ const percentage = Math.max(
42
+ 0,
43
+ Math.min(100, Math.round(position * 1e5) / 1e3)
44
+ );
45
+ if (gradio.props.slider_position !== percentage) {
46
+ gradio.props.slider_position = percentage;
47
+ }
48
+ }
49
+
42
50
  gradio.watch_for_change();
43
51
 
44
52
  $effect(() => {
@@ -96,6 +104,7 @@
96
104
  gradio.dispatch("custom_button_click", { id });
97
105
  }}
98
106
  position={normalised_slider_position}
107
+ onposition={handle_slider_position}
99
108
  slider_color={gradio.props.slider_color}
100
109
  max_height={gradio.props.max_height}
101
110
  />
@@ -140,6 +149,8 @@
140
149
  label={gradio.shared.label}
141
150
  show_label={gradio.shared.show_label}
142
151
  upload_count={gradio.props.upload_count}
152
+ position={normalised_slider_position}
153
+ onposition={handle_slider_position}
143
154
  max_file_size={gradio.shared.max_file_size}
144
155
  i18n={gradio.i18n}
145
156
  upload={(...args) => gradio.shared.client.upload(...args)}
package/dist/Index.svelte CHANGED
@@ -1,5 +1,3 @@
1
- <svelte:options accessors={true} />
2
-
3
1
  <script lang="ts">
4
2
  import { tick } from "svelte";
5
3
  import type { ImageSliderProps, ImageSliderEvents } from "./types";
@@ -39,6 +37,16 @@
39
37
  Math.max(0, Math.min(100, gradio.props.slider_position)) / 100
40
38
  );
41
39
 
40
+ function handle_slider_position(position: number): void {
41
+ const percentage = Math.max(
42
+ 0,
43
+ Math.min(100, Math.round(position * 1e5) / 1e3)
44
+ );
45
+ if (gradio.props.slider_position !== percentage) {
46
+ gradio.props.slider_position = percentage;
47
+ }
48
+ }
49
+
42
50
  gradio.watch_for_change();
43
51
 
44
52
  $effect(() => {
@@ -96,6 +104,7 @@
96
104
  gradio.dispatch("custom_button_click", { id });
97
105
  }}
98
106
  position={normalised_slider_position}
107
+ onposition={handle_slider_position}
99
108
  slider_color={gradio.props.slider_color}
100
109
  max_height={gradio.props.max_height}
101
110
  />
@@ -140,6 +149,8 @@
140
149
  label={gradio.shared.label}
141
150
  show_label={gradio.shared.show_label}
142
151
  upload_count={gradio.props.upload_count}
152
+ position={normalised_slider_position}
153
+ onposition={handle_slider_position}
143
154
  max_file_size={gradio.shared.max_file_size}
144
155
  i18n={gradio.i18n}
145
156
  upload={(...args) => gradio.shared.client.upload(...args)}
@@ -18,6 +18,7 @@
18
18
  show_label,
19
19
  root,
20
20
  position = $bindable(0.5),
21
+ onposition,
21
22
  upload_count = 2,
22
23
  show_download_button = true,
23
24
  slider_color,
@@ -38,6 +39,7 @@
38
39
  show_label: boolean;
39
40
  root: string;
40
41
  position?: number;
42
+ onposition?: (position: number) => void;
41
43
  upload_count?: number;
42
44
  show_download_button?: boolean;
43
45
  slider_color: string;
@@ -126,6 +128,7 @@
126
128
  {/if}
127
129
  <Slider
128
130
  bind:position
131
+ {onposition}
129
132
  disabled={upload_count == 2 || !value?.[0]}
130
133
  {slider_color}
131
134
  >
@@ -8,6 +8,7 @@ type $$ComponentProps = {
8
8
  show_label: boolean;
9
9
  root: string;
10
10
  position?: number;
11
+ onposition?: (position: number) => void;
11
12
  upload_count?: number;
12
13
  show_download_button?: boolean;
13
14
  slider_color: string;
@@ -14,6 +14,7 @@
14
14
  image_size = { top: 0, left: 0, width: 0, height: 0 },
15
15
  el = $bindable<HTMLDivElement | undefined>(undefined),
16
16
  parent_el = $bindable<HTMLDivElement | undefined>(undefined),
17
+ onposition,
17
18
  children
18
19
  }: {
19
20
  position?: number;
@@ -27,6 +28,7 @@
27
28
  };
28
29
  el?: HTMLDivElement;
29
30
  parent_el?: HTMLDivElement;
31
+ onposition?: (position: number) => void;
30
32
  children?: Snippet;
31
33
  } = $props();
32
34
 
@@ -55,7 +57,8 @@
55
57
 
56
58
  function update_position(x: number): void {
57
59
  px = clamp(x, 0, container_width);
58
- position = round((x - image_size.left) / image_size.width, 5);
60
+ position = clamp(round((x - image_size.left) / image_size.width, 5), 0, 1);
61
+ onposition?.(position);
59
62
  }
60
63
 
61
64
  function drag_start(event: any): void {
@@ -11,6 +11,7 @@ type $$ComponentProps = {
11
11
  };
12
12
  el?: HTMLDivElement;
13
13
  parent_el?: HTMLDivElement;
14
+ onposition?: (position: number) => void;
14
15
  children?: Snippet;
15
16
  };
16
17
  declare const Slider: import("svelte").Component<$$ComponentProps, {}, "position" | "el" | "parent_el">;
@@ -24,6 +24,7 @@
24
24
  show_label,
25
25
  i18n,
26
26
  position = $bindable(0.5),
27
+ onposition,
27
28
  layer_images = true,
28
29
  show_single = false,
29
30
  slider_color,
@@ -43,6 +44,7 @@
43
44
  show_label: boolean;
44
45
  i18n: I18nFormatter;
45
46
  position?: number;
47
+ onposition?: (position: number) => void;
46
48
  layer_images?: boolean;
47
49
  show_single?: boolean;
48
50
  slider_color: string;
@@ -213,6 +215,7 @@
213
215
  >
214
216
  <Slider
215
217
  bind:position
218
+ {onposition}
216
219
  {slider_color}
217
220
  bind:el={slider_wrap}
218
221
  bind:parent_el
@@ -8,6 +8,7 @@ type $$ComponentProps = {
8
8
  show_label: boolean;
9
9
  i18n: I18nFormatter;
10
10
  position?: number;
11
+ onposition?: (position: number) => void;
11
12
  layer_images?: boolean;
12
13
  show_single?: boolean;
13
14
  slider_color: string;
@@ -1,5 +1,3 @@
1
- <svelte:options accessors={true} />
2
-
3
1
  <script lang="ts">
4
2
  import type { Snippet } from "svelte";
5
3
  import type { I18nFormatter } from "@gradio/utils";
@@ -24,6 +22,8 @@
24
22
  onclear,
25
23
  ondrag,
26
24
  onupload,
25
+ onposition,
26
+ position = 0.5,
27
27
  children
28
28
  }: {
29
29
  value?: [FileData | null, FileData | null];
@@ -41,6 +41,8 @@
41
41
  onclear?: () => void;
42
42
  ondrag?: (dragging: boolean) => void;
43
43
  onupload?: (value: [FileData | null, FileData | null]) => void;
44
+ onposition?: (position: number) => void;
45
+ position?: number;
44
46
  children?: Snippet;
45
47
  } = $props();
46
48
  </script>
@@ -48,7 +50,8 @@
48
50
  <Image
49
51
  bind:upload_promise
50
52
  slider_color="var(--border-color-primary)"
51
- position={0.5}
53
+ {position}
54
+ {onposition}
52
55
  bind:value
53
56
  bind:dragging
54
57
  {root}
@@ -18,6 +18,8 @@ type $$ComponentProps = {
18
18
  onclear?: () => void;
19
19
  ondrag?: (dragging: boolean) => void;
20
20
  onupload?: (value: [FileData | null, FileData | null]) => void;
21
+ onposition?: (position: number) => void;
22
+ position?: number;
21
23
  children?: Snippet;
22
24
  };
23
25
  declare const SliderUpload: import("svelte").Component<$$ComponentProps, {}, "value" | "dragging" | "upload_promise">;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gradio/imageslider",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Gradio UI packages",
5
5
  "type": "module",
6
6
  "author": "",
@@ -11,12 +11,12 @@
11
11
  "@types/d3-selection": "^3.0.11",
12
12
  "d3-drag": "^3.0.0",
13
13
  "d3-selection": "^3.0.0",
14
+ "@gradio/atoms": "^0.26.2",
14
15
  "@gradio/icons": "^0.16.0",
15
- "@gradio/atoms": "^0.26.0",
16
- "@gradio/statustracker": "^0.15.1",
17
- "@gradio/utils": "^0.13.0",
18
- "@gradio/upload": "^0.18.1",
19
- "@gradio/client": "^2.3.1"
16
+ "@gradio/statustracker": "^0.15.3",
17
+ "@gradio/upload": "^0.18.3",
18
+ "@gradio/utils": "^0.14.2",
19
+ "@gradio/client": "^2.7.0"
20
20
  },
21
21
  "exports": {
22
22
  ".": {
@@ -32,7 +32,7 @@
32
32
  "./package.json": "./package.json"
33
33
  },
34
34
  "devDependencies": {
35
- "@gradio/preview": "^0.16.2"
35
+ "@gradio/preview": "^0.17.1"
36
36
  },
37
37
  "main_changeset": true,
38
38
  "peerDependencies": {
@@ -18,6 +18,7 @@
18
18
  show_label,
19
19
  root,
20
20
  position = $bindable(0.5),
21
+ onposition,
21
22
  upload_count = 2,
22
23
  show_download_button = true,
23
24
  slider_color,
@@ -38,6 +39,7 @@
38
39
  show_label: boolean;
39
40
  root: string;
40
41
  position?: number;
42
+ onposition?: (position: number) => void;
41
43
  upload_count?: number;
42
44
  show_download_button?: boolean;
43
45
  slider_color: string;
@@ -126,6 +128,7 @@
126
128
  {/if}
127
129
  <Slider
128
130
  bind:position
131
+ {onposition}
129
132
  disabled={upload_count == 2 || !value?.[0]}
130
133
  {slider_color}
131
134
  >
@@ -14,6 +14,7 @@
14
14
  image_size = { top: 0, left: 0, width: 0, height: 0 },
15
15
  el = $bindable<HTMLDivElement | undefined>(undefined),
16
16
  parent_el = $bindable<HTMLDivElement | undefined>(undefined),
17
+ onposition,
17
18
  children
18
19
  }: {
19
20
  position?: number;
@@ -27,6 +28,7 @@
27
28
  };
28
29
  el?: HTMLDivElement;
29
30
  parent_el?: HTMLDivElement;
31
+ onposition?: (position: number) => void;
30
32
  children?: Snippet;
31
33
  } = $props();
32
34
 
@@ -55,7 +57,8 @@
55
57
 
56
58
  function update_position(x: number): void {
57
59
  px = clamp(x, 0, container_width);
58
- position = round((x - image_size.left) / image_size.width, 5);
60
+ position = clamp(round((x - image_size.left) / image_size.width, 5), 0, 1);
61
+ onposition?.(position);
59
62
  }
60
63
 
61
64
  function drag_start(event: any): void {
@@ -24,6 +24,7 @@
24
24
  show_label,
25
25
  i18n,
26
26
  position = $bindable(0.5),
27
+ onposition,
27
28
  layer_images = true,
28
29
  show_single = false,
29
30
  slider_color,
@@ -43,6 +44,7 @@
43
44
  show_label: boolean;
44
45
  i18n: I18nFormatter;
45
46
  position?: number;
47
+ onposition?: (position: number) => void;
46
48
  layer_images?: boolean;
47
49
  show_single?: boolean;
48
50
  slider_color: string;
@@ -213,6 +215,7 @@
213
215
  >
214
216
  <Slider
215
217
  bind:position
218
+ {onposition}
216
219
  {slider_color}
217
220
  bind:el={slider_wrap}
218
221
  bind:parent_el
@@ -1,5 +1,3 @@
1
- <svelte:options accessors={true} />
2
-
3
1
  <script lang="ts">
4
2
  import type { Snippet } from "svelte";
5
3
  import type { I18nFormatter } from "@gradio/utils";
@@ -24,6 +22,8 @@
24
22
  onclear,
25
23
  ondrag,
26
24
  onupload,
25
+ onposition,
26
+ position = 0.5,
27
27
  children
28
28
  }: {
29
29
  value?: [FileData | null, FileData | null];
@@ -41,6 +41,8 @@
41
41
  onclear?: () => void;
42
42
  ondrag?: (dragging: boolean) => void;
43
43
  onupload?: (value: [FileData | null, FileData | null]) => void;
44
+ onposition?: (position: number) => void;
45
+ position?: number;
44
46
  children?: Snippet;
45
47
  } = $props();
46
48
  </script>
@@ -48,7 +50,8 @@
48
50
  <Image
49
51
  bind:upload_promise
50
52
  slider_color="var(--border-color-primary)"
51
- position={0.5}
53
+ {position}
54
+ {onposition}
52
55
  bind:value
53
56
  bind:dragging
54
57
  {root}