@pixerate/editor-svelte 0.72.1 → 0.73.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,189 @@
1
+ <script lang="ts">
2
+ import type { EffectControl, ImageEditorController, LayerEffectKind } from '@pixerate/editor/image-editor';
3
+ import { LAYER_EFFECT_MENU, effectControlChange, layerEffectControls, layerEffectsPanel } from '@pixerate/editor/image-editor';
4
+ import { untrack } from 'svelte';
5
+
6
+ /**
7
+ * A layer's effects (Photoshop's layer styles): the master switch, Scale Effects, an "Add
8
+ * effect" menu, and each effect with its enabled toggle, remove button and, when expanded, its
9
+ * settings. Every change is one undo step (a slider drag is one step too).
10
+ */
11
+ interface Props {
12
+ controller: ImageEditorController;
13
+ /** The layer whose effects to show (default: the active layer). */
14
+ layerId?: string | null;
15
+ class?: string;
16
+ }
17
+
18
+ let { controller, layerId = null, class: className = '' }: Props = $props();
19
+
20
+ let tick = $state(0);
21
+ $effect(() => {
22
+ const c = controller;
23
+ return untrack(() => c.subscribe(() => tick++));
24
+ });
25
+
26
+ const view = $derived.by(() => {
27
+ void tick;
28
+ const layer = layerId ? controller.getLayer(layerId) : controller.getActiveLayer();
29
+ const model = layerEffectsPanel(layer);
30
+ const id = layer?.id ?? null;
31
+ const items = id && model.available ? controller.getLayerEffects(id).items : [];
32
+ return { id, model, items, patterns: controller.getDocumentPatterns() };
33
+ });
34
+
35
+ let open = $state<string | null>(null);
36
+ let error = $state<string | null>(null);
37
+ /** Whether the next slider change records an undo step (the first of a drag does, the rest replace it). */
38
+ let commitNext = true;
39
+
40
+ const button = 'px-1.5 py-0.5 rounded text-[10px] bg-slate-800 text-slate-300 hover:text-white disabled:opacity-40';
41
+
42
+ function attempt(fn: () => unknown) {
43
+ try {
44
+ error = null;
45
+ fn();
46
+ } catch (err) {
47
+ error = err instanceof Error ? err.message : String(err);
48
+ }
49
+ }
50
+
51
+ function change(effectId: string, control: EffectControl, value: unknown, drag = false) {
52
+ const id = view.id;
53
+ if (!id) return;
54
+ attempt(() => {
55
+ const effect = controller.getLayerEffects(id).items.find((e) => e.id === effectId)!;
56
+ controller.updateLayerEffect(id, effectId, effectControlChange(effect, control.key, value, view.patterns), drag ? commitNext : true);
57
+ if (drag) commitNext = false;
58
+ });
59
+ }
60
+
61
+ function add(e: Event) {
62
+ const select = e.currentTarget as HTMLSelectElement;
63
+ const kind = select.value as LayerEffectKind;
64
+ select.value = '';
65
+ const id = view.id;
66
+ if (!kind || !id) return;
67
+ attempt(() => (open = controller.addLayerEffect(id, kind).effect.id));
68
+ }
69
+
70
+ function setScale(e: Event) {
71
+ const v = Number((e.currentTarget as HTMLInputElement).value);
72
+ const id = view.id;
73
+ if (id && v >= 1 && v <= 1000) attempt(() => controller.setLayerEffectsEnabled(id, view.model.enabled, v / 100));
74
+ }
75
+
76
+ const k = (c: EffectControl) => (c.type === 'range' && c.percent ? 100 : 1);
77
+ const shown = (c: EffectControl) => (c.type === 'range' ? Math.round(c.value * k(c) * 100) / 100 : 0);
78
+ </script>
79
+
80
+ {#if !view.model.available || !view.id}
81
+ <div class="text-xs text-slate-500 {className}" data-testid="layer-effects">{view.model.reason}</div>
82
+ {:else}
83
+ {@const id = view.id}
84
+ <div class="flex flex-col gap-1.5 text-xs text-slate-200 {className}" data-testid="layer-effects" aria-label="Layer effects" role="group">
85
+ <div class="flex flex-wrap items-center gap-2">
86
+ <span class="font-semibold text-slate-300">fx Effects</span>
87
+ <label class="flex items-center gap-1 text-slate-300">
88
+ <input
89
+ type="checkbox"
90
+ aria-label="Effects on"
91
+ checked={view.model.enabled}
92
+ disabled={view.model.readOnly}
93
+ onchange={(e) => attempt(() => controller.setLayerEffectsEnabled(id, (e.currentTarget as HTMLInputElement).checked))}
94
+ class="accent-indigo-500"
95
+ />
96
+ On
97
+ </label>
98
+ <label class="flex items-center gap-1 text-slate-400">
99
+ Scale
100
+ <input
101
+ type="number"
102
+ aria-label="Scale effects"
103
+ min="1"
104
+ max="1000"
105
+ step="1"
106
+ value={Math.round(view.model.scale * 100)}
107
+ disabled={view.model.readOnly}
108
+ oninput={setScale}
109
+ class="w-14 bg-slate-800 border border-slate-700 rounded px-1"
110
+ />
111
+ %
112
+ </label>
113
+ <select aria-label="Add effect" value="" disabled={view.model.readOnly} onchange={add} class="bg-slate-800 border border-slate-700 rounded px-1.5 py-1">
114
+ <option value="">Add effect…</option>
115
+ {#each LAYER_EFFECT_MENU as m (m.kind)}
116
+ <option value={m.kind}>{m.label}</option>
117
+ {/each}
118
+ </select>
119
+ </div>
120
+ {#if view.model.readOnly && view.model.reason}<p class="text-slate-500">{view.model.reason}</p>{/if}
121
+ <ul class="flex flex-col gap-1" aria-label="Effects">
122
+ {#each view.model.rows as row (row.id)}
123
+ {@const effect = view.items.find((e) => e.id === row.id)}
124
+ {@const expanded = open === row.id}
125
+ <li data-effect-id={row.id} class="rounded bg-slate-900/60 ring-1 ring-slate-800">
126
+ <div class="flex items-center gap-1.5 px-1.5 py-1">
127
+ <input
128
+ type="checkbox"
129
+ aria-label="{row.label} on"
130
+ checked={row.enabled}
131
+ disabled={view.model.readOnly}
132
+ onchange={(e) => attempt(() => controller.updateLayerEffect(id, row.id, { enabled: (e.currentTarget as HTMLInputElement).checked }))}
133
+ class="accent-indigo-500"
134
+ />
135
+ <button type="button" aria-expanded={expanded} class="flex-1 text-left {row.enabled && view.model.enabled ? '' : 'text-slate-500'}" onclick={() => (open = expanded ? null : row.id)}>
136
+ {row.label}
137
+ </button>
138
+ <button type="button" class={button} aria-label="Remove {row.label}" disabled={view.model.readOnly} onclick={() => attempt(() => controller.removeLayerEffect(id, row.id))}>✕</button>
139
+ </div>
140
+ {#if expanded && effect}
141
+ <div class="grid grid-cols-2 gap-x-2 gap-y-1 px-1.5 pb-1.5" data-testid="effect-settings">
142
+ {#each layerEffectControls(effect, view.patterns) as c (c.key)}
143
+ {#if c.type === 'range'}
144
+ <label class="flex flex-col gap-0.5">
145
+ <span class="text-slate-400">{c.label} {shown(c)}{c.unit ?? ''}</span>
146
+ <input
147
+ type="range"
148
+ aria-label={c.label}
149
+ min={c.min * k(c)}
150
+ max={c.max * k(c)}
151
+ step={c.step * k(c)}
152
+ value={shown(c)}
153
+ disabled={view.model.readOnly}
154
+ onpointerdown={() => (commitNext = true)}
155
+ onpointerup={() => (commitNext = true)}
156
+ onkeydown={() => (commitNext = true)}
157
+ oninput={(e) => change(row.id, c, Number((e.currentTarget as HTMLInputElement).value) / k(c), true)}
158
+ class="accent-indigo-500"
159
+ />
160
+ </label>
161
+ {:else if c.type === 'color'}
162
+ <label class="flex items-center gap-1.5 text-slate-300">
163
+ <input type="color" aria-label={c.label} value={c.value} disabled={view.model.readOnly} oninput={(e) => change(row.id, c, (e.currentTarget as HTMLInputElement).value)} />
164
+ {c.label}
165
+ </label>
166
+ {:else if c.type === 'checkbox'}
167
+ <label class="flex items-center gap-1.5 text-slate-300">
168
+ <input type="checkbox" aria-label={c.label} checked={c.value} disabled={view.model.readOnly} onchange={(e) => change(row.id, c, (e.currentTarget as HTMLInputElement).checked)} class="accent-indigo-500" />
169
+ {c.label}
170
+ </label>
171
+ {:else}
172
+ <label class="flex flex-col gap-0.5">
173
+ <span class="text-slate-400">{c.label}</span>
174
+ <select aria-label={c.label} value={c.value} disabled={view.model.readOnly} onchange={(e) => change(row.id, c, (e.currentTarget as HTMLSelectElement).value)} class="bg-slate-800 border border-slate-700 rounded px-1.5 py-1">
175
+ {#each c.options as o (o.value)}
176
+ <option value={o.value}>{o.label}</option>
177
+ {/each}
178
+ </select>
179
+ </label>
180
+ {/if}
181
+ {/each}
182
+ </div>
183
+ {/if}
184
+ </li>
185
+ {/each}
186
+ </ul>
187
+ {#if error}<p role="alert" class="text-rose-400">{error}</p>{/if}
188
+ </div>
189
+ {/if}
@@ -0,0 +1,16 @@
1
+ import type { ImageEditorController } from '@pixerate/editor/image-editor';
2
+ /**
3
+ * A layer's effects (Photoshop's layer styles): the master switch, Scale Effects, an "Add
4
+ * effect" menu, and each effect with its enabled toggle, remove button and, when expanded, its
5
+ * settings. Every change is one undo step (a slider drag is one step too).
6
+ */
7
+ interface Props {
8
+ controller: ImageEditorController;
9
+ /** The layer whose effects to show (default: the active layer). */
10
+ layerId?: string | null;
11
+ class?: string;
12
+ }
13
+ declare const LayerEffectsPanel: import("svelte").Component<Props, {}, "">;
14
+ type LayerEffectsPanel = ReturnType<typeof LayerEffectsPanel>;
15
+ export default LayerEffectsPanel;
16
+ //# sourceMappingURL=LayerEffectsPanel.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LayerEffectsPanel.svelte.d.ts","sourceRoot":"","sources":["../../src/image-editor/LayerEffectsPanel.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAiB,qBAAqB,EAAmB,MAAM,+BAA+B,CAAC;AAKzG;;;;GAIG;AACH,UAAU,KAAK;IACb,UAAU,EAAE,qBAAqB,CAAC;IAClC,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAiJH,QAAA,MAAM,iBAAiB,2CAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
@@ -7,12 +7,14 @@
7
7
  dropPlacement,
8
8
  dropZone,
9
9
  layerBadge,
10
+ layerEffectsBadge,
10
11
  layerMenu,
11
12
  layerPanelRows,
12
13
  openPsdFile,
13
14
  runLayerMenuAction,
14
15
  } from '@pixerate/editor/image-editor';
15
16
  import { untrack } from 'svelte';
17
+ import LayerEffectsPanel from './LayerEffectsPanel.svelte';
16
18
 
17
19
  interface Props {
18
20
  controller: ImageEditorController;
@@ -22,10 +24,12 @@
22
24
  psd?: boolean;
23
25
  /** Base name of exported PSD files (default `image`). */
24
26
  psdFileName?: string;
27
+ /** Show the active layer's effects section (default true). */
28
+ effects?: boolean;
25
29
  class?: string;
26
30
  }
27
31
 
28
- let { controller, thumbnailSize = 32, psd = true, psdFileName = 'image', class: className = '' }: Props = $props();
32
+ let { controller, thumbnailSize = 32, psd = true, psdFileName = 'image', effects = true, class: className = '' }: Props = $props();
29
33
 
30
34
  let tick = $state(0);
31
35
  $effect(() => {
@@ -255,6 +259,10 @@
255
259
  </div>
256
260
  {/if}
257
261
 
262
+ {#if effects && snapshot.active && snapshot.active.type !== 'adjustment'}
263
+ <LayerEffectsPanel {controller} class="border-t border-slate-800 pt-1.5" />
264
+ {/if}
265
+
258
266
  <ul class="flex flex-col gap-0.5" role="tree" aria-label="Layers">
259
267
  {#each snapshot.rows as row (row.layer.id)}
260
268
  {@const layer = row.layer}
@@ -361,6 +369,20 @@
361
369
  renaming = layer.id;
362
370
  }}>{row.label}</span>
363
371
  {/if}
372
+ {#if layerEffectsBadge(layer)}
373
+ {@const fxOn = layerEffectsBadge(layer) === 'on'}
374
+ <button
375
+ type="button"
376
+ data-testid="layer-fx-badge"
377
+ aria-label={fxOn ? `Turn effects off for ${row.label}` : `Turn effects on for ${row.label}`}
378
+ aria-pressed={fxOn}
379
+ class="text-[9px] italic font-semibold {fxOn ? 'text-indigo-300' : 'text-slate-600 line-through'}"
380
+ onclick={(e) => {
381
+ e.stopPropagation();
382
+ attempt(() => controller.setLayerEffectsEnabled(layer.id, !fxOn));
383
+ }}>fx</button
384
+ >
385
+ {/if}
364
386
  {#if locked(layer)}<span aria-label="Locked" class="text-slate-400">🔒</span>{/if}
365
387
  {#if layer.blend !== 'normal' && layer.blend !== 'pass-through'}<span class="text-[9px] text-slate-500">{layer.blend}</span>{/if}
366
388
  </li>
@@ -7,6 +7,8 @@ interface Props {
7
7
  psd?: boolean;
8
8
  /** Base name of exported PSD files (default `image`). */
9
9
  psdFileName?: string;
10
+ /** Show the active layer's effects section (default true). */
11
+ effects?: boolean;
10
12
  class?: string;
11
13
  }
12
14
  declare const LayersPanel: import("svelte").Component<Props, {}, "">;
@@ -1 +1 @@
1
- {"version":3,"file":"LayersPanel.svelte.d.ts","sourceRoot":"","sources":["../../src/image-editor/LayersPanel.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,qBAAqB,EAA2D,MAAM,+BAA+B,CAAC;AAgBlI,UAAU,KAAK;IACb,UAAU,EAAE,qBAAqB,CAAC;IAClC,yCAAyC;IACzC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iDAAiD;IACjD,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAsQH,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"LayersPanel.svelte.d.ts","sourceRoot":"","sources":["../../src/image-editor/LayersPanel.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,qBAAqB,EAA2D,MAAM,+BAA+B,CAAC;AAkBlI,UAAU,KAAK;IACb,UAAU,EAAE,qBAAqB,CAAC;IAClC,yCAAyC;IACzC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iDAAiD;IACjD,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAkRH,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
@@ -7,6 +7,7 @@ import type ControlSliderComponent from "./ControlSlider.svelte";
7
7
  import type SelectionOptionsBarComponent from "./SelectionOptionsBar.svelte";
8
8
  import type RefineEdgePanelComponent from "./RefineEdgePanel.svelte";
9
9
  import type LayersPanelComponent from "./LayersPanel.svelte";
10
+ import type LayerEffectsPanelComponent from "./LayerEffectsPanel.svelte";
10
11
  import type BrushOptionsBarComponent from "./BrushOptionsBar.svelte";
11
12
  export { default as ImageEditor } from './ImageEditor.svelte';
12
13
  export { default as Histogram } from './Histogram.svelte';
@@ -16,6 +17,7 @@ export { default as ControlSlider } from './ControlSlider.svelte';
16
17
  export { default as SelectionOptionsBar } from './SelectionOptionsBar.svelte';
17
18
  export { default as RefineEdgePanel } from './RefineEdgePanel.svelte';
18
19
  export { default as LayersPanel } from './LayersPanel.svelte';
20
+ export { default as LayerEffectsPanel } from './LayerEffectsPanel.svelte';
19
21
  export { default as BrushOptionsBar } from './BrushOptionsBar.svelte';
20
22
  export * from './imageEditorState.svelte.js';
21
23
  export type ImageEditorProps = ComponentProps<typeof ImageEditorComponent>;
@@ -26,6 +28,7 @@ export type ControlSliderProps = ComponentProps<typeof ControlSliderComponent>;
26
28
  export type SelectionOptionsBarProps = ComponentProps<typeof SelectionOptionsBarComponent>;
27
29
  export type RefineEdgePanelProps = ComponentProps<typeof RefineEdgePanelComponent>;
28
30
  export type LayersPanelProps = ComponentProps<typeof LayersPanelComponent>;
31
+ export type LayerEffectsPanelProps = ComponentProps<typeof LayerEffectsPanelComponent>;
29
32
  export type BrushOptionsBarProps = ComponentProps<typeof BrushOptionsBarComponent>;
30
33
  export { applyRegionMosaic, applyRegionBlur, resolveMosaicRegionBounds, type MosaicRegion, type MosaicImageDataLike } from '@pixerate/editor/image-editor';
31
34
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/image-editor/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,KAAK,oBAAoB,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,kBAAkB,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,8BAA8B,MAAM,gCAAgC,CAAC;AACjF,OAAO,KAAK,qBAAqB,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,sBAAsB,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,4BAA4B,MAAM,8BAA8B,CAAC;AAC7E,OAAO,KAAK,wBAAwB,MAAM,0BAA0B,CAAC;AACrE,OAAO,KAAK,oBAAoB,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,wBAAwB,MAAM,0BAA0B,CAAC;AAErE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAClF,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,0BAA0B,CAAC;AACtE,cAAc,8BAA8B,CAAC;AAE7C,MAAM,MAAM,gBAAgB,GAAG,cAAc,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAC3E,MAAM,MAAM,cAAc,GAAG,cAAc,CAAC,OAAO,kBAAkB,CAAC,CAAC;AACvE,MAAM,MAAM,0BAA0B,GAAG,cAAc,CAAC,OAAO,8BAA8B,CAAC,CAAC;AAC/F,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAC7E,MAAM,MAAM,kBAAkB,GAAG,cAAc,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAC/E,MAAM,MAAM,wBAAwB,GAAG,cAAc,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAC3F,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,OAAO,wBAAwB,CAAC,CAAC;AACnF,MAAM,MAAM,gBAAgB,GAAG,cAAc,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAC3E,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAEnF,OAAO,EACN,iBAAiB,EACjB,eAAe,EACf,yBAAyB,EACzB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,MAAM,+BAA+B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/image-editor/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,KAAK,oBAAoB,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,kBAAkB,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,8BAA8B,MAAM,gCAAgC,CAAC;AACjF,OAAO,KAAK,qBAAqB,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,sBAAsB,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,4BAA4B,MAAM,8BAA8B,CAAC;AAC7E,OAAO,KAAK,wBAAwB,MAAM,0BAA0B,CAAC;AACrE,OAAO,KAAK,oBAAoB,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,0BAA0B,MAAM,4BAA4B,CAAC;AACzE,OAAO,KAAK,wBAAwB,MAAM,0BAA0B,CAAC;AAErE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAClF,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,0BAA0B,CAAC;AACtE,cAAc,8BAA8B,CAAC;AAE7C,MAAM,MAAM,gBAAgB,GAAG,cAAc,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAC3E,MAAM,MAAM,cAAc,GAAG,cAAc,CAAC,OAAO,kBAAkB,CAAC,CAAC;AACvE,MAAM,MAAM,0BAA0B,GAAG,cAAc,CAAC,OAAO,8BAA8B,CAAC,CAAC;AAC/F,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAC7E,MAAM,MAAM,kBAAkB,GAAG,cAAc,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAC/E,MAAM,MAAM,wBAAwB,GAAG,cAAc,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAC3F,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,OAAO,wBAAwB,CAAC,CAAC;AACnF,MAAM,MAAM,gBAAgB,GAAG,cAAc,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAC3E,MAAM,MAAM,sBAAsB,GAAG,cAAc,CAAC,OAAO,0BAA0B,CAAC,CAAC;AACvF,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAEnF,OAAO,EACN,iBAAiB,EACjB,eAAe,EACf,yBAAyB,EACzB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,MAAM,+BAA+B,CAAC"}
@@ -6,6 +6,7 @@ export { default as ControlSlider } from './ControlSlider.svelte';
6
6
  export { default as SelectionOptionsBar } from './SelectionOptionsBar.svelte';
7
7
  export { default as RefineEdgePanel } from './RefineEdgePanel.svelte';
8
8
  export { default as LayersPanel } from './LayersPanel.svelte';
9
+ export { default as LayerEffectsPanel } from './LayerEffectsPanel.svelte';
9
10
  export { default as BrushOptionsBar } from './BrushOptionsBar.svelte';
10
11
  export * from './imageEditorState.svelte.js';
11
12
  export { applyRegionMosaic, applyRegionBlur, resolveMosaicRegionBounds } from '@pixerate/editor/image-editor';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor-svelte",
3
- "version": "0.72.1",
3
+ "version": "0.73.0",
4
4
  "description": "Svelte bindings and prompt/rich-text components for @pixerate/editor",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
@@ -131,7 +131,7 @@
131
131
  "@tiptap/extension-bubble-menu": "^2.11.5",
132
132
  "@tiptap/extension-placeholder": "^2.11.5",
133
133
  "@tiptap/starter-kit": "^2.11.5",
134
- "@pixerate/editor": "0.96.0"
134
+ "@pixerate/editor": "0.97.0"
135
135
  },
136
136
  "peerDependencies": {
137
137
  "@dagrejs/dagre": "^1.1.4",