@pixerate/editor-svelte 0.87.0 → 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/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/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/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/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 +3 -0
- package/dist/image-editor/index.d.ts.map +1 -1
- package/dist/image-editor/index.js +1 -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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createCanvasAnimation.svelte.d.ts","sourceRoot":"","sources":["../../src/canvas/createCanvasAnimation.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,KAAK,EACV,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,4BAA4B,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU;IAClF,QAAQ,EAAE,MAAM,KAAK,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;IACnC,mDAAmD;IACnD,OAAO,CAAC,EAAE,sBAAsB,CAAC;IACjC,gFAAgF;IAChF,cAAc,CAAC,EAAE,MAAM,MAAM,EAAE,CAAC;IAChC,+FAA+F;IAC/F,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAC3C,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,EAAE,OAAO,EAAE,4BAA4B,CAAC,KAAK,CAAC;;;;;;;;;;kBA2DnG,KAAK,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"createCanvasAnimation.svelte.d.ts","sourceRoot":"","sources":["../../src/canvas/createCanvasAnimation.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,KAAK,EACV,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,4BAA4B,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU;IAClF,QAAQ,EAAE,MAAM,KAAK,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;IACnC,mDAAmD;IACnD,OAAO,CAAC,EAAE,sBAAsB,CAAC;IACjC,gFAAgF;IAChF,cAAc,CAAC,EAAE,MAAM,MAAM,EAAE,CAAC;IAChC,+FAA+F;IAC/F,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAC3C,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,EAAE,OAAO,EAAE,4BAA4B,CAAC,KAAK,CAAC;;;;;;;;;;kBA2DnG,KAAK,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAa6o2G,CAAC;;;;;;;;;;;YAAg/C,CAAC;mBAA8B,CAAC;;;;;;;YAAmjB,CAAC;gBAA0B,CAAC;;;EAHzw6G;AAED,MAAM,MAAM,qBAAqB,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,IAAI,UAAU,CAAC,OAAO,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createCanvasArrange.svelte.d.ts","sourceRoot":"","sources":["../../src/canvas/createCanvasArrange.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,8BAA8B,EACnC,KAAK,SAAS,EACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,KAAK,WAAW,GAAG,8BAA8B,CAAC,GAAG,CAAC,CAAC;AAEvD,MAAM,WAAW,0BAA0B,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,CAChF,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,UAAU,GAAG,gBAAgB,CAAC;IACrE,QAAQ,EAAE,MAAM,KAAK,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;CAC/C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,EACxE,OAAO,EAAE,0BAA0B,CAAC,KAAK,CAAC;;IAkBzC;;;;;OAKG;wBACiB,MAAM;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"createCanvasArrange.svelte.d.ts","sourceRoot":"","sources":["../../src/canvas/createCanvasArrange.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,8BAA8B,EACnC,KAAK,SAAS,EACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,KAAK,WAAW,GAAG,8BAA8B,CAAC,GAAG,CAAC,CAAC;AAEvD,MAAM,WAAW,0BAA0B,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,CAChF,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,UAAU,GAAG,gBAAgB,CAAC;IACrE,QAAQ,EAAE,MAAM,KAAK,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;CAC/C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,EACxE,OAAO,EAAE,0BAA0B,CAAC,KAAK,CAAC;;IAkBzC;;;;;OAKG;wBACiB,MAAM;;;;;;;;;;sBAoDqnxD,CAAC;sBAAiE,CAAC;sBAAiE,CAAC;oBAA+D,CAAC;cAAyD,CAAC;gBAAiD,CAAC;;;;;;;;;0BAA8tC,CAAC;;yBAA6kB,CAAC;;0BAAgf,CAAC;;;;;;;;;;EAxC/t2D;AAED,MAAM,MAAM,aAAa,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,IAAI,UAAU,CAAC,OAAO,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC;AAEjH,MAAM,WAAW,6BAA6B;IAC7C,OAAO,EAAE;QAAE,SAAS,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,OAAO,CAAA;KAAE,CAAC;IACjE,uEAAuE;IACvE,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,OAAO,CAAA;KAAE,CAAC;IAC1D,aAAa,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IACrC,QAAQ,CAAC,EAAE,SAAS,sBAAsB,EAAE,CAAC;CAC7C;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,6BAA6B,GAAG,MAAM,IAAI,CAqB/F"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createCanvasAutoLayout.svelte.d.ts","sourceRoot":"","sources":["../../src/canvas/createCanvasAutoLayout.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,iCAAiC,EACtC,KAAK,SAAS,EACd,KAAK,kBAAkB,EACvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,KAAK,WAAW,GAAG,iCAAiC,CAAC,GAAG,CAAC,CAAC;AAE1D,MAAM,WAAW,6BAA6B,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,CACnF,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,UAAU,GAAG,gBAAgB,CAAC;IACrE,QAAQ,EAAE,MAAM,KAAK,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;CAC/C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,EAAE,OAAO,EAAE,6BAA6B,CAAC,KAAK,CAAC;;;IA+BzH,2FAA2F;kBAC7E,OAAO,SAAS,kBAAkB,WAAW,OAAO,EAAE,GAAG,OAAO,EAAE;IAKhF,gFAAgF;0BAC1D,QAAQ,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAIjE,4EAA4E;iBAC/D,MAAM;IAInB;;;OAGG;wBACiB,MAAM;;;;;;;;
|
|
1
|
+
{"version":3,"file":"createCanvasAutoLayout.svelte.d.ts","sourceRoot":"","sources":["../../src/canvas/createCanvasAutoLayout.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,iCAAiC,EACtC,KAAK,SAAS,EACd,KAAK,kBAAkB,EACvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,KAAK,WAAW,GAAG,iCAAiC,CAAC,GAAG,CAAC,CAAC;AAE1D,MAAM,WAAW,6BAA6B,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,CACnF,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,UAAU,GAAG,gBAAgB,CAAC;IACrE,QAAQ,EAAE,MAAM,KAAK,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;CAC/C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,EAAE,OAAO,EAAE,6BAA6B,CAAC,KAAK,CAAC;;;IA+BzH,2FAA2F;kBAC7E,OAAO,SAAS,kBAAkB,WAAW,OAAO,EAAE,GAAG,OAAO,EAAE;IAKhF,gFAAgF;0BAC1D,QAAQ,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAIjE,4EAA4E;iBAC/D,MAAM;IAInB;;;OAGG;wBACiB,MAAM;;;;;;;;aAiBusvE,CAAC;;;;aAAiX,CAAC;cAAwB,CAAC;;;;;;;;;;gBAAqrD,CAAC;;;;EAHpyzE;AAED,MAAM,MAAM,gBAAgB,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,IAAI,UAAU,CAAC,OAAO,sBAAsB,CAAC,KAAK,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createCanvasComponents.svelte.d.ts","sourceRoot":"","sources":["../../src/canvas/createCanvasComponents.svelte.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,KAAK,iCAAiC,EACtC,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,KAAK,WAAW,GAAG,iCAAiC,CAAC,GAAG,CAAC,CAAC;AAE1D,MAAM,WAAW,6BAA6B,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,CACnF,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;IAC/D,QAAQ,EAAE,MAAM,KAAK,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;IACnC,oFAAoF;IACpF,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,EAAE,OAAO,EAAE,6BAA6B,CAAC,KAAK,CAAC;IAazH,gCAAgC;;;;;
|
|
1
|
+
{"version":3,"file":"createCanvasComponents.svelte.d.ts","sourceRoot":"","sources":["../../src/canvas/createCanvasComponents.svelte.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,KAAK,iCAAiC,EACtC,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,KAAK,WAAW,GAAG,iCAAiC,CAAC,GAAG,CAAC,CAAC;AAE1D,MAAM,WAAW,6BAA6B,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,CACnF,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;IAC/D,QAAQ,EAAE,MAAM,KAAK,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;IACnC,oFAAoF;IACpF,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,EAAE,OAAO,EAAE,6BAA6B,CAAC,KAAK,CAAC;IAazH,gCAAgC;;;;;4BASmwsI,CAAC;;UAAmM,CAAC;YAAsB,CAAC;eAAyB,CAAC;;8BAA8E,CAAC;;;;;;;;;;6BAA4nC,CAAC;;;;;;;;eAA6yB,CAAC;;;;;;;oBAAi7B,CAAC;;;;;;;;;;;;;;gBAA07C,CAAC;;EAHj41I;AAED,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { effectFieldValue, effectParameterFields, type EffectDescription } from '@pixerate/editor/effects';
|
|
3
|
+
import { parameterLabel, parameterValuesEqual, type ParameterValue } from '@pixerate/editor/parameters';
|
|
4
|
+
import ParameterFieldControl from '../parameters/ParameterFieldControl.svelte';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
/** The effect's description (`describe`). */
|
|
8
|
+
description: EffectDescription;
|
|
9
|
+
/** Its saved values; controls left out show their defaults. */
|
|
10
|
+
values: Readonly<Record<string, unknown>>;
|
|
11
|
+
/**
|
|
12
|
+
* A control changed. While a slider or colour drag is under way `gesture` is a key unique to
|
|
13
|
+
* that drag, so the host can fold its changes into one undo step; otherwise `null`.
|
|
14
|
+
*/
|
|
15
|
+
onchange: (control: string, value: ParameterValue, gesture: string | null) => void;
|
|
16
|
+
/** Resets one control to its default. */
|
|
17
|
+
onreset?: (control: string) => void;
|
|
18
|
+
/** Controls that are keyframed: shown read-only with a note (edit them as keyframes). */
|
|
19
|
+
keyframed?: ReadonlySet<string>;
|
|
20
|
+
/** Applies a preset's values. */
|
|
21
|
+
onpreset?: (values: Readonly<Record<string, unknown>>) => void;
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
class?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let { description, values, onchange, onreset, keyframed, onpreset, disabled = false, class: className = '' }: Props = $props();
|
|
27
|
+
const fields = $derived(effectParameterFields(description));
|
|
28
|
+
const idBase = `fx-${Math.random().toString(36).slice(2, 8)}`;
|
|
29
|
+
let gesture: string | null = null;
|
|
30
|
+
let count = 0;
|
|
31
|
+
function preset(name: string) {
|
|
32
|
+
const p = description.presets.find((x) => x.name === name);
|
|
33
|
+
if (p) onpreset?.({ ...description.defaults, ...p.values });
|
|
34
|
+
}
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<!--
|
|
38
|
+
The parameter panel of an effect, generated from its JSON Schema controls: sliders for bounded
|
|
39
|
+
numbers, switches, choices, colour pickers, vectors and text, with each control's description,
|
|
40
|
+
per-control reset and the effect's presets.
|
|
41
|
+
-->
|
|
42
|
+
<div class="space-y-2 {className}" data-effect-parameters={description.id}>
|
|
43
|
+
{#if onpreset && description.presets.length > 0}
|
|
44
|
+
<select class="w-full rounded border border-border bg-transparent px-1 py-0.5 text-xs" aria-label="{description.name} presets" value="" {disabled} onchange={(e) => preset(e.currentTarget.value)}>
|
|
45
|
+
<option value="">Presets…</option>
|
|
46
|
+
{#each description.presets as p (p.name)}<option value={p.name}>{p.name}</option>{/each}
|
|
47
|
+
</select>
|
|
48
|
+
{/if}
|
|
49
|
+
{#each fields as field (field.id)}
|
|
50
|
+
{@const label = parameterLabel(field)}
|
|
51
|
+
{@const keyed = keyframed?.has(field.id) ?? false}
|
|
52
|
+
{@const value = effectFieldValue(field, values[field.id])}
|
|
53
|
+
<div class="space-y-1" data-effect-control={field.id}>
|
|
54
|
+
<div class="flex items-center gap-1.5">
|
|
55
|
+
<label for="{idBase}-{field.id}" class="min-w-0 flex-1 truncate text-xs font-medium" title={field.description}>{label}</label>
|
|
56
|
+
{#if keyed}<span class="text-[10px] text-muted-foreground">keyframed</span>{/if}
|
|
57
|
+
{#if onreset && !keyed && !disabled && !parameterValuesEqual(value, field.default)}
|
|
58
|
+
<button type="button" class="rounded px-1 text-[11px] text-muted-foreground hover:text-foreground" aria-label="Reset {label}" onclick={() => onreset(field.id)}>↺</button>
|
|
59
|
+
{/if}
|
|
60
|
+
</div>
|
|
61
|
+
<ParameterFieldControl
|
|
62
|
+
{field}
|
|
63
|
+
{value}
|
|
64
|
+
id="{idBase}-{field.id}"
|
|
65
|
+
disabled={disabled || keyed}
|
|
66
|
+
onchange={(v) => onchange(field.id, v, gesture)}
|
|
67
|
+
ongesturestart={() => (gesture = `${idBase}:${field.id}:${++count}`)}
|
|
68
|
+
ongestureend={() => (gesture = null)}
|
|
69
|
+
/>
|
|
70
|
+
</div>
|
|
71
|
+
{/each}
|
|
72
|
+
{#if !fields.length}<p class="text-[11px] text-muted-foreground">No controls.</p>{/if}
|
|
73
|
+
</div>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type EffectDescription } from '@pixerate/editor/effects';
|
|
2
|
+
import { type ParameterValue } from '@pixerate/editor/parameters';
|
|
3
|
+
interface Props {
|
|
4
|
+
/** The effect's description (`describe`). */
|
|
5
|
+
description: EffectDescription;
|
|
6
|
+
/** Its saved values; controls left out show their defaults. */
|
|
7
|
+
values: Readonly<Record<string, unknown>>;
|
|
8
|
+
/**
|
|
9
|
+
* A control changed. While a slider or colour drag is under way `gesture` is a key unique to
|
|
10
|
+
* that drag, so the host can fold its changes into one undo step; otherwise `null`.
|
|
11
|
+
*/
|
|
12
|
+
onchange: (control: string, value: ParameterValue, gesture: string | null) => void;
|
|
13
|
+
/** Resets one control to its default. */
|
|
14
|
+
onreset?: (control: string) => void;
|
|
15
|
+
/** Controls that are keyframed: shown read-only with a note (edit them as keyframes). */
|
|
16
|
+
keyframed?: ReadonlySet<string>;
|
|
17
|
+
/** Applies a preset's values. */
|
|
18
|
+
onpreset?: (values: Readonly<Record<string, unknown>>) => void;
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
class?: string;
|
|
21
|
+
}
|
|
22
|
+
declare const EffectParameters: import("svelte").Component<Props, {}, "">;
|
|
23
|
+
type EffectParameters = ReturnType<typeof EffectParameters>;
|
|
24
|
+
export default EffectParameters;
|
|
25
|
+
//# sourceMappingURL=EffectParameters.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EffectParameters.svelte.d.ts","sourceRoot":"","sources":["../../src/effects/EffectParameters.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EAA2C,KAAK,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC3G,OAAO,EAAwC,KAAK,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAItG,UAAU,KAAK;IACb,6CAA6C;IAC7C,WAAW,EAAE,iBAAiB,CAAC;IAC/B,+DAA+D;IAC/D,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1C;;;OAGG;IACH,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACnF,yCAAyC;IACzC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,yFAAyF;IACzF,SAAS,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,iCAAiC;IACjC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,IAAI,CAAC;IAC/D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA8CH,QAAA,MAAM,gBAAgB,2CAAwC,CAAC;AAC/D,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC5D,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { renderEffectThumbnail, type EffectProvider, type EffectSummary } from '@pixerate/editor/effects';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
provider: EffectProvider;
|
|
6
|
+
effect: EffectSummary;
|
|
7
|
+
/** Pixel size of the preview (default 96 × 54). */
|
|
8
|
+
width?: number;
|
|
9
|
+
height?: number;
|
|
10
|
+
class?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let { provider, effect: item, width = 96, height = 54, class: className = '' }: Props = $props();
|
|
14
|
+
let canvas = $state<HTMLCanvasElement | null>(null);
|
|
15
|
+
let failed = $state(false);
|
|
16
|
+
|
|
17
|
+
$effect(() => {
|
|
18
|
+
failed = item.kind === 'motion';
|
|
19
|
+
if (failed) return;
|
|
20
|
+
let live = true;
|
|
21
|
+
renderEffectThumbnail(provider, item, { width, height }).then(
|
|
22
|
+
(pixels) => {
|
|
23
|
+
const ctx = live ? canvas?.getContext('2d') : null;
|
|
24
|
+
if (!ctx || typeof ImageData === 'undefined') return;
|
|
25
|
+
ctx.putImageData(new ImageData(new Uint8ClampedArray(pixels.data), pixels.width, pixels.height), 0, 0);
|
|
26
|
+
},
|
|
27
|
+
() => {
|
|
28
|
+
if (live) failed = true;
|
|
29
|
+
},
|
|
30
|
+
);
|
|
31
|
+
return () => {
|
|
32
|
+
live = false;
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<!-- A preview of an effect drawn by the provider's own renderer; motion effects and failures show a label. -->
|
|
38
|
+
<div
|
|
39
|
+
class="relative overflow-hidden rounded border border-border bg-[repeating-conic-gradient(#8884_0_25%,transparent_0_50%)] bg-[length:12px_12px] {className}"
|
|
40
|
+
style="aspect-ratio: {width} / {height}"
|
|
41
|
+
data-effect-thumbnail={item.id}
|
|
42
|
+
>
|
|
43
|
+
{#if failed}
|
|
44
|
+
<span class="absolute inset-0 flex items-center justify-center text-[10px] text-muted-foreground">{item.kind === 'motion' ? 'Motion' : 'No preview'}</span>
|
|
45
|
+
{:else}
|
|
46
|
+
<canvas bind:this={canvas} {width} {height} class="h-full w-full" aria-hidden="true"></canvas>
|
|
47
|
+
{/if}
|
|
48
|
+
</div>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type EffectProvider, type EffectSummary } from '@pixerate/editor/effects';
|
|
2
|
+
interface Props {
|
|
3
|
+
provider: EffectProvider;
|
|
4
|
+
effect: EffectSummary;
|
|
5
|
+
/** Pixel size of the preview (default 96 × 54). */
|
|
6
|
+
width?: number;
|
|
7
|
+
height?: number;
|
|
8
|
+
class?: string;
|
|
9
|
+
}
|
|
10
|
+
declare const EffectThumbnail: import("svelte").Component<Props, {}, "">;
|
|
11
|
+
type EffectThumbnail = ReturnType<typeof EffectThumbnail>;
|
|
12
|
+
export default EffectThumbnail;
|
|
13
|
+
//# sourceMappingURL=EffectThumbnail.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EffectThumbnail.svelte.d.ts","sourceRoot":"","sources":["../../src/effects/EffectThumbnail.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EAAyB,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAGxG,UAAU,KAAK;IACb,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,EAAE,aAAa,CAAC;IACtB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAwCH,QAAA,MAAM,eAAe,2CAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
|
|
@@ -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"}
|
|
@@ -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"}
|