@gradio/imageeditor 0.12.13 → 0.13.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.
Files changed (130) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/Example.svelte +1 -1
  3. package/IMAGE_EDITOR_OVERVIEW.md +224 -0
  4. package/ImageEditor.stories.svelte +4 -4
  5. package/Index.svelte +35 -46
  6. package/{shared/InteractiveImageEditor.svelte → InteractiveImageEditor.svelte} +56 -103
  7. package/dist/Example.svelte.d.ts +1 -1
  8. package/dist/Index.svelte +29 -33
  9. package/dist/Index.svelte.d.ts +17 -16
  10. package/dist/{shared/InteractiveImageEditor.svelte → InteractiveImageEditor.svelte} +47 -88
  11. package/dist/{shared/InteractiveImageEditor.svelte.d.ts → InteractiveImageEditor.svelte.d.ts} +13 -15
  12. package/dist/shared/Anchor.svelte +311 -0
  13. package/dist/shared/Anchor.svelte.d.ts +18 -0
  14. package/dist/shared/Controls.svelte +162 -23
  15. package/dist/shared/Controls.svelte.d.ts +7 -2
  16. package/dist/shared/{tools/IconButton.svelte → IconButton.svelte} +19 -3
  17. package/dist/shared/{tools/IconButton.svelte.d.ts → IconButton.svelte.d.ts} +4 -1
  18. package/dist/shared/ImageEditor.svelte +546 -289
  19. package/dist/shared/ImageEditor.svelte.d.ts +51 -56
  20. package/dist/shared/Layers.svelte +233 -0
  21. package/dist/shared/Layers.svelte.d.ts +35 -0
  22. package/dist/shared/Resize.svelte +218 -0
  23. package/dist/shared/Resize.svelte.d.ts +29 -0
  24. package/dist/shared/SecondaryToolbar.svelte +54 -0
  25. package/dist/shared/SecondaryToolbar.svelte.d.ts +35 -0
  26. package/dist/shared/Toolbar.svelte +337 -0
  27. package/dist/shared/Toolbar.svelte.d.ts +42 -0
  28. package/dist/shared/{tools → brush}/BrushOptions.svelte +68 -64
  29. package/dist/shared/{tools → brush}/BrushOptions.svelte.d.ts +9 -9
  30. package/dist/shared/{tools → brush}/BrushSize.svelte +2 -27
  31. package/dist/shared/{tools → brush}/ColorField.svelte +2 -1
  32. package/dist/shared/{tools → brush}/ColorField.svelte.d.ts +1 -0
  33. package/dist/shared/{tools → brush}/ColorPicker.svelte +81 -9
  34. package/dist/shared/{tools → brush}/ColorPicker.svelte.d.ts +1 -0
  35. package/dist/shared/{tools → brush}/ColorSwatch.svelte +78 -38
  36. package/dist/shared/{tools → brush}/ColorSwatch.svelte.d.ts +6 -2
  37. package/dist/shared/brush/brush-cursor.d.ts +101 -0
  38. package/dist/shared/brush/brush-cursor.js +327 -0
  39. package/dist/shared/brush/brush-textures.d.ts +71 -0
  40. package/dist/shared/brush/brush-textures.js +404 -0
  41. package/dist/shared/brush/brush-utils.d.ts +32 -0
  42. package/dist/shared/brush/brush-utils.js +59 -0
  43. package/dist/shared/brush/brush.d.ts +152 -0
  44. package/dist/shared/brush/brush.js +396 -0
  45. package/dist/shared/brush/types.d.ts +37 -0
  46. package/dist/shared/brush/types.js +1 -0
  47. package/dist/shared/core/editor.d.ts +252 -0
  48. package/dist/shared/core/editor.js +1221 -0
  49. package/dist/shared/crop/crop.d.ts +201 -0
  50. package/dist/shared/crop/crop.js +727 -0
  51. package/dist/shared/image/image.d.ts +89 -0
  52. package/dist/shared/image/image.js +185 -0
  53. package/dist/shared/resize/resize.d.ts +270 -0
  54. package/dist/shared/resize/resize.js +1413 -0
  55. package/dist/shared/types.d.ts +12 -0
  56. package/dist/shared/utils/pixi.d.ts +16 -57
  57. package/dist/shared/utils/pixi.js +15 -113
  58. package/dist/shared/zoom/zoom.d.ts +136 -0
  59. package/dist/shared/zoom/zoom.js +548 -0
  60. package/package.json +11 -10
  61. package/shared/Anchor.svelte +384 -0
  62. package/shared/Controls.svelte +194 -27
  63. package/shared/{tools/IconButton.svelte → IconButton.svelte} +21 -4
  64. package/shared/ImageEditor.svelte +682 -349
  65. package/shared/Layers.svelte +249 -0
  66. package/shared/Resize.svelte +239 -0
  67. package/shared/SecondaryToolbar.svelte +61 -0
  68. package/shared/Toolbar.svelte +386 -0
  69. package/shared/brush/BRUSH_TOOL.md +134 -0
  70. package/shared/brush/BrushOptions.svelte +200 -0
  71. package/shared/{tools → brush}/BrushSize.svelte +2 -30
  72. package/shared/{tools → brush}/ColorField.svelte +3 -1
  73. package/shared/{tools → brush}/ColorPicker.svelte +86 -9
  74. package/shared/{tools → brush}/ColorSwatch.svelte +95 -42
  75. package/shared/brush/brush-cursor.ts +408 -0
  76. package/shared/brush/brush-textures.ts +508 -0
  77. package/shared/brush/brush-utils.ts +76 -0
  78. package/shared/brush/brush.ts +506 -0
  79. package/shared/brush/types.ts +41 -0
  80. package/shared/core/EDITOR.md +182 -0
  81. package/shared/core/editor.ts +1730 -0
  82. package/shared/crop/CROP.md +139 -0
  83. package/shared/crop/crop.ts +1027 -0
  84. package/shared/image/IMAGE.md +135 -0
  85. package/shared/image/image.ts +300 -0
  86. package/shared/resize/resize.ts +1894 -0
  87. package/shared/types.ts +14 -0
  88. package/shared/utils/pixi.ts +19 -246
  89. package/shared/zoom/zoom.ts +729 -0
  90. package/dist/shared/layers/Layers.svelte +0 -231
  91. package/dist/shared/layers/Layers.svelte.d.ts +0 -18
  92. package/dist/shared/layers/utils.d.ts +0 -73
  93. package/dist/shared/layers/utils.js +0 -156
  94. package/dist/shared/tools/Brush.svelte +0 -215
  95. package/dist/shared/tools/Brush.svelte.d.ts +0 -29
  96. package/dist/shared/tools/Crop.svelte +0 -155
  97. package/dist/shared/tools/Crop.svelte.d.ts +0 -16
  98. package/dist/shared/tools/Cropper.svelte +0 -271
  99. package/dist/shared/tools/Cropper.svelte.d.ts +0 -41
  100. package/dist/shared/tools/Handle.svelte +0 -260
  101. package/dist/shared/tools/Handle.svelte.d.ts +0 -29
  102. package/dist/shared/tools/Sources.svelte +0 -257
  103. package/dist/shared/tools/Sources.svelte.d.ts +0 -34
  104. package/dist/shared/tools/Tools.svelte +0 -102
  105. package/dist/shared/tools/Tools.svelte.d.ts +0 -48
  106. package/dist/shared/tools/brush.d.ts +0 -62
  107. package/dist/shared/tools/brush.js +0 -133
  108. package/dist/shared/tools/crop.d.ts +0 -15
  109. package/dist/shared/tools/crop.js +0 -154
  110. package/dist/shared/tools/index.d.ts +0 -5
  111. package/dist/shared/tools/index.js +0 -5
  112. package/dist/shared/tools/sources.d.ts +0 -46
  113. package/dist/shared/tools/sources.js +0 -121
  114. package/dist/shared/tools/types.d.ts +0 -1
  115. package/shared/layers/Layers.svelte +0 -250
  116. package/shared/layers/utils.ts +0 -294
  117. package/shared/tools/Brush.svelte +0 -280
  118. package/shared/tools/BrushOptions.svelte +0 -180
  119. package/shared/tools/Crop.svelte +0 -189
  120. package/shared/tools/Cropper.svelte +0 -346
  121. package/shared/tools/Handle.svelte +0 -289
  122. package/shared/tools/Sources.svelte +0 -283
  123. package/shared/tools/Tools.svelte +0 -162
  124. package/shared/tools/brush.ts +0 -247
  125. package/shared/tools/crop.ts +0 -213
  126. package/shared/tools/index.ts +0 -5
  127. package/shared/tools/sources.ts +0 -195
  128. package/shared/tools/types.ts +0 -1
  129. /package/dist/shared/{tools → brush}/BrushSize.svelte.d.ts +0 -0
  130. /package/dist/shared/{tools/types.js → types.js} +0 -0
