@pixerate/editor 0.241.0 → 0.242.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.
Files changed (41) hide show
  1. package/dist/animation-editor/controller.d.cts +10 -0
  2. package/dist/animation-editor/controller.d.ts +10 -0
  3. package/dist/animation-editor/effects.d.cts +1 -1
  4. package/dist/animation-editor/effects.d.ts +1 -1
  5. package/dist/animation-editor/index.cjs +137 -88
  6. package/dist/animation-editor/index.js +60 -11
  7. package/dist/canvas/index.cjs +7 -7
  8. package/dist/canvas/index.js +1 -1
  9. package/dist/{chunk-A7PQNIBX.cjs → chunk-7V7QMFTI.cjs} +14 -14
  10. package/dist/{chunk-JAOSL334.cjs → chunk-GHCSC2WP.cjs} +38 -16
  11. package/dist/{chunk-JWCKJNDR.cjs → chunk-K5DS2JTA.cjs} +6 -6
  12. package/dist/{chunk-WDDUPWVG.js → chunk-L3JFOTBQ.js} +1 -1
  13. package/dist/{chunk-SIK3LT6M.js → chunk-OFH6Q67U.js} +28 -6
  14. package/dist/{chunk-G3RUKJ5C.js → chunk-RXZL4NG5.js} +1 -1
  15. package/dist/{chunk-TEFQISBY.js → chunk-X3ZINLIP.js} +1 -1
  16. package/dist/{chunk-ZQIWBJGH.cjs → chunk-XNZFVYC2.cjs} +7 -7
  17. package/dist/effects/fake.d.cts +4 -0
  18. package/dist/effects/fake.d.ts +4 -0
  19. package/dist/effects/helpers.d.cts +6 -0
  20. package/dist/effects/helpers.d.ts +6 -0
  21. package/dist/effects/index.cjs +222 -94
  22. package/dist/effects/index.js +131 -3
  23. package/dist/effects/types.d.cts +31 -0
  24. package/dist/effects/types.d.ts +31 -0
  25. package/dist/image-editor/index.cjs +13 -13
  26. package/dist/image-editor/index.js +1 -1
  27. package/dist/paint-editor/index.cjs +7 -7
  28. package/dist/paint-editor/index.js +2 -2
  29. package/dist/vector/index.cjs +6 -6
  30. package/dist/vector/index.js +1 -1
  31. package/dist/video-editor/controller.d.cts +49 -1
  32. package/dist/video-editor/controller.d.ts +49 -1
  33. package/dist/video-editor/effect-path.d.cts +66 -0
  34. package/dist/video-editor/effect-path.d.ts +66 -0
  35. package/dist/video-editor/index.cjs +616 -427
  36. package/dist/video-editor/index.d.cts +1 -0
  37. package/dist/video-editor/index.d.ts +1 -0
  38. package/dist/video-editor/index.js +193 -4
  39. package/package.json +1 -1
  40. package/skills/pixerate-animation-editor/SKILL.md +1 -1
  41. package/skills/pixerate-video-editor/SKILL.md +9 -2
@@ -3,7 +3,7 @@ import {
3
3
  } from "../chunk-N4ZXW3WB.js";
4
4
  import {
5
5
  createEffectAuthoringSession
6
- } from "../chunk-TEFQISBY.js";
6
+ } from "../chunk-X3ZINLIP.js";
7
7
  import {
8
8
  EFFECT_LAYER_USES,
9
9
  EFFECT_SEQUENCE_NAME,
@@ -28,16 +28,18 @@ import {
28
28
  templateSlotTakes,
29
29
  templateValueProblem,
30
30
  templateValuesSchema
31
- } from "../chunk-G3RUKJ5C.js";
31
+ } from "../chunk-RXZL4NG5.js";
32
32
  import {
33
33
  EffectRendererPool
34
34
  } from "../chunk-EHLOCVWB.js";
35
35
  import {
36
36
  CAMERA_MOVE_MAX_MS,
37
37
  CAMERA_MOVE_ROLES,
38
+ EFFECT_ACCEPTS,
38
39
  EFFECT_ERROR_CODES,
39
40
  EFFECT_KINDS,
40
41
  EFFECT_LAYER_ROLES,
42
+ EFFECT_PATH_FORMAT,
41
43
  EFFECT_SUBJECT_KINDS,
42
44
  EFFECT_TEMPLATE_SLOT_TYPES,
43
45
  EFFECT_TRANSITION_MS,
@@ -69,13 +71,14 @@ import {
69
71
  isEffectPixels,
70
72
  linearToSrgb,
71
73
  normaliseEffectTag,
74
+ pathControlsOf,
72
75
  resolveCameraMoveSpec,
73
76
  resolveEffectValues,
74
77
  sampleCameraViews,
75
78
  sampleEffectCameraMove,
76
79
  searchEffectSummaries,
77
80
  srgbToLinear
78
- } from "../chunk-SIK3LT6M.js";
81
+ } from "../chunk-OFH6Q67U.js";
79
82
  import "../chunk-V2ZCJRDM.js";
80
83
  import "../chunk-RNSANXPT.js";
