@gradio/imageeditor 0.12.14 → 0.14.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 (131) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/Example.svelte +1 -1
  3. package/IMAGE_EDITOR_OVERVIEW.md +224 -0
  4. package/ImageEditor.stories.svelte +13 -5
  5. package/Index.svelte +46 -45
  6. package/{shared/InteractiveImageEditor.svelte → InteractiveImageEditor.svelte} +65 -103
  7. package/README.md +2 -0
  8. package/dist/Example.svelte.d.ts +1 -1
  9. package/dist/Index.svelte +35 -33
  10. package/dist/Index.svelte.d.ts +25 -16
  11. package/dist/{shared/InteractiveImageEditor.svelte → InteractiveImageEditor.svelte} +54 -88
  12. package/dist/{shared/InteractiveImageEditor.svelte.d.ts → InteractiveImageEditor.svelte.d.ts} +17 -15
  13. package/dist/shared/Anchor.svelte +311 -0
  14. package/dist/shared/Anchor.svelte.d.ts +18 -0
  15. package/dist/shared/Controls.svelte +169 -18
  16. package/dist/shared/Controls.svelte.d.ts +9 -2
  17. package/dist/shared/{tools/IconButton.svelte → IconButton.svelte} +19 -3
  18. package/dist/shared/{tools/IconButton.svelte.d.ts → IconButton.svelte.d.ts} +4 -1
  19. package/dist/shared/ImageEditor.svelte +572 -289
  20. package/dist/shared/ImageEditor.svelte.d.ts +54 -56
  21. package/dist/shared/Layers.svelte +260 -0
  22. package/dist/shared/Layers.svelte.d.ts +37 -0
  23. package/dist/shared/Resize.svelte +218 -0
  24. package/dist/shared/Resize.svelte.d.ts +29 -0
  25. package/dist/shared/SecondaryToolbar.svelte +55 -0
  26. package/dist/shared/SecondaryToolbar.svelte.d.ts +37 -0
  27. package/dist/shared/Toolbar.svelte +337 -0
  28. package/dist/shared/Toolbar.svelte.d.ts +42 -0
  29. package/dist/shared/{tools → brush}/BrushOptions.svelte +68 -64
  30. package/dist/shared/{tools → brush}/BrushOptions.svelte.d.ts +9 -9
  31. package/dist/shared/{tools → brush}/BrushSize.svelte +2 -27
  32. package/dist/shared/{tools → brush}/ColorField.svelte +2 -1
  33. package/dist/shared/{tools → brush}/ColorField.svelte.d.ts +1 -0
  34. package/dist/shared/{tools → brush}/ColorPicker.svelte +81 -9
  35. package/dist/shared/{tools → brush}/ColorPicker.svelte.d.ts +1 -0
  36. package/dist/shared/{tools → brush}/ColorSwatch.svelte +78 -38
  37. package/dist/shared/{tools → brush}/ColorSwatch.svelte.d.ts +6 -2
  38. package/dist/shared/brush/brush-cursor.d.ts +101 -0
  39. package/dist/shared/brush/brush-cursor.js +327 -0
  40. package/dist/shared/brush/brush-textures.d.ts +65 -0
  41. package/dist/shared/brush/brush-textures.js +385 -0
  42. package/dist/shared/brush/brush-utils.d.ts +32 -0
  43. package/dist/shared/brush/brush-utils.js +59 -0
  44. package/dist/shared/brush/brush.d.ts +152 -0
  45. package/dist/shared/brush/brush.js +397 -0
  46. package/dist/shared/brush/types.d.ts +37 -0
  47. package/dist/shared/brush/types.js +1 -0
  48. package/dist/shared/core/editor.d.ts +261 -0
  49. package/dist/shared/core/editor.js +1264 -0
  50. package/dist/shared/crop/crop.d.ts +201 -0
  51. package/dist/shared/crop/crop.js +727 -0
  52. package/dist/shared/image/image.d.ts +89 -0
  53. package/dist/shared/image/image.js +183 -0
  54. package/dist/shared/resize/resize.d.ts +270 -0
  55. package/dist/shared/resize/resize.js +1413 -0
  56. package/dist/shared/types.d.ts +16 -0
  57. package/dist/shared/utils/pixi.d.ts +16 -57
  58. package/dist/shared/utils/pixi.js +15 -113
  59. package/dist/shared/zoom/zoom.d.ts +136 -0
  60. package/dist/shared/zoom/zoom.js +548 -0
  61. package/package.json +8 -7
  62. package/shared/Anchor.svelte +384 -0
  63. package/shared/Controls.svelte +178 -37
  64. package/shared/{tools/IconButton.svelte → IconButton.svelte} +21 -4
  65. package/shared/ImageEditor.svelte +712 -350
  66. package/shared/Layers.svelte +282 -0
  67. package/shared/Resize.svelte +239 -0
  68. package/shared/SecondaryToolbar.svelte +67 -0
  69. package/shared/Toolbar.svelte +386 -0
  70. package/shared/brush/BRUSH_TOOL.md +134 -0
  71. package/shared/brush/BrushOptions.svelte +200 -0
  72. package/shared/{tools → brush}/BrushSize.svelte +2 -30
  73. package/shared/{tools → brush}/ColorField.svelte +3 -1
  74. package/shared/{tools → brush}/ColorPicker.svelte +86 -9
  75. package/shared/{tools → brush}/ColorSwatch.svelte +95 -42
  76. package/shared/brush/brush-cursor.ts +408 -0
  77. package/shared/brush/brush-textures.ts +485 -0
  78. package/shared/brush/brush-utils.ts +76 -0
  79. package/shared/brush/brush.ts +510 -0
  80. package/shared/brush/types.ts +41 -0
  81. package/shared/core/EDITOR.md +182 -0
  82. package/shared/core/editor.ts +1788 -0
  83. package/shared/crop/CROP.md +139 -0
  84. package/shared/crop/crop.ts +1027 -0
  85. package/shared/image/IMAGE.md +135 -0
  86. package/shared/image/image.ts +298 -0
  87. package/shared/resize/resize.ts +1894 -0
  88. package/shared/types.ts +19 -0
  89. package/shared/utils/pixi.ts +19 -246
  90. package/shared/zoom/zoom.ts +729 -0
  91. package/dist/shared/layers/Layers.svelte +0 -231
  92. package/dist/shared/layers/Layers.svelte.d.ts +0 -18
  93. package/dist/shared/layers/utils.d.ts +0 -73
  94. package/dist/shared/layers/utils.js +0 -156
  95. package/dist/shared/tools/Brush.svelte +0 -215
  96. package/dist/shared/tools/Brush.svelte.d.ts +0 -29
  97. package/dist/shared/tools/Crop.svelte +0 -155
  98. package/dist/shared/tools/Crop.svelte.d.ts +0 -16
  99. package/dist/shared/tools/Cropper.svelte +0 -271
  100. package/dist/shared/tools/Cropper.svelte.d.ts +0 -41
  101. package/dist/shared/tools/Handle.svelte +0 -260
  102. package/dist/shared/tools/Handle.svelte.d.ts +0 -29
  103. package/dist/shared/tools/Sources.svelte +0 -257
  104. package/dist/shared/tools/Sources.svelte.d.ts +0 -34
  105. package/dist/shared/tools/Tools.svelte +0 -102
  106. package/dist/shared/tools/Tools.svelte.d.ts +0 -48
  107. package/dist/shared/tools/brush.d.ts +0 -62
  108. package/dist/shared/tools/brush.js +0 -133
  109. package/dist/shared/tools/crop.d.ts +0 -15
  110. package/dist/shared/tools/crop.js +0 -154
  111. package/dist/shared/tools/index.d.ts +0 -5
  112. package/dist/shared/tools/index.js +0 -5
  113. package/dist/shared/tools/sources.d.ts +0 -46
  114. package/dist/shared/tools/sources.js +0 -121
  115. package/dist/shared/tools/types.d.ts +0 -1
  116. package/shared/layers/Layers.svelte +0 -250
  117. package/shared/layers/utils.ts +0 -294
  118. package/shared/tools/Brush.svelte +0 -280
  119. package/shared/tools/BrushOptions.svelte +0 -180
  120. package/shared/tools/Crop.svelte +0 -189
  121. package/shared/tools/Cropper.svelte +0 -346
  122. package/shared/tools/Handle.svelte +0 -289
  123. package/shared/tools/Sources.svelte +0 -283
  124. package/shared/tools/Tools.svelte +0 -162
  125. package/shared/tools/brush.ts +0 -247
  126. package/shared/tools/crop.ts +0 -213
  127. package/shared/tools/index.ts +0 -5
  128. package/shared/tools/sources.ts +0 -195
  129. package/shared/tools/types.ts +0 -1
  130. /package/dist/shared/{tools → brush}/BrushSize.svelte.d.ts +0 -0
  131. /package/dist/shared/{tools/types.js → types.js} +0 -0
