@gradio/imageeditor 0.14.5 → 0.15.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 (39) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/InteractiveImageEditor.svelte +4 -7
  3. package/dist/InteractiveImageEditor.svelte +4 -3
  4. package/dist/InteractiveImageEditor.svelte.d.ts +1 -1
  5. package/dist/shared/Controls.svelte +32 -1
  6. package/dist/shared/Controls.svelte.d.ts +2 -0
  7. package/dist/shared/ImageEditor.svelte +23 -1
  8. package/dist/shared/ImageEditor.svelte.d.ts +2 -1
  9. package/dist/shared/brush/brush-cursor.js +0 -42
  10. package/dist/shared/brush/brush-textures.d.ts +19 -2
  11. package/dist/shared/brush/brush-textures.js +120 -82
  12. package/dist/shared/brush/brush.js +0 -52
  13. package/dist/shared/{utils → core}/commands.d.ts +19 -58
  14. package/dist/shared/core/commands.js +70 -0
  15. package/dist/shared/core/editor.d.ts +4 -91
  16. package/dist/shared/core/editor.js +18 -708
  17. package/dist/shared/core/layers.d.ts +143 -0
  18. package/dist/shared/core/layers.js +774 -0
  19. package/dist/shared/image/image.d.ts +14 -4
  20. package/dist/shared/image/image.js +91 -18
  21. package/dist/shared/resize/resize.d.ts +31 -0
  22. package/dist/shared/resize/resize.js +127 -290
  23. package/dist/shared/zoom/zoom.js +0 -51
  24. package/package.json +7 -7
  25. package/shared/Controls.svelte +33 -1
  26. package/shared/ImageEditor.svelte +25 -9
  27. package/shared/Toolbar.svelte +1 -4
  28. package/shared/brush/ColorSwatch.svelte +0 -3
  29. package/shared/brush/brush-cursor.ts +0 -42
  30. package/shared/brush/brush-textures.ts +166 -83
  31. package/shared/brush/brush.ts +0 -53
  32. package/shared/core/commands.ts +118 -0
  33. package/shared/core/editor.ts +33 -957
  34. package/shared/core/layers.ts +1068 -0
  35. package/shared/image/image.ts +139 -21
  36. package/shared/resize/resize.ts +160 -299
  37. package/shared/zoom/zoom.ts +0 -51
  38. package/dist/shared/utils/commands.js +0 -73
  39. package/shared/utils/commands.ts +0 -174
