@pixerate/editor-svelte 0.158.0 → 0.160.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.
@@ -0,0 +1,102 @@
1
+ <script lang="ts">
2
+ import type { ImageEditorController, ImageLayer } from '@pixerate/editor/image-editor';
3
+ import { untrack } from 'svelte';
4
+
5
+ /**
6
+ * Edge Colour: decontamination, despill and the live edge cast of a layer's soft edge, applied
7
+ * when compositing (nothing is baked), as the `set_edge_*` tools set them. A slider drag is one
8
+ * undo step.
9
+ */
10
+ interface Props {
11
+ controller: ImageEditorController;
12
+ /** The layer to edit (a pixel, shape, type or smart object layer). */
13
+ layer: ImageLayer;
14
+ class?: string;
15
+ }
16
+
17
+ let { controller, layer, class: className = '' }: Props = $props();
18
+
19
+ const SLIDERS = [
20
+ { key: 'decontaminate', label: 'Decontaminate', hint: 'Unmix the old background from a soft-edged mask' },
21
+ { key: 'despill', label: 'Despill', hint: "Take out the old background's hue at the edge" },
22
+ { key: 'ambient', label: 'Cast', hint: 'Tint the edge with what is behind the layer, live' },
23
+ ] as const;
24
+
25
+ let tick = $state(0);
26
+ $effect(() => {
27
+ const c = controller;
28
+ return untrack(() => c.subscribe(() => tick++));
29
+ });
30
+ let error = $state<string | null>(null);
31
+ let commitNext = true;
32
+ const info = $derived.by(() => {
33
+ void tick;
34
+ return controller.getEdgeColor(layer.id);
35
+ });
36
+ const fixed = $derived(info.ambientSource !== 'auto');
37
+
38
+ function set(change: Parameters<ImageEditorController['setEdgeColor']>[1]) {
39
+ error = null;
40
+ try {
41
+ controller.setEdgeColor(layer.id, change, commitNext);
42
+ commitNext = false;
43
+ } catch (err) {
44
+ error = err instanceof Error ? err.message : String(err);
45
+ }
46
+ }
47
+ const startDrag = () => (commitNext = true);
48
+ </script>
49
+
50
+ <details class="text-xs {className}" data-testid="edge-color-panel" open={Boolean(info.decontaminate || info.despill || info.ambient) || undefined}>
51
+ <summary class="cursor-pointer text-muted-foreground">Edge Colour</summary>
52
+ <div class="flex flex-col gap-1.5 pt-1">
53
+ {#each SLIDERS as s (s.key)}
54
+ <label class="flex flex-col gap-0.5" title={s.hint}>
55
+ <span class="flex justify-between text-muted-foreground">
56
+ <span>{s.label}</span>
57
+ <span class="font-mono">{info[s.key]}%</span>
58
+ </span>
59
+ <input
60
+ type="range"
61
+ min="0"
62
+ max="100"
63
+ aria-label="Edge {s.label.toLowerCase()}"
64
+ value={info[s.key]}
65
+ onpointerdown={startDrag}
66
+ onpointerup={startDrag}
67
+ onkeydown={startDrag}
68
+ oninput={(e) => set({ [s.key]: Number((e.currentTarget as HTMLInputElement).value) })}
69
+ class="accent-primary"
70
+ />
71
+ </label>
72
+ {/each}
73
+ <label class="flex items-center gap-1.5 text-foreground">
74
+ <input
75
+ type="checkbox"
76
+ aria-label="Fixed cast colour"
77
+ checked={fixed}
78
+ onchange={(e) => {
79
+ commitNext = true;
80
+ set({ ambientColor: (e.currentTarget as HTMLInputElement).checked ? '#808080' : 'auto' });
81
+ }}
82
+ class="accent-primary"
83
+ />
84
+ Fixed cast colour
85
+ {#if fixed}
86
+ <input
87
+ type="color"
88
+ aria-label="Cast colour"
89
+ value={info.ambientSource}
90
+ onchange={(e) => {
91
+ commitNext = true;
92
+ set({ ambientColor: (e.currentTarget as HTMLInputElement).value });
93
+ }}
94
+ class="h-5 w-8 bg-background border border-border rounded"
95
+ />
96
+ {/if}
97
+ </label>
98
+ {#if error}
99
+ <p role="alert" class="text-destructive">{error}</p>
100
+ {/if}
101
+ </div>
102
+ </details>
@@ -0,0 +1,15 @@
1
+ import type { ImageEditorController, ImageLayer } from '@pixerate/editor/image-editor';
2
+ /**
3
+ * Edge Colour: decontamination, despill and the live edge cast of a layer's soft edge, applied
4
+ * when compositing (nothing is baked), as the `set_edge_*` tools set them. A slider drag is one
5
+ * undo step.
6
+ */
7
+ interface Props {
8
+ controller: ImageEditorController;
9
+ /** The layer to edit (a pixel, shape, type or smart object layer). */
10
+ layer: ImageLayer;
11
+ class?: string;
12
+ }
13
+ declare const EdgeColorPanel: import("svelte").Component<Props, {}, "">;
14
+ type EdgeColorPanel = ReturnType<typeof EdgeColorPanel>;
15
+ export default EdgeColorPanel;
@@ -23,6 +23,7 @@
23
23
  } from '@pixerate/editor/image-editor';
24
24
  import { untrack } from 'svelte';
25
25
  import LayerEffectsPanel from './LayerEffectsPanel.svelte';
26
+ import EdgeColorPanel from './EdgeColorPanel.svelte';
26
27
 
27
28
  interface Props {
28
29
  controller: ImageEditorController;
@@ -283,6 +284,12 @@
283
284
  </div>
284
285
  {/if}
285
286
 
287
+ {#if snapshot.active && (snapshot.active.type === 'pixel' || snapshot.active.type === 'shape' || snapshot.active.type === 'type' || snapshot.active.type === 'smart')}
288
+ {#key snapshot.active.id}
289
+ <EdgeColorPanel {controller} layer={snapshot.active} class="border-t border-border pt-1.5" />
290
+ {/key}
291
+ {/if}
292
+
286
293
  {#if effects && snapshot.active && snapshot.active.type !== 'adjustment'}
287
294
  <LayerEffectsPanel {controller} class="border-t border-border pt-1.5" />
288
295
  {/if}
@@ -52,6 +52,7 @@
52
52
  let output = $state<RefineOutput>('selection');
53
53
  let decontaminate = $state(0);
54
54
  let objectAware = $state(false);
55
+ let onlyUncertain = $state(false);
55
56
  const canObject = $derived.by(() => {
56
57
  void tick;
57
58
  return Boolean(controller.segmentationProvider);
@@ -67,9 +68,13 @@
67
68
  busy = true;
68
69
  error = null;
69
70
  try {
71
+ // Only where the edge has no image edge under it (the selection's uncertain regions).
72
+ const regions = onlyUncertain ? controller.selectionUncertainty().regions.map((r) => r.bounds) : undefined;
73
+ if (regions && !regions.length) throw new Error("No uncertain areas: the selection's edge already follows edges in the image. Untick Only uncertain areas to refine everywhere.");
70
74
  await controller.refineSelectionTo({ ...params }, output, {
71
75
  decontaminate: toLayer ? decontaminate : 0,
72
76
  refineMode: canObject && objectAware ? 'object' : 'color',
77
+ ...(regions ? { regions } : {}),
73
78
  });
74
79
  } catch (err) {
75
80
  error = err instanceof Error ? err.message : String(err);
@@ -115,6 +120,10 @@
115
120
  />
116
121
  Smart Radius
117
122
  </label>
123
+ <label class="flex items-center gap-2 text-foreground" title="Refine only where the edge has no image edge under it">
124
+ <input type="checkbox" aria-label="Only uncertain areas" checked={onlyUncertain} onchange={(e) => (onlyUncertain = (e.currentTarget as HTMLInputElement).checked)} />
125
+ Only uncertain areas
126
+ </label>
118
127
  {#if canObject}
119
128
  <label class="flex items-center gap-2 text-foreground">
120
129
  <input type="checkbox" aria-label="Object aware" checked={objectAware} onchange={(e) => (objectAware = (e.currentTarget as HTMLInputElement).checked)} />
@@ -16,6 +16,7 @@ import type ChannelsPanelComponent from "./ChannelsPanel.svelte";
16
16
  import type LayersPanelComponent from "./LayersPanel.svelte";
17
17
  import type ColorProfilePanelComponent from "./ColorProfilePanel.svelte";
18
18
  import type LayerEffectsPanelComponent from "./LayerEffectsPanel.svelte";
19
+ import type EdgeColorPanelComponent from "./EdgeColorPanel.svelte";
19
20
  import type BrushOptionsBarComponent from "./BrushOptionsBar.svelte";
20
21
  import type FreeTransformOptionsBarComponent from "./FreeTransformOptionsBar.svelte";
21
22
  import type ShapeOptionsBarComponent from "./ShapeOptionsBar.svelte";
@@ -44,6 +45,7 @@ export { default as ChannelsPanel } from './ChannelsPanel.svelte';
44
45
  export { default as LayersPanel } from './LayersPanel.svelte';
45
46
  export { default as ColorProfilePanel } from './ColorProfilePanel.svelte';
46
47
  export { default as LayerEffectsPanel } from './LayerEffectsPanel.svelte';
48
+ export { default as EdgeColorPanel } from './EdgeColorPanel.svelte';
47
49
  export { default as BrushOptionsBar } from './BrushOptionsBar.svelte';
48
50
  export { default as FreeTransformOptionsBar } from './FreeTransformOptionsBar.svelte';
49
51
  export { default as ShapeOptionsBar } from './ShapeOptionsBar.svelte';
@@ -74,6 +76,7 @@ export type ChannelsPanelProps = ComponentProps<typeof ChannelsPanelComponent>;
74
76
  export type LayersPanelProps = ComponentProps<typeof LayersPanelComponent>;
75
77
  export type ColorProfilePanelProps = ComponentProps<typeof ColorProfilePanelComponent>;
76
78
  export type LayerEffectsPanelProps = ComponentProps<typeof LayerEffectsPanelComponent>;
79
+ export type EdgeColorPanelProps = ComponentProps<typeof EdgeColorPanelComponent>;
77
80
  export type BrushOptionsBarProps = ComponentProps<typeof BrushOptionsBarComponent>;
78
81
  export type FreeTransformOptionsBarProps = ComponentProps<typeof FreeTransformOptionsBarComponent>;
79
82
  export type ShapeOptionsBarProps = ComponentProps<typeof ShapeOptionsBarComponent>;
@@ -18,6 +18,7 @@ export { default as ChannelsPanel } from './ChannelsPanel.svelte';
18
18
  export { default as LayersPanel } from './LayersPanel.svelte';
19
19
  export { default as ColorProfilePanel } from './ColorProfilePanel.svelte';
20
20
  export { default as LayerEffectsPanel } from './LayerEffectsPanel.svelte';
21
+ export { default as EdgeColorPanel } from './EdgeColorPanel.svelte';
21
22
  export { default as BrushOptionsBar } from './BrushOptionsBar.svelte';
22
23
  export { default as FreeTransformOptionsBar } from './FreeTransformOptionsBar.svelte';
23
24
  export { default as ShapeOptionsBar } from './ShapeOptionsBar.svelte';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor-svelte",
3
- "version": "0.158.0",
3
+ "version": "0.160.0",
4
4
  "description": "Svelte bindings and prompt/rich-text components for @pixerate/editor",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
@@ -165,7 +165,7 @@
165
165
  "**/*.css"
166
166
  ],
167
167
  "dependencies": {
168
- "@pixerate/editor": "0.214.0"
168
+ "@pixerate/editor": "0.216.0"
169
169
  },
170
170
  "peerDependencies": {
171
171
  "@dagrejs/dagre": "^1.1.4",