@@ -0,0 +1,55 @@
1
+ <script>import Layers from "./Layers.svelte";
2
+ export let layers;
3
+ export let enable_additional_layers = true;
4
+ export let enable_layers = true;
5
+ export let show_layers = false;
6
+ </script>
7
+
8
+ <div class="toolbar-wrap-wrap">
9
+ <div class="toolbar-wrap">
10
+ {#if enable_layers}
11
+ <Layers
12
+ {layers}
13
+ {enable_additional_layers}
14
+ {enable_layers}
15
+ {show_layers}
16
+ on:new_layer
17
+ on:change_layer
18
+ on:move_layer
19
+ on:delete_layer
20
+ on:toggle_layer_visibility
21
+ />
22
+ {/if}
23
+ </div>
24
+ </div>
25
+
26
+ <style>
27
+ .toolbar-wrap-wrap {
28
+ position: absolute;
29
+ right: 0;
30
+ bottom: 0;
31
+ width: fit-content;
32
+ max-height: 100%;
33
+ overflow-y: auto;
34
+ display: flex;
35
+ flex-direction: column-reverse;
36
+ }
37
+
38
+ .toolbar-wrap {
39
+ min-width: 110px;
40
+ display: flex;
41
+ flex-direction: column;
42
+ justify-content: center;
43
+ align-items: center;
44
+ position: relative;
45
+ right: 0;
46
+ bottom: 0;
47
+ border: 1px solid var(--block-border-color);
48
+ border-radius: 0;
49
+ border-top-left-radius: var(--radius-md);
50
+ border-right: none;
51
+ border-bottom: none;
52
+ z-index: 1000;
53
+ background-color: var(--block-background-fill);
54
+ }
55
+ </style>
@@ -0,0 +1,37 @@
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
+ visible: boolean;
12
+ }[];
13
+ }>;
14
+ enable_additional_layers?: boolean | undefined;
15
+ enable_layers?: boolean | undefined;
16
+ show_layers?: boolean | undefined;
17
+ };
18
+ events: {
19
+ new_layer: CustomEvent<void>;
20
+ change_layer: CustomEvent<string>;
21
+ move_layer: CustomEvent<{
22
+ id: string;
23
+ direction: "up" | "down";
24
+ }>;
25
+ delete_layer: CustomEvent<string>;
26
+ toggle_layer_visibility: CustomEvent<string>;
27
+ } & {
28
+ [evt: string]: CustomEvent<any>;
29
+ };
30
+ slots: {};
31
+ };
32
+ export type SecondaryToolbarProps = typeof __propDef.props;
33
+ export type SecondaryToolbarEvents = typeof __propDef.events;
34
+ export type SecondaryToolbarSlots = typeof __propDef.slots;
35
+ export default class SecondaryToolbar extends SvelteComponent<SecondaryToolbarProps, SecondaryToolbarEvents, SecondaryToolbarSlots> {
36
+ }
37
+ 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>;