@gradio/imageslider 0.7.1 → 0.8.1
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 +40 -0
- package/ImageSlider.stories.svelte +57 -0
- package/ImageSlider.test.ts +15 -26
- package/Index.svelte +13 -2
- package/dist/Index.svelte +13 -2
- package/dist/shared/Image.svelte +3 -0
- package/dist/shared/Image.svelte.d.ts +1 -0
- package/dist/shared/Slider.svelte +4 -1
- package/dist/shared/Slider.svelte.d.ts +1 -0
- package/dist/shared/SliderPreview.svelte +3 -0
- package/dist/shared/SliderPreview.svelte.d.ts +1 -0
- package/dist/shared/SliderUpload.svelte +6 -3
- package/dist/shared/SliderUpload.svelte.d.ts +2 -0
- package/package.json +7 -7
- package/shared/Image.svelte +3 -0
- package/shared/Slider.svelte +4 -1
- package/shared/SliderPreview.svelte +3 -0
- package/shared/SliderUpload.svelte +6 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# @gradio/imageslider
|
|
2
2
|
|
|
3
|
+
## 0.8.1
|
|
4
|
+
|
|
5
|
+
### Dependency updates
|
|
6
|
+
|
|
7
|
+
- @gradio/upload@0.19.0
|
|
8
|
+
- @gradio/statustracker@0.15.4
|
|
9
|
+
- @gradio/client@2.7.1
|
|
10
|
+
|
|
11
|
+
## 0.8.0
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
- [#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.
|
|
16
|
+
|
|
17
|
+
### Dependency updates
|
|
18
|
+
|
|
19
|
+
- @gradio/utils@0.14.2
|
|
20
|
+
- @gradio/client@2.7.0
|
|
21
|
+
|
|
22
|
+
## 0.7.1
|
|
23
|
+
|
|
24
|
+
### Dependency updates
|
|
25
|
+
|
|
26
|
+
- @gradio/client@2.6.0
|
|
27
|
+
- @gradio/atoms@0.26.2
|
|
28
|
+
- @gradio/utils@0.14.1
|
|
29
|
+
- @gradio/upload@0.18.3
|
|
30
|
+
|
|
31
|
+
## 0.7.1
|
|
32
|
+
|
|
33
|
+
### Dependency updates
|
|
34
|
+
|
|
35
|
+
- @gradio/client@2.5.1
|
|
36
|
+
|
|
37
|
+
## 0.7.1
|
|
38
|
+
|
|
39
|
+
### Dependency updates
|
|
40
|
+
|
|
41
|
+
- @gradio/client@2.5.0
|
|
42
|
+
|
|
3
43
|
## 0.7.1
|
|
4
44
|
|
|
5
45
|
### Dependency updates
|
|
@@ -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>
|
package/ImageSlider.test.ts
CHANGED
|
@@ -296,13 +296,6 @@ describe("Props: slider_position", () => {
|
|
|
296
296
|
|
|
297
297
|
expect(getByTestId("slider")).toBeInTheDocument();
|
|
298
298
|
});
|
|
299
|
-
|
|
300
|
-
test.todo(
|
|
301
|
-
"VISUAL: slider_position=0 positions the slider at the left edge — needs Playwright visual regression screenshot comparison"
|
|
302
|
-
);
|
|
303
|
-
test.todo(
|
|
304
|
-
"VISUAL: slider_position=100 positions the slider at the right edge — needs Playwright visual regression screenshot comparison"
|
|
305
|
-
);
|
|
306
299
|
});
|
|
307
300
|
|
|
308
301
|
describe("Props: buttons", () => {
|
|
@@ -521,6 +514,21 @@ describe("Events: clear", () => {
|
|
|
521
514
|
expect(clear).toHaveBeenCalledTimes(1);
|
|
522
515
|
});
|
|
523
516
|
|
|
517
|
+
test("clearing keeps the configured slider_position", async () => {
|
|
518
|
+
// One image keeps the component on the uploader branch, which is where the
|
|
519
|
+
// X lives while a slider is still waiting for its second image.
|
|
520
|
+
const { get_data, getByLabelText } = await render(ImageSlider, {
|
|
521
|
+
...default_props,
|
|
522
|
+
interactive: true,
|
|
523
|
+
slider_position: 30,
|
|
524
|
+
value: [img_a, null]
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
await fireEvent.click(getByLabelText("Remove Image"));
|
|
528
|
+
|
|
529
|
+
expect((await get_data()).slider_position).toBe(30);
|
|
530
|
+
});
|
|
531
|
+
|
|
524
532
|
test("value is [null, null] after clicking Remove Image", async () => {
|
|
525
533
|
const { get_data, getByLabelText } = await render(ImageSlider, {
|
|
526
534
|
...default_props,
|
|
@@ -725,22 +733,3 @@ describe("Edge cases", () => {
|
|
|
725
733
|
expect(change).not.toHaveBeenCalled();
|
|
726
734
|
});
|
|
727
735
|
});
|
|
728
|
-
|
|
729
|
-
test.todo(
|
|
730
|
-
"VISUAL: slider_color applies the given color to the slider line and handles — needs Playwright visual regression screenshot comparison"
|
|
731
|
-
);
|
|
732
|
-
test.todo(
|
|
733
|
-
"VISUAL: height prop constrains the component height — needs Playwright visual regression screenshot comparison"
|
|
734
|
-
);
|
|
735
|
-
test.todo(
|
|
736
|
-
"VISUAL: width prop constrains the component width — needs Playwright visual regression screenshot comparison"
|
|
737
|
-
);
|
|
738
|
-
test.todo(
|
|
739
|
-
"VISUAL: max_height limits image display height — needs Playwright visual regression screenshot comparison"
|
|
740
|
-
);
|
|
741
|
-
test.todo(
|
|
742
|
-
"VISUAL: scroll wheel zoom scales both images together — needs Playwright visual regression screenshot comparison"
|
|
743
|
-
);
|
|
744
|
-
test.todo(
|
|
745
|
-
"VISUAL: mouse drag pans both images when zoomed in — needs Playwright visual regression screenshot comparison"
|
|
746
|
-
);
|
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)}
|
package/dist/shared/Image.svelte
CHANGED
|
@@ -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 {
|
|
@@ -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
|
|
@@ -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
|
|
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.
|
|
3
|
+
"version": "0.8.1",
|
|
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.
|
|
15
|
-
"@gradio/client": "^2.
|
|
14
|
+
"@gradio/atoms": "^0.26.2",
|
|
15
|
+
"@gradio/client": "^2.7.1",
|
|
16
|
+
"@gradio/statustracker": "^0.15.4",
|
|
17
|
+
"@gradio/upload": "^0.19.0",
|
|
16
18
|
"@gradio/icons": "^0.16.0",
|
|
17
|
-
"@gradio/
|
|
18
|
-
"@gradio/utils": "^0.14.0",
|
|
19
|
-
"@gradio/upload": "^0.18.2"
|
|
19
|
+
"@gradio/utils": "^0.14.2"
|
|
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.17.
|
|
35
|
+
"@gradio/preview": "^0.17.1"
|
|
36
36
|
},
|
|
37
37
|
"main_changeset": true,
|
|
38
38
|
"peerDependencies": {
|
package/shared/Image.svelte
CHANGED
|
@@ -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
|
>
|
package/shared/Slider.svelte
CHANGED
|
@@ -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
|
|
53
|
+
{position}
|
|
54
|
+
{onposition}
|
|
52
55
|
bind:value
|
|
53
56
|
bind:dragging
|
|
54
57
|
{root}
|