@gradio/imageslider 0.5.0 → 0.7.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 +45 -0
- package/Example.svelte +11 -4
- package/ImageSlider.test.ts +32 -0
- package/Index.svelte +16 -49
- package/dist/Example.svelte +11 -4
- package/dist/Example.svelte.d.ts +4 -18
- package/dist/Index.svelte +16 -49
- package/dist/shared/ClearImage.svelte +2 -3
- package/dist/shared/ClearImage.svelte.d.ts +5 -19
- package/dist/shared/Image.svelte +67 -45
- package/dist/shared/Image.svelte.d.ts +14 -40
- package/dist/shared/ImageEl.svelte +22 -23
- package/dist/shared/ImageEl.svelte.d.ts +7 -22
- package/dist/shared/Slider.svelte +34 -19
- package/dist/shared/Slider.svelte.d.ts +8 -29
- package/dist/shared/SliderPreview.svelte +85 -47
- package/dist/shared/SliderPreview.svelte.d.ts +8 -23
- package/dist/shared/SliderUpload.svelte +43 -20
- package/dist/shared/SliderUpload.svelte.d.ts +11 -49
- package/dist/types.d.ts +1 -1
- package/package.json +7 -7
- package/shared/ClearImage.svelte +2 -3
- package/shared/Image.svelte +67 -45
- package/shared/ImageEl.svelte +22 -23
- package/shared/Slider.svelte +34 -19
- package/shared/SliderPreview.svelte +85 -47
- package/shared/SliderUpload.svelte +43 -20
- package/types.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
# @gradio/imageslider
|
|
2
2
|
|
|
3
|
+
## 0.7.0
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- [#13543](https://github.com/gradio-app/gradio/pull/13543) [`0533483`](https://github.com/gradio-app/gradio/commit/0533483bccdee38f334a598f18297e8c02966343) - Migrate Image components to Svelte 5. Thanks @dawoodkhan82!
|
|
8
|
+
|
|
9
|
+
### Dependency updates
|
|
10
|
+
|
|
11
|
+
- @gradio/statustracker@0.15.1
|
|
12
|
+
- @gradio/icons@0.16.0
|
|
13
|
+
- @gradio/atoms@0.26.0
|
|
14
|
+
- @gradio/client@2.3.1
|
|
15
|
+
- @gradio/upload@0.18.1
|
|
16
|
+
|
|
17
|
+
## 0.6.0
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
- [#13526](https://github.com/gradio-app/gradio/pull/13526) [`53cb4ca`](https://github.com/gradio-app/gradio/commit/53cb4cae1ec3521e9170d12867253516413ba37a) - Run `pnpm lint` and `pnpm ts:check` on CI. Thanks @abidlabs!
|
|
22
|
+
|
|
23
|
+
### Fixes
|
|
24
|
+
|
|
25
|
+
- [#13533](https://github.com/gradio-app/gradio/pull/13533) [`e5ec1ca`](https://github.com/gradio-app/gradio/commit/e5ec1ca66c45e7e3a057b75ac2b8b86660b2827b) - Fix fullscreen button not working in ImageSlider, interactive Image, native plots, and AnnotatedImage. Thanks @hysts!
|
|
26
|
+
|
|
27
|
+
### Dependency updates
|
|
28
|
+
|
|
29
|
+
- @gradio/atoms@0.25.0
|
|
30
|
+
- @gradio/statustracker@0.15.0
|
|
31
|
+
- @gradio/utils@0.13.0
|
|
32
|
+
- @gradio/client@2.3.0
|
|
33
|
+
- @gradio/upload@0.18.0
|
|
34
|
+
|
|
35
|
+
## 0.5.0
|
|
36
|
+
|
|
37
|
+
### Dependency updates
|
|
38
|
+
|
|
39
|
+
- @gradio/client@2.2.2
|
|
40
|
+
|
|
41
|
+
## 0.5.0
|
|
42
|
+
|
|
43
|
+
### Dependency updates
|
|
44
|
+
|
|
45
|
+
- @gradio/client@2.2.1
|
|
46
|
+
- @gradio/upload@0.17.10
|
|
47
|
+
|
|
3
48
|
## 0.5.0
|
|
4
49
|
|
|
5
50
|
### Features
|
package/Example.svelte
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
let {
|
|
3
|
+
value,
|
|
4
|
+
samples_dir,
|
|
5
|
+
type,
|
|
6
|
+
selected = false
|
|
7
|
+
}: {
|
|
8
|
+
value: [string, string];
|
|
9
|
+
samples_dir: string;
|
|
10
|
+
type: "gallery" | "table";
|
|
11
|
+
selected?: boolean;
|
|
12
|
+
} = $props();
|
|
6
13
|
</script>
|
|
7
14
|
|
|
8
15
|
<!-- TODO: fix -->
|
package/ImageSlider.test.ts
CHANGED
|
@@ -110,6 +110,21 @@ describe("ImageSlider", () => {
|
|
|
110
110
|
expect(btns[0]).toBeVisible();
|
|
111
111
|
});
|
|
112
112
|
|
|
113
|
+
test("renders upload area when value is undefined", async () => {
|
|
114
|
+
const { getAllByRole, get_data } = await render(ImageSlider, {
|
|
115
|
+
...default_props,
|
|
116
|
+
interactive: true,
|
|
117
|
+
value: undefined,
|
|
118
|
+
client: mock_client()
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const btns = getAllByRole("button", {
|
|
122
|
+
name: "Click to upload or drop files"
|
|
123
|
+
});
|
|
124
|
+
expect(btns[0]).toBeVisible();
|
|
125
|
+
expect((await get_data()).value).toEqual([null, null]);
|
|
126
|
+
});
|
|
127
|
+
|
|
113
128
|
test("renders both images when value has two images", async () => {
|
|
114
129
|
const { getAllByTestId } = await render(ImageSlider, {
|
|
115
130
|
...default_props,
|
|
@@ -345,6 +360,23 @@ describe("Props: buttons", () => {
|
|
|
345
360
|
expect(getByLabelText("Fullscreen")).toBeVisible();
|
|
346
361
|
});
|
|
347
362
|
|
|
363
|
+
test("clicking the fullscreen button toggles fullscreen mode", async () => {
|
|
364
|
+
const { getByLabelText } = await render(ImageSlider, {
|
|
365
|
+
...preview_props,
|
|
366
|
+
buttons: ["fullscreen"]
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
await fireEvent.click(getByLabelText("Fullscreen"));
|
|
370
|
+
await waitFor(() => {
|
|
371
|
+
expect(getByLabelText("Exit fullscreen mode")).toBeVisible();
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
await fireEvent.click(getByLabelText("Exit fullscreen mode"));
|
|
375
|
+
await waitFor(() => {
|
|
376
|
+
expect(getByLabelText("Fullscreen")).toBeVisible();
|
|
377
|
+
});
|
|
378
|
+
});
|
|
379
|
+
|
|
348
380
|
test("interactive: true with both images shows Remove Image button", async () => {
|
|
349
381
|
const { getByLabelText } = await render(ImageSlider, {
|
|
350
382
|
...default_props,
|
package/Index.svelte
CHANGED
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
let fullscreen = $state(false);
|
|
34
34
|
let dragging = $state(false);
|
|
35
35
|
let active_source: sources = $state(null);
|
|
36
|
-
let
|
|
36
|
+
let value = $state(gradio.props.value ?? [null, null]);
|
|
37
37
|
|
|
38
38
|
let normalised_slider_position = $derived(
|
|
39
39
|
Math.max(0, Math.min(100, gradio.props.slider_position)) / 100
|
|
@@ -41,32 +41,16 @@
|
|
|
41
41
|
|
|
42
42
|
gradio.watch_for_change();
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
drag_event.stopPropagation();
|
|
48
|
-
if (drag_event.type === "dragenter" || drag_event.type === "dragover") {
|
|
49
|
-
dragging = true;
|
|
50
|
-
} else if (drag_event.type === "dragleave") {
|
|
51
|
-
dragging = false;
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const handle_drop = (event: Event): void => {
|
|
56
|
-
if (gradio.shared.interactive) {
|
|
57
|
-
const drop_event = event as DragEvent;
|
|
58
|
-
drop_event.preventDefault();
|
|
59
|
-
drop_event.stopPropagation();
|
|
60
|
-
dragging = false;
|
|
44
|
+
$effect(() => {
|
|
45
|
+
value = gradio.props.value ?? [null, null];
|
|
46
|
+
});
|
|
61
47
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
};
|
|
48
|
+
$effect(() => {
|
|
49
|
+
gradio.props.value = value;
|
|
50
|
+
});
|
|
67
51
|
</script>
|
|
68
52
|
|
|
69
|
-
{#if !gradio.shared.interactive || (
|
|
53
|
+
{#if !gradio.shared.interactive || (value?.[1] && value?.[0])}
|
|
70
54
|
<Block
|
|
71
55
|
visible={gradio.shared.visible}
|
|
72
56
|
variant={"solid"}
|
|
@@ -88,19 +72,16 @@
|
|
|
88
72
|
{...gradio.shared.loading_status}
|
|
89
73
|
/>
|
|
90
74
|
<StaticImage
|
|
91
|
-
|
|
92
|
-
on:share={({ detail }) => gradio.dispatch("share", detail)}
|
|
93
|
-
on:error={({ detail }) => gradio.dispatch("error", detail)}
|
|
94
|
-
on:clear={() => {
|
|
75
|
+
onclear={() => {
|
|
95
76
|
gradio.dispatch("clear");
|
|
96
77
|
gradio.dispatch("input");
|
|
97
78
|
}}
|
|
98
|
-
|
|
79
|
+
onfullscreen={(detail) => {
|
|
99
80
|
fullscreen = detail;
|
|
100
81
|
}}
|
|
101
82
|
{fullscreen}
|
|
102
83
|
interactive={gradio.shared.interactive}
|
|
103
|
-
bind:value
|
|
84
|
+
bind:value
|
|
104
85
|
label={gradio.shared.label}
|
|
105
86
|
show_label={gradio.shared.show_label}
|
|
106
87
|
show_download_button={gradio.props.buttons.some(
|
|
@@ -122,7 +103,7 @@
|
|
|
122
103
|
{:else}
|
|
123
104
|
<Block
|
|
124
105
|
visible={gradio.shared.visible}
|
|
125
|
-
variant={
|
|
106
|
+
variant={value?.[0] || value?.[1] ? "solid" : "dashed"}
|
|
126
107
|
border_mode={dragging ? "focus" : "base"}
|
|
127
108
|
padding={false}
|
|
128
109
|
elem_id={gradio.shared.elem_id}
|
|
@@ -133,10 +114,6 @@
|
|
|
133
114
|
container={gradio.shared.container}
|
|
134
115
|
scale={gradio.shared.scale}
|
|
135
116
|
min_width={gradio.shared.min_width}
|
|
136
|
-
on:dragenter={handle_drag_event}
|
|
137
|
-
on:dragleave={handle_drag_event}
|
|
138
|
-
on:dragover={handle_drag_event}
|
|
139
|
-
on:drop={handle_drop}
|
|
140
117
|
>
|
|
141
118
|
<StatusTracker
|
|
142
119
|
autoscroll={gradio.shared.autoscroll}
|
|
@@ -148,28 +125,18 @@
|
|
|
148
125
|
|
|
149
126
|
<ImageUploader
|
|
150
127
|
bind:upload_promise
|
|
151
|
-
bind:
|
|
152
|
-
bind:value={gradio.props.value}
|
|
128
|
+
bind:value
|
|
153
129
|
bind:dragging
|
|
154
130
|
root={gradio.shared.root}
|
|
155
|
-
|
|
156
|
-
on:clear={() => {
|
|
131
|
+
onclear={() => {
|
|
157
132
|
gradio.dispatch("clear");
|
|
158
133
|
gradio.dispatch("input");
|
|
159
134
|
}}
|
|
160
|
-
|
|
161
|
-
|
|
135
|
+
ondrag={(detail) => (dragging = detail)}
|
|
136
|
+
onupload={() => {
|
|
162
137
|
gradio.dispatch("upload");
|
|
163
138
|
gradio.dispatch("input");
|
|
164
139
|
}}
|
|
165
|
-
on:error={({ detail }) => {
|
|
166
|
-
if (gradio.shared.loading_status)
|
|
167
|
-
gradio.shared.loading_status.status = "error";
|
|
168
|
-
gradio.dispatch("error", detail);
|
|
169
|
-
}}
|
|
170
|
-
on:close_stream={() => {
|
|
171
|
-
gradio.dispatch("close_stream", "stream");
|
|
172
|
-
}}
|
|
173
140
|
label={gradio.shared.label}
|
|
174
141
|
show_label={gradio.shared.show_label}
|
|
175
142
|
upload_count={gradio.props.upload_count}
|
package/dist/Example.svelte
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
let {
|
|
3
|
+
value,
|
|
4
|
+
samples_dir,
|
|
5
|
+
type,
|
|
6
|
+
selected = false
|
|
7
|
+
}: {
|
|
8
|
+
value: [string, string];
|
|
9
|
+
samples_dir: string;
|
|
10
|
+
type: "gallery" | "table";
|
|
11
|
+
selected?: boolean;
|
|
12
|
+
} = $props();
|
|
6
13
|
</script>
|
|
7
14
|
|
|
8
15
|
<!-- TODO: fix -->
|
package/dist/Example.svelte.d.ts
CHANGED
|
@@ -1,23 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
-
$$bindings?: Bindings;
|
|
4
|
-
} & Exports;
|
|
5
|
-
(internal: unknown, props: Props & {
|
|
6
|
-
$$events?: Events;
|
|
7
|
-
$$slots?: Slots;
|
|
8
|
-
}): Exports & {
|
|
9
|
-
$set?: any;
|
|
10
|
-
$on?: any;
|
|
11
|
-
};
|
|
12
|
-
z_$$bindings?: Bindings;
|
|
13
|
-
}
|
|
14
|
-
declare const Example: $$__sveltets_2_IsomorphicComponent<{
|
|
1
|
+
type $$ComponentProps = {
|
|
15
2
|
value: [string, string];
|
|
16
3
|
samples_dir: string;
|
|
17
4
|
type: "gallery" | "table";
|
|
18
5
|
selected?: boolean;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
type Example = InstanceType<typeof Example>;
|
|
6
|
+
};
|
|
7
|
+
declare const Example: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
|
+
type Example = ReturnType<typeof Example>;
|
|
23
9
|
export default Example;
|
package/dist/Index.svelte
CHANGED
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
let fullscreen = $state(false);
|
|
34
34
|
let dragging = $state(false);
|
|
35
35
|
let active_source: sources = $state(null);
|
|
36
|
-
let
|
|
36
|
+
let value = $state(gradio.props.value ?? [null, null]);
|
|
37
37
|
|
|
38
38
|
let normalised_slider_position = $derived(
|
|
39
39
|
Math.max(0, Math.min(100, gradio.props.slider_position)) / 100
|
|
@@ -41,32 +41,16 @@
|
|
|
41
41
|
|
|
42
42
|
gradio.watch_for_change();
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
drag_event.stopPropagation();
|
|
48
|
-
if (drag_event.type === "dragenter" || drag_event.type === "dragover") {
|
|
49
|
-
dragging = true;
|
|
50
|
-
} else if (drag_event.type === "dragleave") {
|
|
51
|
-
dragging = false;
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const handle_drop = (event: Event): void => {
|
|
56
|
-
if (gradio.shared.interactive) {
|
|
57
|
-
const drop_event = event as DragEvent;
|
|
58
|
-
drop_event.preventDefault();
|
|
59
|
-
drop_event.stopPropagation();
|
|
60
|
-
dragging = false;
|
|
44
|
+
$effect(() => {
|
|
45
|
+
value = gradio.props.value ?? [null, null];
|
|
46
|
+
});
|
|
61
47
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
};
|
|
48
|
+
$effect(() => {
|
|
49
|
+
gradio.props.value = value;
|
|
50
|
+
});
|
|
67
51
|
</script>
|
|
68
52
|
|
|
69
|
-
{#if !gradio.shared.interactive || (
|
|
53
|
+
{#if !gradio.shared.interactive || (value?.[1] && value?.[0])}
|
|
70
54
|
<Block
|
|
71
55
|
visible={gradio.shared.visible}
|
|
72
56
|
variant={"solid"}
|
|
@@ -88,19 +72,16 @@
|
|
|
88
72
|
{...gradio.shared.loading_status}
|
|
89
73
|
/>
|
|
90
74
|
<StaticImage
|
|
91
|
-
|
|
92
|
-
on:share={({ detail }) => gradio.dispatch("share", detail)}
|
|
93
|
-
on:error={({ detail }) => gradio.dispatch("error", detail)}
|
|
94
|
-
on:clear={() => {
|
|
75
|
+
onclear={() => {
|
|
95
76
|
gradio.dispatch("clear");
|
|
96
77
|
gradio.dispatch("input");
|
|
97
78
|
}}
|
|
98
|
-
|
|
79
|
+
onfullscreen={(detail) => {
|
|
99
80
|
fullscreen = detail;
|
|
100
81
|
}}
|
|
101
82
|
{fullscreen}
|
|
102
83
|
interactive={gradio.shared.interactive}
|
|
103
|
-
bind:value
|
|
84
|
+
bind:value
|
|
104
85
|
label={gradio.shared.label}
|
|
105
86
|
show_label={gradio.shared.show_label}
|
|
106
87
|
show_download_button={gradio.props.buttons.some(
|
|
@@ -122,7 +103,7 @@
|
|
|
122
103
|
{:else}
|
|
123
104
|
<Block
|
|
124
105
|
visible={gradio.shared.visible}
|
|
125
|
-
variant={
|
|
106
|
+
variant={value?.[0] || value?.[1] ? "solid" : "dashed"}
|
|
126
107
|
border_mode={dragging ? "focus" : "base"}
|
|
127
108
|
padding={false}
|
|
128
109
|
elem_id={gradio.shared.elem_id}
|
|
@@ -133,10 +114,6 @@
|
|
|
133
114
|
container={gradio.shared.container}
|
|
134
115
|
scale={gradio.shared.scale}
|
|
135
116
|
min_width={gradio.shared.min_width}
|
|
136
|
-
on:dragenter={handle_drag_event}
|
|
137
|
-
on:dragleave={handle_drag_event}
|
|
138
|
-
on:dragover={handle_drag_event}
|
|
139
|
-
on:drop={handle_drop}
|
|
140
117
|
>
|
|
141
118
|
<StatusTracker
|
|
142
119
|
autoscroll={gradio.shared.autoscroll}
|
|
@@ -148,28 +125,18 @@
|
|
|
148
125
|
|
|
149
126
|
<ImageUploader
|
|
150
127
|
bind:upload_promise
|
|
151
|
-
bind:
|
|
152
|
-
bind:value={gradio.props.value}
|
|
128
|
+
bind:value
|
|
153
129
|
bind:dragging
|
|
154
130
|
root={gradio.shared.root}
|
|
155
|
-
|
|
156
|
-
on:clear={() => {
|
|
131
|
+
onclear={() => {
|
|
157
132
|
gradio.dispatch("clear");
|
|
158
133
|
gradio.dispatch("input");
|
|
159
134
|
}}
|
|
160
|
-
|
|
161
|
-
|
|
135
|
+
ondrag={(detail) => (dragging = detail)}
|
|
136
|
+
onupload={() => {
|
|
162
137
|
gradio.dispatch("upload");
|
|
163
138
|
gradio.dispatch("input");
|
|
164
139
|
}}
|
|
165
|
-
on:error={({ detail }) => {
|
|
166
|
-
if (gradio.shared.loading_status)
|
|
167
|
-
gradio.shared.loading_status.status = "error";
|
|
168
|
-
gradio.dispatch("error", detail);
|
|
169
|
-
}}
|
|
170
|
-
on:close_stream={() => {
|
|
171
|
-
gradio.dispatch("close_stream", "stream");
|
|
172
|
-
}}
|
|
173
140
|
label={gradio.shared.label}
|
|
174
141
|
show_label={gradio.shared.show_label}
|
|
175
142
|
upload_count={gradio.props.upload_count}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { createEventDispatcher } from "svelte";
|
|
3
2
|
import { IconButton } from "@gradio/atoms";
|
|
4
3
|
import { Clear } from "@gradio/icons";
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
let { onremove_image }: { onremove_image?: () => void } = $props();
|
|
7
6
|
</script>
|
|
8
7
|
|
|
9
8
|
<div>
|
|
@@ -11,7 +10,7 @@
|
|
|
11
10
|
Icon={Clear}
|
|
12
11
|
label="Remove Image"
|
|
13
12
|
onclick={(event) => {
|
|
14
|
-
|
|
13
|
+
onremove_image?.();
|
|
15
14
|
event.stopPropagation();
|
|
16
15
|
}}
|
|
17
16
|
/>
|
|
@@ -1,20 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
$$events?: Events;
|
|
7
|
-
$$slots?: Slots;
|
|
8
|
-
}): Exports & {
|
|
9
|
-
$set?: any;
|
|
10
|
-
$on?: any;
|
|
11
|
-
};
|
|
12
|
-
z_$$bindings?: Bindings;
|
|
13
|
-
}
|
|
14
|
-
declare const ClearImage: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
-
remove_image: CustomEvent<any>;
|
|
16
|
-
} & {
|
|
17
|
-
[evt: string]: CustomEvent<any>;
|
|
18
|
-
}, {}, {}, string>;
|
|
19
|
-
type ClearImage = InstanceType<typeof ClearImage>;
|
|
1
|
+
type $$ComponentProps = {
|
|
2
|
+
onremove_image?: () => void;
|
|
3
|
+
};
|
|
4
|
+
declare const ClearImage: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
5
|
+
type ClearImage = ReturnType<typeof ClearImage>;
|
|
20
6
|
export default ClearImage;
|
package/dist/shared/Image.svelte
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import Slider from "./Slider.svelte";
|
|
3
|
-
import {
|
|
3
|
+
import { tick, type Snippet } from "svelte";
|
|
4
4
|
import { BlockLabel, Empty, IconButton, DownloadLink } from "@gradio/atoms";
|
|
5
5
|
import { Download } from "@gradio/icons";
|
|
6
6
|
import { Image } from "@gradio/icons";
|
|
7
|
-
import { type
|
|
7
|
+
import { type I18nFormatter } from "@gradio/utils";
|
|
8
8
|
import ClearImage from "./ClearImage.svelte";
|
|
9
9
|
import ImageEl from "./ImageEl.svelte";
|
|
10
10
|
|
|
@@ -12,65 +12,87 @@
|
|
|
12
12
|
|
|
13
13
|
import { type FileData, type Client } from "@gradio/client";
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
let {
|
|
16
|
+
value = $bindable<[FileData | null, FileData | null]>([null, null]),
|
|
17
|
+
label = undefined,
|
|
18
|
+
show_label,
|
|
19
|
+
root,
|
|
20
|
+
position = $bindable(0.5),
|
|
21
|
+
upload_count = 2,
|
|
22
|
+
show_download_button = true,
|
|
23
|
+
slider_color,
|
|
24
|
+
upload,
|
|
25
|
+
stream_handler,
|
|
26
|
+
max_file_size = null,
|
|
27
|
+
i18n,
|
|
28
|
+
max_height,
|
|
29
|
+
upload_promise = $bindable(),
|
|
30
|
+
dragging = $bindable(false),
|
|
31
|
+
onclear,
|
|
32
|
+
ondrag,
|
|
33
|
+
onupload,
|
|
34
|
+
children
|
|
35
|
+
}: {
|
|
36
|
+
value?: [FileData | null, FileData | null];
|
|
37
|
+
label?: string;
|
|
38
|
+
show_label: boolean;
|
|
39
|
+
root: string;
|
|
40
|
+
position?: number;
|
|
41
|
+
upload_count?: number;
|
|
42
|
+
show_download_button?: boolean;
|
|
43
|
+
slider_color: string;
|
|
44
|
+
upload: Client["upload"];
|
|
45
|
+
stream_handler: Client["stream"];
|
|
46
|
+
max_file_size?: number | null;
|
|
47
|
+
i18n: I18nFormatter;
|
|
48
|
+
max_height: number;
|
|
49
|
+
upload_promise?: Promise<any>;
|
|
50
|
+
dragging?: boolean;
|
|
51
|
+
onclear?: () => void;
|
|
52
|
+
ondrag?: (dragging: boolean) => void;
|
|
53
|
+
onupload?: (value: [FileData | null, FileData | null]) => void;
|
|
54
|
+
children?: Snippet;
|
|
55
|
+
} = $props();
|
|
16
56
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
export let position: number;
|
|
21
|
-
export let upload_count = 2;
|
|
22
|
-
|
|
23
|
-
export let show_download_button = true;
|
|
24
|
-
export let slider_color: string;
|
|
25
|
-
export let upload: Client["upload"];
|
|
26
|
-
export let stream_handler: Client["stream"];
|
|
27
|
-
export let max_file_size: number | null = null;
|
|
28
|
-
export let i18n: I18nFormatter;
|
|
29
|
-
export let max_height: number;
|
|
30
|
-
export let upload_promise: Promise<any> | null = null;
|
|
31
|
-
|
|
32
|
-
let value_: [FileData | null, FileData | null] = value || [null, null];
|
|
57
|
+
let value_ = $state<[FileData | null, FileData | null]>(
|
|
58
|
+
value || [null, null]
|
|
59
|
+
);
|
|
33
60
|
|
|
34
61
|
let img: HTMLImageElement;
|
|
35
|
-
let el_width
|
|
36
|
-
let el_height
|
|
62
|
+
let el_width = $state(0);
|
|
63
|
+
let el_height = $state(0);
|
|
37
64
|
|
|
38
|
-
async function handle_upload(
|
|
65
|
+
async function handle_upload(
|
|
66
|
+
detail: Blob | File | FileData | FileData[],
|
|
67
|
+
n: number
|
|
68
|
+
): Promise<void> {
|
|
69
|
+
const file_data = Array.isArray(detail) ? detail : [detail as FileData];
|
|
39
70
|
const new_value = [value[0], value[1]] as [
|
|
40
71
|
FileData | null,
|
|
41
72
|
FileData | null
|
|
42
73
|
];
|
|
43
|
-
if (
|
|
44
|
-
new_value[n] =
|
|
74
|
+
if (file_data.length > 1) {
|
|
75
|
+
new_value[n] = file_data[0];
|
|
45
76
|
} else {
|
|
46
|
-
new_value[n] =
|
|
77
|
+
new_value[n] = file_data[n];
|
|
47
78
|
}
|
|
48
79
|
value = new_value;
|
|
49
80
|
await tick();
|
|
50
81
|
|
|
51
|
-
|
|
82
|
+
onupload?.(new_value);
|
|
52
83
|
}
|
|
53
84
|
|
|
54
85
|
let old_value = "";
|
|
55
86
|
|
|
56
|
-
|
|
87
|
+
$effect(() => {
|
|
88
|
+
if (JSON.stringify(value) === old_value) return;
|
|
57
89
|
old_value = JSON.stringify(value);
|
|
58
90
|
value_ = value;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const dispatch = createEventDispatcher<{
|
|
62
|
-
change: string | null;
|
|
63
|
-
stream: string | null;
|
|
64
|
-
edit: undefined;
|
|
65
|
-
clear: undefined;
|
|
66
|
-
drag: boolean;
|
|
67
|
-
upload: [FileData | null, FileData | null];
|
|
68
|
-
select: SelectData;
|
|
69
|
-
}>();
|
|
70
|
-
|
|
71
|
-
export let dragging = false;
|
|
91
|
+
});
|
|
72
92
|
|
|
73
|
-
|
|
93
|
+
$effect(() => {
|
|
94
|
+
ondrag?.(dragging);
|
|
95
|
+
});
|
|
74
96
|
</script>
|
|
75
97
|
|
|
76
98
|
<BlockLabel {show_label} Icon={Image} label={label || i18n("image.image")} />
|
|
@@ -83,10 +105,10 @@
|
|
|
83
105
|
>
|
|
84
106
|
{#if value?.[0]?.url || value?.[1]?.url}
|
|
85
107
|
<ClearImage
|
|
86
|
-
|
|
108
|
+
onremove_image={() => {
|
|
87
109
|
position = 0.5;
|
|
88
110
|
value = [null, null];
|
|
89
|
-
|
|
111
|
+
onclear?.();
|
|
90
112
|
}}
|
|
91
113
|
/>
|
|
92
114
|
{/if}
|
|
@@ -126,7 +148,7 @@
|
|
|
126
148
|
{stream_handler}
|
|
127
149
|
{max_file_size}
|
|
128
150
|
>
|
|
129
|
-
|
|
151
|
+
{#if children}{@render children()}{/if}
|
|
130
152
|
</Upload>
|
|
131
153
|
</div>
|
|
132
154
|
{:else}
|
|
@@ -152,7 +174,7 @@
|
|
|
152
174
|
{stream_handler}
|
|
153
175
|
{max_file_size}
|
|
154
176
|
>
|
|
155
|
-
|
|
177
|
+
{#if children}{@render children()}{/if}
|
|
156
178
|
</Upload>
|
|
157
179
|
{:else if !value_?.[1] && upload_count === 1}
|
|
158
180
|
<div
|