@gradio/imageeditor 0.19.0 → 0.20.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 +21 -0
- package/Example.svelte +9 -3
- package/Index.svelte +23 -24
- package/InteractiveImageEditor.svelte +99 -61
- package/dist/Example.svelte +9 -3
- package/dist/Example.svelte.d.ts +4 -18
- package/dist/Index.svelte +23 -24
- package/dist/Index.svelte.d.ts +2 -19
- package/dist/InteractiveImageEditor.svelte +99 -61
- package/dist/InteractiveImageEditor.svelte.d.ts +15 -32
- package/dist/shared/Anchor.svelte +13 -11
- package/dist/shared/Anchor.svelte.d.ts +4 -19
- package/dist/shared/Controls.svelte +63 -39
- package/dist/shared/Controls.svelte.d.ts +13 -28
- package/dist/shared/IconButton.svelte +38 -17
- package/dist/shared/IconButton.svelte.d.ts +5 -19
- package/dist/shared/ImageEditor.svelte +235 -160
- package/dist/shared/ImageEditor.svelte.d.ts +55 -2
- package/dist/shared/Layers.svelte +43 -29
- package/dist/shared/Layers.svelte.d.ts +10 -25
- package/dist/shared/Resize.svelte +22 -16
- package/dist/shared/Resize.svelte.d.ts +6 -22
- package/dist/shared/SecondaryToolbar.svelte +34 -18
- package/dist/shared/SecondaryToolbar.svelte.d.ts +10 -25
- package/dist/shared/Toolbar.svelte +60 -76
- package/dist/shared/Toolbar.svelte.d.ts +9 -24
- package/dist/shared/brush/BrushOptions.svelte +49 -29
- package/dist/shared/brush/BrushOptions.svelte.d.ts +6 -21
- package/dist/shared/brush/BrushSize.svelte +12 -9
- package/dist/shared/brush/BrushSize.svelte.d.ts +5 -20
- package/dist/shared/brush/ColorField.svelte +21 -16
- package/dist/shared/brush/ColorField.svelte.d.ts +6 -22
- package/dist/shared/brush/ColorPicker.svelte +22 -16
- package/dist/shared/brush/ColorPicker.svelte.d.ts +4 -18
- package/dist/shared/brush/ColorSwatch.svelte +41 -21
- package/dist/shared/brush/ColorSwatch.svelte.d.ts +10 -24
- package/dist/shared/brush/brush.js +7 -8
- package/dist/shared/core/editor.d.ts +5 -0
- package/dist/shared/core/editor.js +43 -2
- package/dist/shared/resize/resize.d.ts +2 -0
- package/dist/shared/resize/resize.js +27 -18
- package/package.json +8 -8
- package/shared/Anchor.svelte +13 -11
- package/shared/Controls.svelte +63 -39
- package/shared/IconButton.svelte +38 -17
- package/shared/ImageEditor.svelte +235 -160
- package/shared/Layers.svelte +43 -29
- package/shared/Resize.svelte +22 -16
- package/shared/SecondaryToolbar.svelte +34 -18
- package/shared/Toolbar.svelte +60 -76
- package/shared/brush/BrushOptions.svelte +49 -29
- package/shared/brush/BrushSize.svelte +12 -9
- package/shared/brush/ColorField.svelte +21 -16
- package/shared/brush/ColorPicker.svelte +22 -16
- package/shared/brush/ColorSwatch.svelte +41 -21
- package/shared/brush/brush.ts +8 -10
- package/shared/core/editor.ts +49 -2
- package/shared/resize/resize.ts +28 -20
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
</script>
|
|
14
14
|
|
|
15
15
|
<script lang="ts">
|
|
16
|
-
import { createEventDispatcher } from "svelte";
|
|
17
16
|
import { type I18nFormatter } from "@gradio/utils";
|
|
18
17
|
import { prepare_files, type FileData, type Client } from "@gradio/client";
|
|
19
18
|
import { type CommandNode } from "./shared/core/commands";
|
|
@@ -31,48 +30,82 @@
|
|
|
31
30
|
type WebcamOptions
|
|
32
31
|
} from "./shared/types";
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
33
|
+
let {
|
|
34
|
+
brush,
|
|
35
|
+
eraser,
|
|
36
|
+
sources,
|
|
37
|
+
i18n,
|
|
38
|
+
root,
|
|
39
|
+
label = undefined,
|
|
40
|
+
show_label,
|
|
41
|
+
changeable = false,
|
|
42
|
+
theme_mode,
|
|
43
|
+
layers,
|
|
44
|
+
composite,
|
|
45
|
+
background,
|
|
46
|
+
layer_options = {
|
|
47
|
+
allow_additional_layers: true,
|
|
48
|
+
layers: [],
|
|
49
|
+
disabled: false
|
|
50
|
+
},
|
|
51
|
+
transforms,
|
|
52
|
+
accept_blobs,
|
|
53
|
+
canvas_size,
|
|
54
|
+
fixed_canvas = false,
|
|
55
|
+
realtime = false,
|
|
56
|
+
upload,
|
|
57
|
+
is_dragging = $bindable(),
|
|
58
|
+
placeholder = undefined,
|
|
59
|
+
border_region,
|
|
60
|
+
full_history = $bindable(null),
|
|
61
|
+
webcam_options = { mirror: true, constraints: {} },
|
|
62
|
+
show_download_button = false,
|
|
63
|
+
image_id = $bindable(null),
|
|
64
|
+
onclear,
|
|
65
|
+
onupload,
|
|
66
|
+
onchange,
|
|
67
|
+
oninput,
|
|
68
|
+
onsave,
|
|
69
|
+
onreceive_null,
|
|
70
|
+
ondownload_error
|
|
71
|
+
}: {
|
|
72
|
+
brush: IBrush | false;
|
|
73
|
+
eraser: Eraser | false;
|
|
74
|
+
sources: Source[];
|
|
75
|
+
i18n: I18nFormatter;
|
|
76
|
+
root: string;
|
|
77
|
+
label?: string;
|
|
78
|
+
show_label: boolean;
|
|
79
|
+
changeable?: boolean;
|
|
80
|
+
theme_mode: "dark" | "light";
|
|
81
|
+
layers: FileData[];
|
|
82
|
+
composite: FileData | null;
|
|
83
|
+
background: FileData | null;
|
|
84
|
+
layer_options?: LayerOptions;
|
|
85
|
+
transforms: Transform[];
|
|
86
|
+
accept_blobs: (a: any) => void;
|
|
87
|
+
canvas_size: [number, number];
|
|
88
|
+
fixed_canvas?: boolean;
|
|
89
|
+
realtime?: boolean;
|
|
90
|
+
upload: Client["upload"];
|
|
91
|
+
is_dragging?: boolean;
|
|
92
|
+
placeholder?: string;
|
|
93
|
+
border_region: number;
|
|
94
|
+
full_history?: CommandNode | null;
|
|
95
|
+
webcam_options?: WebcamOptions;
|
|
96
|
+
show_download_button?: boolean;
|
|
97
|
+
image_id?: null | string;
|
|
98
|
+
onclear?: () => void;
|
|
99
|
+
onupload?: () => void;
|
|
100
|
+
onchange?: () => void;
|
|
101
|
+
oninput?: () => void;
|
|
102
|
+
onsave?: () => void;
|
|
103
|
+
onreceive_null?: () => void;
|
|
104
|
+
ondownload_error?: (error: string) => void;
|
|
105
|
+
} = $props();
|
|
73
106
|
|
|
74
107
|
let editor: ImageEditor;
|
|
75
|
-
let has_drawn = false;
|
|
108
|
+
let has_drawn = $state(false);
|
|
76
109
|
|
|
77
110
|
function is_not_null(o: Blob | null): o is Blob {
|
|
78
111
|
return !!o;
|
|
@@ -82,7 +115,9 @@
|
|
|
82
115
|
return !!o;
|
|
83
116
|
}
|
|
84
117
|
|
|
85
|
-
|
|
118
|
+
$effect(() => {
|
|
119
|
+
if (background_image) onupload?.();
|
|
120
|
+
});
|
|
86
121
|
|
|
87
122
|
export async function get_data(): Promise<ImageBlobs> {
|
|
88
123
|
let blobs;
|
|
@@ -131,16 +166,16 @@
|
|
|
131
166
|
if (!editor) return;
|
|
132
167
|
if (value == null) {
|
|
133
168
|
editor.handle_remove();
|
|
134
|
-
|
|
169
|
+
onreceive_null?.();
|
|
135
170
|
}
|
|
136
171
|
}
|
|
137
172
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
let can_undo: boolean;
|
|
173
|
+
$effect(() => {
|
|
174
|
+
handle_value({ layers, composite, background });
|
|
175
|
+
});
|
|
142
176
|
|
|
143
|
-
|
|
177
|
+
let background_image = $state(false);
|
|
178
|
+
let can_undo = $state(false);
|
|
144
179
|
|
|
145
180
|
type BinaryImages = [string, string, File, number | null][];
|
|
146
181
|
|
|
@@ -148,9 +183,9 @@
|
|
|
148
183
|
return new Promise((resolve) => setTimeout(() => resolve(), 30));
|
|
149
184
|
}
|
|
150
185
|
|
|
151
|
-
let uploading = false;
|
|
152
|
-
let pending = false;
|
|
153
|
-
async function handle_change(
|
|
186
|
+
let uploading = $state(false);
|
|
187
|
+
let pending = $state(false);
|
|
188
|
+
async function handle_change(): Promise<void> {
|
|
154
189
|
if (!realtime) return;
|
|
155
190
|
if (uploading) {
|
|
156
191
|
pending = true;
|
|
@@ -193,19 +228,23 @@
|
|
|
193
228
|
})
|
|
194
229
|
);
|
|
195
230
|
image_id = id;
|
|
196
|
-
|
|
231
|
+
onchange?.();
|
|
197
232
|
await nextframe();
|
|
198
233
|
uploading = false;
|
|
199
234
|
if (pending) {
|
|
200
235
|
pending = false;
|
|
201
236
|
uploading = false;
|
|
202
|
-
handle_change(
|
|
237
|
+
handle_change();
|
|
203
238
|
}
|
|
204
239
|
}
|
|
205
240
|
|
|
206
|
-
|
|
241
|
+
let placeholder_parts = $derived(
|
|
242
|
+
placeholder ? inject(placeholder) : [false, false]
|
|
243
|
+
);
|
|
244
|
+
let heading = $derived(placeholder_parts[0]);
|
|
245
|
+
let paragraph = $derived(placeholder_parts[1]);
|
|
207
246
|
|
|
208
|
-
let current_tool
|
|
247
|
+
let current_tool = $state<ToolbarTool>("image");
|
|
209
248
|
</script>
|
|
210
249
|
|
|
211
250
|
<BlockLabel
|
|
@@ -218,15 +257,14 @@
|
|
|
218
257
|
{composite}
|
|
219
258
|
{layers}
|
|
220
259
|
{background}
|
|
221
|
-
on:history
|
|
222
260
|
{canvas_size}
|
|
223
261
|
bind:this={editor}
|
|
224
262
|
{changeable}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
263
|
+
{onsave}
|
|
264
|
+
{oninput}
|
|
265
|
+
onchange={handle_change}
|
|
266
|
+
onclear={() => onclear?.()}
|
|
267
|
+
{ondownload_error}
|
|
230
268
|
{sources}
|
|
231
269
|
bind:background_image
|
|
232
270
|
bind:current_tool
|
|
@@ -13,26 +13,13 @@ import { type FileData, type Client } from "@gradio/client";
|
|
|
13
13
|
import { type CommandNode } from "./shared/core/commands";
|
|
14
14
|
import { type Brush as IBrush, type Eraser } from "./shared/brush/types";
|
|
15
15
|
import { type LayerOptions, type Transform, type Source, type WebcamOptions } from "./shared/types";
|
|
16
|
-
|
|
17
|
-
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
18
|
-
$$bindings?: Bindings;
|
|
19
|
-
} & Exports;
|
|
20
|
-
(internal: unknown, props: Props & {
|
|
21
|
-
$$events?: Events;
|
|
22
|
-
$$slots?: Slots;
|
|
23
|
-
}): Exports & {
|
|
24
|
-
$set?: any;
|
|
25
|
-
$on?: any;
|
|
26
|
-
};
|
|
27
|
-
z_$$bindings?: Bindings;
|
|
28
|
-
}
|
|
29
|
-
declare const InteractiveImageEditor: $$__sveltets_2_IsomorphicComponent<{
|
|
16
|
+
type $$ComponentProps = {
|
|
30
17
|
brush: IBrush | false;
|
|
31
18
|
eraser: Eraser | false;
|
|
32
19
|
sources: Source[];
|
|
33
20
|
i18n: I18nFormatter;
|
|
34
21
|
root: string;
|
|
35
|
-
label?: string
|
|
22
|
+
label?: string;
|
|
36
23
|
show_label: boolean;
|
|
37
24
|
changeable?: boolean;
|
|
38
25
|
theme_mode: "dark" | "light";
|
|
@@ -46,27 +33,23 @@ declare const InteractiveImageEditor: $$__sveltets_2_IsomorphicComponent<{
|
|
|
46
33
|
fixed_canvas?: boolean;
|
|
47
34
|
realtime?: boolean;
|
|
48
35
|
upload: Client["upload"];
|
|
49
|
-
is_dragging
|
|
50
|
-
placeholder?: string
|
|
36
|
+
is_dragging?: boolean;
|
|
37
|
+
placeholder?: string;
|
|
51
38
|
border_region: number;
|
|
52
39
|
full_history?: CommandNode | null;
|
|
53
40
|
webcam_options?: WebcamOptions;
|
|
54
41
|
show_download_button?: boolean;
|
|
55
|
-
get_data?: () => Promise<ImageBlobs>;
|
|
56
42
|
image_id?: null | string;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
} & {
|
|
67
|
-
[evt: string]: CustomEvent<any>;
|
|
68
|
-
}, {}, {
|
|
43
|
+
onclear?: () => void;
|
|
44
|
+
onupload?: () => void;
|
|
45
|
+
onchange?: () => void;
|
|
46
|
+
oninput?: () => void;
|
|
47
|
+
onsave?: () => void;
|
|
48
|
+
onreceive_null?: () => void;
|
|
49
|
+
ondownload_error?: (error: string) => void;
|
|
50
|
+
};
|
|
51
|
+
declare const InteractiveImageEditor: import("svelte").Component<$$ComponentProps, {
|
|
69
52
|
get_data: () => Promise<ImageBlobs>;
|
|
70
|
-
},
|
|
71
|
-
type InteractiveImageEditor =
|
|
53
|
+
}, "is_dragging" | "full_history" | "image_id">;
|
|
54
|
+
type InteractiveImageEditor = ReturnType<typeof InteractiveImageEditor>;
|
|
72
55
|
export default InteractiveImageEditor;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { spring } from "svelte/motion";
|
|
3
3
|
import { Image } from "@gradio/icons";
|
|
4
|
-
import { onMount
|
|
4
|
+
import { onMount } from "svelte";
|
|
5
5
|
|
|
6
6
|
const positions = [
|
|
7
7
|
"top-left",
|
|
@@ -14,9 +14,11 @@
|
|
|
14
14
|
"bottom",
|
|
15
15
|
"bottom-right"
|
|
16
16
|
] as const;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
17
|
+
let {
|
|
18
|
+
onposition
|
|
19
|
+
}: {
|
|
20
|
+
onposition?: (position: (typeof positions)[number]) => void;
|
|
21
|
+
} = $props();
|
|
20
22
|
|
|
21
23
|
const spring_opt = {
|
|
22
24
|
stiffness: 0.1,
|
|
@@ -35,8 +37,8 @@
|
|
|
35
37
|
};
|
|
36
38
|
const arrow_spring = spring<Arrow[]>([], spring_opt);
|
|
37
39
|
|
|
38
|
-
let last_i = 0;
|
|
39
|
-
let expanded = true;
|
|
40
|
+
let last_i = $state(0);
|
|
41
|
+
let expanded = $state(true);
|
|
40
42
|
const box_size = (120 - 5 * 2) / 3;
|
|
41
43
|
|
|
42
44
|
async function handle_box_hover(i: number): Promise<void> {
|
|
@@ -49,7 +51,7 @@
|
|
|
49
51
|
dimensions.set(init);
|
|
50
52
|
}
|
|
51
53
|
|
|
52
|
-
let last_pos = 0;
|
|
54
|
+
let last_pos = $state(0);
|
|
53
55
|
async function handle_box_click(i: number, stagger = false): Promise<void> {
|
|
54
56
|
if (expanded && stagger) return;
|
|
55
57
|
|
|
@@ -77,7 +79,7 @@
|
|
|
77
79
|
dimensions.set([120 + 10, 120 + 10]);
|
|
78
80
|
arrow_spring.set(eventual_arrows);
|
|
79
81
|
|
|
80
|
-
|
|
82
|
+
onposition?.(positions[i]);
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
function get_valid_offsets(anchorPoint: {
|
|
@@ -215,14 +217,14 @@
|
|
|
215
217
|
class="box-wrap"
|
|
216
218
|
role="grid"
|
|
217
219
|
tabindex="0"
|
|
218
|
-
|
|
220
|
+
onmouseleave={() => handle_box_click(last_pos, true)}
|
|
219
221
|
>
|
|
220
222
|
{#each { length: 9 } as _, i}
|
|
221
223
|
<button
|
|
222
224
|
class="box"
|
|
223
225
|
class:active-box={last_pos === i}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
+
onmouseenter={() => handle_box_hover(i)}
|
|
227
|
+
onclick={() => handle_box_click(i)}
|
|
226
228
|
>
|
|
227
229
|
<span class:active={last_pos === i} class="icon-wrap">
|
|
228
230
|
<Image />
|
|
@@ -1,20 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
(internal: unknown, props: {
|
|
6
|
-
$$events?: Events;
|
|
7
|
-
$$slots?: Slots;
|
|
8
|
-
}): Exports & {
|
|
9
|
-
$set?: any;
|
|
10
|
-
$on?: any;
|
|
11
|
-
};
|
|
12
|
-
z_$$bindings?: Bindings;
|
|
13
|
-
}
|
|
14
|
-
declare const Anchor: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
-
position: CustomEvent<"center" | "left" | "right" | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "top" | "bottom">;
|
|
16
|
-
} & {
|
|
17
|
-
[evt: string]: CustomEvent<any>;
|
|
18
|
-
}, {}, {}, string>;
|
|
19
|
-
type Anchor = InstanceType<typeof Anchor>;
|
|
1
|
+
declare const Anchor: import("svelte").Component<{
|
|
2
|
+
onposition?: (position: "center" | "left" | "right" | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "top" | "bottom") => void;
|
|
3
|
+
}, {}, "">;
|
|
4
|
+
type Anchor = ReturnType<typeof Anchor>;
|
|
20
5
|
export default Anchor;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { createEventDispatcher } from "svelte";
|
|
3
2
|
import { IconButton, IconButtonWrapper } from "@gradio/atoms";
|
|
4
3
|
import {
|
|
5
4
|
Check,
|
|
@@ -11,30 +10,45 @@
|
|
|
11
10
|
Undo,
|
|
12
11
|
Redo
|
|
13
12
|
} from "@gradio/icons";
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
13
|
+
let {
|
|
14
|
+
can_save = false,
|
|
15
|
+
changeable = false,
|
|
16
|
+
current_zoom = 1,
|
|
17
|
+
tool,
|
|
18
|
+
min_zoom = true,
|
|
19
|
+
enable_download = false,
|
|
20
|
+
can_undo,
|
|
21
|
+
can_redo,
|
|
22
|
+
onremove_image,
|
|
23
|
+
onundo,
|
|
24
|
+
onredo,
|
|
25
|
+
onsave,
|
|
26
|
+
onzoom_in,
|
|
27
|
+
onzoom_out,
|
|
28
|
+
onset_zoom,
|
|
29
|
+
onpan,
|
|
30
|
+
ondownload
|
|
31
|
+
}: {
|
|
32
|
+
can_save?: boolean;
|
|
33
|
+
changeable?: boolean;
|
|
34
|
+
current_zoom?: number;
|
|
35
|
+
tool: string;
|
|
36
|
+
min_zoom?: boolean;
|
|
37
|
+
enable_download?: boolean;
|
|
38
|
+
can_undo: boolean;
|
|
39
|
+
can_redo: boolean;
|
|
40
|
+
onremove_image?: () => void;
|
|
41
|
+
onundo?: () => void;
|
|
42
|
+
onredo?: () => void;
|
|
43
|
+
onsave?: () => void;
|
|
44
|
+
onzoom_in?: () => void;
|
|
45
|
+
onzoom_out?: () => void;
|
|
46
|
+
onset_zoom?: (zoom: number | "fit") => void;
|
|
47
|
+
onpan?: () => void;
|
|
48
|
+
ondownload?: () => void;
|
|
49
|
+
} = $props();
|
|
50
|
+
|
|
51
|
+
let show_zoom_popup = $state(false);
|
|
38
52
|
|
|
39
53
|
function handle_zoom_click(e: MouseEvent): void {
|
|
40
54
|
e.stopPropagation();
|
|
@@ -42,7 +56,7 @@
|
|
|
42
56
|
}
|
|
43
57
|
|
|
44
58
|
function handle_zoom_change(zoom: number | "fit"): void {
|
|
45
|
-
|
|
59
|
+
onset_zoom?.(zoom);
|
|
46
60
|
show_zoom_popup = false;
|
|
47
61
|
}
|
|
48
62
|
|
|
@@ -52,7 +66,7 @@
|
|
|
52
66
|
}
|
|
53
67
|
}
|
|
54
68
|
|
|
55
|
-
|
|
69
|
+
let formatted_zoom = $derived(Math.round(current_zoom * 100));
|
|
56
70
|
</script>
|
|
57
71
|
|
|
58
72
|
<IconButtonWrapper>
|
|
@@ -61,7 +75,7 @@
|
|
|
61
75
|
Icon={Download}
|
|
62
76
|
label="Download"
|
|
63
77
|
onclick={(event) => {
|
|
64
|
-
|
|
78
|
+
ondownload?.();
|
|
65
79
|
event.stopPropagation();
|
|
66
80
|
}}
|
|
67
81
|
/>
|
|
@@ -72,7 +86,7 @@
|
|
|
72
86
|
label="Pan"
|
|
73
87
|
onclick={(e) => {
|
|
74
88
|
e.stopPropagation();
|
|
75
|
-
|
|
89
|
+
onpan?.();
|
|
76
90
|
}}
|
|
77
91
|
highlight={tool === "pan"}
|
|
78
92
|
size="small"
|
|
@@ -85,7 +99,7 @@
|
|
|
85
99
|
Icon={ZoomOut}
|
|
86
100
|
label="Zoom out"
|
|
87
101
|
onclick={(event) => {
|
|
88
|
-
|
|
102
|
+
onzoom_out?.();
|
|
89
103
|
event.stopPropagation();
|
|
90
104
|
}}
|
|
91
105
|
/>
|
|
@@ -93,7 +107,7 @@
|
|
|
93
107
|
Icon={ZoomIn}
|
|
94
108
|
label="Zoom in"
|
|
95
109
|
onclick={(event) => {
|
|
96
|
-
|
|
110
|
+
onzoom_in?.();
|
|
97
111
|
event.stopPropagation();
|
|
98
112
|
}}
|
|
99
113
|
/>
|
|
@@ -102,20 +116,30 @@
|
|
|
102
116
|
<span
|
|
103
117
|
role="button"
|
|
104
118
|
tabindex="0"
|
|
105
|
-
|
|
106
|
-
|
|
119
|
+
onclick={handle_zoom_click}
|
|
120
|
+
onkeydown={handle_zoom_keydown}>{formatted_zoom}%</span
|
|
107
121
|
>
|
|
108
122
|
{#if show_zoom_popup}
|
|
109
123
|
<div class="zoom-controls">
|
|
110
124
|
<ul>
|
|
111
125
|
<li>
|
|
112
|
-
<button
|
|
126
|
+
<button
|
|
127
|
+
onclick={(event) => {
|
|
128
|
+
event.stopPropagation();
|
|
129
|
+
handle_zoom_change("fit");
|
|
130
|
+
}}
|
|
131
|
+
>
|
|
113
132
|
Fit to screen
|
|
114
133
|
</button>
|
|
115
134
|
</li>
|
|
116
135
|
{#each [0.25, 0.5, 1, 2, 4] as zoom}
|
|
117
136
|
<li>
|
|
118
|
-
<button
|
|
137
|
+
<button
|
|
138
|
+
onclick={(event) => {
|
|
139
|
+
event.stopPropagation();
|
|
140
|
+
handle_zoom_change(zoom);
|
|
141
|
+
}}
|
|
142
|
+
>
|
|
119
143
|
{zoom * 100}%
|
|
120
144
|
</button>
|
|
121
145
|
</li>
|
|
@@ -130,7 +154,7 @@
|
|
|
130
154
|
Icon={Undo}
|
|
131
155
|
label="Undo"
|
|
132
156
|
onclick={(event) => {
|
|
133
|
-
|
|
157
|
+
onundo?.();
|
|
134
158
|
event.stopPropagation();
|
|
135
159
|
}}
|
|
136
160
|
disabled={!can_undo}
|
|
@@ -140,7 +164,7 @@
|
|
|
140
164
|
Icon={Redo}
|
|
141
165
|
label="Redo"
|
|
142
166
|
onclick={(event) => {
|
|
143
|
-
|
|
167
|
+
onredo?.();
|
|
144
168
|
event.stopPropagation();
|
|
145
169
|
}}
|
|
146
170
|
disabled={!can_redo}
|
|
@@ -152,7 +176,7 @@
|
|
|
152
176
|
Icon={Check}
|
|
153
177
|
label="Save changes"
|
|
154
178
|
onclick={(event) => {
|
|
155
|
-
|
|
179
|
+
onsave?.();
|
|
156
180
|
event.stopPropagation();
|
|
157
181
|
}}
|
|
158
182
|
color="var(--color-accent)"
|
|
@@ -163,7 +187,7 @@
|
|
|
163
187
|
Icon={Trash}
|
|
164
188
|
label="Clear canvas"
|
|
165
189
|
onclick={(event) => {
|
|
166
|
-
|
|
190
|
+
onremove_image?.();
|
|
167
191
|
event.stopPropagation();
|
|
168
192
|
}}
|
|
169
193
|
/>
|
|
@@ -1,17 +1,4 @@
|
|
|
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 Controls: $$__sveltets_2_IsomorphicComponent<{
|
|
1
|
+
type $$ComponentProps = {
|
|
15
2
|
can_save?: boolean;
|
|
16
3
|
changeable?: boolean;
|
|
17
4
|
current_zoom?: number;
|
|
@@ -20,18 +7,16 @@ declare const Controls: $$__sveltets_2_IsomorphicComponent<{
|
|
|
20
7
|
enable_download?: boolean;
|
|
21
8
|
can_undo: boolean;
|
|
22
9
|
can_redo: boolean;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}, {}, {}, string>;
|
|
36
|
-
type Controls = InstanceType<typeof Controls>;
|
|
10
|
+
onremove_image?: () => void;
|
|
11
|
+
onundo?: () => void;
|
|
12
|
+
onredo?: () => void;
|
|
13
|
+
onsave?: () => void;
|
|
14
|
+
onzoom_in?: () => void;
|
|
15
|
+
onzoom_out?: () => void;
|
|
16
|
+
onset_zoom?: (zoom: number | "fit") => void;
|
|
17
|
+
onpan?: () => void;
|
|
18
|
+
ondownload?: () => void;
|
|
19
|
+
};
|
|
20
|
+
declare const Controls: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
21
|
+
type Controls = ReturnType<typeof Controls>;
|
|
37
22
|
export default Controls;
|