@pixerate/editor 0.231.1 → 0.233.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 (62) hide show
  1. package/dist/animation-editor/compile.d.cts +3 -0
  2. package/dist/animation-editor/compile.d.ts +3 -0
  3. package/dist/animation-editor/controller.d.cts +67 -2
  4. package/dist/animation-editor/controller.d.ts +67 -2
  5. package/dist/animation-editor/edit.d.cts +1 -1
  6. package/dist/animation-editor/edit.d.ts +1 -1
  7. package/dist/animation-editor/evaluate.d.cts +8 -1
  8. package/dist/animation-editor/evaluate.d.ts +8 -1
  9. package/dist/animation-editor/index.cjs +1202 -371
  10. package/dist/animation-editor/index.d.cts +3 -0
  11. package/dist/animation-editor/index.d.ts +3 -0
  12. package/dist/animation-editor/index.js +1032 -201
  13. package/dist/animation-editor/issues.d.cts +28 -0
  14. package/dist/animation-editor/issues.d.ts +28 -0
  15. package/dist/animation-editor/layer-edit.d.cts +55 -0
  16. package/dist/animation-editor/layer-edit.d.ts +55 -0
  17. package/dist/animation-editor/layer-tools.d.cts +11 -0
  18. package/dist/animation-editor/layer-tools.d.ts +11 -0
  19. package/dist/animation-editor/layers.d.cts +166 -0
  20. package/dist/animation-editor/layers.d.ts +166 -0
  21. package/dist/animation-editor/parse.d.cts +2 -0
  22. package/dist/animation-editor/parse.d.ts +2 -0
  23. package/dist/animation-editor/types.d.cts +44 -1
  24. package/dist/animation-editor/types.d.ts +44 -1
  25. package/dist/canvas/index.cjs +10 -10
  26. package/dist/canvas/index.js +4 -4
  27. package/dist/chunk-6RZVFYGJ.cjs +255 -0
  28. package/dist/{chunk-C73U5UI3.cjs → chunk-A7PQNIBX.cjs} +14 -14
  29. package/dist/{chunk-ERJA5CGT.cjs → chunk-DGWOGQJ5.cjs} +8 -1
  30. package/dist/{chunk-TYCJGFCF.js → chunk-EUKY4KFX.js} +8 -1
  31. package/dist/chunk-I277KJLQ.js +255 -0
  32. package/dist/{chunk-OPSK22DL.cjs → chunk-JAOSL334.cjs} +24 -7
  33. package/dist/{chunk-TCZ2J7PR.js → chunk-SIK3LT6M.js} +26 -9
  34. package/dist/{chunk-SBPGIZQN.js → chunk-TEFQISBY.js} +1 -1
  35. package/dist/{chunk-CSM5T6SE.js → chunk-WDDUPWVG.js} +1 -1
  36. package/dist/{chunk-5T3H7CGG.cjs → chunk-ZQIWBJGH.cjs} +7 -7
  37. package/dist/effects/conformance.d.cts +4 -1
  38. package/dist/effects/conformance.d.ts +4 -1
  39. package/dist/effects/errors.d.cts +6 -1
  40. package/dist/effects/errors.d.ts +6 -1
  41. package/dist/effects/fake-templates.d.cts +17 -0
  42. package/dist/effects/fake-templates.d.ts +17 -0
  43. package/dist/effects/fake.d.cts +6 -1
  44. package/dist/effects/fake.d.ts +6 -1
  45. package/dist/effects/index.cjs +322 -67
  46. package/dist/effects/index.d.cts +1 -0
  47. package/dist/effects/index.d.ts +1 -0
  48. package/dist/effects/index.js +258 -3
  49. package/dist/effects/templates.d.cts +56 -0
  50. package/dist/effects/templates.d.ts +56 -0
  51. package/dist/effects/types.d.cts +212 -0
  52. package/dist/effects/types.d.ts +212 -0
  53. package/dist/image-editor/index.cjs +16 -16
  54. package/dist/image-editor/index.js +4 -4
  55. package/dist/paint-editor/index.cjs +10 -10
  56. package/dist/paint-editor/index.js +5 -5
  57. package/dist/vector/index.cjs +6 -6
  58. package/dist/vector/index.js +1 -1
  59. package/dist/video-editor/index.cjs +339 -339
  60. package/dist/video-editor/index.js +5 -5
  61. package/package.json +1 -1
  62. package/skills/pixerate-animation-editor/SKILL.md +37 -0