@@ -10,10 +10,8 @@ export class ZoomTool {
10
10
  name = "zoom";
11
11
  min_zoom = writable(true);
12
12
  image_editor_context;
13
- // Constants
14
13
  max_zoom = 10;
15
14
  border_padding = 30;
16
- // State
17
15
  pad_bottom = 0;
18
16
  is_pinching = false;
19
17
  is_dragging = false;
@@ -52,30 +50,23 @@ export class ZoomTool {
52
50
  * @returns {void}
53
51
  */
54
52
  set_zoom(zoom_level) {
55
- // Calculate the min zoom level
56
53
  const fit_zoom = this.calculate_min_zoom(this.local_dimensions.width, this.local_dimensions.height);
57
- // Determine the target zoom level
58
54
  let target_zoom;
59
55
  const is_fit_zoom = zoom_level === "fit";
60
56
  if (is_fit_zoom) {
61
57
  target_zoom = fit_zoom;
62
58
  }
63
59
  else {
64
- // Ensure zoom_level is between 0 and 1, then scale it to the range [min_zoom, max_zoom]
65
60
  target_zoom = Math.max(0, Math.min(this.max_zoom, zoom_level));
66
61
  }
67
- // Get the canvas dimensions
68
62
  const canvas = this.image_editor_context.app.screen;
69
63
  const canvas_width = canvas.width;
70
64
  const canvas_height = canvas.height;
71
- // Determine the center point for zooming
72
65
  let center_point;
73
- // Always use the center of the screen
74
66
  center_point = {
75
67
  x: canvas_width / 2,
76
68
  y: canvas_height / 2
77
69
  };
78
- // Apply the zoom using the existing zoom_to_point method
79
70
  this.zoom_to_point(target_zoom, center_point, true, is_fit_zoom);
80
71
  }
81
72
  /**
@@ -90,26 +81,19 @@ export class ZoomTool {
90
81
  this.current_tool = tool;
91
82
  this.current_subtool = subtool;
92
83
  this.pad_bottom = context.pad_bottom;
93
- // Initialize zoom and position
94
84
  const { width, height } = await this.get_container_dimensions();
95
85
  const fit_zoom = this.calculate_min_zoom(width, height);
96
- // Use fit zoom or 1, whichever is smaller
97
86
  const min_zoom = Math.min(fit_zoom, 1);
98
- // Set initial zoom
99
87
  this.local_scale = min_zoom;
100
- // Use simple center positioning
101
88
  const canvas = this.image_editor_context.app.screen;
102
89
  const center_x = canvas.width / 2;
103
90
  const center_y = canvas.height / 2;
104
- // Calculate initial position to center the scaled image
105
91
  const scaled_width = width * min_zoom;
106
92
  const scaled_height = height * min_zoom;
107
93
  const initial_x = center_x - scaled_width / 2;
108
94
  const initial_y = center_y - scaled_height / 2;
109
95
  this.local_position = { x: initial_x, y: initial_y };
110
- // Setup event listeners
111
96
  this.setup_event_listeners();
112
- // Update context with initial values
113
97
  await this.image_editor_context.set_image_properties({
114
98
  scale: min_zoom,
115
99
  position: { x: initial_x, y: initial_y }
@@ -132,13 +116,10 @@ export class ZoomTool {
132
116
  const stage = this.image_editor_context.app.stage;
133
117
  const canvas = this.image_editor_context.app.canvas;
134
118
  canvas.addEventListener("wheel", this.prevent_default, { passive: false });
135
- // Configure stage for interaction
136
119
  stage.eventMode = "static";
137
120
  stage.hitArea = this.image_editor_context.app.screen;
138
- // Add wheel event with options
139
121
  const wheel_listener = this.handle_wheel.bind(this);
140
122
  stage.addEventListener("wheel", wheel_listener, { passive: false });
141
- // Setup touch/pointer events based on device
142
123
  if ("ontouchstart" in window) {
143
124
  stage.addEventListener("touchstart", this.handle_touch_start.bind(this));
144
125
  stage.addEventListener("touchmove", this.handle_touch_move.bind(this));
@@ -160,14 +141,12 @@ export class ZoomTool {
160
141
  const is_trackpad = event.deltaMode === 0 && Math.abs(event.deltaY) < 50;
161
142
  const scroll_speed = is_trackpad ? 30 : 10;
162
143
  if (event.altKey || event.metaKey) {
163
- // Handle zooming with our new simplified logic
164
144
  const local_point = this.image_editor_context.app.stage.toLocal(event.global);
165
145
  const zoom_delta = -event.deltaY * (is_trackpad ? 0.001 : 0.0005);
166
146
  const new_scale = this.local_scale * (1 + zoom_delta);
167
147
  this.zoom_to_point(new_scale, local_point, true);
168
148
  }
169
149
  else {
170
- // Handle panning with bounds
171
150
  const delta_x = event.deltaX;
172
151
  const delta_y = event.deltaY;
173
152
  const raw_position = {
@@ -180,12 +159,10 @@ export class ZoomTool {
180
159
  const available_width = canvas.width - this.border_padding * 2;
181
160
  const available_height = canvas.height - this.border_padding * 2 - this.pad_bottom;
182
161
  let final_position = { ...raw_position };
183
- // If image is smaller than available space, center it
184
162
  if (scaled_width <= available_width) {
185
163
  final_position.x = (canvas.width - scaled_width) / 2;
186
164
  }
187
165
  else {
188
- // Apply 50% rule for horizontal bounds
189
166
  const max_offset = canvas.width / 2;
190
167
  const left_bound = max_offset;
191
168
  const right_bound = canvas.width - max_offset - scaled_width;
@@ -196,7 +173,6 @@ export class ZoomTool {
196
173
  (canvas.height - this.pad_bottom - scaled_height) / 2;
197
174
  }
198
175
  else {
199
- // Apply 50% rule for vertical bounds, accounting for pad_bottom
200
176
  const max_offset = (canvas.height - this.pad_bottom) / 2;
201
177
  const top_bound = max_offset;
202
178
  const bottom_bound = canvas.height - this.pad_bottom - max_offset - scaled_height;
@@ -257,14 +233,10 @@ export class ZoomTool {
257
233
  !viewport_height) {
258
234
  return 1;
259
235
  }
260
- // Calculate available space accounting for padding
261
236
  const available_width = viewport_width - this.border_padding * 2;
262
237
  const available_height = viewport_height - this.border_padding * 2 - this.pad_bottom;
263
- // Calculate zoom ratios for both dimensions
264
238
  const width_ratio = available_width / container_width;
265
239
  const height_ratio = available_height / container_height;
266
- // Use the smaller ratio to ensure the image fits in both dimensions
267
- // Note: we no longer cap at 1, as 'fit' can be above 1
268
240
  return Math.min(width_ratio, height_ratio);
269
241
  }
270
242
  /**
@@ -274,7 +246,6 @@ export class ZoomTool {
274
246
  */
275
247
  handle_touch_start(event) {
276
248
  event.preventDefault();
277
- // Cast to any to access TouchEvent properties
278
249
  const touchEvent = event;
279
250
  if (touchEvent.touches && touchEvent.touches.length === 2) {
280
251
  this.is_pinching = true;
@@ -293,7 +264,6 @@ export class ZoomTool {
293
264
  */
294
265
  handle_touch_move(event) {
295
266
  event.preventDefault();
296
- // Cast to any to access TouchEvent properties
297
267
  const touchEvent = event;
298
268
  if (this.is_pinching &&
299
269
  touchEvent.touches &&
@@ -308,7 +278,6 @@ export class ZoomTool {
308
278
  };
309
279
  const scale_val = current_distance / this.last_pinch_distance;
310
280
  this.last_pinch_distance = current_distance;
311
- // Update zoom based on pinch
312
281
  this.zoom_to_point(this.local_scale * scale_val, pinch_center);
313
282
  }
314
283
  else if (this.is_dragging &&
@@ -319,7 +288,6 @@ export class ZoomTool {
319
288
  const current_position = new Point(touchEvent.touches[0].pageX - rect.left, touchEvent.touches[0].pageY - rect.top);
320
289
  const dx = current_position.x - this.last_touch_position.x;
321
290
  const dy = current_position.y - this.last_touch_position.y;
322
- // Update position based on drag
323
291
  this.image_editor_context.set_image_properties({
324
292
  position: {
325
293
  x: this.local_position.x + dx,
@@ -336,7 +304,6 @@ export class ZoomTool {
336
304
  */
337
305
  handle_touch_end(event) {
338
306
  event.preventDefault();
339
- // Cast to any to access TouchEvent properties
340
307
  const touchEvent = event;
341
308
  if (touchEvent.touches && touchEvent.touches.length < 2) {
342
309
  this.is_pinching = false;
@@ -364,7 +331,6 @@ export class ZoomTool {
364
331
  const canvas = this.image_editor_context.app.screen;
365
332
  const scaled_width = this.local_dimensions.width * this.local_scale;
366
333
  const scaled_height = this.local_dimensions.height * this.local_scale;
367
- // Calculate center position, accounting for pad_bottom
368
334
  const center_position = {
369
335
  x: (canvas.width - scaled_width) / 2,
370
336
  y: (canvas.height - scaled_height - this.pad_bottom) / 2
@@ -403,34 +369,26 @@ export class ZoomTool {
403
369
  * @private
404
370
  */
405
371
  zoom_to_point(new_zoom, point, hard, is_fit_zoom) {
406
- // Get the cursor position relative to the image's top-left corner
407
372
  const cursor_relative_to_image = {
408
373
  x: (point.x - this.local_position.x) / this.local_scale,
409
374
  y: (point.y - this.local_position.y) / this.local_scale
410
375
  };
411
- // Calculate what percentage of the image width/height this represents
412
376
  const image_percentages = {
413
377
  x: cursor_relative_to_image.x / this.local_dimensions.width,
414
378
  y: cursor_relative_to_image.y / this.local_dimensions.height
415
379
  };
416
- // Apply zoom limits
417
380
  const fit_zoom = this.calculate_min_zoom(this.local_dimensions.width, this.local_dimensions.height);
418
- // Use the fit zoom or 1, whichever is smaller as the minimum zoom
419
381
  const min_zoom = Math.min(fit_zoom, 1);
420
382
  new_zoom = Math.min(Math.max(new_zoom, min_zoom), this.max_zoom);
421
- // Calculate new dimensions
422
383
  const new_scaled_width = this.local_dimensions.width * new_zoom;
423
384
  const new_scaled_height = this.local_dimensions.height * new_zoom;
424
- // Calculate new position maintaining the same relative cursor position
425
385
  let new_position = {
426
386
  x: point.x - new_scaled_width * image_percentages.x,
427
387
  y: point.y - new_scaled_height * image_percentages.y
428
388
  };
429
- // Center the image if we're at minimum zoom or if this is a fit zoom operation
430
389
  if (new_zoom === min_zoom || is_fit_zoom) {
431
390
  const canvas_width = this.image_editor_context.app.screen.width;
432
391
  const canvas_height = this.image_editor_context.app.screen.height;
433
- // Center the image, accounting for pad_bottom
434
392
  new_position = {
435
393
  x: (canvas_width - new_scaled_width) / 2,
436
394
  y: (canvas_height - this.pad_bottom - new_scaled_height) / 2
@@ -449,7 +407,6 @@ export class ZoomTool {
449
407
  * @private
450
408
  */
451
409
  handle_pointer_down(event) {
452
- // Only allow dragging if the current tool is 'pan'
453
410
  if (event.button === 0 && this.current_tool === "pan") {
454
411
  this.is_pointer_dragging = true;
455
412
  this.drag_start.copyFrom(event.global);
@@ -463,7 +420,6 @@ export class ZoomTool {
463
420
  * @private
464
421
  */
465
422
  handle_pointer_move(event) {
466
- // Only handle move if we're dragging and the tool is 'pan'
467
423
  if (this.is_pointer_dragging && this.current_tool === "pan") {
468
424
  const raw_position = {
469
425
  x: event.global.x - this.drag_start.x,
@@ -475,12 +431,10 @@ export class ZoomTool {
475
431
  const available_width = canvas.width - this.border_padding * 2;
476
432
  const available_height = canvas.height - this.border_padding * 2 - this.pad_bottom;
477
433
  let final_position = { ...raw_position };
478
- // If image is smaller than available space, center it
479
434
  if (scaled_width <= available_width) {
480
435
  final_position.x = (canvas.width - scaled_width) / 2;
481
436
  }
482
437
  else {
483
- // Allow free movement during drag, bounds will be applied on pointer up
484
438
  final_position.x = raw_position.x;
485
439
  }
486
440
  if (scaled_height <= available_height) {
@@ -488,7 +442,6 @@ export class ZoomTool {
488
442
  (canvas.height - this.pad_bottom - scaled_height) / 2;
489
443
  }
490
444
  else {
491
- // Allow free movement during drag, bounds will be applied on pointer up
492
445
  final_position.y = raw_position.y;
493
446
  }
494
447
  this.image_editor_context.set_image_properties({
@@ -503,7 +456,6 @@ export class ZoomTool {
503
456
  * @private
504
457
  */
505
458
  handle_pointer_up(event) {
506
- // Only handle up if we're dragging and the tool is 'pan'
507
459
  if (this.is_pointer_dragging && this.current_tool === "pan") {
508
460
  this.is_pointer_dragging = false;
509
461
  const raw_position = {
@@ -516,12 +468,10 @@ export class ZoomTool {
516
468
  const available_width = canvas.width - this.border_padding * 2;
517
469
  const available_height = canvas.height - this.border_padding * 2 - this.pad_bottom;
518
470
  let final_position = { ...raw_position };
519
- // If image is smaller than available space, center it
520
471
  if (scaled_width <= available_width) {
521
472
  final_position.x = (canvas.width - scaled_width) / 2;
522
473
  }
523
474
  else {
524
- // Apply 50% rule for horizontal snapping
525
475
  const max_offset = canvas.width / 2;
526
476
  const left_bound = max_offset;
527
477
  const right_bound = canvas.width - max_offset - scaled_width;
@@ -532,7 +482,6 @@ export class ZoomTool {
532
482
  (canvas.height - this.pad_bottom - scaled_height) / 2;
533
483
  }
534
484
  else {
535
- // Apply 50% rule for vertical snapping, accounting for pad_bottom
536
485
  const max_offset = (canvas.height - this.pad_bottom) / 2;
537
486
  const top_bound = max_offset;
538
487
  const bottom_bound = canvas.height - this.pad_bottom - max_offset - scaled_height;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gradio/imageeditor",
3
- "version": "0.14.5",
3
+ "version": "0.15.0",
4
4
  "description": "Gradio UI packages",
5
5
  "type": "module",
6
6
  "author": "",
@@ -11,14 +11,14 @@
11
11
  "pixi-filters": "^6.1.0",
12
12
  "pixi.js": "^8.7.3",
13
13
  "tinycolor2": "^1.6.0",
14
- "@gradio/client": "^1.14.2",
15
- "@gradio/atoms": "^0.16.0",
14
+ "@gradio/atoms": "^0.16.1",
15
+ "@gradio/image": "^0.22.6",
16
+ "@gradio/client": "^1.15.0",
16
17
  "@gradio/icons": "^0.12.0",
17
- "@gradio/image": "^0.22.5",
18
- "@gradio/statustracker": "^0.10.10",
19
- "@gradio/wasm": "^0.18.1",
18
+ "@gradio/upload": "^0.16.5",
20
19
  "@gradio/utils": "^0.10.2",
21
- "@gradio/upload": "^0.16.4"
20
+ "@gradio/wasm": "^0.18.1",
21
+ "@gradio/statustracker": "^0.10.11"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@gradio/preview": "^0.13.0"
@@ -1,7 +1,17 @@
1
1
  <script lang="ts">
2
2
  import { createEventDispatcher } from "svelte";
3
3
  import { IconButton, IconButtonWrapper } from "@gradio/atoms";
4
- import { Check, Trash, ZoomIn, ZoomOut, Pan, Download } from "@gradio/icons";
4
+ import {
5
+ Check,
6
+ Trash,
7
+ ZoomIn,
8
+ ZoomOut,
9
+ Pan,
10
+ Download,
11
+ Undo,
12
+ Redo
13
+ } from "@gradio/icons";
14
+ import type { Writable } from "svelte/store";
5
15
 
6
16
  export let can_save = false;
7
17
  export let changeable = false;
@@ -9,6 +19,8 @@
9
19
  export let tool: string;
10
20
  export let min_zoom = true;
11
21
  export let enable_download = false;
22
+ export let can_undo: boolean;
23
+ export let can_redo: boolean;
12
24
 
13
25
  const dispatch = createEventDispatcher<{
14
26
  remove_image: void;
@@ -114,6 +126,26 @@
114
126
  </div>
115
127
  <div class="separator"></div>
116
128
 
129
+ <IconButton
130
+ Icon={Undo}
131
+ label="Undo"
132
+ on:click={(event) => {
133
+ dispatch("undo");
134
+ event.stopPropagation();
135
+ }}
136
+ disabled={!can_undo}
137
+ />
138
+
139
+ <IconButton
140
+ Icon={Redo}
141
+ label="Redo"
142
+ on:click={(event) => {
143
+ dispatch("redo");
144
+ event.stopPropagation();
145
+ }}
146
+ disabled={!can_redo}
147
+ />
148
+
117
149
  {#if changeable}
118
150
  <IconButton
119
151
  disabled={!can_save}
@@ -15,7 +15,7 @@
15
15
  import type { Client, FileData } from "@gradio/client";
16
16
  import tinycolor, { type ColorInput } from "tinycolor2";
17
17
  import { ZoomTool } from "./zoom/zoom";
18
- import { type CommandManager, type CommandNode } from "./utils/commands";
18
+ import { type CommandManager, type CommandNode } from "./core/commands";
19
19
  import { ImageEditor } from "./core/editor";
20
20
  import { type Brush, type Eraser } from "./brush/types";
21
21
  import { BrushTool } from "./brush/brush";
@@ -249,6 +249,8 @@
249
249
 
250
250
  let crop: ImageEditor;
251
251
  let crop_zoom: ZoomTool;
252
+ export let can_undo = false;
253
+ let can_redo = false;
252
254
  async function init_image_editor(): Promise<void> {
253
255
  brush = new BrushTool();
254
256
  zoom = new ZoomTool();
@@ -306,6 +308,8 @@
306
308
 
307
309
  editor.on("change", () => {
308
310
  dispatch("change");
311
+ can_undo = editor.command_manager.history.previous !== null;
312
+ can_redo = editor.command_manager.history.next !== null;
309
313
  });
310
314
 
311
315
  if (background || layers.length > 0) {
@@ -339,13 +343,6 @@
339
343
  current_subtool === "crop" &&
340
344
  crop_zoom.set_zoom("fit");
341
345
 
342
- // function resize_canvas(width: number, height: number): void {
343
- // if (!editor) return;
344
- // if (mounted && ready) {
345
- // editor.resize(width, height);
346
- // }
347
- // }
348
-
349
346
  /**
350
347
  * Handles file uploads
351
348
  * @param {File[]} files - The uploaded files
@@ -364,8 +361,12 @@
364
361
  dispatch("upload");
365
362
  dispatch("input");
366
363
  dispatch("change");
364
+ can_undo = editor.command_manager.history.previous !== null;
365
+ can_redo = editor.command_manager.history.next !== null;
367
366
  }
368
367
 
368
+ $: background_image = can_undo && editor.command_manager.contains("AddImage");
369
+
369
370
  /**
370
371
  * Handles tool change events
371
372
  * @param {{ tool: ToolbarTool }} param0 - Object containing the selected tool
@@ -496,7 +497,6 @@
496
497
  })()
497
498
  );
498
499
 
499
- // Type-safe brush size handling
500
500
  $: brush?.set_brush_size(
501
501
  typeof selected_size === "number" ? selected_size : 25
502
502
  );
@@ -583,6 +583,18 @@
583
583
  link.click();
584
584
  URL.revokeObjectURL(url);
585
585
  }
586
+
587
+ function handle_undo(): void {
588
+ editor.undo();
589
+ can_undo = editor.command_manager.history.previous !== null;
590
+ can_redo = editor.command_manager.history.next !== null;
591
+ }
592
+
593
+ function handle_redo(): void {
594
+ editor.redo();
595
+ can_undo = editor.command_manager.history.previous !== null;
596
+ can_redo = editor.command_manager.history.next !== null;
597
+ }
586
598
  </script>
587
599
 
588
600
  <div
@@ -622,6 +634,10 @@
622
634
  }}
623
635
  enable_download={show_download_button}
624
636
  on:download={() => handle_download()}
637
+ {can_undo}
638
+ {can_redo}
639
+ on:undo={handle_undo}
640
+ on:redo={handle_redo}
625
641
  />
626
642
  {/if}
627
643
 
@@ -30,8 +30,7 @@
30
30
  import type { Source, Transform } from "./types";
31
31
  import {
32
32
  type Brush as BrushType,
33
- type Eraser as EraserType,
34
- type ColorTuple
33
+ type Eraser as EraserType
35
34
  } from "./brush/types";
36
35
  import tinycolor from "tinycolor2";
37
36
 
@@ -78,13 +77,11 @@
78
77
  })();
79
78
 
80
79
  export let preview = false;
81
- // export let opacity = 1;
82
80
  export let show_brush_color = false;
83
81
  export let show_brush_size = false;
84
82
  export let show_eraser_size = false;
85
83
  export let sources: Source[];
86
84
  export let transforms: Transform[];
87
- // Required by the component interface
88
85
  let recent_colors: string[] = [];
89
86
 
90
87
  let enable_layers = true;
@@ -21,7 +21,6 @@
21
21
 
22
22
  $: _colors = show_empty ? colors : colors.filter((c) => c);
23
23
 
24
- // Helper function to extract color from either a color input or a tuple
25
24
  function get_color(color_input: ColorInput | ColorTuple): string {
26
25
  if (Array.isArray(color_input)) {
27
26
  return color_input[0] as string;
@@ -29,7 +28,6 @@
29
28
  return color_input as string;
30
29
  }
31
30
 
32
- // Helper function to extract opacity from a tuple or return undefined
33
31
  function get_opacity(
34
32
  color_input: ColorInput | ColorTuple
35
33
  ): number | undefined {
@@ -37,7 +35,6 @@
37
35
  return color_input[1];
38
36
  }
39
37
 
40
- // For string colors, check if there's opacity in the color itself
41
38
  const color = tinycolor(color_input);
42
39
  return color.getAlpha();
43
40
  }