@pixerate/editor-svelte 0.130.3 → 0.131.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.
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { imageOutlineButtonClass } from './styles.js';
|
|
3
|
-
import { EFFECT_LAYER_USES,
|
|
3
|
+
import { EFFECT_LAYER_USES, effectLayerTiming, findLayer, type ImageEditorController, type ImageLayer, type SmartObjectLayer } from '@pixerate/editor/image-editor';
|
|
4
4
|
import { untrack } from 'svelte';
|
|
5
5
|
import EffectsBrowser from '../effects/EffectsBrowser.svelte';
|
|
6
6
|
import { effectDescriptionOf } from '../effects/effects.svelte.js';
|
|
7
7
|
import ImageEffectControls from './ImageEffectControls.svelte';
|
|
8
|
-
import LayerEffectsPanel from './LayerEffectsPanel.svelte';
|
|
9
8
|
import ImageCheckbox from './controls/ImageCheckbox.svelte';
|
|
10
9
|
import ImageRange from './controls/ImageRange.svelte';
|
|
11
|
-
import ImageSelect from './controls/ImageSelect.svelte';
|
|
12
10
|
import type { ParameterComponents } from '../parameters/index.js';
|
|
13
11
|
|
|
14
12
|
interface Props {
|
|
@@ -38,14 +36,9 @@
|
|
|
38
36
|
const layer = $derived(snapshot.layer);
|
|
39
37
|
const all = $derived(layer?.type === 'smart' ? ((layer as SmartObjectLayer).smartFilters?.filters ?? []) : []);
|
|
40
38
|
const generator = $derived(layer?.type === 'pixel' ? layer.generator : undefined);
|
|
41
|
-
const canFilter = $derived(!!layer && layer.type !== 'adjustment' && layer.type !== 'annotation');
|
|
42
|
-
const styles = $derived(layerEffectsPanel(layer));
|
|
39
|
+
const canFilter = $derived(!!provider && !!layer && layer.type !== 'adjustment' && layer.type !== 'annotation');
|
|
43
40
|
const described = effectDescriptionOf(() => provider, () => generator?.effect);
|
|
44
41
|
const timing = $derived(generator ? effectLayerTiming(generator, described.description) : null);
|
|
45
|
-
const addOptions = $derived([
|
|
46
|
-
...(provider && canFilter ? [{ value: 'filter', label: 'Filter…' }] : []),
|
|
47
|
-
...(styles.available && !styles.readOnly ? LAYER_EFFECT_MENU.map((m) => ({ value: `style:${m.kind}`, label: m.label })) : []),
|
|
48
|
-
]);
|
|
49
42
|
const drags = new Set<string>();
|
|
50
43
|
/** Changes during a drag skip the undo stack after the first, so the drag is one step. */
|
|
51
44
|
function commit(gesture: string | null) {
|
|
@@ -60,12 +53,6 @@
|
|
|
60
53
|
.then(work)
|
|
61
54
|
.catch((e: unknown) => (message = e instanceof Error ? e.message : String(e)));
|
|
62
55
|
}
|
|
63
|
-
function add(value: string) {
|
|
64
|
-
const id = layer?.id;
|
|
65
|
-
if (!value || !id) return;
|
|
66
|
-
if (value === 'filter') browse = browse === 'filter' ? null : 'filter';
|
|
67
|
-
else run(() => controller.addLayerEffect(id, value.slice('style:'.length) as LayerEffectKind));
|
|
68
|
-
}
|
|
69
56
|
|
|
70
57
|
// Scrubbing the frame draws the effect again: one render at a time, the latest frame wins.
|
|
71
58
|
let scrub: { layerId: string; time: number; commit: boolean } | null = null;
|
|
@@ -94,11 +81,12 @@
|
|
|
94
81
|
</script>
|
|
95
82
|
|
|
96
83
|
<!--
|
|
97
|
-
|
|
84
|
+
Provider effects for the active layer. An effect layer first: its effect (change it or
|
|
98
85
|
rasterize it), a still frame or an animation for an effect that moves, and its controls. Then
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
86
|
+
the provider filters applied to the layer (smart filters; applying one converts a pixel layer to
|
|
87
|
+
a smart object in the same undo step). Layer styles (drop shadow, stroke…) are not here: they
|
|
88
|
+
are part of the layer's properties (LayerEffectsPanel). New effect layers come from the layers
|
|
89
|
+
panel. Without a provider it says why nothing can be added.
|
|
102
90
|
-->
|
|
103
91
|
<section class="flex flex-col gap-2 text-xs {className}" aria-label="Effects" data-image-provider-effects="">
|
|
104
92
|
{#if !provider}<p class="text-[11px] text-muted-foreground">No effects provider is registered. Effects in the document are kept.</p>{/if}
|
|
@@ -169,10 +157,8 @@
|
|
|
169
157
|
{/if}
|
|
170
158
|
{#if layer && canFilter}
|
|
171
159
|
<div class="flex items-center gap-1" data-effect-part="applied">
|
|
172
|
-
<span class="flex-1 text-[11px] font-semibold uppercase tracking-wider text-foreground">
|
|
173
|
-
{
|
|
174
|
-
<ImageSelect label="Add effect" value="" placeholder="Add…" options={addOptions} onchange={add} />
|
|
175
|
-
{/if}
|
|
160
|
+
<span class="flex-1 text-[11px] font-semibold uppercase tracking-wider text-foreground">Filters</span>
|
|
161
|
+
<button type="button" class={imageOutlineButtonClass} aria-pressed={browse === 'filter'} onclick={() => (browse = browse === 'filter' ? null : 'filter')}>Add filter…</button>
|
|
176
162
|
</div>
|
|
177
163
|
{#if browse === 'filter'}
|
|
178
164
|
{@const id = layer.id}
|
|
@@ -219,11 +205,8 @@
|
|
|
219
205
|
{/each}
|
|
220
206
|
</ol>
|
|
221
207
|
{/if}
|
|
222
|
-
{#if layer &&
|
|
223
|
-
<
|
|
224
|
-
{/if}
|
|
225
|
-
{#if layer && canFilter && !generator && !all.some((f) => f.kind === 'effect') && !styles.rows.length}
|
|
226
|
-
<p class="text-[11px] text-muted-foreground">No effects yet. Add a filter, or a style such as a drop shadow. New effect layers are added from the layers panel.</p>
|
|
208
|
+
{#if layer && canFilter && !generator && !all.some((f) => f.kind === 'effect')}
|
|
209
|
+
<p class="text-[11px] text-muted-foreground">No filters yet. A filter changes the layer's pixels and stays editable. Layer styles such as a drop shadow are in the layer's properties; new effect layers are added from the layers panel.</p>
|
|
227
210
|
{/if}
|
|
228
211
|
{#if !layer}<p class="text-[11px] text-muted-foreground">Select a layer to apply effects to it.</p>{/if}
|
|
229
212
|
{#if message}<p role="alert" class="text-[11px] text-destructive">{message}</p>{/if}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* A layer's effects (Photoshop's layer styles): the master switch, Scale Effects, an "Add
|
|
13
|
-
*
|
|
13
|
+
* style" menu, and each effect with its enabled toggle, remove button and, when expanded, its
|
|
14
14
|
* settings. Every change is one undo step (a slider drag is one step too).
|
|
15
15
|
*/
|
|
16
16
|
interface Props {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
/** The layer whose effects to show (default: the active layer). */
|
|
19
19
|
layerId?: string | null;
|
|
20
20
|
/**
|
|
21
|
-
* Show the "
|
|
21
|
+
* Show the "Layer Style" title and the "Add style" menu (default true). Without them (inside a
|
|
22
22
|
* panel that adds styles from its own menu) the master switch and Scale stay.
|
|
23
23
|
*/
|
|
24
24
|
heading?: boolean;
|
|
@@ -87,9 +87,9 @@
|
|
|
87
87
|
<div class="text-xs text-muted-foreground {className}" data-testid="layer-effects">{view.model.reason}</div>
|
|
88
88
|
{:else}
|
|
89
89
|
{@const id = view.id}
|
|
90
|
-
<div class="flex flex-col gap-1.5 text-xs text-foreground {className}" data-testid="layer-effects" aria-label="Layer
|
|
90
|
+
<div class="flex flex-col gap-1.5 text-xs text-foreground {className}" data-testid="layer-effects" aria-label="Layer style" role="group">
|
|
91
91
|
<div class="flex flex-wrap items-center gap-2">
|
|
92
|
-
{#if heading}<span class="font-semibold text-foreground">
|
|
92
|
+
{#if heading}<span class="font-semibold text-foreground">Layer Style</span>{:else}<span class="font-semibold text-foreground">Styles</span>{/if}
|
|
93
93
|
<label class="flex items-center gap-1 text-foreground">
|
|
94
94
|
<ImageCheckbox
|
|
95
95
|
label="Effects on"
|
|
@@ -116,9 +116,9 @@
|
|
|
116
116
|
</label>
|
|
117
117
|
{#if heading}
|
|
118
118
|
<ImageSelect
|
|
119
|
-
label="Add
|
|
119
|
+
label="Add style"
|
|
120
120
|
value=""
|
|
121
|
-
placeholder="Add
|
|
121
|
+
placeholder="Add style…"
|
|
122
122
|
disabled={view.model.readOnly}
|
|
123
123
|
options={LAYER_EFFECT_MENU.map((m) => ({ value: m.kind, label: m.label }))}
|
|
124
124
|
onchange={add}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ImageEditorController } from '@pixerate/editor/image-editor';
|
|
2
2
|
/**
|
|
3
3
|
* A layer's effects (Photoshop's layer styles): the master switch, Scale Effects, an "Add
|
|
4
|
-
*
|
|
4
|
+
* style" menu, and each effect with its enabled toggle, remove button and, when expanded, its
|
|
5
5
|
* settings. Every change is one undo step (a slider drag is one step too).
|
|
6
6
|
*/
|
|
7
7
|
interface Props {
|
|
@@ -9,7 +9,7 @@ interface Props {
|
|
|
9
9
|
/** The layer whose effects to show (default: the active layer). */
|
|
10
10
|
layerId?: string | null;
|
|
11
11
|
/**
|
|
12
|
-
* Show the "
|
|
12
|
+
* Show the "Layer Style" title and the "Add style" menu (default true). Without them (inside a
|
|
13
13
|
* panel that adds styles from its own menu) the master switch and Scale stay.
|
|
14
14
|
*/
|
|
15
15
|
heading?: boolean;
|
|
@@ -68,6 +68,10 @@
|
|
|
68
68
|
onchange={(val) => controller.setLayerProperties(activeLayer.id, { opacity: val })}
|
|
69
69
|
/>
|
|
70
70
|
</div>
|
|
71
|
+
<!-- Layer Style (drop shadow, stroke, glow…) is part of the layer's properties; adjustment layers have none. -->
|
|
72
|
+
{#if activeLayer.type !== 'adjustment'}
|
|
73
|
+
<LayerEffectsPanel {controller} layerId={activeLayer.id} class="border-t border-border pt-2" />
|
|
74
|
+
{/if}
|
|
71
75
|
{:else}
|
|
72
76
|
<div class="text-muted-foreground">No active layer selected.</div>
|
|
73
77
|
{/if}
|
|
@@ -78,10 +82,8 @@
|
|
|
78
82
|
<BrushOptionsBar {controller} />
|
|
79
83
|
</div>
|
|
80
84
|
{:else if panelId === 'effects'}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
<LayerEffectsPanel {controller} />
|
|
84
|
-
</div>
|
|
85
|
+
<!-- Kept for hosts that still ask for it by id: layerPanels() folds it into 'properties'. -->
|
|
86
|
+
<LayerEffectsPanel {controller} />
|
|
85
87
|
{:else if panelId === 'adjustment'}
|
|
86
88
|
<AdjustmentLayersPanel {controller} />
|
|
87
89
|
{:else if panelId === 'type'}
|
|
@@ -95,10 +97,8 @@
|
|
|
95
97
|
<ShapeOptionsBar {controller} options={shapeOptions} onchange={(o) => (shapeOptions = o)} />
|
|
96
98
|
</div>
|
|
97
99
|
{:else if panelId === 'smart-filters'}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
<LayerEffectsPanel {controller} />
|
|
101
|
-
</div>
|
|
100
|
+
<!-- Kept for hosts that still ask for it by id: smart filters are under 'provider-effects'. -->
|
|
101
|
+
<ImageProviderEffectsPanel {controller} />
|
|
102
102
|
{:else if panelId === 'provider-effects'}
|
|
103
103
|
<ImageProviderEffectsPanel {controller} />
|
|
104
104
|
{:else if panelId === 'selection'}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pixerate/editor-svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.131.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.
|
|
168
|
+
"@pixerate/editor": "0.178.0"
|
|
169
169
|
},
|
|
170
170
|
"peerDependencies": {
|
|
171
171
|
"@dagrejs/dagre": "^1.1.4",
|