@@ -0,0 +1,255 @@
1
+ import {
2
+ EFFECT_LAYER_ROLES,
3
+ hasEffectTags
4
+ } from "./chunk-SIK3LT6M.js";
5
+
6
+ // src/effects/templates.ts
7
+ var SLOT_NAME = /^[A-Za-z][\w-]*$/;
8
+ var COLOR = /^#[0-9a-fA-F]{6}$/;
9
+ var EFFECT_SEQUENCE_NAME = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
10
+ var isObject = (v) => !!v && typeof v === "object" && !Array.isArray(v);
11
+ var isSubjectTemplateSlot = (slot) => slot.type === "image" || slot.type === "video" || slot.type === "svg";
12
+ function effectSubjectKind(subject) {
13
+ if (!isObject(subject)) return void 0;
14
+ for (const k of ["slot", "image", "video", "svg", "text"]) if (typeof subject[k] === "string") return k;
15
+ return void 0;
16
+ }
17
+ var typeName = (value) => value === null ? "null" : Array.isArray(value) ? "a list" : typeof value === "object" ? "an object" : typeof value === "string" ? `the words ${JSON.stringify(value.length > 40 ? `${value.slice(0, 40)}\u2026` : value)}` : `${typeof value === "number" ? "the number" : "the value"} ${String(value)}`;
18
+ function range(slot) {
19
+ const whole = slot.integer ? "whole number" : "number";
20
+ if (slot.min !== void 0 && slot.max !== void 0) return `a ${whole} from ${slot.min} to ${slot.max}`;
21
+ if (slot.min !== void 0) return `a ${whole} of at least ${slot.min}`;
22
+ if (slot.max !== void 0) return `a ${whole} of at most ${slot.max}`;
23
+ return `a ${whole}`;
24
+ }
25
+ function templateSlotTakes(slot) {
26
+ switch (slot.type) {
27
+ case "text":
28
+ return `words${slot.maxLength !== void 0 ? ` (up to ${slot.maxLength} characters)` : ""}`;
29
+ case "color":
30
+ return `a colour written #RRGGBB, like "${slot.default}"`;
31
+ case "number":
32
+ return range(slot);
33
+ case "video":
34
+ return "a video URL";
35
+ case "svg":
36
+ return "SVG markup or an SVG URL";
37
+ default:
38
+ return "a picture: a URL, a data: URL or <svg> markup";
39
+ }
40
+ }
41
+ function templateValueProblem(slot, value) {
42
+ const no = (extra = "") => `Slot "${slot.name}" takes ${templateSlotTakes(slot)}${extra}, not ${typeName(value)}.`;
43
+ switch (slot.type) {
44
+ case "text":
45
+ if (typeof value !== "string") return no();
46
+ if (slot.maxLength !== void 0 && value.length > slot.maxLength) return `Slot "${slot.name}" takes up to ${slot.maxLength} characters; the value has ${value.length}. Shorten it.`;
47
+ return void 0;
48
+ case "color":
49
+ return typeof value === "string" && COLOR.test(value) ? void 0 : no();
50
+ case "number":
51
+ if (typeof value !== "number" || !Number.isFinite(value)) return no();
52
+ if (slot.integer && !Number.isInteger(value)) return `Slot "${slot.name}" takes ${range(slot)}; ${value} is not whole.`;
53
+ if (slot.min !== void 0 && value < slot.min || slot.max !== void 0 && value > slot.max) return `Slot "${slot.name}" takes ${range(slot)}; ${value} is out of range.`;
54
+ return void 0;
55
+ default: {
56
+ const host = ` (or { "slot": "${slot.name}" } to leave it for the host)`;
57
+ if (typeof value === "string") return value.trim() ? void 0 : no(host);
58
+ const kind = effectSubjectKind(value);
59
+ if (!kind) return no(host);
60
+ if (kind === "slot") return SLOT_NAME.test(value.slot) ? void 0 : `Slot "${slot.name}" left for the host is { "slot": name }, the name letters, digits, "-" and "_", starting with a letter.`;
61
+ const fits = kind === slot.type || slot.type === "image" && kind === "svg";
62
+ if (!fits) return `Slot "${slot.name}" takes { "${slot.type}": \u2026 }${slot.type === "image" ? ' or { "svg": \u2026 }' : ""}, not { "${kind}": \u2026 }.`;
63
+ return value[kind].trim() ? void 0 : `Slot "${slot.name}"'s "${kind}" is a non-empty string.`;
64
+ }
65
+ }
66
+ }
67
+ var slotList = (slots) => slots.length ? `the slots are ${slots.map((s) => `${s.name} (${s.type})`).join(", ")}` : "the template has no slots";
68
+ function checkTemplateValues(slots, values) {
69
+ if (values === void 0) return [];
70
+ if (!isObject(values)) return [`Values are an object of slot names to values; ${slotList(slots)}.`];
71
+ const byName = new Map(slots.map((s) => [s.name, s]));
72
+ const errors = [];
73
+ for (const [name, value] of Object.entries(values)) {
74
+ const slot = byName.get(name);
75
+ if (!slot) errors.push(`There is no slot "${name}"; ${slotList(slots)}.`);
76
+ else if (value !== void 0) {
77
+ const problem = templateValueProblem(slot, value);
78
+ if (problem) errors.push(problem);
79
+ }
80
+ }
81
+ return errors;
82
+ }
83
+ function templateSlotSchema(slot) {
84
+ const about = `${slot.label}${slot.description ? `: ${slot.description}` : ""}.`;
85
+ switch (slot.type) {
86
+ case "text":
87
+ return { type: "string", ...slot.maxLength !== void 0 ? { maxLength: slot.maxLength } : {}, description: `${about} Words${slot.maxLength !== void 0 ? `, up to ${slot.maxLength} characters` : ""}. Default ${JSON.stringify(slot.default)}.` };
88
+ case "color":
89
+ return { type: "string", pattern: COLOR.source, description: `${about} A colour as #RRGGBB. Default ${slot.default}.` };
90
+ case "number":
91
+ return {
92
+ type: slot.integer ? "integer" : "number",
93
+ ...slot.min !== void 0 ? { minimum: slot.min } : {},
94
+ ...slot.max !== void 0 ? { maximum: slot.max } : {},
95
+ description: `${about} ${range(slot).replace(/^a /, "A ")}. Default ${slot.default}.`
96
+ };
97
+ default: {
98
+ const key = slot.type;
99
+ const object = (k, what) => ({ type: "object", properties: { [k]: { type: "string", description: what } }, required: [k], additionalProperties: false, description: `{ "${k}": \u2026 }` });
100
+ return {
101
+ anyOf: [
102
+ { type: "string", minLength: 1, description: key === "video" ? "A video URL." : key === "svg" ? "SVG markup or an SVG URL." : "A picture URL, a data: URL or <svg> markup." },
103
+ object(key, key === "video" ? "A video URL." : key === "svg" ? "SVG markup or an SVG URL." : "A picture URL or a data: URL."),
104
+ ...key === "image" ? [object("svg", "SVG markup.")] : [],
105
+ object("slot", "A slot name, to leave the subject for the host to fill.")
106
+ ],
107
+ description: `${about} ${templateSlotTakes(slot).replace(/^a /, "A ")}. ${slot.hasDefault ? "Default: a placeholder picture." : "No default: left out, the host fills it."}`
108
+ };
109
+ }
110
+ }
111
+ }
112
+ function templateValuesSchema(slots) {
113
+ return {
114
+ type: "object",
115
+ properties: Object.fromEntries(slots.map((s) => [s.name, templateSlotSchema(s)])),
116
+ additionalProperties: false,
117
+ description: `Slot values by name; slots left out take their defaults. ${slots.length ? `Slots: ${slots.map((s) => s.name).join(", ")}.` : "This template has no slots."}`
118
+ };
119
+ }
120
+ function templateDefaultValues(slots) {
121
+ const out = {};
122
+ for (const s of slots) if (!isSubjectTemplateSlot(s)) out[s.name] = s.default;
123
+ return out;
124
+ }
125
+ function templateSlotSummary(slot) {
126
+ const fallback = isSubjectTemplateSlot(slot) ? slot.hasDefault ? "a placeholder by default" : "the host fills it when none is given" : `default ${JSON.stringify(slot.default)}`;
127
+ return `${slot.name} (${slot.type}): ${slot.label}; takes ${templateSlotTakes(slot)}; ${fallback}.`;
128
+ }
129
+ function searchTemplateSummaries(catalog, options = {}) {
130
+ const words = (options.query ?? "").toLowerCase().split(/\s+/).filter(Boolean);
131
+ const scored = [];
132
+ for (const t of catalog) {
133
+ if (!hasEffectTags(t, options.tags)) continue;
134
+ let score = 0;
135
+ const name = t.name.toLowerCase();
136
+ const rest = [t.id, ...t.tags ?? [], t.description].join(" ").toLowerCase();
137
+ if (!words.every((w) => name.includes(w) || rest.includes(w))) continue;
138
+ for (const w of words) score += name.includes(w) ? 2 : 1;
139
+ scored.push({ t, score });
140
+ }
141
+ scored.sort((a, b) => b.score - a.score);
142
+ const out = scored.map((s) => s.t);
143
+ return options.limit !== void 0 ? out.slice(0, Math.max(0, options.limit)) : out;
144
+ }
145
+ var effectLayerRole = (layer) => layer.role ?? (layer.rect ? "subject" : "background");
146
+ function effectLayerInput(description) {
147
+ const images = description.inputs.filter((i) => i.kind === "image");
148
+ return (images.find((i) => i.name === "source") ?? images.find((i) => i.name !== "from" && i.name !== "to"))?.name;
149
+ }
150
+ var EFFECT_LAYER_USES = ["generator", "filter", "overlay", "title"];
151
+ var effectLayerOffered = (e) => (e.kind === "shader" || e.kind === "vector") && e.uses.some((u) => EFFECT_LAYER_USES.includes(u));
152
+ var isRect = (r) => isObject(r) && ["x", "y", "width", "height"].every((k) => Number.isFinite(r[k])) && r.width > 0 && r.height > 0;
153
+ var isLayerTime = (t) => typeof t === "number" && Number.isFinite(t) && t >= 0 || isObject(t) && Number.isInteger(t.shots) && t.shots >= 1;
154
+ function effectSubjectProblem(subject) {
155
+ const kind = effectSubjectKind(subject);
156
+ if (!kind) return `a subject is one of { image }, { video }, { svg }, { text } or { slot }, not ${typeName(subject)}`;
157
+ if (!subject[kind].trim()) return `a subject's "${kind}" is a non-empty string`;
158
+ return void 0;
159
+ }
160
+ function checkEffectSequence(sequence, catalog) {
161
+ const problems = [];
162
+ if (!isObject(sequence)) return ["A sequence is an object with name, stage and shots."];
163
+ if (typeof sequence.name !== "string" || !sequence.name) problems.push("The sequence needs a name.");
164
+ const stage = sequence.stage;
165
+ if (!isObject(stage) || !(Number(stage.width) > 0) || !(Number(stage.height) > 0)) problems.push("The sequence needs a stage { width, height } in pixels, both > 0.");
166
+ if (!Array.isArray(sequence.shots) || !sequence.shots.length) return [...problems, "The sequence needs at least one shot."];
167
+ const byId = catalog ? new Map(catalog.map((e) => [e.id, e])) : void 0;
168
+ const ids = /* @__PURE__ */ new Set();
169
+ sequence.shots.forEach((shot, i) => {
170
+ const at = `shot ${i + 1}`;
171
+ if (!isObject(shot)) return void problems.push(`${at} is not an object.`);
172
+ if (!(Number.isFinite(shot.hold) && shot.hold >= 0)) problems.push(`${at}: hold must be ms \u2265 0.`);
173
+ for (const k of ["title", "caption"]) if (shot[k] !== void 0 && typeof shot[k] !== "string") problems.push(`${at}: ${k} must be words.`);
174
+ if (shot.camera !== void 0) {
175
+ const camera = shot.camera;
176
+ if (!isObject(camera)) problems.push(`${at}: camera must be an object.`);
177
+ else if (camera.framing !== void 0 && !isRect(camera.framing)) problems.push(`${at}: camera.framing must be { x, y, width, height } with width and height > 0.`);
178
+ }
179
+ if (!Array.isArray(shot.layers)) problems.push(`${at}: layers must be a list (it may be empty).`);
180
+ else
181
+ shot.layers.forEach((layer, j) => {
182
+ const where = `${at}, layer ${j + 1}`;
183
+ if (!isObject(layer)) return void problems.push(`${where} is not an object.`);
184
+ if (layer.id !== void 0) {
185
+ if (typeof layer.id !== "string" || !layer.id) problems.push(`${where}: id must be a non-empty string.`);
186
+ else if (ids.has(layer.id)) problems.push(`${where}: id "${layer.id}" is used twice.`);
187
+ else ids.add(layer.id);
188
+ }
189
+ if (layer.effect === void 0 && layer.subject === void 0) problems.push(`${where} has neither an effect nor a subject.`);
190
+ if (layer.effect !== void 0 && (typeof layer.effect !== "string" || !layer.effect)) problems.push(`${where}: effect must be an effect id.`);
191
+ else if (typeof layer.effect === "string" && byId) {
192
+ const e = byId.get(layer.effect);
193
+ if (!e) problems.push(`${where}: the provider has no effect "${layer.effect}".`);
194
+ else if (!effectLayerOffered(e)) problems.push(`${where}: "${layer.effect}" (${e.kind}, ${e.uses.join("/")}) cannot be a layer; a layer's effect is a generator, filter, overlay or title.`);
195
+ }
196
+ if (layer.subject !== void 0) {
197
+ const p = effectSubjectProblem(layer.subject);
198
+ if (p) problems.push(`${where}: ${p}.`);
199
+ }
200
+ if (layer.role !== void 0 && !EFFECT_LAYER_ROLES.includes(layer.role)) problems.push(`${where}: role is one of ${EFFECT_LAYER_ROLES.join(", ")}.`);
201
+ if (layer.rect !== void 0 && !isRect(layer.rect)) problems.push(`${where}: rect must be { x, y, width, height } with width and height > 0.`);
202
+ for (const k of ["from", "until"]) if (layer[k] !== void 0 && !isLayerTime(layer[k])) problems.push(`${where}: ${k} is ms \u2265 0 or { shots: n } with n \u2265 1.`);
203
+ if (layer.opacity !== void 0 && !(typeof layer.opacity === "number" && layer.opacity >= 0 && layer.opacity <= 1)) problems.push(`${where}: opacity is 0\u20131.`);
204
+ if (layer.fade !== void 0 && !(typeof layer.fade === "number" && layer.fade >= 0)) problems.push(`${where}: fade is ms \u2265 0.`);
205
+ if (layer.values !== void 0 && !isObject(layer.values)) problems.push(`${where}: values must be an object of control values.`);
206
+ });
207
+ if (shot.transition !== void 0) {
208
+ const t = shot.transition;
209
+ if (i === 0) problems.push(`${at} has a transition, but there is no shot before it.`);
210
+ if (!isObject(t) || typeof t.effect !== "string" || !t.effect) problems.push(`${at}: transition needs an effect id.`);
211
+ else {
212
+ if (t.ms !== void 0 && !(typeof t.ms === "number" && t.ms > 0)) problems.push(`${at}: transition ms must be > 0.`);
213
+ const e = byId?.get(t.effect);
214
+ if (byId && !e) problems.push(`${at}: the provider has no transition "${t.effect}".`);
215
+ else if (e && !e.uses.includes("transition")) problems.push(`${at}: "${t.effect}" is not a transition (its uses are ${e.uses.join(", ")}).`);
216
+ }
217
+ }
218
+ });
219
+ return problems;
220
+ }
221
+ function effectSequenceEffects(sequence) {
222
+ const out = /* @__PURE__ */ new Set();
223
+ for (const shot of sequence.shots) {
224
+ for (const l of shot.layers) if (l.effect) out.add(l.effect);
225
+ if (shot.transition) out.add(shot.transition.effect);
226
+ }
227
+ return [...out];
228
+ }
229
+ function effectSequenceSlots(sequence) {
230
+ const out = /* @__PURE__ */ new Set();
231
+ for (const shot of sequence.shots) for (const l of shot.layers) if (l.subject && "slot" in l.subject) out.add(l.subject.slot);
232
+ return [...out];
233
+ }
234
+
235
+ export {
236
+ EFFECT_SEQUENCE_NAME,
237
+ isSubjectTemplateSlot,
238
+ effectSubjectKind,
239
+ templateSlotTakes,
240
+ templateValueProblem,
241
+ checkTemplateValues,
242
+ templateSlotSchema,
243
+ templateValuesSchema,
244
+ templateDefaultValues,
245
+ templateSlotSummary,
246
+ searchTemplateSummaries,
247
+ effectLayerRole,
248
+ effectLayerInput,
249
+ EFFECT_LAYER_USES,
250
+ effectLayerOffered,
251
+ effectSubjectProblem,
252
+ checkEffectSequence,
253
+ effectSequenceEffects,
254
+ effectSequenceSlots
255
+ };
@@ -2,8 +2,17 @@
2
2
 