81
84
  import {
@@ -105,6 +108,7 @@ function checkSummary(e, issues) {
105
108
  if (typeof e.loop !== "boolean") at("loop is not a boolean");
106
109
  if (e.duration !== void 0 && !(e.duration > 0)) at("duration must be a positive number of ms when present");
107
110
  if (e.backgroundOpacity !== void 0 && (typeof e.backgroundOpacity !== "string" || !e.backgroundOpacity)) at("backgroundOpacity must name a control when present");
111
+ for (const a of e.accepts ?? []) if (!EFFECT_ACCEPTS.includes(a)) at(`accepts "${a}" is not one of ${EFFECT_ACCEPTS.join(", ")}`);
108
112
  if (e.kind === "camera") {
109
113
  if (e.uses?.length !== 1 || e.uses[0] !== "camera") at('a camera effect must have exactly the use "camera"');
110
114
  const m = e.camera;
@@ -136,6 +140,9 @@ function checkDescription(id, d, issues) {
136
140
  if (!control) at(`backgroundOpacity "${d.backgroundOpacity}" is not a control`);
137
141
  else if (control.type !== "number" || control.minimum !== 0 || control.maximum !== 1) at(`backgroundOpacity "${d.backgroundOpacity}" must be a number control from 0 to 1`);
138
142
  }
143
+ const paths = pathControlsOf(d);
144
+ if (paths.length && !d.accepts?.includes("path")) at(`controls ${paths.map((p) => `"${p}"`).join(", ")} take a path, but accepts does not list "path"`);
145
+ if (!paths.length && d.accepts?.includes("path")) at('accepts lists "path", but no control has format "svg-path"');
139
146
  for (const e of effectValueErrors(d, d.defaults)) at(`default ${e.path}: ${e.message}`);
140
147
  for (const p of d.presets ?? []) for (const e of effectValueErrors(d, p.values)) at(`preset "${p.name}" ${e.path}: ${e.message}`);
141
148
  for (const input2 of d.inputs ?? []) {
@@ -547,6 +554,13 @@ function fakeTemplateMethods() {
547
554
  var HEX = "^#[0-9a-fA-F]{6}$";
548
555
  var colour = (description) => ({ type: "string", pattern: HEX, description });
549
556
  var amount = (description) => ({ type: "number", minimum: 0, maximum: 1, description });
557
+ var pathControl = (what) => ({
558
+ description: `${what}: SVG path data (fitted into the frame, contain, 8% margin), or points [x0, y0, x1, y1, \u2026] in frame pixels from the top left (used as given), or "" for none.`,
559
+ anyOf: [
560
+ { type: "string", format: "svg-path", description: 'SVG path data, or "" for no path.' },
561
+ { type: "array", items: { type: "number", description: "x or y, frame pixels." }, description: "Points x0, y0, x1, y1, \u2026 in frame pixels." }
562
+ ]
563
+ });
550
564
  var DESCRIPTIONS = [
551
565
  {
552
566
  id: "fake.invert",
@@ -711,8 +725,77 @@ var DESCRIPTIONS = [
711
725
  defaults: { color: "#f43f5e", ms: 500 },
712
726
  presets: [],
713
727
  inputs: []
728
+ },
729
+ {
730
+ id: "fake.trail",
731
+ name: "Trail",
732
+ kind: "shader",
733
+ category: "path",
734
+ uses: ["overlay"],
735
+ description: "A line drawn along its path control over transparency; with no path, a line across the middle.",
736
+ tags: ["path", "line"],
737
+ transparent: true,
738
+ loop: false,
739
+ accepts: ["path"],
740
+ controls: {
741
+ type: "object",
742
+ additionalProperties: false,
743
+ properties: {
744
+ path: pathControl("Where the line runs"),
745
+ color: colour("Line colour as #rrggbb. Default #22d3ee."),
746
+ width: { type: "number", minimum: 1, maximum: 64, description: "Line width in pixels. Default 6." }
747
+ }
748
+ },
749
+ defaults: { path: "", color: "#22d3ee", width: 6 },
750
+ presets: [],
751
+ inputs: []
752
+ },
753
+ {
754
+ id: "fake.route",
755
+ name: "Route",
756
+ kind: "vector",
757
+ category: "path",
758
+ uses: ["title"],
759
+ description: "A vector line along its path control, its picture fitted to the path (viewBox = the path bounds); with no path, a short wave.",
760
+ tags: ["path", "route"],
761
+ transparent: true,
762
+ loop: false,
763
+ duration: 400,
764
+ accepts: ["path"],
765
+ controls: {
766
+ type: "object",
767
+ additionalProperties: false,
768
+ properties: {
769
+ path: pathControl("The route"),
770
+ color: colour("Line colour as #rrggbb. Default #f59e0b.")
771
+ }
772
+ },
773
+ defaults: { path: "", color: "#f59e0b" },
774
+ presets: [],
775
+ inputs: []
714
776
  }
715
777
  ];
778
+ function pathNumbers(d) {
779
+ return [...d.matchAll(/-?\d*\.?\d+(?:e[-+]?\d+)?/gi)].map((m) => Number(m[0]));
780
+ }
781
+ function framePoints(value, width, height, fallback) {
782
+ if (Array.isArray(value)) return value.length >= 4 ? value : fallback;
783
+ if (typeof value !== "string" || !value.trim()) return fallback;
784
+ const n = pathNumbers(value);
785
+ if (n.length < 4) return fallback;
786
+ let x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;
787
+ for (let i = 0; i + 1 < n.length; i += 2) {
788
+ x0 = Math.min(x0, n[i]);
789
+ x1 = Math.max(x1, n[i]);
790
+ y0 = Math.min(y0, n[i + 1]);
791
+ y1 = Math.max(y1, n[i + 1]);
792
+ }
793
+ const m = 0.08;
794
+ const k = Math.min(width * (1 - 2 * m) / Math.max(1e-9, x1 - x0), height * (1 - 2 * m) / Math.max(1e-9, y1 - y0));
795
+ const ox = (width - (x1 - x0) * k) / 2 - x0 * k;
796
+ const oy = (height - (y1 - y0) * k) / 2 - y0 * k;
797
+ return n.map((v, i) => i % 2 ? v * k + oy : v * k + ox);
798
+ }
716
799
  var CAMERA_DESCRIPTIONS = [
717
800
  {
718
801
  id: "fake.glide",
@@ -831,6 +914,29 @@ function renderPixels(d, v, request, width, height) {
831
914
  }
832
915
  break;
833
916
  }
917
+ case "fake.trail": {
918
+ const rgb = hexToRgb(v.color);
919
+ const pts = framePoints(v.path, width, height, [0, height / 2, width, height / 2]);
920
+ const r = v.width / 2;
921
+ for (let i = 0; i + 3 < pts.length; i += 2) {
922
+ const [ax, ay, bx, by] = [pts[i], pts[i + 1], pts[i + 2], pts[i + 3]];
923
+ const steps = Math.max(1, Math.ceil(Math.hypot(bx - ax, by - ay)));
924
+ for (let s = 0; s <= steps; s++) {
925
+ const cx = ax + (bx - ax) * s / steps;
926
+ const cy = ay + (by - ay) * s / steps;
927
+ for (let y = Math.max(0, Math.floor(cy - r)); y <= Math.min(height - 1, Math.ceil(cy + r)); y++)
928
+ for (let x = Math.max(0, Math.floor(cx - r)); x <= Math.min(width - 1, Math.ceil(cx + r)); x++) {
929
+ if ((x + 0.5 - cx) ** 2 + (y + 0.5 - cy) ** 2 > r * r) continue;
930
+ const i4 = (y * width + x) * 4;
931
+ o[i4] = rgb[0];
932
+ o[i4 + 1] = rgb[1];
933
+ o[i4 + 2] = rgb[2];
934
+ o[i4 + 3] = 255;
935
+ }
936
+ }
937
+ }
938
+ break;
939
+ }
834
940
  case "fake.bar": {
835
941
  const rgb = hexToRgb(v.color);
836
942
  const slide = v.slide;
@@ -983,10 +1089,29 @@ function createFakeEffectProvider(options = {}) {
983
1089
  }
984
1090
  };
985
1091
  },
1092
+ pathFromText(text, opts) {
1093
+ if (typeof text !== "string" || !text.trim()) throw new EffectUnsupportedError("There are no words to write; pass some text.");
1094
+ if (opts?.font !== void 0 && opts.font !== "zig") throw new EffectUnsupportedError(`The fake provider has no font "${opts.font}"; its only font is "zig".`);
1095
+ return [...text].map((_, i) => `M${i * 10} 10 L${i * 10 + 3} 0 L${i * 10 + 6} 10`).join(" ");
1096
+ },
986
1097
  applyVectorEffect(id, target, values) {
987
1098
  const d = get(id);
988
1099
  if (d.kind !== "motion" && d.kind !== "vector") throw new EffectUnsupportedError(`"${id}" is a ${d.kind} effect, not a vector one.`, id);
989
1100
  const v = resolveEffectValues(d, values);
1101
+ if (d.id === "fake.route") {
1102
+ const pts = Array.isArray(v.path) && v.path.length >= 4 ? v.path : typeof v.path === "string" && pathNumbers(v.path).length >= 4 ? pathNumbers(v.path) : [0, 20, 25, 0, 50, 20, 75, 40, 100, 20];
1103
+ const xs = pts.filter((_, i) => i % 2 === 0);
1104
+ const ys = pts.filter((_, i) => i % 2 === 1);
1105
+ const [x0, y0] = [Math.min(...xs), Math.min(...ys)];
1106
+ const [w, h] = [Math.max(1, Math.max(...xs) - x0), Math.max(1, Math.max(...ys) - y0)];
1107
+ const dpath = "M" + pts.map((p) => +p.toFixed(3)).join(" ").replace(/^(\S+ \S+) /, "$1 L");
1108
+ return {
1109
+ svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${x0} ${y0} ${w} ${h}" width="${w}" height="${h}"><path id="route" d="${dpath}" fill="none" stroke="${v.color}" stroke-width="2"/></svg>`,
1110
+ animate: [{ id: "route", ms: 400, attrs: { opacity: [0, 1] } }],
1111
+ duration: 400,
1112
+ loop: false
1113
+ };
1114
+ }
990
1115
  if (d.kind === "vector") {
991
1116
  return { svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100"><circle id="badge" cx="50" cy="50" r="40" fill="${v.color}"/></svg>`, animate: [{ id: "badge", ms: v.ms, attrs: { opacity: [0, 1] } }], duration: v.ms, loop: false };
992
1117
  }
@@ -1537,10 +1662,12 @@ function createEffectAuthoringToolProvider(host, options) {
1537
1662
  export {
1538
1663
  CAMERA_MOVE_MAX_MS,
1539
1664
  CAMERA_MOVE_ROLES,
1665
+ EFFECT_ACCEPTS,
1540
1666
  EFFECT_ERROR_CODES,
1541
1667
  EFFECT_KINDS,
1542
1668
  EFFECT_LAYER_ROLES,
1543
1669
  EFFECT_LAYER_USES,
1670
+ EFFECT_PATH_FORMAT,
1544
1671
  EFFECT_SEQUENCE_NAME,
1545
1672
  EFFECT_SUBJECT_KINDS,
1546
1673
  EFFECT_TEMPLATE_SLOT_TYPES,
@@ -1601,6 +1728,7 @@ export {
1601
1728
  isSubjectTemplateSlot,
1602
1729
  linearToSrgb,
1603
1730
  normaliseEffectTag,
1731
+ pathControlsOf,
1604
1732
  renderEffectThumbnail,
1605
1733
  resolveCameraMoveSpec,
1606
1734
  resolveEffectValues,
@@ -76,6 +76,29 @@ export interface EffectSummary {
76
76
  backgroundOpacity?: string;
77
77
  /** How a `camera` effect moves. Present exactly when `kind` is `camera`. */
78
78
  camera?: EffectCameraMove;
79
+ /**
80
+ * What it takes besides pictures, for search: `path` when a control draws along a path given at
81
+ * run time (`pathControlsOf` names them). Present exactly when it takes one.
82
+ */
83
+ accepts?: readonly EffectAccept[];
84
+ }
85
+ /** What an effect can take besides pictures: `path`, a control that draws along a path given at run time. */
86
+ export type EffectAccept = 'path';
87
+ export declare const EFFECT_ACCEPTS: readonly EffectAccept[];
88
+ /**
89
+ * The JSON Schema `format` of a path control: a string of SVG path data (fitted into the frame as
90
+ * the control's description says), a flat list of numbers `[x0, y0, x1, y1, …]` in frame pixels
91
+ * from the top left (used as given), or `""` for no path.
92
+ */
93
+ export declare const EFFECT_PATH_FORMAT = "svg-path";
94
+ /** A path control's value: SVG path data, points in frame pixels, or `""` for none. */
95
+ export type EffectPathValue = string | readonly number[];
96
+ /** How `pathFromText` writes words. */
97
+ export interface EffectTextPathOptions {
98
+ /** A font the provider offers for single-stroke writing (its own names, e.g. `script`, `sans`); default its first. */
99
+ font?: string;
100
+ /** Where the line sits in its box (default `start`). */
101
+ align?: 'start' | 'middle' | 'end';
79
102
  }
80
103
  export interface EffectSearchOptions {
81
104
  kind?: EffectKind;
@@ -85,6 +108,8 @@ export interface EffectSearchOptions {
85
108
  tags?: readonly string[];
86
109
  /** Most results to return. */
87
110
  limit?: number;
111
+ /** Only effects that take every one of these (e.g. `['path']`: effects that draw along a path). */
112
+ accepts?: readonly EffectAccept[];
88
113
  }
89
114
  /** One control value: a number, a `#rrggbb` colour or other string, a switch, or a vector of numbers. */
90
115
  export type EffectValue = number | string | boolean | readonly number[];
@@ -524,6 +549,12 @@ export interface EffectProvider {
524
549
  * effect cannot use with `EffectUnsupportedError`.
525
550
  */
526
551
  applyVectorEffect?(id: string, target: EffectVectorTarget, values?: EffectValues): MaybePromise<EffectVectorMotion>;
552
+ /**
553
+ * Words as single-stroke SVG path data, for a path control (an effect that writes a name along
554
+ * its path). Optional: editors refuse words when it is missing. Throws `EffectUnsupportedError`
555
+ * for a font it does not have.
556
+ */
557
+ pathFromText?(text: string, options?: EffectTextPathOptions): MaybePromise<string>;
527
558
  /**
528
559
  * Opens an effect for editing. Present when `capabilities.supportsAuthoring`. Unknown ids throw
529
560
  * `UnknownEffectError`; an effect the provider cannot edit throws `EffectUnsupportedError`.
@@ -76,6 +76,29 @@ export interface EffectSummary {
76
76
  backgroundOpacity?: string;
77
77
  /** How a `camera` effect moves. Present exactly when `kind` is `camera`. */
78
78
  camera?: EffectCameraMove;
79
+ /**
80
+ * What it takes besides pictures, for search: `path` when a control draws along a path given at
81
+ * run time (`pathControlsOf` names them). Present exactly when it takes one.
82
+ */
83
+ accepts?: readonly EffectAccept[];
84
+ }
85
+ /** What an effect can take besides pictures: `path`, a control that draws along a path given at run time. */
86
+ export type EffectAccept = 'path';
87
+ export declare const EFFECT_ACCEPTS: readonly EffectAccept[];
88
+ /**
89
+ * The JSON Schema `format` of a path control: a string of SVG path data (fitted into the frame as
90
+ * the control's description says), a flat list of numbers `[x0, y0, x1, y1, …]` in frame pixels
91
+ * from the top left (used as given), or `""` for no path.
92
+ */
93
+ export declare const EFFECT_PATH_FORMAT = "svg-path";
94
+ /** A path control's value: SVG path data, points in frame pixels, or `""` for none. */
95
+ export type EffectPathValue = string | readonly number[];
96
+ /** How `pathFromText` writes words. */
97
+ export interface EffectTextPathOptions {
98
+ /** A font the provider offers for single-stroke writing (its own names, e.g. `script`, `sans`); default its first. */
99
+ font?: string;
100
+ /** Where the line sits in its box (default `start`). */
101
+ align?: 'start' | 'middle' | 'end';
79
102
  }
80
103
  export interface EffectSearchOptions {
81
104
  kind?: EffectKind;
@@ -85,6 +108,8 @@ export interface EffectSearchOptions {
85
108
  tags?: readonly string[];
86
109
  /** Most results to return. */
87
110
  limit?: number;
111
+ /** Only effects that take every one of these (e.g. `['path']`: effects that draw along a path). */
112
+ accepts?: readonly EffectAccept[];
88
113
  }
89
114
  /** One control value: a number, a `#rrggbb` colour or other string, a switch, or a vector of numbers. */
90
115
  export type EffectValue = number | string | boolean | readonly number[];
@@ -524,6 +549,12 @@ export interface EffectProvider {
524
549
  * effect cannot use with `EffectUnsupportedError`.
525
550
  */
526
551
  applyVectorEffect?(id: string, target: EffectVectorTarget, values?: EffectValues): MaybePromise<EffectVectorMotion>;
552
+ /**
553
+ * Words as single-stroke SVG path data, for a path control (an effect that writes a name along
554
+ * its path). Optional: editors refuse words when it is missing. Throws `EffectUnsupportedError`
555
+ * for a font it does not have.
556
+ */
557
+ pathFromText?(text: string, options?: EffectTextPathOptions): MaybePromise<string>;
527
558
  /**
528
559
  * Opens an effect for editing. Present when `capabilities.supportsAuthoring`. Unknown ids throw
529
560
  * `UnknownEffectError`; an effect the provider cannot edit throws `EffectUnsupportedError`.
@@ -748,7 +748,7 @@ var _chunkPY4GWSE2cjs = require('../chunk-PY4GWSE2.cjs');
748
748
 
749
749
 
750
750
 
751
- var _chunkJAOSL334cjs = require('../chunk-JAOSL334.cjs');
751
+ var _chunkGHCSC2WPcjs = require('../chunk-GHCSC2WP.cjs');
752
752
  require('../chunk-WOFXZ3XU.cjs');
753
753
 
754
754
 
@@ -4837,7 +4837,7 @@ function checkImageEffectPlace(d, place) {
4837
4837
  const allowed = IMAGE_EFFECT_PLACES[place];
4838
4838
  if (d.kind === "motion" || !d.uses.some((u) => allowed.includes(u))) {
4839
4839
  const instead = place === "filter" && d.uses.some((u) => IMAGE_EFFECT_PLACES.layer.includes(u)) ? "; add it as an effect layer with add_effect_layer instead" : place === "layer" && d.uses.includes("filter") ? "; apply it to a layer as a smart filter with apply_effect instead" : "";
4840
- throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(
4840
+ throw new (0, _chunkGHCSC2WPcjs.EffectUnsupportedError)(
4841
4841
  `"${d.id}" (${d.name}) is a ${d.uses.join(" / ")} effect, and ${place === "filter" ? "a smart filter takes filter effects" : "an effect layer takes generator, overlay or title effects"}${instead}.`,
4842
4842
  d.id
4843
4843
  );
@@ -4861,9 +4861,9 @@ function effectPixelsToSurface(p, depth) {
4861
4861
  const d = new Uint16Array(f.length);
4862
4862
  const code = (v) => v > 0 ? v < 1 ? Math.round(v * 65535) : 65535 : 0;
4863
4863
  for (let i = 0; i < f.length; i += 4) {
4864
- d[i] = code(_chunkJAOSL334cjs.linearToSrgb.call(void 0, f[i]));
4865
- d[i + 1] = code(_chunkJAOSL334cjs.linearToSrgb.call(void 0, f[i + 1]));
4866
- d[i + 2] = code(_chunkJAOSL334cjs.linearToSrgb.call(void 0, f[i + 2]));
4864
+ d[i] = code(_chunkGHCSC2WPcjs.linearToSrgb.call(void 0, f[i]));
4865
+ d[i + 1] = code(_chunkGHCSC2WPcjs.linearToSrgb.call(void 0, f[i + 1]));
4866
+ d[i + 2] = code(_chunkGHCSC2WPcjs.linearToSrgb.call(void 0, f[i + 2]));
4867
4867
  d[i + 3] = code(f[i + 3]);
4868
4868
  }
4869
4869
  return _chunkOLNIPTB3cjs.surfaceFromDeepPixels.call(void 0, { width: p.width, height: p.height, data: d }, 4);
@@ -4880,7 +4880,7 @@ var ImageEffectsEngine = (_class9 = class {
4880
4880
  __init49() {this.generation = 0}
4881
4881
 
4882
4882
  constructor(options = {}) {;_class9.prototype.__init44.call(this);_class9.prototype.__init45.call(this);_class9.prototype.__init46.call(this);_class9.prototype.__init47.call(this);_class9.prototype.__init48.call(this);_class9.prototype.__init49.call(this);
4883
- this.slot = _nullishCoalesce(options.slot, () => ( new (0, _chunkJAOSL334cjs.EffectsSlot)()));
4883
+ this.slot = _nullishCoalesce(options.slot, () => ( new (0, _chunkGHCSC2WPcjs.EffectsSlot)()));
4884
4884
  this.maxEntries = _nullishCoalesce(options.maxEntries, () => ( 24));
4885
4885
  this.pool = new (0, _chunkPY4GWSE2cjs.EffectRendererPool)({ maxRenderers: options.maxRenderers });
4886
4886
  this.detach = this.slot.subscribe(() => {
@@ -4940,7 +4940,7 @@ var ImageEffectsEngine = (_class9 = class {
4940
4940
  const provider = this.slot.require();
4941
4941
  const depth = _nullishCoalesce(size.depth, () => ( 8));
4942
4942
  const out = await this.render(provider, effect, size.width, size.height, depth, { time: _nullishCoalesce(size.time, () => ( 0)), values });
4943
- return out.width === size.width && out.height === size.height ? out : _chunkJAOSL334cjs.createEffectPixels.call(void 0, size.width, size.height);
4943
+ return out.width === size.width && out.height === size.height ? out : _chunkGHCSC2WPcjs.createEffectPixels.call(void 0, size.width, size.height);
4944
4944
  }
4945
4945
  /** Why the result for `key` failed, if it did. */
4946
4946
  failure(key2) {
@@ -6202,7 +6202,7 @@ var ImageEditorController = (_class12 = class {
6202
6202
  __init84() {this.selectionWorker = null}
6203
6203
  __init85() {this.documentOpener = null}
6204
6204
  /** The effects provider slot (see `setEffectsProvider`). */
6205
- __init86() {this.effects = new (0, _chunkJAOSL334cjs.EffectsSlot)()}
6205
+ __init86() {this.effects = new (0, _chunkGHCSC2WPcjs.EffectsSlot)()}
6206
6206
  /** Renders provider effects: effect smart filter results and effect layers. */
6207
6207
  __init87() {this.effectsEngine = new ImageEffectsEngine({ slot: this.effects })}
6208
6208
  __init88() {this.effectRefresh = "none"}
@@ -6538,7 +6538,7 @@ var ImageEditorController = (_class12 = class {
6538
6538
  */
6539
6539
  async applyEffectFilter(layerId, effect, options = {}) {
6540
6540
  const d = await this.describeEffect(effect, "filter");
6541
- const values = _chunkJAOSL334cjs.resolveEffectValues.call(void 0, d, options.values);
6541
+ const values = _chunkGHCSC2WPcjs.resolveEffectValues.call(void 0, d, options.values);
6542
6542
  const found = _chunkHB4ICNNAcjs.findLayer.call(void 0, this.state.layers, layerId);
6543
6543
  if (!found) throw new (0, _chunkHW72ABGRcjs.LayerOperationError)(`There is no layer "${layerId}"; call list_layers for the layer ids.`);
6544
6544
  let layers = this.state.layers;
@@ -6580,7 +6580,7 @@ var ImageEditorController = (_class12 = class {
6580
6580
  else if (k in d.controls.properties) base[k] = d.defaults[k];
6581
6581
  else throw new (0, _chunkHW72ABGRcjs.LayerOperationError)(`"${k}" is not a control of "${d.id}"; its controls are ${Object.keys(d.controls.properties).join(", ")}.`);
6582
6582
  }
6583
- update.values = { ...base, ..._chunkJAOSL334cjs.resolveEffectValues.call(void 0, { ...d, defaults: base }, given) };
6583
+ update.values = { ...base, ..._chunkGHCSC2WPcjs.resolveEffectValues.call(void 0, { ...d, defaults: base }, given) };
6584
6584
  }
6585
6585
  for (const k of ["enabled", "blend", "opacity", "preserveTransparency"]) if (changes[k] !== void 0) update[k] = changes[k];
6586
6586
  let res = _chunkHW72ABGRcjs.updateSmartFilter.call(void 0, this.state.layers, layerId, filterId, update, this.canvasSize);
@@ -6607,7 +6607,7 @@ var ImageEditorController = (_class12 = class {
6607
6607
  const id = options.id && !ids.has(options.id) ? options.id : _chunkHW72ABGRcjs.newLayerId.call(void 0, );
6608
6608
  const placed = _chunkHW72ABGRcjs.placeLayer.call(void 0, this.state.layers, { type: "pixel", id, name: "", visible: true, opacity: 1, blend: "normal", surface: _chunk474IQG74cjs.emptySurface.call(void 0, 4), offset: { x: 0, y: 0 } }, this.newLayerPlacement(options));
6609
6609
  if (options.clipped) requireClipBase(placed, id);
6610
- const values = _chunkJAOSL334cjs.resolveEffectValues.call(void 0, d, withBackgroundOpacity(d, options.values, hasLayersBelow(placed, id)));
6610
+ const values = _chunkGHCSC2WPcjs.resolveEffectValues.call(void 0, d, withBackgroundOpacity(d, options.values, hasLayersBelow(placed, id)));
6611
6611
  const { width, height } = this.naturalSize;
6612
6612
  const pixels = await this.effectsEngine.renderLayer(d.id, values, { width, height, depth: this.bitDepth, time });
6613
6613
  const layer = {
@@ -6652,7 +6652,7 @@ var ImageEditorController = (_class12 = class {
6652
6652
  else if (k in d.controls.properties) base[k] = d.defaults[k];
6653
6653
  else throw new (0, _chunkHW72ABGRcjs.LayerOperationError)(`"${k}" is not a control of "${d.id}"; its controls are ${Object.keys(d.controls.properties).join(", ")}.`);
6654
6654
  }
6655
- const values = { ...base, ..._chunkJAOSL334cjs.resolveEffectValues.call(void 0, { ...d, defaults: base }, given) };
6655
+ const values = { ...base, ..._chunkGHCSC2WPcjs.resolveEffectValues.call(void 0, { ...d, defaults: base }, given) };
6656
6656
  const time = changes.time === void 0 ? _nullishCoalesce(g.time, () => ( 0)) : checkEffectTime(changes.time);
6657
6657
  const animate = changes.animate === void 0 ? g.animate : changes.animate === null ? void 0 : checkEffectAnimation(changes.animate);
6658
6658
  const { width, height } = this.naturalSize;
@@ -21973,7 +21973,7 @@ function createImageEffectsToolProvider(controller, options = {}) {
21973
21973
  return { target, effect: _nullishCoalesce(effects.find((e) => e.id === instance), () => ( effects[effects.length - 1])), effects, ...extra };
21974
21974
  };
21975
21975
  const plainValues = (v) => v;
21976
- return withImagePlayback(_chunkJAOSL334cjs.createEffectToolProvider.call(void 0, {
21976
+ return withImagePlayback(_chunkGHCSC2WPcjs.createEffectToolProvider.call(void 0, {
21977
21977
  id: _nullishCoalesce(options.id, () => ( "image-effects")),
21978
21978
  namespace: options.namespace,
21979
21979
  title: "Image effects",
@@ -748,7 +748,7 @@ import {
748
748
  createEffectToolProvider,
749
749
  linearToSrgb,
750
750
  resolveEffectValues
751
- } from "../chunk-SIK3LT6M.js";
751
+ } from "../chunk-OFH6Q67U.js";
752
752
  import "../chunk-V2ZCJRDM.js";
753
753
  import {
754
754
  BrushstrokeCache,
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7; var _class8; var _class9; var _class10; var _class11; var _class12;
2
2
 
3
- var _chunkZQIWBJGHcjs = require('../chunk-ZQIWBJGH.cjs');
3
+ var _chunkXNZFVYC2cjs = require('../chunk-XNZFVYC2.cjs');
4
4
 
5
5
 
6
6
 
@@ -143,7 +143,7 @@ var _chunkPY4GWSE2cjs = require('../chunk-PY4GWSE2.cjs');
143
143
 
144
144
 
145
145
 
146
- var _chunkJAOSL334cjs = require('../chunk-JAOSL334.cjs');
146
+ var _chunkGHCSC2WPcjs = require('../chunk-GHCSC2WP.cjs');
147
147
  require('../chunk-WOFXZ3XU.cjs');
148
148
 
149
149
 
@@ -3286,7 +3286,7 @@ function timeLapseVideo(frameCount, width, height, fps, holdMs, name = "Time-lap
3286
3286
  }
3287
3287
  const video = { version: 1, name, width: w, height: h, fps, background: "#000000", assets, tracks: [{ id: "v1", kind: "video", clips }] };
3288
3288
  const durationMs = frameCount ? clips[clips.length - 1].start + clips[clips.length - 1].duration : 0;
3289
- return { video, ffmpeg: _chunkZQIWBJGHcjs.toVideoFfmpeg.call(void 0, video, { output: "timelapse.mp4" }), durationMs };
3289
+ return { video, ffmpeg: _chunkXNZFVYC2cjs.toVideoFfmpeg.call(void 0, video, { output: "timelapse.mp4" }), durationMs };
3290
3290
  }
3291
3291
  async function buildTimeLapse(source, target, options = {}) {
3292
3292
  const maxSide = Math.max(32, Math.min(4096, Math.round(_nullishCoalesce(options.maxSide, () => ( 720)))));
@@ -3369,7 +3369,7 @@ function checkPaintEffectPlace(d, place) {
3369
3369
  else if (d.uses.includes("filter") && place !== "light") instead = "; run it on a layer's dried paint with apply_effect instead";
3370
3370
  else if (place === "light" && d.uses.some((u) => PAINT_EFFECT_PLACES.layer.includes(u))) instead = "; add it as an effect layer (add_effect_layer) or fill a layer with it (fill_layer_with_effect) instead";
3371
3371
  else if (place === "paper" && d.uses.some((u) => u === "overlay" || u === "title")) instead = "; add it as an effect layer with add_effect_layer instead";
3372
- throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`"${d.id}" (${d.name}) is a ${d.uses.join(" / ") || d.kind} effect, and ${PLACE_WORDS[place]}${instead}.`, d.id);
3372
+ throw new (0, _chunkGHCSC2WPcjs.EffectUnsupportedError)(`"${d.id}" (${d.name}) is a ${d.uses.join(" / ") || d.kind} effect, and ${PLACE_WORDS[place]}${instead}.`, d.id);
3373
3373
  }
3374
3374
  var PAPER_EFFECT_BLENDS = ["multiply", "normal", "overlay", "soft-light", "screen", "color"];
3375
3375
  var paperVersion = 1;
@@ -3568,7 +3568,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
3568
3568
  /** Set while an operation that changes wet paint runs: the simulation before it (for undo). */
3569
3569
  __init117() {this.wetOp = null}
3570
3570
  /** The effects provider slot (see `setEffectsProvider`). */
3571
- __init118() {this.effects = new (0, _chunkJAOSL334cjs.EffectsSlot)()}
3571
+ __init118() {this.effects = new (0, _chunkGHCSC2WPcjs.EffectsSlot)()}
3572
3572
  __init119() {this.effectsRenderer = new PaintEffectsRenderer()}
3573
3573
  __init120() {this.paperEffectNodeCache = null}
3574
3574
  constructor(options = {}) {;_class10.prototype.__init74.call(this);_class10.prototype.__init75.call(this);_class10.prototype.__init76.call(this);_class10.prototype.__init77.call(this);_class10.prototype.__init78.call(this);_class10.prototype.__init79.call(this);_class10.prototype.__init80.call(this);_class10.prototype.__init81.call(this);_class10.prototype.__init82.call(this);_class10.prototype.__init83.call(this);_class10.prototype.__init84.call(this);_class10.prototype.__init85.call(this);_class10.prototype.__init86.call(this);_class10.prototype.__init87.call(this);_class10.prototype.__init88.call(this);_class10.prototype.__init89.call(this);_class10.prototype.__init90.call(this);_class10.prototype.__init91.call(this);_class10.prototype.__init92.call(this);_class10.prototype.__init93.call(this);_class10.prototype.__init94.call(this);_class10.prototype.__init95.call(this);_class10.prototype.__init96.call(this);_class10.prototype.__init97.call(this);_class10.prototype.__init98.call(this);_class10.prototype.__init99.call(this);_class10.prototype.__init100.call(this);_class10.prototype.__init101.call(this);_class10.prototype.__init102.call(this);_class10.prototype.__init103.call(this);_class10.prototype.__init104.call(this);_class10.prototype.__init105.call(this);_class10.prototype.__init106.call(this);_class10.prototype.__init107.call(this);_class10.prototype.__init108.call(this);_class10.prototype.__init109.call(this);_class10.prototype.__init110.call(this);_class10.prototype.__init111.call(this);_class10.prototype.__init112.call(this);_class10.prototype.__init113.call(this);_class10.prototype.__init114.call(this);_class10.prototype.__init115.call(this);_class10.prototype.__init116.call(this);_class10.prototype.__init117.call(this);_class10.prototype.__init118.call(this);_class10.prototype.__init119.call(this);_class10.prototype.__init120.call(this);_class10.prototype.__init121.call(this);_class10.prototype.__init122.call(this);_class10.prototype.__init123.call(this);_class10.prototype.__init124.call(this);
@@ -4252,7 +4252,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
4252
4252
  if (v === null) merged[k] = d.defaults[k];
4253
4253
  else given[k] = v;
4254
4254
  }
4255
- return { ...merged, ..._chunkJAOSL334cjs.resolveEffectValues.call(void 0, { ...d, defaults: merged }, given) };
4255
+ return { ...merged, ..._chunkGHCSC2WPcjs.resolveEffectValues.call(void 0, { ...d, defaults: merged }, given) };
4256
4256
  }
4257
4257
  /** Renders a generator, overlay or title effect at the canvas size. */
4258
4258
  renderEffectCanvas(d, values, time = 0) {
@@ -9903,7 +9903,7 @@ function createPaintEffectsToolProvider(controller, options = {}) {
9903
9903
  if (changes.enabled !== void 0) throw new Error("enabled does not apply here: hide an effect layer with update_layer visible false, or remove the effect paper.");
9904
9904
  };
9905
9905
  const values = (v) => v;
9906
- return withPaintPlayback(_chunkJAOSL334cjs.createEffectToolProvider.call(void 0, {
9906
+ return withPaintPlayback(_chunkGHCSC2WPcjs.createEffectToolProvider.call(void 0, {
9907
9907
  id: _nullishCoalesce(options.id, () => ( "paint-effects")),
9908
9908
  namespace: options.namespace,
9909
9909
  title: "Paint effects",
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  toVideoFfmpeg
3
- } from "../chunk-WDDUPWVG.js";
3
+ } from "../chunk-L3JFOTBQ.js";
4
4
  import {
5
5
  deserializeLayers,
6
6
  exportPsd,
@@ -143,7 +143,7 @@ import {
143
143
  EffectsSlot,
144
144
  createEffectToolProvider,
145
145
  resolveEffectValues
146
- } from "../chunk-SIK3LT6M.js";
146
+ } from "../chunk-OFH6Q67U.js";
147
147
  import "../chunk-V2ZCJRDM.js";
148
148
  import {
149
149
  CoverageMap,
@@ -558,7 +558,7 @@ var _chunkNM3G4VQTcjs = require('../chunk-NM3G4VQT.cjs');
558
558
 
559
559
 
560
560
 
561
- var _chunkJAOSL334cjs = require('../chunk-JAOSL334.cjs');
561
+ var _chunkGHCSC2WPcjs = require('../chunk-GHCSC2WP.cjs');
562
562
  require('../chunk-WOFXZ3XU.cjs');
563
563
 
564
564
 
@@ -7329,7 +7329,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
7329
7329
  }
7330
7330
  // --- Provider effects ---
7331
7331
  /** The effects provider slot (see `setEffectsProvider`). */
7332
- __init59() {this.effects = new (0, _chunkJAOSL334cjs.EffectsSlot)()}
7332
+ __init59() {this.effects = new (0, _chunkGHCSC2WPcjs.EffectsSlot)()}
7333
7333
  /** The registered effects provider, or `null`. */
7334
7334
  get effectsProvider() {
7335
7335
  return this.effects.provider;
@@ -7353,10 +7353,10 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
7353
7353
  /** The effect's picture as group children, scaled into `box` (an affine fit). */
7354
7354
  async vectorEffectPicture(effect, values) {
7355
7355
  const provider = this.effects.require();
7356
- if (!provider.applyVectorEffect) throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`${provider.name} has no vector effects.`);
7356
+ if (!provider.applyVectorEffect) throw new (0, _chunkGHCSC2WPcjs.EffectUnsupportedError)(`${provider.name} has no vector effects.`);
7357
7357
  const d = await provider.describe(effect);
7358
- if (d.kind !== "vector") throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`"${d.id}" (${d.name}) is a ${d.kind} effect; the vector editor adds vector effects, which bring their own picture${d.kind === "motion" ? " (apply motion in the animation editor)" : ""}.`, d.id);
7359
- const resolved = _chunkJAOSL334cjs.resolveEffectValues.call(void 0, d, values);
7358
+ if (d.kind !== "vector") throw new (0, _chunkGHCSC2WPcjs.EffectUnsupportedError)(`"${d.id}" (${d.name}) is a ${d.kind} effect; the vector editor adds vector effects, which bring their own picture${d.kind === "motion" ? " (apply motion in the animation editor)" : ""}.`, d.id);
7359
+ const resolved = _chunkGHCSC2WPcjs.resolveEffectValues.call(void 0, d, values);
7360
7360
  const motion = await provider.applyVectorEffect(d.id, this.toSvg(), resolved);
7361
7361
  const parsed = _chunkKCMV2534cjs.parseVectorSvg.call(void 0, motion.svg);
7362
7362
  if (!parsed.nodes.length) throw new Error(`"${d.name}" drew no shapes the editor can read.`);
@@ -18173,7 +18173,7 @@ function createVectorEffectsToolProvider(controller, options = {}) {
18173
18173
  const effects = _optionalChain([g, 'optionalAccess', _765 => _765.providerEffect]) ? [info(g)] : [];
18174
18174
  return { target: id, effect: _nullishCoalesce(removed, () => ( effects[0])), effects };
18175
18175
  };
18176
- return _chunkJAOSL334cjs.createEffectToolProvider.call(void 0, {
18176
+ return _chunkGHCSC2WPcjs.createEffectToolProvider.call(void 0, {
18177
18177
  id: _nullishCoalesce(options.id, () => ( "vector-effects")),
18178
18178
  namespace: options.namespace,
18179
18179
  title: "Vector effects",
@@ -558,7 +558,7 @@ import {
558
558
  EffectsSlot,
559
559
  createEffectToolProvider,
560
560
  resolveEffectValues
561
- } from "../chunk-SIK3LT6M.js";
561
+ } from "../chunk-OFH6Q67U.js";
562
562
  import "../chunk-V2ZCJRDM.js";
563
563
  import {
564
564
  GRAIN_PATTERNS