@pixerate/editor-svelte 0.86.3 → 0.88.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.
- package/dist/canvas/CanvasDrawLayer.svelte +8 -3
- package/dist/canvas/CanvasDrawLayer.svelte.d.ts.map +1 -1
- package/dist/canvas/ShapeNode.svelte +57 -1
- package/dist/canvas/ShapeNode.svelte.d.ts.map +1 -1
- package/dist/canvas/createCanvasAnimation.svelte.d.ts.map +1 -1
- package/dist/canvas/createCanvasArrange.svelte.d.ts.map +1 -1
- package/dist/canvas/createCanvasAutoLayout.svelte.d.ts.map +1 -1
- package/dist/canvas/createCanvasComponents.svelte.d.ts.map +1 -1
- package/dist/canvas/createCanvasDraw.svelte.d.ts +6 -2
- package/dist/canvas/createCanvasDraw.svelte.d.ts.map +1 -1
- package/dist/canvas/createCanvasDraw.svelte.js +5 -1
- package/dist/canvas/index.d.ts +2 -1
- package/dist/canvas/index.d.ts.map +1 -1
- package/dist/canvas/index.js +3 -0
- package/dist/canvas/shapeBrushstroke.svelte.d.ts +16 -0
- package/dist/canvas/shapeBrushstroke.svelte.d.ts.map +1 -0
- package/dist/canvas/shapeBrushstroke.svelte.js +39 -0
- package/dist/effects/EffectParameters.svelte +73 -0
- package/dist/effects/EffectParameters.svelte.d.ts +25 -0
- package/dist/effects/EffectParameters.svelte.d.ts.map +1 -0
- package/dist/effects/EffectThumbnail.svelte +48 -0
- package/dist/effects/EffectThumbnail.svelte.d.ts +13 -0
- package/dist/effects/EffectThumbnail.svelte.d.ts.map +1 -0
- package/dist/effects/EffectsBrowser.svelte +112 -0
- package/dist/effects/EffectsBrowser.svelte.d.ts +18 -0
- package/dist/effects/EffectsBrowser.svelte.d.ts.map +1 -0
- package/dist/effects/effects.svelte.d.ts +17 -0
- package/dist/effects/effects.svelte.d.ts.map +1 -0
- package/dist/effects/effects.svelte.js +49 -0
- package/dist/effects/index.d.ts +12 -0
- package/dist/effects/index.d.ts.map +1 -0
- package/dist/effects/index.js +4 -0
- package/dist/image-editor/BrushOptionsBar.svelte +14 -0
- package/dist/image-editor/BrushOptionsBar.svelte.d.ts.map +1 -1
- package/dist/image-editor/ImageEditor.svelte +15 -0
- package/dist/image-editor/ImageEditor.svelte.d.ts +7 -0
- package/dist/image-editor/ImageEditor.svelte.d.ts.map +1 -1
- package/dist/image-editor/ImageEffectControls.svelte +29 -0
- package/dist/image-editor/ImageEffectControls.svelte.d.ts +13 -0
- package/dist/image-editor/ImageEffectControls.svelte.d.ts.map +1 -0
- package/dist/image-editor/ImageProviderEffectsPanel.svelte +129 -0
- package/dist/image-editor/ImageProviderEffectsPanel.svelte.d.ts +9 -0
- package/dist/image-editor/ImageProviderEffectsPanel.svelte.d.ts.map +1 -0
- package/dist/image-editor/PaintGradientEditor.svelte +16 -0
- package/dist/image-editor/PaintGradientEditor.svelte.d.ts +15 -0
- package/dist/image-editor/PaintGradientEditor.svelte.d.ts.map +1 -0
- package/dist/image-editor/imageEditorState.svelte.d.ts +9 -1
- package/dist/image-editor/imageEditorState.svelte.d.ts.map +1 -1
- package/dist/image-editor/imageEditorState.svelte.js +15 -1
- package/dist/image-editor/index.d.ts +4 -0
- package/dist/image-editor/index.d.ts.map +1 -1
- package/dist/image-editor/index.js +2 -0
- package/dist/paint-editor/BrushPanel.svelte +13 -41
- package/dist/paint-editor/BrushPanel.svelte.d.ts.map +1 -1
- package/dist/paint-editor/ColorPanel.svelte +27 -7
- package/dist/paint-editor/ColorPanel.svelte.d.ts.map +1 -1
- package/dist/paint-editor/PaintGradientEditor.svelte +16 -0
- package/dist/paint-editor/PaintGradientEditor.svelte.d.ts +15 -0
- package/dist/paint-editor/PaintGradientEditor.svelte.d.ts.map +1 -0
- package/dist/paint-editor/PaintGradientEditorView.svelte +157 -0
- package/dist/paint-editor/PaintGradientEditorView.svelte.d.ts +17 -0
- package/dist/paint-editor/PaintGradientEditorView.svelte.d.ts.map +1 -0
- package/dist/paint-editor/WetPanel.svelte +9 -2
- package/dist/paint-editor/WetPanel.svelte.d.ts.map +1 -1
- package/dist/paint-editor/index.d.ts +3 -0
- package/dist/paint-editor/index.d.ts.map +1 -1
- package/dist/paint-editor/index.js +1 -0
- package/dist/paint-editor/paintGradientTypes.d.ts +76 -0
- package/dist/paint-editor/paintGradientTypes.d.ts.map +1 -0
- package/dist/paint-editor/paintGradientTypes.js +8 -0
- package/dist/video-editor/ClipInspector.svelte +10 -3
- package/dist/video-editor/ClipInspector.svelte.d.ts.map +1 -1
- package/dist/video-editor/EffectControls.svelte +32 -0
- package/dist/video-editor/EffectControls.svelte.d.ts +15 -0
- package/dist/video-editor/EffectControls.svelte.d.ts.map +1 -0
- package/dist/video-editor/VideoEditor.svelte +18 -2
- package/dist/video-editor/VideoEditor.svelte.d.ts +9 -0
- package/dist/video-editor/VideoEditor.svelte.d.ts.map +1 -1
- package/dist/video-editor/VideoEffectsPanel.svelte +154 -0
- package/dist/video-editor/VideoEffectsPanel.svelte.d.ts +9 -0
- package/dist/video-editor/VideoEffectsPanel.svelte.d.ts.map +1 -0
- package/dist/video-editor/createVideoEditor.svelte.d.ts +8 -1
- package/dist/video-editor/createVideoEditor.svelte.d.ts.map +1 -1
- package/dist/video-editor/createVideoEditor.svelte.js +15 -1
- package/dist/video-editor/index.d.ts +3 -0
- package/dist/video-editor/index.d.ts.map +1 -1
- package/dist/video-editor/index.js +1 -0
- package/package.json +7 -2
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { EFFECT_USE_LABELS, type EffectProvider, type EffectSummary, type EffectUse } from '@pixerate/editor/effects';
|
|
3
|
+
import EffectThumbnail from './EffectThumbnail.svelte';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
/** The editor's provider; without one the browser says effects are unavailable. */
|
|
7
|
+
provider: EffectProvider | null | undefined;
|
|
8
|
+
/** Only effects with one of these uses (default: all but motion). */
|
|
9
|
+
uses?: readonly EffectUse[];
|
|
10
|
+
/** Called with the effect the user picks. */
|
|
11
|
+
onpick: (effect: EffectSummary) => void;
|
|
12
|
+
/** Draw previews with the provider's renderer (default true). */
|
|
13
|
+
thumbnails?: boolean;
|
|
14
|
+
/** Heading (default "Effects"; empty for none). */
|
|
15
|
+
title?: string;
|
|
16
|
+
class?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let { provider, uses, onpick, thumbnails = true, title = 'Effects', class: className = '' }: Props = $props();
|
|
20
|
+
let all = $state.raw<readonly EffectSummary[]>([]);
|
|
21
|
+
let found = $state.raw<readonly EffectSummary[]>([]);
|
|
22
|
+
let query = $state('');
|
|
23
|
+
let category = $state('');
|
|
24
|
+
let use = $state<EffectUse | ''>('');
|
|
25
|
+
let error = $state<string | null>(null);
|
|
26
|
+
|
|
27
|
+
$effect(() => {
|
|
28
|
+
const p = provider;
|
|
29
|
+
all = [];
|
|
30
|
+
if (!p) return;
|
|
31
|
+
let live = true;
|
|
32
|
+
Promise.resolve()
|
|
33
|
+
.then(() => p.list())
|
|
34
|
+
.then(
|
|
35
|
+
(list) => {
|
|
36
|
+
if (live) (all = list), (error = null);
|
|
37
|
+
},
|
|
38
|
+
(e: unknown) => {
|
|
39
|
+
if (live) error = e instanceof Error ? e.message : String(e);
|
|
40
|
+
},
|
|
41
|
+
);
|
|
42
|
+
return () => {
|
|
43
|
+
live = false;
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
$effect(() => {
|
|
47
|
+
const p = provider;
|
|
48
|
+
const q = query;
|
|
49
|
+
const options = { ...(category ? { category } : {}), ...(use ? { use } : {}) };
|
|
50
|
+
if (!p) {
|
|
51
|
+
found = [];
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
let live = true;
|
|
55
|
+
Promise.resolve()
|
|
56
|
+
.then(() => p.search(q, options))
|
|
57
|
+
.then(
|
|
58
|
+
(list) => {
|
|
59
|
+
if (live) found = list;
|
|
60
|
+
},
|
|
61
|
+
() => {
|
|
62
|
+
if (live) found = [];
|
|
63
|
+
},
|
|
64
|
+
);
|
|
65
|
+
return () => {
|
|
66
|
+
live = false;
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
const allowed = (e: EffectSummary) => (uses ? e.kind !== 'motion' || uses.includes('motion') : e.kind !== 'motion') && (!uses || e.uses.some((u) => uses.includes(u)));
|
|
70
|
+
const categories = $derived([...new Set(all.filter(allowed).map((e) => e.category))]);
|
|
71
|
+
const shown = $derived(found.filter(allowed));
|
|
72
|
+
</script>
|
|
73
|
+
|
|
74
|
+
<!--
|
|
75
|
+
Browses a provider's effects: a search box, a category filter (and a use filter when more than one
|
|
76
|
+
use is allowed), and a grid of effects with previews. Picking one calls `onpick`.
|
|
77
|
+
-->
|
|
78
|
+
{#if !provider}
|
|
79
|
+
<div class="rounded-md border border-dashed border-border p-3 text-xs text-muted-foreground {className}" data-effects-browser="" data-effects-unavailable="">
|
|
80
|
+
No effects provider is registered, so effects cannot be added. Effects already in the document are kept.
|
|
81
|
+
</div>
|
|
82
|
+
{:else}
|
|
83
|
+
<section class="flex flex-col gap-2 {className}" data-effects-browser="" aria-label="Effects browser">
|
|
84
|
+
{#if title}<h3 class="text-xs font-semibold">{title}</h3>{/if}
|
|
85
|
+
<div class="flex flex-wrap gap-1">
|
|
86
|
+
<input type="search" class="min-w-0 flex-1 rounded border border-border bg-transparent px-1.5 py-0.5 text-xs" placeholder="Search effects" aria-label="Search effects" bind:value={query} />
|
|
87
|
+
<select class="rounded border border-border bg-transparent px-1 py-0.5 text-xs" aria-label="Category" bind:value={category}>
|
|
88
|
+
<option value="">All categories</option>
|
|
89
|
+
{#each categories as c (c)}<option value={c}>{c}</option>{/each}
|
|
90
|
+
</select>
|
|
91
|
+
{#if uses && uses.length > 1}
|
|
92
|
+
<select class="rounded border border-border bg-transparent px-1 py-0.5 text-xs" aria-label="Use" bind:value={use}>
|
|
93
|
+
<option value="">Any use</option>
|
|
94
|
+
{#each uses as u (u)}<option value={u}>{EFFECT_USE_LABELS[u]}</option>{/each}
|
|
95
|
+
</select>
|
|
96
|
+
{/if}
|
|
97
|
+
</div>
|
|
98
|
+
{#if error}<p role="alert" class="text-[11px] text-destructive">{error}</p>{/if}
|
|
99
|
+
<ul class="grid grid-cols-[repeat(auto-fill,minmax(6.5rem,1fr))] gap-1.5" role="list">
|
|
100
|
+
{#each shown as e (e.id)}
|
|
101
|
+
<li>
|
|
102
|
+
<button type="button" class="flex w-full flex-col gap-1 rounded border border-transparent p-1 text-left hover:border-border focus-visible:border-border" title={e.description ?? e.name} data-effect-id={e.id} onclick={() => onpick(e)}>
|
|
103
|
+
{#if thumbnails}<EffectThumbnail {provider} effect={e} />{/if}
|
|
104
|
+
<span class="truncate text-[11px] font-medium">{e.name}</span>
|
|
105
|
+
<span class="truncate text-[10px] text-muted-foreground">{e.uses.map((u) => EFFECT_USE_LABELS[u]).join(' · ')}</span>
|
|
106
|
+
</button>
|
|
107
|
+
</li>
|
|
108
|
+
{/each}
|
|
109
|
+
</ul>
|
|
110
|
+
{#if !shown.length && !error}<p class="text-[11px] text-muted-foreground">No effects match.</p>{/if}
|
|
111
|
+
</section>
|
|
112
|
+
{/if}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type EffectProvider, type EffectSummary, type EffectUse } from '@pixerate/editor/effects';
|
|
2
|
+
interface Props {
|
|
3
|
+
/** The editor's provider; without one the browser says effects are unavailable. */
|
|
4
|
+
provider: EffectProvider | null | undefined;
|
|
5
|
+
/** Only effects with one of these uses (default: all but motion). */
|
|
6
|
+
uses?: readonly EffectUse[];
|
|
7
|
+
/** Called with the effect the user picks. */
|
|
8
|
+
onpick: (effect: EffectSummary) => void;
|
|
9
|
+
/** Draw previews with the provider's renderer (default true). */
|
|
10
|
+
thumbnails?: boolean;
|
|
11
|
+
/** Heading (default "Effects"; empty for none). */
|
|
12
|
+
title?: string;
|
|
13
|
+
class?: string;
|
|
14
|
+
}
|
|
15
|
+
declare const EffectsBrowser: import("svelte").Component<Props, {}, "">;
|
|
16
|
+
type EffectsBrowser = ReturnType<typeof EffectsBrowser>;
|
|
17
|
+
export default EffectsBrowser;
|
|
18
|
+
//# sourceMappingURL=EffectsBrowser.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EffectsBrowser.svelte.d.ts","sourceRoot":"","sources":["../../src/effects/EffectsBrowser.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EAAqB,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAIpH,UAAU,KAAK;IACb,mFAAmF;IACnF,QAAQ,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,CAAC;IAC5C,qEAAqE;IACrE,IAAI,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IAC5B,6CAA6C;IAC7C,MAAM,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IACxC,iEAAiE;IACjE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAoGH,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { EffectDescription, EffectProvider } from "@pixerate/editor/effects";
|
|
2
|
+
/** Anything that takes an effects provider: every editor controller with effects support. */
|
|
3
|
+
export interface EffectsHost {
|
|
4
|
+
useEffects(provider: EffectProvider): () => void;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Registers a provider with an editor for the lifetime of the calling component (call it during
|
|
8
|
+
* initialisation), following the getters: a new provider replaces the old one, `null` or
|
|
9
|
+
* `undefined` removes it. Without a provider the editor behaves as without effects support.
|
|
10
|
+
*/
|
|
11
|
+
export declare function useEffects(host: EffectsHost | null | undefined | (() => EffectsHost | null | undefined), provider: EffectProvider | null | undefined | (() => EffectProvider | null | undefined)): void;
|
|
12
|
+
/** An effect's description from the provider, reloaded when the getters change (`null` while loading or on error). */
|
|
13
|
+
export declare function effectDescriptionOf(provider: () => EffectProvider | null | undefined, effect: () => string | null | undefined): {
|
|
14
|
+
readonly description: EffectDescription | null;
|
|
15
|
+
readonly error: string | null;
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=effects.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effects.svelte.d.ts","sourceRoot":"","sources":["../../src/effects/effects.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAElF,6FAA6F;AAC7F,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,IAAI,CAAC;CAClD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,GAAG,CAAC,MAAM,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,GAAG,CAAC,MAAM,cAAc,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,IAAI,CAOvM;AAED,sHAAsH;AACtH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,cAAc,GAAG,IAAI,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG;IAAE,QAAQ,CAAC,WAAW,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAgCjN"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { untrack } from "svelte";
|
|
2
|
+
/**
|
|
3
|
+
* Registers a provider with an editor for the lifetime of the calling component (call it during
|
|
4
|
+
* initialisation), following the getters: a new provider replaces the old one, `null` or
|
|
5
|
+
* `undefined` removes it. Without a provider the editor behaves as without effects support.
|
|
6
|
+
*/
|
|
7
|
+
export function useEffects(host, provider) {
|
|
8
|
+
$effect(() => {
|
|
9
|
+
const h = typeof host === "function" ? host() : host;
|
|
10
|
+
const p = typeof provider === "function" ? provider() : provider;
|
|
11
|
+
if (!h || !p)
|
|
12
|
+
return;
|
|
13
|
+
return untrack(() => h.useEffects(p));
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/** An effect's description from the provider, reloaded when the getters change (`null` while loading or on error). */
|
|
17
|
+
export function effectDescriptionOf(provider, effect) {
|
|
18
|
+
let description = $state.raw(null);
|
|
19
|
+
let error = $state(null);
|
|
20
|
+
$effect(() => {
|
|
21
|
+
const p = provider();
|
|
22
|
+
const id = effect();
|
|
23
|
+
description = null;
|
|
24
|
+
error = null;
|
|
25
|
+
if (!p || !id)
|
|
26
|
+
return;
|
|
27
|
+
let live = true;
|
|
28
|
+
Promise.resolve()
|
|
29
|
+
.then(() => p.describe(id))
|
|
30
|
+
.then((d) => {
|
|
31
|
+
if (live)
|
|
32
|
+
description = d;
|
|
33
|
+
}, (e) => {
|
|
34
|
+
if (live)
|
|
35
|
+
error = e instanceof Error ? e.message : String(e);
|
|
36
|
+
});
|
|
37
|
+
return () => {
|
|
38
|
+
live = false;
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
return {
|
|
42
|
+
get description() {
|
|
43
|
+
return description;
|
|
44
|
+
},
|
|
45
|
+
get error() {
|
|
46
|
+
return error;
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ComponentProps } from "svelte";
|
|
2
|
+
import type EffectsBrowserComponent from "./EffectsBrowser.svelte";
|
|
3
|
+
import type EffectParametersComponent from "./EffectParameters.svelte";
|
|
4
|
+
import type EffectThumbnailComponent from "./EffectThumbnail.svelte";
|
|
5
|
+
export { default as EffectsBrowser } from "./EffectsBrowser.svelte";
|
|
6
|
+
export { default as EffectParameters } from "./EffectParameters.svelte";
|
|
7
|
+
export { default as EffectThumbnail } from "./EffectThumbnail.svelte";
|
|
8
|
+
export * from "./effects.svelte.js";
|
|
9
|
+
export type EffectsBrowserProps = ComponentProps<typeof EffectsBrowserComponent>;
|
|
10
|
+
export type EffectParametersProps = ComponentProps<typeof EffectParametersComponent>;
|
|
11
|
+
export type EffectThumbnailProps = ComponentProps<typeof EffectThumbnailComponent>;
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/effects/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,KAAK,uBAAuB,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,yBAAyB,MAAM,2BAA2B,CAAC;AACvE,OAAO,KAAK,wBAAwB,MAAM,0BAA0B,CAAC;AAErE,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,0BAA0B,CAAC;AACtE,cAAc,qBAAqB,CAAC;AAEpC,MAAM,MAAM,mBAAmB,GAAG,cAAc,CAAC,OAAO,uBAAuB,CAAC,CAAC;AACjF,MAAM,MAAM,qBAAqB,GAAG,cAAc,CAAC,OAAO,yBAAyB,CAAC,CAAC;AACrF,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
setRetouchChoice,
|
|
15
15
|
} from '@pixerate/editor/image-editor';
|
|
16
16
|
import { untrack } from 'svelte';
|
|
17
|
+
import { DEFAULT_PAINT_GRADIENT } from '@pixerate/editor/image-editor';
|
|
18
|
+
import PaintGradientEditor from './PaintGradientEditor.svelte';
|
|
17
19
|
import ControlSlider from './ControlSlider.svelte';
|
|
18
20
|
|
|
19
21
|
interface Props {
|
|
@@ -83,7 +85,19 @@
|
|
|
83
85
|
</label>
|
|
84
86
|
<button type="button" title="Swap colours (X)" class={chip(false)} onclick={() => controller.swapPaintColors()}>Swap</button>
|
|
85
87
|
<button type="button" title="Default colours (D)" class={chip(false)} onclick={() => controller.resetPaintColors()}>Default</button>
|
|
88
|
+
{#if view.tool === 'brush'}
|
|
89
|
+
<button
|
|
90
|
+
type="button"
|
|
91
|
+
aria-pressed={view.paint.type === 'gradient'}
|
|
92
|
+
title="Gradient paint: the brush changes colour as the stroke goes"
|
|
93
|
+
class={chip(view.paint.type === 'gradient')}
|
|
94
|
+
onclick={() => attempt(() => controller.setPaintOptions(view.paint.type === 'gradient' ? { foreground: view.foreground } : { paint: DEFAULT_PAINT_GRADIENT }))}>Gradient</button
|
|
95
|
+
>
|
|
96
|
+
{/if}
|
|
86
97
|
</div>
|
|
98
|
+
{#if view.tool === 'brush' && view.paint.type === 'gradient'}
|
|
99
|
+
<PaintGradientEditor value={view.paint} colors={{ paint: view.foreground, secondary: view.background }} onchange={(g) => attempt(() => controller.setPaintOptions({ paint: g }))} />
|
|
100
|
+
{/if}
|
|
87
101
|
|
|
88
102
|
{#each BRUSH_OPTION_CONTROLS as spec (spec.id)}
|
|
89
103
|
<ControlSlider {spec} value={view.brush[spec.id]} onchange={(v) => controller.setPaintOptions({ brush: { [spec.id]: v } })} />
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BrushOptionsBar.svelte.d.ts","sourceRoot":"","sources":["../../src/image-editor/BrushOptionsBar.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"BrushOptionsBar.svelte.d.ts","sourceRoot":"","sources":["../../src/image-editor/BrushOptionsBar.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAoBzE,UAAU,KAAK;IACb,UAAU,EAAE,qBAAqB,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAsJH,QAAA,MAAM,eAAe,2CAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
|
|
@@ -50,6 +50,9 @@
|
|
|
50
50
|
import TypeOptionsBar from './TypeOptionsBar.svelte';
|
|
51
51
|
import { onDestroy, untrack } from 'svelte';
|
|
52
52
|
import { createReactiveImageEditor, type ReactiveImageEditor } from './imageEditorState.svelte.js';
|
|
53
|
+
import ImageProviderEffectsPanel from './ImageProviderEffectsPanel.svelte';
|
|
54
|
+
import type { EffectProvider } from '@pixerate/editor/effects';
|
|
55
|
+
import { useEffects } from '../effects/effects.svelte.js';
|
|
53
56
|
|
|
54
57
|
interface Props {
|
|
55
58
|
editor?: ReactiveImageEditor;
|
|
@@ -62,6 +65,12 @@
|
|
|
62
65
|
onRemoveBackground?: RemoveBackgroundHook;
|
|
63
66
|
aiHooks?: ImageEditorAIHooks;
|
|
64
67
|
fit?: ImageEditorFit;
|
|
68
|
+
/**
|
|
69
|
+
* An effects provider (see `@pixerate/editor/effects`), registered with the controller while
|
|
70
|
+
* mounted: filter effects as smart filters and generator or overlay effects as effect layers,
|
|
71
|
+
* with an Effects section in the Layers tab. Optional: without one the editor is as before.
|
|
72
|
+
*/
|
|
73
|
+
effects?: EffectProvider | null;
|
|
65
74
|
}
|
|
66
75
|
|
|
67
76
|
let {
|
|
@@ -75,11 +84,16 @@
|
|
|
75
84
|
onRemoveBackground,
|
|
76
85
|
aiHooks,
|
|
77
86
|
fit,
|
|
87
|
+
effects,
|
|
78
88
|
}: Props = $props();
|
|
79
89
|
|
|
80
90
|
const internalEditor = createReactiveImageEditor();
|
|
81
91
|
const editor = $derived(propEditor || internalEditor);
|
|
82
92
|
onDestroy(() => internalEditor.destroy());
|
|
93
|
+
useEffects(() => editor.controller, () => effects);
|
|
94
|
+
const hasEffects = (l: import('@pixerate/editor/image-editor').ImageLayer): boolean =>
|
|
95
|
+
(l.type === 'pixel' && !!l.generator) || (l.type === 'smart' && !!l.smartFilters?.filters.some((f) => f.kind === 'effect')) || (l.type === 'group' && l.children.some(hasEffects));
|
|
96
|
+
const effectsShown = $derived(!!effects || !!editor.controller.effectsProvider || editor.state.layers.some(hasEffects));
|
|
83
97
|
const legacyProcess = $derived(
|
|
84
98
|
normalizeProcessVersion(editor.state.adjustments.process) < LATEST_PROCESS_VERSION
|
|
85
99
|
);
|
|
@@ -1280,6 +1294,7 @@
|
|
|
1280
1294
|
disabled={transformActive}
|
|
1281
1295
|
onclick={() => transformTool.begin()}>Free Transform</button>
|
|
1282
1296
|
<LayersPanel controller={editor.controller} />
|
|
1297
|
+
{#if effectsShown}<ImageProviderEffectsPanel controller={editor.controller} class="border-t border-slate-700/60 pt-3" />{/if}
|
|
1283
1298
|
<span class="font-semibold text-slate-200 uppercase tracking-wider text-[11px]">Colour</span>
|
|
1284
1299
|
<ColorProfilePanel controller={editor.controller} />
|
|
1285
1300
|
</div>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ExportOptions, InpaintHook, RemoveBackgroundHook, ImageEditorAIHooks, ImageEditorFit } from '@pixerate/editor/image-editor';
|
|
2
2
|
import { type ReactiveImageEditor } from './imageEditorState.svelte.js';
|
|
3
|
+
import type { EffectProvider } from '@pixerate/editor/effects';
|
|
3
4
|
interface Props {
|
|
4
5
|
editor?: ReactiveImageEditor;
|
|
5
6
|
src?: string;
|
|
@@ -11,6 +12,12 @@ interface Props {
|
|
|
11
12
|
onRemoveBackground?: RemoveBackgroundHook;
|
|
12
13
|
aiHooks?: ImageEditorAIHooks;
|
|
13
14
|
fit?: ImageEditorFit;
|
|
15
|
+
/**
|
|
16
|
+
* An effects provider (see `@pixerate/editor/effects`), registered with the controller while
|
|
17
|
+
* mounted: filter effects as smart filters and generator or overlay effects as effect layers,
|
|
18
|
+
* with an Effects section in the Layers tab. Optional: without one the editor is as before.
|
|
19
|
+
*/
|
|
20
|
+
effects?: EffectProvider | null;
|
|
14
21
|
}
|
|
15
22
|
declare const ImageEditor: import("svelte").Component<Props, {}, "">;
|
|
16
23
|
type ImageEditor = ReturnType<typeof ImageEditor>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageEditor.svelte.d.ts","sourceRoot":"","sources":["../../src/image-editor/ImageEditor.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAIR,aAAa,EAGb,WAAW,EACX,oBAAoB,EACpB,kBAAkB,EAClB,cAAc,EACf,MAAM,+BAA+B,CAAC;AAuCzC,OAAO,EAA6B,KAAK,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"ImageEditor.svelte.d.ts","sourceRoot":"","sources":["../../src/image-editor/ImageEditor.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAIR,aAAa,EAGb,WAAW,EACX,oBAAoB,EACpB,kBAAkB,EAClB,cAAc,EACf,MAAM,+BAA+B,CAAC;AAuCzC,OAAO,EAA6B,KAAK,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAI7D,UAAU,KAAK;IACb,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,kBAAkB,CAAC,EAAE,oBAAoB,CAAC;IAC1C,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB;;;;OAIG;IACH,OAAO,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;CACjC;AA+2CH,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { EffectProvider } from '@pixerate/editor/effects';
|
|
3
|
+
import EffectParameters from '../effects/EffectParameters.svelte';
|
|
4
|
+
import { effectDescriptionOf } from '../effects/effects.svelte.js';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
provider: EffectProvider | null;
|
|
8
|
+
effect: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
values: Readonly<Record<string, unknown>>;
|
|
11
|
+
onchange: (control: string, value: unknown, gesture: string | null) => void;
|
|
12
|
+
onpreset: (values: Readonly<Record<string, unknown>>) => void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
let { provider, effect, name, values, onchange, onpreset }: Props = $props();
|
|
16
|
+
const loaded = effectDescriptionOf(() => provider, () => effect);
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<!-- One effect's controls, loaded from the provider; a note when it does not have the effect. -->
|
|
20
|
+
{#if !provider}
|
|
21
|
+
<p class="text-[11px] text-slate-400">No effects provider: "{name ?? effect}" is kept but not drawn.</p>
|
|
22
|
+
{:else if loaded.error}
|
|
23
|
+
<p class="text-[11px] text-amber-400">{loaded.error}</p>
|
|
24
|
+
{:else if !loaded.description}
|
|
25
|
+
<p class="text-[11px] text-slate-400">Loading…</p>
|
|
26
|
+
{:else}
|
|
27
|
+
{@const description = loaded.description}
|
|
28
|
+
<EffectParameters {description} {values} {onchange} onreset={(k) => onchange(k, description.defaults[k], null)} {onpreset} />
|
|
29
|
+
{/if}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { EffectProvider } from '@pixerate/editor/effects';
|
|
2
|
+
interface Props {
|
|
3
|
+
provider: EffectProvider | null;
|
|
4
|
+
effect: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
values: Readonly<Record<string, unknown>>;
|
|
7
|
+
onchange: (control: string, value: unknown, gesture: string | null) => void;
|
|
8
|
+
onpreset: (values: Readonly<Record<string, unknown>>) => void;
|
|
9
|
+
}
|
|
10
|
+
declare const ImageEffectControls: import("svelte").Component<Props, {}, "">;
|
|
11
|
+
type ImageEffectControls = ReturnType<typeof ImageEffectControls>;
|
|
12
|
+
export default ImageEffectControls;
|
|
13
|
+
//# sourceMappingURL=ImageEffectControls.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImageEffectControls.svelte.d.ts","sourceRoot":"","sources":["../../src/image-editor/ImageEffectControls.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAK7D,UAAU,KAAK;IACb,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1C,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC5E,QAAQ,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,IAAI,CAAC;CAC/D;AAyBH,QAAA,MAAM,mBAAmB,2CAAwC,CAAC;AAClE,KAAK,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAClE,eAAe,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { findLayer, type ImageEditorController, type ImageLayer, type SmartObjectLayer } from '@pixerate/editor/image-editor';
|
|
3
|
+
import { untrack } from 'svelte';
|
|
4
|
+
import EffectsBrowser from '../effects/EffectsBrowser.svelte';
|
|
5
|
+
import ImageEffectControls from './ImageEffectControls.svelte';
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
controller: ImageEditorController;
|
|
9
|
+
class?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let { controller, class: className = '' }: Props = $props();
|
|
13
|
+
let tick = $state(0);
|
|
14
|
+
$effect(() => {
|
|
15
|
+
const c = controller;
|
|
16
|
+
return untrack(() => c.subscribe(() => tick++));
|
|
17
|
+
});
|
|
18
|
+
let browse = $state<null | 'filter' | 'layer'>(null);
|
|
19
|
+
let message = $state<string | null>(null);
|
|
20
|
+
let open = $state<string | null>(null);
|
|
21
|
+
const snapshot = $derived.by(() => {
|
|
22
|
+
void tick;
|
|
23
|
+
const s = controller.getState();
|
|
24
|
+
const layer: ImageLayer | null = s.activeLayerId ? (findLayer(s.layers, s.activeLayerId)?.layer ?? null) : null;
|
|
25
|
+
return { provider: controller.effectsProvider, layer };
|
|
26
|
+
});
|
|
27
|
+
const provider = $derived(snapshot.provider);
|
|
28
|
+
const layer = $derived(snapshot.layer);
|
|
29
|
+
const all = $derived(layer?.type === 'smart' ? ((layer as SmartObjectLayer).smartFilters?.filters ?? []) : []);
|
|
30
|
+
const generator = $derived(layer?.type === 'pixel' ? layer.generator : undefined);
|
|
31
|
+
const canFilter = $derived(!!layer && layer.type !== 'adjustment' && layer.type !== 'annotation');
|
|
32
|
+
const btn = 'rounded border border-slate-700 px-1.5 py-0.5 text-[11px] text-slate-300 hover:text-white disabled:opacity-40';
|
|
33
|
+
const drags = new Set<string>();
|
|
34
|
+
/** Changes during a drag skip the undo stack after the first, so the drag is one step. */
|
|
35
|
+
function commit(gesture: string | null) {
|
|
36
|
+
if (!gesture) return true;
|
|
37
|
+
if (drags.has(gesture)) return false;
|
|
38
|
+
drags.add(gesture);
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
function run(work: () => unknown) {
|
|
42
|
+
message = null;
|
|
43
|
+
Promise.resolve()
|
|
44
|
+
.then(work)
|
|
45
|
+
.catch((e: unknown) => (message = e instanceof Error ? e.message : String(e)));
|
|
46
|
+
}
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<!--
|
|
50
|
+
Provider effects for the active layer: its effect smart filters (apply, turn on and off, opacity,
|
|
51
|
+
reorder, change controls, remove) and, for an effect layer, its own controls; plus adding effect
|
|
52
|
+
layers. Applying a filter effect to a pixel layer converts it to a smart object in the same undo
|
|
53
|
+
step. Without a provider it says why nothing can be added.
|
|
54
|
+
-->
|
|
55
|
+
<section class="flex flex-col gap-2 text-xs {className}" aria-label="Provider effects" data-image-provider-effects="">
|
|
56
|
+
<div class="flex items-center gap-1">
|
|
57
|
+
<span class="flex-1 text-[11px] font-semibold uppercase tracking-wider text-slate-200">Effects</span>
|
|
58
|
+
<button type="button" class={btn} disabled={!provider || !canFilter} aria-pressed={browse === 'filter'} onclick={() => (browse = browse === 'filter' ? null : 'filter')}>Apply effect…</button>
|
|
59
|
+
<button type="button" class={btn} disabled={!provider} aria-pressed={browse === 'layer'} onclick={() => (browse = browse === 'layer' ? null : 'layer')}>Effect layer…</button>
|
|
60
|
+
</div>
|
|
61
|
+
{#if !provider}<p class="text-[11px] text-slate-400">No effects provider is registered. Effects in the document are kept.</p>{/if}
|
|
62
|
+
{#if browse === 'filter' && layer}
|
|
63
|
+
{@const id = layer.id}
|
|
64
|
+
<EffectsBrowser {provider} uses={['filter']} title="Filters" onpick={(e) => ((browse = null), run(() => controller.applyEffectFilter(id, e.id)))} />
|
|
65
|
+
{/if}
|
|
66
|
+
{#if browse === 'layer'}
|
|
67
|
+
<EffectsBrowser {provider} uses={['generator', 'overlay', 'title']} title="Generators and overlays" onpick={(e) => ((browse = null), run(() => controller.addEffectLayer(e.id)))} />
|
|
68
|
+
{/if}
|
|
69
|
+
{#if generator && layer}
|
|
70
|
+
{@const id = layer.id}
|
|
71
|
+
<div class="space-y-1" data-effect-part="generator">
|
|
72
|
+
<div class="flex items-center gap-1">
|
|
73
|
+
<span class="flex-1 font-medium text-slate-200">{generator.name ?? generator.effect}</span>
|
|
74
|
+
<button type="button" class={btn} title="Keep the pixels as a plain layer" onclick={() => run(() => controller.rasterizeEffectLayer(id))}>Rasterize</button>
|
|
75
|
+
</div>
|
|
76
|
+
<ImageEffectControls
|
|
77
|
+
{provider}
|
|
78
|
+
effect={generator.effect}
|
|
79
|
+
name={generator.name}
|
|
80
|
+
values={generator.values}
|
|
81
|
+
onchange={(k, v, g) => run(() => controller.updateEffectLayer(id, { values: { [k]: v as never } }, commit(g)))}
|
|
82
|
+
onpreset={(values) => run(() => controller.updateEffectLayer(id, { values: values as never }))}
|
|
83
|
+
/>
|
|
84
|
+
</div>
|
|
85
|
+
{/if}
|
|
86
|
+
{#if layer && all.some((f) => f.kind === 'effect')}
|
|
87
|
+
{@const id = layer.id}
|
|
88
|
+
<ol class="space-y-1" data-effect-part="filters">
|
|
89
|
+
{#each all as f, index (f.id)}
|
|
90
|
+
{#if f.kind === 'effect'}
|
|
91
|
+
{@const label = f.name ?? f.effect}
|
|
92
|
+
<li class="rounded border border-slate-700 p-1" data-smart-effect={f.id}>
|
|
93
|
+
<div class="flex items-center gap-1">
|
|
94
|
+
<input type="checkbox" checked={f.enabled} aria-label="{label} on" onchange={(e) => {
|
|
95
|
+
const enabled = e.currentTarget.checked;
|
|
96
|
+
run(() => controller.updateEffectFilter(id, f.id, { enabled }));
|
|
97
|
+
}} />
|
|
98
|
+
<button type="button" class="min-w-0 flex-1 truncate text-left text-slate-200" aria-expanded={open === f.id} onclick={() => (open = open === f.id ? null : f.id)}>{label}</button>
|
|
99
|
+
<button type="button" class={btn} disabled={index === all.length - 1} aria-label="Move up" onclick={() => run(() => controller.updateEffectFilter(id, f.id, { index: index + 1 }))}>↑</button>
|
|
100
|
+
<button type="button" class={btn} disabled={index === 0} aria-label="Move down" onclick={() => run(() => controller.updateEffectFilter(id, f.id, { index: index - 1 }))}>↓</button>
|
|
101
|
+
<button type="button" class={btn} aria-label="Remove {label}" onclick={() => run(() => controller.removeSmartFilter(id, f.id))}>✕</button>
|
|
102
|
+
</div>
|
|
103
|
+
{#if open === f.id}
|
|
104
|
+
<div class="mt-1 space-y-2">
|
|
105
|
+
<label class="flex items-center gap-1">
|
|
106
|
+
<span class="w-14 text-[11px] text-slate-300">Opacity</span>
|
|
107
|
+
<input type="range" min="0" max="1" step="0.01" class="flex-1" value={f.opacity} aria-label="{label} opacity" oninput={(e) => {
|
|
108
|
+
const opacity = Number(e.currentTarget.value);
|
|
109
|
+
run(() => controller.updateEffectFilter(id, f.id, { opacity }));
|
|
110
|
+
}} />
|
|
111
|
+
</label>
|
|
112
|
+
<ImageEffectControls
|
|
113
|
+
{provider}
|
|
114
|
+
effect={f.effect}
|
|
115
|
+
name={f.name}
|
|
116
|
+
values={f.values}
|
|
117
|
+
onchange={(k, v, g) => run(() => controller.updateEffectFilter(id, f.id, { values: { [k]: v as never } }, commit(g)))}
|
|
118
|
+
onpreset={(values) => run(() => controller.updateEffectFilter(id, f.id, { values: values as never }))}
|
|
119
|
+
/>
|
|
120
|
+
</div>
|
|
121
|
+
{/if}
|
|
122
|
+
</li>
|
|
123
|
+
{/if}
|
|
124
|
+
{/each}
|
|
125
|
+
</ol>
|
|
126
|
+
{/if}
|
|
127
|
+
{#if !layer}<p class="text-[11px] text-slate-400">Select a layer to apply effects to it.</p>{/if}
|
|
128
|
+
{#if message}<p role="alert" class="text-[11px] text-rose-400">{message}</p>{/if}
|
|
129
|
+
</section>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ImageEditorController } from '@pixerate/editor/image-editor';
|
|
2
|
+
interface Props {
|
|
3
|
+
controller: ImageEditorController;
|
|
4
|
+
class?: string;
|
|
5
|
+
}
|
|
6
|
+
declare const ImageProviderEffectsPanel: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type ImageProviderEffectsPanel = ReturnType<typeof ImageProviderEffectsPanel>;
|
|
8
|
+
export default ImageProviderEffectsPanel;
|
|
9
|
+
//# sourceMappingURL=ImageProviderEffectsPanel.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImageProviderEffectsPanel.svelte.d.ts","sourceRoot":"","sources":["../../src/image-editor/ImageProviderEffectsPanel.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EAAa,KAAK,qBAAqB,EAA0C,MAAM,+BAA+B,CAAC;AAM5H,UAAU,KAAK;IACb,UAAU,EAAE,qBAAqB,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA8GH,QAAA,MAAM,yBAAyB,2CAAwC,CAAC;AACxE,KAAK,yBAAyB,GAAG,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAC9E,eAAe,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { PAINT_GRADIENT_KIT, type PaintGradientSource } from '@pixerate/editor/image-editor';
|
|
3
|
+
import PaintGradientEditorView from '../paint-editor/PaintGradientEditorView.svelte';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
value: PaintGradientSource;
|
|
7
|
+
onchange: (paint: PaintGradientSource) => void;
|
|
8
|
+
/** What `paint` / `secondary` stops show as (the editor's two colours). */
|
|
9
|
+
colors: { paint: string; secondary: string };
|
|
10
|
+
class?: string;
|
|
11
|
+
}
|
|
12
|
+
let { value, onchange, colors, class: className = '' }: Props = $props();
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<!-- The gradient paint editor (see PaintGradientEditorView). -->
|
|
16
|
+
<PaintGradientEditorView {value} {onchange} {colors} class={className} kit={PAINT_GRADIENT_KIT} />
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type PaintGradientSource } from '@pixerate/editor/image-editor';
|
|
2
|
+
interface Props {
|
|
3
|
+
value: PaintGradientSource;
|
|
4
|
+
onchange: (paint: PaintGradientSource) => void;
|
|
5
|
+
/** What `paint` / `secondary` stops show as (the editor's two colours). */
|
|
6
|
+
colors: {
|
|
7
|
+
paint: string;
|
|
8
|
+
secondary: string;
|
|
9
|
+
};
|
|
10
|
+
class?: string;
|
|
11
|
+
}
|
|
12
|
+
declare const PaintGradientEditor: import("svelte").Component<Props, {}, "">;
|
|
13
|
+
type PaintGradientEditor = ReturnType<typeof PaintGradientEditor>;
|
|
14
|
+
export default PaintGradientEditor;
|
|
15
|
+
//# sourceMappingURL=PaintGradientEditor.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PaintGradientEditor.svelte.d.ts","sourceRoot":"","sources":["../../src/image-editor/PaintGradientEditor.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EAAsB,KAAK,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAI3F,UAAU,KAAK;IACb,KAAK,EAAE,mBAAmB,CAAC;IAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC/C,2EAA2E;IAC3E,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAaH,QAAA,MAAM,mBAAmB,2CAAwC,CAAC;AAClE,KAAK,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAClE,eAAe,mBAAmB,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { ToolRegistry } from '@pixerate/editor/tools';
|
|
2
|
+
import { ImageEditorController, type ImageEffectsToolProviderOptions, type ImageEditorFit, type ImageEditorOptions, type ImageEditorState, type ImageEditorTool, type CropBox, type AspectRatio, type ImageAdjustments, type DepthMaskOptions, type Annotation, type CreateAnnotationPayload, type ExportOptions, type SerializedImageEditorState, type AIResultOptions, type ImagePoint, type AdjustmentKind, type AdjustmentLayerInit, type AdjustmentLayerUpdate, type ImageHistogram } from '@pixerate/editor/image-editor';
|
|
2
3
|
export declare function createReactiveImageEditor(options?: ImageEditorOptions): {
|
|
3
4
|
readonly controller: ImageEditorController;
|
|
4
5
|
readonly state: ImageEditorState;
|
|
@@ -68,4 +69,11 @@ export declare function createImageHistogram(controller: ImageEditorController):
|
|
|
68
69
|
readonly current: ImageHistogram | null;
|
|
69
70
|
destroy(): void;
|
|
70
71
|
};
|
|
72
|
+
/**
|
|
73
|
+
* Registers the image editor's provider-effect tools (`search_effects`, `describe_effect`,
|
|
74
|
+
* `apply_effect`, `add_effect_layer`, …) for the lifetime of the calling component. They work once
|
|
75
|
+
* an effects provider is registered (see `useEffects`); before that the read tools say so and the
|
|
76
|
+
* write tools refuse.
|
|
77
|
+
*/
|
|
78
|
+
export declare function useImageEffectsTools(registry: ToolRegistry | null | undefined | (() => ToolRegistry | null | undefined), controller: ImageEditorController, options?: ImageEffectsToolProviderOptions): void;
|
|
71
79
|
//# sourceMappingURL=imageEditorState.svelte.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"imageEditorState.svelte.d.ts","sourceRoot":"","sources":["../../src/image-editor/imageEditorState.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,
|
|
1
|
+
{"version":3,"file":"imageEditorState.svelte.d.ts","sourceRoot":"","sources":["../../src/image-editor/imageEditorState.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EACL,qBAAqB,EAErB,KAAK,+BAA+B,EACpC,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,uBAAuB,EAC5B,KAAK,aAAa,EAClB,KAAK,0BAA0B,EAC/B,KAAK,eAAe,EACpB,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,cAAc,EACpB,MAAM,+BAA+B,CAAC;AAEvC,wBAAgB,yBAAyB,CAAC,OAAO,GAAE,kBAAuB;;;;IA2BtE,mGAAmG;;;kBAQrF,eAAe;kBAGf,OAAO,GAAG,IAAI;2BAGL,WAAW;;oBAMlB,MAAM;yBAGD,MAAM;;;4BASH,OAAO,CAAC,gBAAgB,CAAC;;IAMjD,oGAAoG;;IAIpG,mEAAmE;6BAC1C,cAAc,GAAG,mBAAmB,UAAU,MAAM;8BAGnD,MAAM,UAAU,qBAAqB;8BAGrC,MAAM;4BAGR,MAAM,WAAW,MAAM;8BAGrB,MAAM,YAAY,OAAO;0BAG7B,OAAO,CAAC,gBAAgB,CAAC;;uBAM5B,uBAAuB;yBAGrB,MAAM,WAAW,OAAO,CAAC,UAAU,CAAC;yBAGpC,MAAM;;yBAMN,MAAM,GAAG,IAAI;;;;oBAYlB,MAAM;qBAGL,MAAM;;kBAMT,MAAM;gBAGR,UAAU;4BAGE,OAAO;gBAGnB,cAAc;mBAGX,MAAM,GAAG,gBAAgB;qBAGvB,aAAa;kBAGhB,aAAa;;mBAMZ,0BAA0B;sBAGvB;QAAE,cAAc,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE;yBAG5C;QAAE,cAAc,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE;2BAG7C,IAAI,CAAC,aAAa,EAAE,QAAQ,GAAG,SAAS,CAAC;IAGhE,kGAAkG;oCAClE,MAAM,YAAY,eAAe;IAGjE,6GAA6G;4CACrE,MAAM,YAAY,eAAe;IAGzE,8EAA8E;;EAMjF;AAED,MAAM,MAAM,mBAAmB,GAAG,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE/E,6GAA6G;AAC7G,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,qBAAqB;;;EAarE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,GAAG,CAAC,MAAM,YAAY,GAAG,IAAI,GAAG,SAAS,CAAC,EACnF,UAAU,EAAE,qBAAqB,EACjC,OAAO,GAAE,+BAAoC,GAC5C,IAAI,CAMN"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ImageEditorController, } from '@pixerate/editor/image-editor';
|
|
1
|
+
import { ImageEditorController, createImageEffectsToolProvider, } from '@pixerate/editor/image-editor';
|
|
2
2
|
export function createReactiveImageEditor(options = {}) {
|
|
3
3
|
const controller = new ImageEditorController(options);
|
|
4
4
|
let state = $state(controller.getState());
|
|
@@ -186,3 +186,17 @@ export function createImageHistogram(controller) {
|
|
|
186
186
|
},
|
|
187
187
|
};
|
|
188
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* Registers the image editor's provider-effect tools (`search_effects`, `describe_effect`,
|
|
191
|
+
* `apply_effect`, `add_effect_layer`, …) for the lifetime of the calling component. They work once
|
|
192
|
+
* an effects provider is registered (see `useEffects`); before that the read tools say so and the
|
|
193
|
+
* write tools refuse.
|
|
194
|
+
*/
|
|
195
|
+
export function useImageEffectsTools(registry, controller, options = {}) {
|
|
196
|
+
$effect(() => {
|
|
197
|
+
const target = typeof registry === 'function' ? registry() : registry;
|
|
198
|
+
if (!target)
|
|
199
|
+
return;
|
|
200
|
+
return target.register(createImageEffectsToolProvider(controller, options));
|
|
201
|
+
});
|
|
202
|
+
}
|