3
3
  var _chunkWOFXZ3XUcjs = require('./chunk-WOFXZ3XU.cjs');
4
4
 
5
+ // src/effects/types.ts
6
+ var EFFECT_KINDS = ["shader", "vector", "motion", "camera"];
7
+ var EFFECT_USES = ["filter", "transition", "generator", "overlay", "title", "motion", "interactive", "camera"];
8
+ var CAMERA_MOVE_ROLES = ["transition", "hold"];
9
+ var EFFECT_SUBJECT_KINDS = ["image", "video", "svg", "text", "slot"];
10
+ var EFFECT_LAYER_ROLES = ["background", "subject", "overlay"];
11
+ var EFFECT_TRANSITION_MS = 800;
12
+ var EFFECT_TEMPLATE_SLOT_TYPES = ["image", "video", "svg", "text", "color", "number"];
13
+
5
14
  // src/effects/errors.ts
6
- var EFFECT_ERROR_CODES = ["unknown_effect", "invalid_values", "unsupported", "disposed", "no_provider"];
15
+ var EFFECT_ERROR_CODES = ["unknown_effect", "invalid_values", "unsupported", "disposed", "no_provider", "unknown_template"];
7
16
  var EffectError = class extends Error {
8
17
 
9
18
 
@@ -24,6 +33,14 @@ var UnknownEffectError = class extends EffectError {
24
33
  this.name = "UnknownEffectError";
25
34
  }
26
35
  };