@@ -0,0 +1,35 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import type { Writable } from "svelte/store";
3
+ declare const __propDef: {
4
+ props: {
5
+ layers: Writable<{
6
+ active_layer: string;
7
+ layers: {
8
+ name: string;
9
+ id: string;
10
+ user_created: boolean;
11
+ }[];
12
+ }>;
13
+ enable_additional_layers?: boolean | undefined;
14
+ enable_layers?: boolean | undefined;
15
+ show_layers?: boolean | undefined;
16
+ };
17
+ events: {
18
+ new_layer: CustomEvent<void>;
19
+ change_layer: CustomEvent<string>;
20
+ move_layer: CustomEvent<{
21
+ id: string;
22
+ direction: "up" | "down";
23
+ }>;
24
+ delete_layer: CustomEvent<string>;
25
+ } & {
26
+ [evt: string]: CustomEvent<any>;
27
+ };
28
+ slots: {};
29
+ };
30
+ export type SecondaryToolbarProps = typeof __propDef.props;
31
+ export type SecondaryToolbarEvents = typeof __propDef.events;
32
+ export type SecondaryToolbarSlots = typeof __propDef.slots;
33
+ export default class SecondaryToolbar extends SvelteComponent<SecondaryToolbarProps, SecondaryToolbarEvents, SecondaryToolbarSlots> {
34
+ }
35
+ export {};
@@ -0,0 +1,337 @@
1
+ <script context="module"></script>
2
+
3
+ <script>import { createEventDispatcher } from "svelte";
4
+ import IconButton from "./IconButton.svelte";
5
+ import {
6
+ Image,
7
+ Brush,
8
+ Erase,
9
+ Crop,
10
+ Upload,
11
+ ImagePaste,
12
+ Webcam,
13
+ Circle,
14
+ Resize,
15
+ ColorPickerSolid
16
+ } from "@gradio/icons";
17
+ import BrushOptions from "./brush/BrushOptions.svelte";
18
+ import {
19
+ } from "./brush/types";
20
+ import tinycolor from "tinycolor2";
21
+ export let tool = "image";
22
+ export let subtool = null;
23
+ export let background = false;
24
+ export let brush_options;
25
+ export let selected_size = brush_options && typeof brush_options.default_size === "number" ? brush_options.default_size : 25;
26
+ export let eraser_options;
27
+ export let selected_eraser_size = eraser_options && typeof eraser_options.default_size === "number" ? eraser_options.default_size : 25;
28
+ export let selected_color = brush_options && (() => {
29
+ const default_color = brush_options.default_color;
30
+ if (Array.isArray(default_color)) {
31
+ return default_color[0];
32
+ }
33
+ return default_color;
34
+ })();
35
+ export let selected_opacity = brush_options && (() => {
36
+ const default_color = brush_options.default_color;
37
+ if (Array.isArray(default_color)) {
38
+ return default_color[1];
39
+ }
40
+ const color = tinycolor(default_color);
41
+ if (color.getAlpha() < 1) {
42
+ return color.getAlpha();
43
+ }
44
+ return 1;
45
+ })();
46
+ export let preview = false;
47
+ export let show_brush_color = false;
48
+ export let show_brush_size = false;
49
+ export let show_eraser_size = false;
50
+ export let sources;
51
+ export let transforms;
52
+ let recent_colors = [];
53
+ let enable_layers = true;
54
+ const dispatch = createEventDispatcher();
55
+ function handle_tool_click(e, _tool) {
56
+ e.stopPropagation();
57
+ dispatch("tool_change", { tool: _tool });
58
+ }
59
+ function handle_subtool_click(e, _subtool) {
60
+ e.stopPropagation();
61
+ dispatch("subtool_change", { tool, subtool: _subtool });
62
+ }
63
+ $:
64
+ show_brush_size = tool === "draw" && subtool === "size";
65
+ $:
66
+ show_brush_color = tool === "draw" && subtool === "color";
67
+ $:
68
+ show_eraser_size = tool === "erase" && subtool === "size";
69
+ $:
70
+ can_crop = transforms.includes("crop");
71
+ $:
72
+ can_resize = transforms.includes("resize");
73
+ $:
74
+ can_upload = sources.includes("upload");
75
+ $:
76
+ can_webcam = sources.includes("webcam");
77
+ $:
78
+ can_paste = sources.includes("clipboard");
79
+ </script>
80
+
81
+ <div class="toolbar-wrap">
82
+ <div class="half-container">
83
+ {#if sources.length > 0}
84
+ <IconButton
85
+ Icon={Image}
86
+ label="Image"
87
+ highlight={tool === "image"}
88
+ on:click={(e) => handle_tool_click(e, "image")}
89
+ size="medium"
90
+ padded={false}
91
+ transparent={true}
92
+ />
93
+ {/if}
94
+ {#if brush_options}
95
+ <IconButton
96
+ Icon={Brush}
97
+ label="Brush"
98
+ on:click={(e) => handle_tool_click(e, "draw")}
99
+ highlight={tool === "draw"}
100
+ size="medium"
101
+ padded={false}
102
+ transparent={true}
103
+ />
104
+ {/if}
105
+ {#if eraser_options}
106
+ <IconButton
107
+ Icon={Erase}
108
+ label="Erase"
109
+ on:click={(e) => handle_tool_click(e, "erase")}
110
+ highlight={tool === "erase"}
111
+ size="medium"
112
+ padded={false}
113
+ transparent={true}
114
+ />
115
+ {/if}
116
+ </div>
117
+ <div
118
+ class="half-container right"
119
+ class:hide={tool === "pan" ||
120
+ (tool === "image" && !background && sources.length === 0) ||
121
+ (tool === "image" && background && transforms.length === 0)}
122
+ >
123
+ {#if tool === "image"}
124
+ {#if background}
125
+ {#if can_crop}
126
+ <IconButton
127
+ Icon={Crop}
128
+ label="Crop"
129
+ on:click={(e) => handle_subtool_click(e, "crop")}
130
+ highlight={subtool === "crop"}
131
+ size="medium"
132
+ padded={false}
133
+ transparent={true}
134
+ offset={0}
135
+ />
136
+ {/if}
137
+ {#if can_resize}
138
+ <IconButton
139
+ Icon={Resize}
140
+ label="Resize"
141
+ on:click={(e) => handle_subtool_click(e, "size")}
142
+ highlight={subtool === "size"}
143
+ size="medium"
144
+ padded={false}
145
+ transparent={true}
146
+ offset={0}
147
+ />
148
+ {/if}
149
+ {:else}
150
+ {#if can_upload}
151
+ <IconButton
152
+ Icon={Upload}
153
+ label="Upload"
154
+ on:click={(e) => handle_subtool_click(e, "upload")}
155
+ highlight={subtool === "upload"}
156
+ size="medium"
157
+ padded={false}
158
+ transparent={true}
159
+ offset={0}
160
+ />
161
+ {/if}
162
+ {#if can_paste}
163
+ <IconButton
164
+ Icon={ImagePaste}
165
+ label="Paste"
166
+ on:click={(e) => handle_subtool_click(e, "paste")}
167
+ highlight={subtool === "paste"}
168
+ size="large"
169
+ padded={false}
170
+ transparent={true}
171
+ offset={0}
172
+ />
173
+ {/if}
174
+ {#if can_webcam}
175
+ <IconButton
176
+ Icon={Webcam}
177
+ label="Webcam"
178
+ on:click={(e) => handle_subtool_click(e, "webcam")}
179
+ highlight={subtool === "webcam"}
180
+ size="medium"
181
+ padded={false}
182
+ transparent={true}
183
+ offset={0}
184
+ />
185
+ {/if}
186
+ {/if}
187
+ {/if}
188
+
189
+ {#if tool === "draw" && brush_options}
190
+ <IconButton
191
+ Icon={ColorPickerSolid}
192
+ label="Color"
193
+ color={selected_color}
194
+ on:click={(e) => handle_subtool_click(e, "color")}
195
+ size="medium"
196
+ padded={false}
197
+ transparent={true}
198
+ offset={0}
199
+ />
200
+ <IconButton
201
+ Icon={Circle}
202
+ label="Brush Size"
203
+ on:click={(e) => handle_subtool_click(e, "size")}
204
+ highlight={subtool === "size"}
205
+ size="medium"
206
+ padded={false}
207
+ transparent={true}
208
+ offset={0}
209
+ />
210
+
211
+ {#if show_brush_color || show_brush_size}
212
+ <BrushOptions
213
+ colors={brush_options.colors}
214
+ color_mode={brush_options.color_mode}
215
+ {recent_colors}
216
+ show_swatch={show_brush_color}
217
+ show_size={show_brush_size}
218
+ bind:selected_size
219
+ bind:selected_color
220
+ bind:selected_opacity
221
+ bind:preview
222
+ on:click_outside={(e) => {
223
+ e.stopPropagation();
224
+ preview = false;
225
+ show_brush_color = false;
226
+ show_brush_size = false;
227
+ handle_subtool_click(e, null);
228
+ }}
229
+ mode="brush"
230
+ />
231
+ {/if}
232
+ {/if}
233
+
234
+ {#if tool === "erase" && eraser_options}
235
+ <IconButton
236
+ Icon={Circle}
237
+ label="Eraser Size"
238
+ on:click={(e) => handle_subtool_click(e, "size")}
239
+ highlight={subtool === "size"}
240
+ size="medium"
241
+ padded={false}
242
+ transparent={true}
243
+ offset={0}
244
+ />
245
+ {/if}
246
+ {#if show_eraser_size}
247
+ <BrushOptions
248
+ colors={[]}
249
+ show_swatch={false}
250
+ show_size={true}
251
+ bind:selected_size={selected_eraser_size}
252
+ bind:selected_color
253
+ bind:selected_opacity
254
+ bind:preview
255
+ on:click_outside={(e) => {
256
+ e.stopPropagation();
257
+ preview = false;
258
+ show_eraser_size = false;
259
+ handle_subtool_click(e, null);
260
+ }}
261
+ mode="eraser"
262
+ />
263
+ {/if}
264
+ </div>
265
+ </div>
266
+
267
+ <style>
268
+ .toolbar-wrap {
269
+ display: inline-flex;
270
+ flex-direction: column;
271
+ justify-content: center;
272
+ align-items: center;
273
+ position: absolute;
274
+ left: 15px;
275
+ right: 0;
276
+ top: 30%;
277
+ /* transform: translateY(-50%); */
278
+ width: 30px;
279
+ border: 1px solid var(--block-border-color);
280
+ border-radius: var(--radius-md);
281
+
282
+ gap: var(--spacing-sm);
283
+ z-index: 1000;
284
+ background-color: var(--block-background-fill);
285
+ }
286
+
287
+ .half-container {
288
+ flex: 1;
289
+ display: flex;
290
+ flex-direction: column;
291
+ gap: var(--spacing-sm);
292
+ position: relative;
293
+ }
294
+
295
+ .half-container {
296
+ width: 100%;
297
+ padding: var(--spacing-sm) 0;
298
+ }
299
+
300
+ .half-container:last-child {
301
+ border-top: 1px solid var(--block-border-color);
302
+ }
303
+
304
+ .hide {
305
+ display: none;
306
+ }
307
+
308
+ /* .toolbar-left,
309
+ .toolbar-right {
310
+ display: flex;
311
+ flex-direction: row;
312
+ align-items: center;
313
+ gap: var(--spacing-sm);
314
+ display: flex;
315
+ z-index: 1000;
316
+ border-radius: var(--radius-sm);
317
+ background-color: #fff;
318
+ padding: var(--spacing-sm) 0.3rem;
319
+ width: auto;
320
+ }
321
+
322
+ .toolbar-right {
323
+ border-left: 0;
324
+ border-top-left-radius: 0;
325
+ border-bottom-left-radius: 0;
326
+ }
327
+
328
+ .toolbar-left {
329
+ border-top-right-radius: 0;
330
+ border-bottom-right-radius: 0;
331
+ }
332
+
333
+ .toolbar-layers {
334
+ border-top-left-radius: 0;
335
+ border-bottom-left-radius: 0;
336
+ } */
337
+ </style>
@@ -0,0 +1,42 @@
1
+ import { SvelteComponent } from "svelte";
2
+ export type Tool = "image" | "draw" | "erase" | "pan";
3
+ export type Subtool = "upload" | "paste" | "webcam" | "color" | "size" | "crop" | "remove_background" | null;
4
+ import type { Source, Transform } from "./types";
5
+ import { type Brush as BrushType, type Eraser as EraserType } from "./brush/types";
6
+ declare const __propDef: {
7
+ props: {
8
+ tool?: Tool | undefined;
9
+ subtool?: Subtool | undefined;
10
+ background?: boolean | undefined;
11
+ brush_options: BrushType | false;
12
+ selected_size?: number | undefined;
13
+ eraser_options: EraserType;
14
+ selected_eraser_size?: number | undefined;
15
+ selected_color?: any;
16
+ selected_opacity?: any;
17
+ preview?: boolean | undefined;
18
+ show_brush_color?: boolean | undefined;
19
+ show_brush_size?: boolean | undefined;
20
+ show_eraser_size?: boolean | undefined;
21
+ sources: Source[];
22
+ transforms: Transform[];
23
+ };
24
+ events: {
25
+ tool_change: CustomEvent<{
26
+ tool: Tool;
27
+ }>;
28
+ subtool_change: CustomEvent<{
29
+ tool: Tool;
30
+ subtool: Subtool;
31
+ }>;
32
+ } & {
33
+ [evt: string]: CustomEvent<any>;
34
+ };
35
+ slots: {};
36
+ };
37
+ export type ToolbarProps = typeof __propDef.props;
38
+ export type ToolbarEvents = typeof __propDef.events;
39
+ export type ToolbarSlots = typeof __propDef.slots;
40
+ export default class Toolbar extends SvelteComponent<ToolbarProps, ToolbarEvents, ToolbarSlots> {
41
+ }
42
+ export {};
@@ -1,6 +1,6 @@
1
- <script>import { createEventDispatcher } from "svelte";
1
+ <script>import { createEventDispatcher, tick } from "svelte";
2
2
  import { click_outside } from "../utils/events";
3
- import {} from "./Brush.svelte";
3
+ import {} from "./types";
4
4
  import ColorPicker from "./ColorPicker.svelte";
5
5
  import ColorSwatch from "./ColorSwatch.svelte";
6
6
  import ColorField from "./ColorField.svelte";
@@ -10,19 +10,18 @@ export let selected_color;
10
10
  export let color_mode = void 0;
11
11
  export let recent_colors = [];
12
12
  export let selected_size;
13
- export let dimensions;
14
- export let parent_width;
15
- export let parent_height;
16
- export let parent_left;
17
- export let toolbar_box;
13
+ export let selected_opacity;
18
14
  export let show_swatch;
15
+ export let show_size;
16
+ export let mode = "brush";
19
17
  let color_picker = false;
20
18
  let current_mode = "hex";
21
19
  let editing_index = null;
22
20
  const dispatch = createEventDispatcher();
23
21
  function handle_color_selection({
24
22
  index,
25
- color
23
+ color,
24
+ opacity
26
25
  }, type) {
27
26
  if (type === "user" && !color) {
28
27
  editing_index = index;
@@ -31,6 +30,9 @@ function handle_color_selection({
31
30
  if (!color)
32
31
  return;
33
32
  selected_color = color;
33
+ if (opacity !== void 0) {
34
+ selected_opacity = opacity;
35
+ }
34
36
  if (type === "core") {
35
37
  color_picker = false;
36
38
  }
@@ -44,30 +46,45 @@ $:
44
46
  handle_color_change(selected_color);
45
47
  let width = 0;
46
48
  let height = 0;
47
- let c_width = 0;
48
- let c_height = 0;
49
- let wrap_el;
50
- let full_screen = false;
51
- let anchor = "default";
52
- let left_anchor = 0;
53
- let top_anchor = null;
54
- $: {
55
- if (wrap_el && (width || height || c_height || c_width)) {
56
- const box = wrap_el.getBoundingClientRect();
57
- color_picker;
58
- if (box.width > parent_width) {
59
- full_screen = true;
60
- } else if (parent_width > box.width + 230 * 2 + 25) {
61
- anchor = "default";
62
- left_anchor = toolbar_box.right - parent_left + 24;
63
- } else {
64
- anchor = "center";
65
- }
66
- if (box.height + 50 > parent_height) {
67
- anchor = "top";
68
- top_anchor = true;
49
+ function debounce(func, delay) {
50
+ let timeout;
51
+ return function(...args) {
52
+ clearTimeout(timeout);
53
+ timeout = setTimeout(() => func(...args), delay);
54
+ };
55
+ }
56
+ export let preview = false;
57
+ function handle_preview() {
58
+ if (!preview) {
59
+ preview = true;
60
+ debounced_close_preview();
61
+ } else {
62
+ debounced_close_preview();
63
+ }
64
+ }
65
+ function handle_close_preview() {
66
+ preview = false;
67
+ }
68
+ const debounced_close_preview = debounce(handle_close_preview, 1e3);
69
+ $:
70
+ selected_size, selected_color, handle_preview();
71
+ function handle_select(color) {
72
+ selected_color = color;
73
+ }
74
+ function handle_add_color() {
75
+ if (recent_colors.length >= 5) {
76
+ recent_colors.pop();
77
+ }
78
+ if (recent_colors.some((color) => {
79
+ if (Array.isArray(color)) {
80
+ return color[0] === selected_color && color[1] === selected_opacity;
69
81
  }
82
+ return color === selected_color;
83
+ })) {
84
+ return;
70
85
  }
86
+ recent_colors.push([selected_color, selected_opacity]);
87
+ recent_colors = recent_colors;
71
88
  }
72
89
  </script>
73
90
 
@@ -77,22 +94,21 @@ $: {
77
94
  class="wrap"
78
95
  class:padded={!color_picker}
79
96
  use:click_outside={() => dispatch("click_outside")}
80
- class:anchor_default={anchor === "default"}
81
- class:anchor_center={anchor === "center"}
82
- class:anchor_top={anchor === "top"}
83
- bind:this={wrap_el}
84
- bind:clientWidth={c_width}
85
- bind:clientHeight={c_height}
86
- class:anchor={`${left_anchor}px`}
97
+ class:color_picker
98
+ class:size_picker={show_size && mode === "brush"}
99
+ class:eraser_picker={mode === "eraser"}
87
100
  >
88
101
  {#if color_mode === "defaults"}
89
102
  {#if color_picker}
90
- <ColorPicker bind:color={selected_color} />
103
+ <ColorPicker
104
+ bind:color={selected_color}
105
+ bind:opacity={selected_opacity}
106
+ />
91
107
  <ColorField
92
108
  bind:current_mode
93
109
  color={selected_color}
94
110
  on:close={() => (color_picker = false)}
95
- on:selected={({ detail }) => (selected_color = detail)}
111
+ on:selected={({ detail }) => handle_select(detail)}
96
112
  />
97
113
  {/if}
98
114
  {/if}
@@ -105,20 +121,19 @@ $: {
105
121
  user_colors={color_mode === "defaults" ? recent_colors : null}
106
122
  {selected_color}
107
123
  {current_mode}
124
+ on:add_color={handle_add_color}
108
125
  />
109
126
  {/if}
110
127
 
111
- {#if color_picker || show_swatch}
112
- <div class="sep"></div>
128
+ {#if show_size}
129
+ <BrushSize max={100} min={1} bind:selected_size />
113
130
  {/if}
114
-
115
- <BrushSize max={dimensions[0] / 10} min={1} bind:selected_size />
116
131
  </div>
117
132
 
118
133
  <style>
119
134
  .wrap {
120
135
  max-width: 230px;
121
- width: 90%;
136
+ /* width: 90%; */
122
137
  position: absolute;
123
138
  display: flex;
124
139
  flex-direction: column;
@@ -132,31 +147,20 @@ $: {
132
147
  cursor: default;
133
148
  z-index: var(--layer-top);
134
149
  overflow: hidden;
135
- }
150
+ top: 0;
136
151
 
137
- .anchor_default {
138
- position: absolute;
139
- left: var(--left-anchor);
140
- bottom: 8px;
152
+ transform: translate(35px, -12px);
141
153
  }
142
- .anchor_center {
143
- position: absolute;
144
- bottom: 50px;
145
- left: 50%;
146
- transform: translateX(-50%);
154
+
155
+ .color_picker {
156
+ transform: translate(35px, -50%);
147
157
  }
148
158
 
149
- .anchor_top {
150
- position: absolute;
151
- top: 1px;
152
- left: 50%;
153
- transform: translateX(-50%);
159
+ .size_picker {
160
+ transform: translate(35px, 18px);
154
161
  }
155
162
 
156
- .sep {
157
- height: 1px;
158
- background-color: var(--block-border-color);
159
- margin: 0 var(--size-3);
160
- margin-top: var(--size-1);
163
+ .eraser_picker {
164
+ transform: translate(35px, -7px);
161
165
  }
162
166
  </style>
@@ -1,18 +1,18 @@
1
1
  import { SvelteComponent } from "svelte";
2
- import { type Brush } from "./Brush.svelte";
2
+ import { type Brush, type ColorTuple } from "./types";
3
+ import type { ColorInput } from "tinycolor2";
3
4
  declare const __propDef: {
4
5
  props: {
5
- colors: string[];
6
- selected_color: string;
6
+ colors: (ColorInput | ColorTuple)[];
7
+ selected_color: any;
7
8
  color_mode?: Brush["color_mode"] | undefined;
8
- recent_colors?: (string | null)[] | undefined;
9
+ recent_colors?: (ColorInput | ColorTuple)[] | undefined;
9
10
  selected_size: number;
10
- dimensions: [number, number];
11
- parent_width: number;
12
- parent_height: number;
13
- parent_left: number;
14
- toolbar_box: DOMRect | Record<string, never>;
11
+ selected_opacity: number;
15
12
  show_swatch: boolean;
13
+ show_size: boolean;
14
+ mode?: ("brush" | "eraser") | undefined;
15
+ preview?: boolean | undefined;
16
16
  };
17
17
  events: {
18
18
  click_outside: CustomEvent<void>;
@@ -5,34 +5,9 @@ export let selected_size;
5
5
  export let min;
6
6
  export let max;
7
7
  const dispatch = createEventDispatcher();
8
- let width = 0;
9
- let height = 0;
10
- let c_width = 0;
11
- let c_height = 0;
12
- let wrap_el;
13
- let anchor_right = false;
14
- let anchor_top = false;
15
- $: {
16
- if (wrap_el && (width || height || c_height || c_width)) {
17
- const box = wrap_el.getBoundingClientRect();
18
- anchor_right = box.width + 30 > width / 2;
19
- anchor_top = box.y < 80;
20
- }
21
- }
22
8
  </script>
23
9
 
24
- <svelte:window bind:innerHeight={height} bind:innerWidth={width} />
25
-
26
- <div
27
- class="wrap"
28
- use:click_outside={() => dispatch("click_outside")}
29
- bind:this={wrap_el}
30
- bind:clientWidth={c_width}
31
- bind:clientHeight={c_height}
32
- class:right={anchor_right}
33
- class:top={anchor_top}
34
- class:bottom={!anchor_top}
35
- >
10
+ <div class="wrap" use:click_outside={() => dispatch("click_outside")}>
36
11
  <span>
37
12
  <BrushSize />
38
13
  </span>
@@ -41,7 +16,7 @@ $: {
41
16
 
42
17
  <style>
43
18
  .wrap {
44
- width: 100%;
19
+ width: 230px;
45
20
  display: flex;
46
21
  gap: var(--size-4);
47
22
  background: var(--background-fill-secondary);
@@ -1,6 +1,7 @@
1
- <script>import { Eyedropper } from "@gradio/icons";
1
+ <script>import { Eyedropper, Plus } from "@gradio/icons";
2
2
  import { createEventDispatcher } from "svelte";
3
3
  import tinycolor from "tinycolor2";
4
+ import IconButton from "../IconButton.svelte";
4
5
  export let color;
5
6
  export let current_mode = "hex";
6
7
  const dispatch = createEventDispatcher();