36
+ var UnknownTemplateError = class extends EffectError {
37
+
38
+ constructor(templateId, providerName) {
39
+ super("unknown_template", `Unknown template "${templateId}"${providerName ? ` in ${providerName}` : ""}. Call list_templates or listTemplates() for valid ids.`);
40
+ this.name = "UnknownTemplateError";
41
+ this.templateId = templateId;
42
+ }
43
+ };
27
44
  var EffectControlError = class extends EffectError {
28
45
 
29
46
  constructor(effectId, details) {
@@ -273,11 +290,6 @@ function cameraBoxOfView(view, stage) {
273
290
  return { x: -view.scrollX, y: -view.scrollY, width, height };
274
291
  }
275
292
 
276
- // src/effects/types.ts
277
- var EFFECT_KINDS = ["shader", "vector", "motion", "camera"];
278
- var EFFECT_USES = ["filter", "transition", "generator", "overlay", "title", "motion", "interactive", "camera"];
279
- var CAMERA_MOVE_ROLES = ["transition", "hold"];
280
-
281
293
  // src/effects/tools.ts
282
294
  var ANNOTATIONS = {
283
295
  read: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
@@ -553,4 +565,9 @@ function createEffectToolProvider(host) {
553
565
 
554
566
 
555
567
 
556
- exports.EFFECT_ERROR_CODES = EFFECT_ERROR_CODES; exports.EffectError = EffectError; exports.UnknownEffectError = UnknownEffectError; exports.EffectControlError = EffectControlError; exports.EffectUnsupportedError = EffectUnsupportedError; exports.EffectDisposedError = EffectDisposedError; exports.NoEffectsProviderError = NoEffectsProviderError; exports.isEffectError = isEffectError; exports.effectValueErrors = effectValueErrors; exports.resolveEffectValues = resolveEffectValues; exports.effectOffered = effectOffered; exports.normaliseEffectTag = normaliseEffectTag; exports.hasEffectTags = hasEffectTags; exports.countEffectTags = countEffectTags; exports.searchEffectSummaries = searchEffectSummaries; exports.createEffectPixels = createEffectPixels; exports.isEffectPixels = isEffectPixels; exports.srgbToLinear = srgbToLinear; exports.linearToSrgb = linearToSrgb; exports.encodeEffectFloat = encodeEffectFloat; exports.applyEffectMask = applyEffectMask; exports.EffectsSlot = EffectsSlot; exports.isCameraView = isCameraView; exports.sampleCameraViews = sampleCameraViews; exports.sampleEffectCameraMove = sampleEffectCameraMove; exports.cameraMoveField = cameraMoveField; exports.cameraMovesFor = cameraMovesFor; exports.cameraMoveIdList = cameraMoveIdList; exports.cameraMoveParts = cameraMoveParts; exports.CAMERA_MOVE_MAX_MS = CAMERA_MOVE_MAX_MS; exports.resolveCameraMoveSpec = resolveCameraMoveSpec; exports.cameraViewOfBox = cameraViewOfBox; exports.cameraBoxOfView = cameraBoxOfView; exports.EFFECT_KINDS = EFFECT_KINDS; exports.EFFECT_USES = EFFECT_USES; exports.CAMERA_MOVE_ROLES = CAMERA_MOVE_ROLES; exports.createEffectToolProvider = createEffectToolProvider;
568
+
569
+
570
+
571
+
572
+
573
+ exports.EFFECT_KINDS = EFFECT_KINDS; exports.EFFECT_USES = EFFECT_USES; exports.CAMERA_MOVE_ROLES = CAMERA_MOVE_ROLES; exports.EFFECT_SUBJECT_KINDS = EFFECT_SUBJECT_KINDS; exports.EFFECT_LAYER_ROLES = EFFECT_LAYER_ROLES; exports.EFFECT_TRANSITION_MS = EFFECT_TRANSITION_MS; exports.EFFECT_TEMPLATE_SLOT_TYPES = EFFECT_TEMPLATE_SLOT_TYPES; exports.EFFECT_ERROR_CODES = EFFECT_ERROR_CODES; exports.EffectError = EffectError; exports.UnknownEffectError = UnknownEffectError; exports.UnknownTemplateError = UnknownTemplateError; exports.EffectControlError = EffectControlError; exports.EffectUnsupportedError = EffectUnsupportedError; exports.EffectDisposedError = EffectDisposedError; exports.NoEffectsProviderError = NoEffectsProviderError; exports.isEffectError = isEffectError; exports.effectValueErrors = effectValueErrors; exports.resolveEffectValues = resolveEffectValues; exports.effectOffered = effectOffered; exports.normaliseEffectTag = normaliseEffectTag; exports.hasEffectTags = hasEffectTags; exports.countEffectTags = countEffectTags; exports.searchEffectSummaries = searchEffectSummaries; exports.createEffectPixels = createEffectPixels; exports.isEffectPixels = isEffectPixels; exports.srgbToLinear = srgbToLinear; exports.linearToSrgb = linearToSrgb; exports.encodeEffectFloat = encodeEffectFloat; exports.applyEffectMask = applyEffectMask; exports.EffectsSlot = EffectsSlot; exports.isCameraView = isCameraView; exports.sampleCameraViews = sampleCameraViews; exports.sampleEffectCameraMove = sampleEffectCameraMove; exports.cameraMoveField = cameraMoveField; exports.cameraMovesFor = cameraMovesFor; exports.cameraMoveIdList = cameraMoveIdList; exports.cameraMoveParts = cameraMoveParts; exports.CAMERA_MOVE_MAX_MS = CAMERA_MOVE_MAX_MS; exports.resolveCameraMoveSpec = resolveCameraMoveSpec; exports.cameraViewOfBox = cameraViewOfBox; exports.cameraBoxOfView = cameraBoxOfView; exports.createEffectToolProvider = createEffectToolProvider;
@@ -2,8 +2,17 @@ import {
2
2
  validateJsonSchema
3
3
  } from "./chunk-V2ZCJRDM.js";
4
4
 
5
+ // src/effects/types.ts
6
+ var EFFECT_KINDS = ["shader", "vector", "motion", "camera"];
7
+ var EFFECT_USES = ["filter", "transition", "generator", "overlay", "title", "motion", "interactive", "camera"];
8
+ var CAMERA_MOVE_ROLES = ["transition", "hold"];
9
+ var EFFECT_SUBJECT_KINDS = ["image", "video", "svg", "text", "slot"];
10
+ var EFFECT_LAYER_ROLES = ["background", "subject", "overlay"];
11
+ var EFFECT_TRANSITION_MS = 800;
12
+ var EFFECT_TEMPLATE_SLOT_TYPES = ["image", "video", "svg", "text", "color", "number"];
13
+
5
14
  // src/effects/errors.ts
6
- var EFFECT_ERROR_CODES = ["unknown_effect", "invalid_values", "unsupported", "disposed", "no_provider"];
15
+ var EFFECT_ERROR_CODES = ["unknown_effect", "invalid_values", "unsupported", "disposed", "no_provider", "unknown_template"];
7
16
  var EffectError = class extends Error {
8
17
  code;
9
18
  effectId;
@@ -24,6 +33,14 @@ var UnknownEffectError = class extends EffectError {
24
33
  this.name = "UnknownEffectError";
25
34
  }
26
35
  };
36
+ var UnknownTemplateError = class extends EffectError {
37
+ templateId;
38
+ constructor(templateId, providerName) {
39
+ super("unknown_template", `Unknown template "${templateId}"${providerName ? ` in ${providerName}` : ""}. Call list_templates or listTemplates() for valid ids.`);
40
+ this.name = "UnknownTemplateError";
41
+ this.templateId = templateId;
42
+ }
43
+ };
27
44
  var EffectControlError = class extends EffectError {
28
45
  details;
29
46
  constructor(effectId, details) {
@@ -273,11 +290,6 @@ function cameraBoxOfView(view, stage) {
273
290
  return { x: -view.scrollX, y: -view.scrollY, width, height };
274
291
  }
275
292
 
276
- // src/effects/types.ts
277
- var EFFECT_KINDS = ["shader", "vector", "motion", "camera"];
278
- var EFFECT_USES = ["filter", "transition", "generator", "overlay", "title", "motion", "interactive", "camera"];
279
- var CAMERA_MOVE_ROLES = ["transition", "hold"];
280
-
281
293
  // src/effects/tools.ts
282
294
  var ANNOTATIONS = {
283
295
  read: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
@@ -516,9 +528,17 @@ function createEffectToolProvider(host) {
516
528
  }
517
529
 
518
530
  export {
531
+ EFFECT_KINDS,
532
+ EFFECT_USES,
533
+ CAMERA_MOVE_ROLES,
534
+ EFFECT_SUBJECT_KINDS,
535
+ EFFECT_LAYER_ROLES,
536
+ EFFECT_TRANSITION_MS,
537
+ EFFECT_TEMPLATE_SLOT_TYPES,
519
538
  EFFECT_ERROR_CODES,
520
539
  EffectError,
521
540
  UnknownEffectError,
541
+ UnknownTemplateError,
522
542
  EffectControlError,
523
543
  EffectUnsupportedError,
524
544
  EffectDisposedError,
@@ -549,8 +569,5 @@ export {
549
569
  resolveCameraMoveSpec,
550
570
  cameraViewOfBox,
551
571
  cameraBoxOfView,
552
- EFFECT_KINDS,
553
- EFFECT_USES,
554
- CAMERA_MOVE_ROLES,
555
572
  createEffectToolProvider
556
573
  };
@@ -3,7 +3,7 @@ import {
3
3
  EffectDisposedError,
4
4
  EffectUnsupportedError,
5
5
  effectValueErrors
6
- } from "./chunk-TCZ2J7PR.js";
6
+ } from "./chunk-SIK3LT6M.js";
7
7
  import {
8
8
  HistoryManager
9
9
  } from "./chunk-RNSANXPT.js";
@@ -7,7 +7,7 @@ import {
7
7
  EffectsSlot,
8
8
  createEffectPixels,
9
9
  effectValueErrors
10
- } from "./chunk-TCZ2J7PR.js";
10
+ } from "./chunk-SIK3LT6M.js";
11
11
  import {
12
12
  validateJsonSchema
13
13
  } from "./chunk-V2ZCJRDM.js";
@@ -7,7 +7,7 @@ var _chunkPY4GWSE2cjs = require('./chunk-PY4GWSE2.cjs');
7
7
 
8
8
 
9
9
 
10
- var _chunkOPSK22DLcjs = require('./chunk-OPSK22DL.cjs');
10
+ var _chunkJAOSL334cjs = require('./chunk-JAOSL334.cjs');
11
11
 
12
12
 
13
13
  var _chunkWOFXZ3XUcjs = require('./chunk-WOFXZ3XU.cjs');
@@ -1316,12 +1316,12 @@ function videoEffectLayerKey(layer, width, height) {
1316
1316
  }
1317
1317
  function mixEffectPixels(a, b, k) {
1318
1318
  if (k >= 1) return b;
1319
- const out = _chunkOPSK22DLcjs.createEffectPixels.call(void 0, a.width, a.height);
1319
+ const out = _chunkJAOSL334cjs.createEffectPixels.call(void 0, a.width, a.height);
1320
1320
  for (let i = 0; i < out.data.length; i++) out.data[i] = a.data[i] + (b.data[i] - a.data[i]) * k;
1321
1321
  return out;
1322
1322
  }
1323
1323
  function overEffectPixels(base, top, opacity = 1) {
1324
- const out = _chunkOPSK22DLcjs.createEffectPixels.call(void 0, base.width, base.height);
1324
+ const out = _chunkJAOSL334cjs.createEffectPixels.call(void 0, base.width, base.height);
1325
1325
  const o = out.data;
1326
1326
  const b = base.data;
1327
1327
  const t = top.data;
@@ -1366,7 +1366,7 @@ var VideoEffectsEngine = (_class2 = class {
1366
1366
  __init10() {this.generation = 0}
1367
1367
 
1368
1368
  constructor(options = {}) {;_class2.prototype.__init5.call(this);_class2.prototype.__init6.call(this);_class2.prototype.__init7.call(this);_class2.prototype.__init8.call(this);_class2.prototype.__init9.call(this);_class2.prototype.__init10.call(this);
1369
- this.slot = _nullishCoalesce(options.slot, () => ( new (0, _chunkOPSK22DLcjs.EffectsSlot)()));
1369
+ this.slot = _nullishCoalesce(options.slot, () => ( new (0, _chunkJAOSL334cjs.EffectsSlot)()));
1370
1370
  this.maxEntries = _nullishCoalesce(options.maxEntries, () => ( 120));
1371
1371
  this.toImage = _nullishCoalesce(options.toImage, () => ( defaultToImage));
1372
1372
  this.pool = new (0, _chunkPY4GWSE2cjs.EffectRendererPool)({ maxRenderers: options.maxRenderers });
@@ -1508,7 +1508,7 @@ function checkVideoEffectPlace(d, place) {
1508
1508
  if (d.kind === "motion" || !d.uses.some((u) => allowed.includes(u))) {
1509
1509
  const where = place === "clip" ? "on a clip" : place === "transition" ? "as a transition" : "as an effect clip";
1510
1510
  const instead = d.uses.includes("transition") ? "set_video_effect_transition" : d.uses.some((u) => VIDEO_EFFECT_PLACES.generator.includes(u)) ? "add_video_effect_clip" : d.uses.some((u) => u === "filter") ? "apply_effect" : null;
1511
- throw new (0, _chunkOPSK22DLcjs.EffectUnsupportedError)(
1511
+ throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(
1512
1512
  `"${d.id}" (${d.name}) is a ${d.uses.join(" / ")} effect and cannot be used ${where}, which takes ${allowed.join(" or ")} effects${instead ? `; use ${instead} instead` : ""}. search_effects with use "${allowed[0]}" lists ones that fit.`,
1513
1513
  d.id
1514
1514
  );
@@ -1529,12 +1529,12 @@ function checkVideoEffectValues(d, values, options = {}) {
1529
1529
  else if (type !== "number" && type !== "integer") errors.push({ path: `/${k}`, message: "only number controls can be keyframed." });
1530
1530
  else for (const [i, key] of v.keys.entries()) for (const e of _chunkWOFXZ3XUcjs.validateJsonSchema.call(void 0, key.v, schema)) errors.push({ path: `/${k}/keys/${i}/v`, message: e.message });
1531
1531
  }
1532
- for (const e of _chunkOPSK22DLcjs.effectValueErrors.call(void 0, d, plain)) {
1532
+ for (const e of _chunkJAOSL334cjs.effectValueErrors.call(void 0, d, plain)) {
1533
1533
  const name = e.path.split("/")[1];
1534
1534
  const about = name && _optionalChain([d, 'access', _46 => _46.controls, 'access', _47 => _47.properties, 'access', _48 => _48[name], 'optionalAccess', _49 => _49.description]);
1535
1535
  errors.push(about ? { path: e.path, message: `${e.message} (${about})` } : e);
1536
1536
  }
1537
- if (errors.length) throw new (0, _chunkOPSK22DLcjs.EffectControlError)(d.id, errors);
1537
+ if (errors.length) throw new (0, _chunkJAOSL334cjs.EffectControlError)(d.id, errors);
1538
1538
  return { ..._nullishCoalesce(options.base, () => ( d.defaults)), ..._nullishCoalesce(values, () => ( {})) };
1539
1539
  }
1540
1540
 
@@ -6,6 +6,8 @@
6
6
  import { type EffectProvider } from './types.cjs';
7
7
  export interface EffectConformanceIssue {
8
8
  effectId?: string;
9
+ /** Set for an issue with a sequence template. */
10
+ templateId?: string;
9
11
  message: string;
10
12
  }
11
13
  export interface EffectConformanceOptions {
@@ -17,6 +19,7 @@ export interface EffectConformanceOptions {
17
19
  size?: number;
18
20
  /** Also check authoring when supportsAuthoring is true (default true). */
19
21
  authoring?: boolean;
22
+ /** Also check sequence templates when supportsTemplates is true (default true). */
23
+ templates?: boolean;
20
24
  }
21
- /** Runs the contract checks against `provider` and returns every issue found (empty when it conforms). */
22
25
  export declare function checkEffectProvider(provider: EffectProvider, options?: EffectConformanceOptions): Promise<EffectConformanceIssue[]>;
@@ -6,6 +6,8 @@
6
6
  import { type EffectProvider } from './types.js';
7
7
  export interface EffectConformanceIssue {
8
8
  effectId?: string;
9
+ /** Set for an issue with a sequence template. */
10
+ templateId?: string;
9
11
  message: string;
10
12
  }
11
13
  export interface EffectConformanceOptions {
@@ -17,6 +19,7 @@ export interface EffectConformanceOptions {
17
19
  size?: number;
18
20
  /** Also check authoring when supportsAuthoring is true (default true). */
19
21
  authoring?: boolean;
22
+ /** Also check sequence templates when supportsTemplates is true (default true). */
23
+ templates?: boolean;
20
24
  }
21
- /** Runs the contract checks against `provider` and returns every issue found (empty when it conforms). */
22
25
  export declare function checkEffectProvider(provider: EffectProvider, options?: EffectConformanceOptions): Promise<EffectConformanceIssue[]>;
@@ -1,5 +1,5 @@
1
1
  import type { SchemaValidationError } from '../tools/schema.cjs';
2
- export type EffectErrorCode = 'unknown_effect' | 'invalid_values' | 'unsupported' | 'disposed' | 'no_provider';
2
+ export type EffectErrorCode = 'unknown_effect' | 'invalid_values' | 'unsupported' | 'disposed' | 'no_provider' | 'unknown_template';
3
3
  export declare const EFFECT_ERROR_CODES: readonly EffectErrorCode[];
4
4
  /**
5
5
  * Base of every effects error. Check `code` (or use `isEffectError`) rather than `instanceof`
@@ -14,6 +14,11 @@ export declare class EffectError extends Error {
14
14
  export declare class UnknownEffectError extends EffectError {
15
15
  constructor(effectId: string, providerName?: string);
16
16
  }
17
+ /** No sequence template has this id. */
18
+ export declare class UnknownTemplateError extends EffectError {
19
+ readonly templateId: string;
20
+ constructor(templateId: string, providerName?: string);
21
+ }
17
22
  /** Control values do not match the effect's control schema (unknown control, wrong type, out of range). */
18
23
  export declare class EffectControlError extends EffectError {
19
24
  readonly details: readonly SchemaValidationError[];
@@ -1,5 +1,5 @@
1
1
  import type { SchemaValidationError } from '../tools/schema.js';
2
- export type EffectErrorCode = 'unknown_effect' | 'invalid_values' | 'unsupported' | 'disposed' | 'no_provider';
2
+ export type EffectErrorCode = 'unknown_effect' | 'invalid_values' | 'unsupported' | 'disposed' | 'no_provider' | 'unknown_template';
3
3
  export declare const EFFECT_ERROR_CODES: readonly EffectErrorCode[];
4
4
  /**
5
5
  * Base of every effects error. Check `code` (or use `isEffectError`) rather than `instanceof`
@@ -14,6 +14,11 @@ export declare class EffectError extends Error {
14
14
  export declare class UnknownEffectError extends EffectError {
15
15
  constructor(effectId: string, providerName?: string);
16
16
  }
17
+ /** No sequence template has this id. */
18
+ export declare class UnknownTemplateError extends EffectError {
19
+ readonly templateId: string;
20
+ constructor(templateId: string, providerName?: string);
21
+ }
17
22
  /** Control values do not match the effect's control schema (unknown control, wrong type, out of range). */
18
23
  export declare class EffectControlError extends EffectError {
19
24
  readonly details: readonly SchemaValidationError[];
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The fake provider's sequence templates (`createFakeEffectProvider({ templates: true })`), built
3
+ * only from its own effects, and a small reference of how a provider fills one: `{{slot}}` in any
4
+ * string (a whole-string placeholder takes the typed value), and `{ slot }` subjects.
5
+ *
6
+ * - `fake.title-sequence`: a gradient behind a title with a lower-third bar, then a crossfade to
7
+ * a second shot with a caption. Text, colour and number slots.
8
+ * - `fake.picture-reveal`: a tinted picture, then a crossfade to the picture with a logo over it.
9
+ * An image slot with a default and one without (left for the host when not given).
10
+ */
11
+ import type { EffectTemplateDescription, EffectTemplateOptions, EffectTemplateResult, EffectTemplateSearchOptions, EffectTemplateSummary, EffectTemplateValues } from './types.cjs';
12
+ /** The template methods of the fake provider. */
13
+ export declare function fakeTemplateMethods(): {
14
+ listTemplates: (options?: EffectTemplateSearchOptions) => EffectTemplateSummary[];
15
+ describeTemplate: (id: string) => EffectTemplateDescription;
16
+ instantiateTemplate(id: string, values?: EffectTemplateValues, options?: EffectTemplateOptions): EffectTemplateResult;
17
+ };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The fake provider's sequence templates (`createFakeEffectProvider({ templates: true })`), built
3
+ * only from its own effects, and a small reference of how a provider fills one: `{{slot}}` in any
4
+ * string (a whole-string placeholder takes the typed value), and `{ slot }` subjects.
5
+ *
6
+ * - `fake.title-sequence`: a gradient behind a title with a lower-third bar, then a crossfade to
7
+ * a second shot with a caption. Text, colour and number slots.
8
+ * - `fake.picture-reveal`: a tinted picture, then a crossfade to the picture with a logo over it.
9
+ * An image slot with a default and one without (left for the host when not given).
10
+ */
11
+ import type { EffectTemplateDescription, EffectTemplateOptions, EffectTemplateResult, EffectTemplateSearchOptions, EffectTemplateSummary, EffectTemplateValues } from './types.js';
12
+ /** The template methods of the fake provider. */
13
+ export declare function fakeTemplateMethods(): {
14
+ listTemplates: (options?: EffectTemplateSearchOptions) => EffectTemplateSummary[];
15
+ describeTemplate: (id: string) => EffectTemplateDescription;
16
+ instantiateTemplate(id: string, values?: EffectTemplateValues, options?: EffectTemplateOptions): EffectTemplateResult;
17
+ };
@@ -12,6 +12,9 @@
12
12
  *
13
13
  * With `camera: true` it also has camera moves (no pixels): `glide` and `whip` (transitions; the
14
14
  * whip cuts halfway) and `drift` (a hold that zooms in slowly).
15
+ *
16
+ * With `templates: true` it also has two sequence templates (see `fake-templates.ts`):
17
+ * `fake.title-sequence` and `fake.picture-reveal`.
15
18
  */
16
19
  import type { EffectProvider, EffectProviderCapabilities, EffectRenderRequest } from './types.cjs';
17
20
  export interface FakeEffectProviderOptions {
@@ -23,6 +26,8 @@ export interface FakeEffectProviderOptions {
23
26
  authoring?: boolean;
24
27
  /** Adds the camera moves and `cameraView` / `sampleCameraMove` (default false). */
25
28
  camera?: boolean;
29
+ /** Adds two sequence templates and `listTemplates` / `describeTemplate` / `instantiateTemplate` (default false). */
30
+ templates?: boolean;
26
31
  }
27
- /** A deterministic CPU effects provider with seven effects, and three camera moves on request (see the module comment). */
32
+ /** A deterministic CPU effects provider with seven effects, and camera moves and templates on request (see the module comment). */
28
33
  export declare function createFakeEffectProvider(options?: FakeEffectProviderOptions): EffectProvider;
@@ -12,6 +12,9 @@
12
12
  *
13
13
  * With `camera: true` it also has camera moves (no pixels): `glide` and `whip` (transitions; the
14
14
  * whip cuts halfway) and `drift` (a hold that zooms in slowly).
15
+ *
16
+ * With `templates: true` it also has two sequence templates (see `fake-templates.ts`):
17
+ * `fake.title-sequence` and `fake.picture-reveal`.
15
18
  */
16
19
  import type { EffectProvider, EffectProviderCapabilities, EffectRenderRequest } from './types.js';
17
20
  export interface FakeEffectProviderOptions {
@@ -23,6 +26,8 @@ export interface FakeEffectProviderOptions {
23
26
  authoring?: boolean;
24
27
  /** Adds the camera moves and `cameraView` / `sampleCameraMove` (default false). */
25
28
  camera?: boolean;
29
+ /** Adds two sequence templates and `listTemplates` / `describeTemplate` / `instantiateTemplate` (default false). */
30
+ templates?: boolean;
26
31
  }
27
- /** A deterministic CPU effects provider with seven effects, and three camera moves on request (see the module comment). */
32
+ /** A deterministic CPU effects provider with seven effects, and camera moves and templates on request (see the module comment). */
28
33
  export declare function createFakeEffectProvider(options?: FakeEffectProviderOptions): EffectProvider;