@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
@@ -3,7 +3,28 @@
3
3
  var _chunk4XSBOGMKcjs = require('../chunk-4XSBOGMK.cjs');
4
4
 
5
5
 
6
- var _chunkC73U5UI3cjs = require('../chunk-C73U5UI3.cjs');
6
+ var _chunkA7PQNIBXcjs = require('../chunk-A7PQNIBX.cjs');
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+ var _chunk6RZVFYGJcjs = require('../chunk-6RZVFYGJ.cjs');
7
28
 
8
29
 
9
30
  var _chunkPY4GWSE2cjs = require('../chunk-PY4GWSE2.cjs');
@@ -45,7 +66,12 @@ var _chunkPY4GWSE2cjs = require('../chunk-PY4GWSE2.cjs');
45
66
 
46
67
 
47
68
 
48
- var _chunkOPSK22DLcjs = require('../chunk-OPSK22DL.cjs');
69
+
70
+
71
+
72
+
73
+
74
+ var _chunkJAOSL334cjs = require('../chunk-JAOSL334.cjs');
49
75
  require('../chunk-WOFXZ3XU.cjs');
50
76
  require('../chunk-FJ2MSI43.cjs');
51
77
 
@@ -53,7 +79,7 @@ require('../chunk-FJ2MSI43.cjs');
53
79
  var _chunkDWJJI6RTcjs = require('../chunk-DWJJI6RT.cjs');
54
80
 
55
81
  // src/effects/conformance.ts
56
- var codeOf = (e) => _chunkOPSK22DLcjs.isEffectError.call(void 0, e) ? e.code : e instanceof Error ? `untyped ${e.name}: ${e.message}` : String(e);
82
+ var codeOf = (e) => _chunkJAOSL334cjs.isEffectError.call(void 0, e) ? e.code : e instanceof Error ? `untyped ${e.name}: ${e.message}` : String(e);
57
83
  async function rejectsWith(code, run) {
58
84
  try {
59
85
  await run();
@@ -67,10 +93,10 @@ function checkSummary(e, issues) {
67
93
  const at = (message) => issues.push({ effectId: e.id, message });
68
94
  if (!e.id || typeof e.id !== "string") at("summary has no id");
69
95
  if (!e.name) at("summary has no name");
70
- if (!_chunkOPSK22DLcjs.EFFECT_KINDS.includes(e.kind)) at(`kind "${e.kind}" is not one of ${_chunkOPSK22DLcjs.EFFECT_KINDS.join(", ")}`);
96
+ if (!_chunkJAOSL334cjs.EFFECT_KINDS.includes(e.kind)) at(`kind "${e.kind}" is not one of ${_chunkJAOSL334cjs.EFFECT_KINDS.join(", ")}`);
71
97
  if (!e.category) at("summary has no category");
72
98
  if (!Array.isArray(e.uses) || !e.uses.length) at("summary has no uses");
73
- for (const u of _nullishCoalesce(e.uses, () => ( []))) if (!_chunkOPSK22DLcjs.EFFECT_USES.includes(u)) at(`use "${u}" is not one of ${_chunkOPSK22DLcjs.EFFECT_USES.join(", ")}`);
99
+ for (const u of _nullishCoalesce(e.uses, () => ( []))) if (!_chunkJAOSL334cjs.EFFECT_USES.includes(u)) at(`use "${u}" is not one of ${_chunkJAOSL334cjs.EFFECT_USES.join(", ")}`);
74
100
  if (typeof e.transparent !== "boolean") at("transparent is not a boolean");
75
101
  if (typeof e.loop !== "boolean") at("loop is not a boolean");
76
102
  if (e.duration !== void 0 && !(e.duration > 0)) at("duration must be a positive number of ms when present");
@@ -80,7 +106,7 @@ function checkSummary(e, issues) {
80
106
  const m = e.camera;
81
107
  if (!m) at("a camera effect needs camera: { role, durationMs }");
82
108
  else {
83
- if (!_chunkOPSK22DLcjs.CAMERA_MOVE_ROLES.includes(m.role)) at(`camera.role "${m.role}" is not one of ${_chunkOPSK22DLcjs.CAMERA_MOVE_ROLES.join(", ")}`);
109
+ if (!_chunkJAOSL334cjs.CAMERA_MOVE_ROLES.includes(m.role)) at(`camera.role "${m.role}" is not one of ${_chunkJAOSL334cjs.CAMERA_MOVE_ROLES.join(", ")}`);
84
110
  if (!(Number.isFinite(m.durationMs) && m.durationMs >= 0)) at("camera.durationMs must be a number of ms \u2265 0");
85
111
  if (m.cut !== void 0 && !(m.cut >= 0 && m.cut <= 1)) at("camera.cut must be 0\u20131 when present");
86
112
  if (e.duration !== void 0 && e.duration !== m.durationMs) at(`duration ${e.duration} differs from camera.durationMs ${m.durationMs}`);
@@ -106,8 +132,8 @@ function checkDescription(id, d, issues) {
106
132
  if (!control) at(`backgroundOpacity "${d.backgroundOpacity}" is not a control`);
107
133
  else if (control.type !== "number" || control.minimum !== 0 || control.maximum !== 1) at(`backgroundOpacity "${d.backgroundOpacity}" must be a number control from 0 to 1`);
108
134
  }
109
- for (const e of _chunkOPSK22DLcjs.effectValueErrors.call(void 0, d, d.defaults)) at(`default ${e.path}: ${e.message}`);
110
- for (const p of _nullishCoalesce(d.presets, () => ( []))) for (const e of _chunkOPSK22DLcjs.effectValueErrors.call(void 0, d, p.values)) at(`preset "${p.name}" ${e.path}: ${e.message}`);
135
+ for (const e of _chunkJAOSL334cjs.effectValueErrors.call(void 0, d, d.defaults)) at(`default ${e.path}: ${e.message}`);
136
+ for (const p of _nullishCoalesce(d.presets, () => ( []))) for (const e of _chunkJAOSL334cjs.effectValueErrors.call(void 0, d, p.values)) at(`preset "${p.name}" ${e.path}: ${e.message}`);
111
137
  for (const input2 of _nullishCoalesce(d.inputs, () => ( []))) {
112
138
  if (!input2.name || !input2.description) at("every input needs a name and a description");
113
139
  if (input2.kind !== "image" && input2.kind !== "audio") at(`input "${input2.name}" has kind "${input2.kind}"`);
@@ -118,7 +144,7 @@ function checkDescription(id, d, issues) {
118
144
  }
119
145
  }
120
146
  function grey(size) {
121
- const p = _chunkOPSK22DLcjs.createEffectPixels.call(void 0, size, size);
147
+ const p = _chunkJAOSL334cjs.createEffectPixels.call(void 0, size, size);
122
148
  p.data.fill(128);
123
149
  return p;
124
150
  }
@@ -135,7 +161,7 @@ async function checkRender(provider, d, size, issues) {
135
161
  }
136
162
  try {
137
163
  const out = await renderer.render({ time: 0, inputs });
138
- if (!_chunkOPSK22DLcjs.isEffectPixels.call(void 0, out)) at("render did not return EffectPixels");
164
+ if (!_chunkJAOSL334cjs.isEffectPixels.call(void 0, out)) at("render did not return EffectPixels");
139
165
  else if (out.width !== size || out.height !== size || out.data.length !== size * size * 4) at(`render returned ${out.width}\xD7${out.height}, not ${size}\xD7${size}`);
140
166
  } catch (e) {
141
167
  at(`render failed: ${codeOf(e)}`);
@@ -165,10 +191,10 @@ async function checkCamera(provider, d, issues) {
165
191
  at("cameraView must be synchronous; it returned a Promise");
166
192
  return;
167
193
  }
168
- if (!_chunkOPSK22DLcjs.isCameraView.call(void 0, view)) at(`cameraView at u ${u} is not a CameraView (zoom > 0, finite scrollX and scrollY): ${JSON.stringify(view)}`);
194
+ if (!_chunkJAOSL334cjs.isCameraView.call(void 0, view)) at(`cameraView at u ${u} is not a CameraView (zoom > 0, finite scrollX and scrollY): ${JSON.stringify(view)}`);
169
195
  else views.push(view);
170
196
  const again = provider.cameraView(d.id, ctx(u));
171
- if (_chunkOPSK22DLcjs.isCameraView.call(void 0, view) && !sameView(view, again)) at(`cameraView is not pure: two calls at u ${u} gave different views`);
197
+ if (_chunkJAOSL334cjs.isCameraView.call(void 0, view) && !sameView(view, again)) at(`cameraView is not pure: two calls at u ${u} gave different views`);
172
198
  } catch (e) {
173
199
  at(`cameraView at u ${u} failed: ${codeOf(e)}`);
174
200
  }
@@ -181,7 +207,7 @@ async function checkCamera(provider, d, issues) {
181
207
  const keys = _optionalChain([sample, 'optionalAccess', _11 => _11.keys]);
182
208
  if (!Array.isArray(keys) || keys.length < 2) at("sampleCameraMove returned fewer than two keys");
183
209
  else {
184
- if (keys.some((k, i) => !_chunkOPSK22DLcjs.isCameraView.call(void 0, k.view) || !Number.isFinite(k.t) || i > 0 && k.t < keys[i - 1].t)) at("sampleCameraMove keys must be CameraViews in time order");
210
+ if (keys.some((k, i) => !_chunkJAOSL334cjs.isCameraView.call(void 0, k.view) || !Number.isFinite(k.t) || i > 0 && k.t < keys[i - 1].t)) at("sampleCameraMove keys must be CameraViews in time order");
185
211
  if (keys[0].t !== 0 || keys[keys.length - 1].t !== ms) at(`sampleCameraMove keys must run from 0 to ${ms} ms, got ${keys[0].t} to ${keys[keys.length - 1].t}`);
186
212
  else if (!near(keys[0].view, views[0]) || !near(keys[keys.length - 1].view, views[4])) at("sampleCameraMove disagrees with cameraView at the start or end of the move");
187
213
  if (camera.cut !== void 0 && sample.cut === void 0) at("sampleCameraMove gave no cut for a move that cuts");
@@ -191,20 +217,107 @@ async function checkCamera(provider, d, issues) {
191
217
  }
192
218
  }
193
219
  }
220
+ var wrongValue = (slot) => slot.type === "number" ? "not a number" : slot.type === "text" ? 42 : slot.type === "color" ? "blue" : 42;
221
+ function checkSlot(templateId, slot, issues) {
222
+ const at = (message) => issues.push({ templateId, message: `slot ${JSON.stringify(_optionalChain([slot, 'optionalAccess', _12 => _12.name]))}: ${message}` });
223
+ if (!slot || typeof slot.name !== "string" || !/^[A-Za-z][\w-]*$/.test(slot.name)) return at('needs a name of letters, digits, "-" and "_", starting with a letter');
224
+ if (!_chunkJAOSL334cjs.EFFECT_TEMPLATE_SLOT_TYPES.includes(slot.type)) return at(`type "${slot.type}" is not one of ${_chunkJAOSL334cjs.EFFECT_TEMPLATE_SLOT_TYPES.join(", ")}`);
225
+ if (typeof slot.label !== "string" || !slot.label) at("needs a label");
226
+ if (_chunk6RZVFYGJcjs.isSubjectTemplateSlot.call(void 0, slot)) {
227
+ if (typeof slot.hasDefault !== "boolean") at("a subject slot needs hasDefault (a boolean)");
228
+ if ("default" in slot) at("a subject slot describes hasDefault, not its default");
229
+ return;
230
+ }
231
+ const fallback = slot.default;
232
+ if (fallback === void 0) return at("needs a default");
233
+ const problem = _chunk6RZVFYGJcjs.templateValueProblem.call(void 0, slot, fallback);
234
+ if (problem) at(`its default does not fit: ${problem}`);
235
+ if (slot.type === "number" && slot.min !== void 0 && slot.max !== void 0 && slot.min > slot.max) at("min is above max");
236
+ }
237
+ async function checkTemplates(provider, list, issues) {
238
+ const top = (message) => issues.push({ message });
239
+ const templates = await provider.listTemplates();
240
+ if (!Array.isArray(templates)) return top("listTemplates did not return a list");
241
+ const seen = /* @__PURE__ */ new Set();
242
+ for (const t of templates) if (seen.has(t.id)) top(`duplicate template id "${t.id}"`);
243
+ else seen.add(t.id);
244
+ const unknownDescribe = await rejectsWith("unknown_template", () => provider.describeTemplate("__no_such_template__"));
245
+ if (unknownDescribe) top(`describeTemplate of an unknown id ${unknownDescribe}`);
246
+ const unknownFill = await rejectsWith("unknown_template", () => provider.instantiateTemplate("__no_such_template__"));
247
+ if (unknownFill) top(`instantiateTemplate of an unknown id ${unknownFill}`);
248
+ for (const summary of templates) {
249
+ const id = summary.id;
250
+ const at = (message) => issues.push({ templateId: id, message });
251
+ if (!id || typeof id !== "string") top("a template has no id");
252
+ if (!summary.name) at("template has no name");
253
+ if (!summary.description) at("template has no description");
254
+ if (!(Number.isInteger(summary.shots) && summary.shots >= 1)) at("shots must be a whole number \u2265 1");
255
+ if (summary.durationMs !== void 0 && !(summary.durationMs > 0)) at("durationMs must be > 0 when present");
256
+ let slots;
257
+ try {
258
+ const d = await provider.describeTemplate(id);
259
+ if (d.id !== id) at(`describeTemplate returned id "${d.id}"`);
260
+ if (!Array.isArray(d.slots)) {
261
+ at("describeTemplate gave no slots list");
262
+ continue;
263
+ }
264
+ slots = d.slots;
265
+ const names = /* @__PURE__ */ new Set();
266
+ for (const slot of slots) {
267
+ if (names.has(_optionalChain([slot, 'optionalAccess', _13 => _13.name]))) at(`slot "${slot.name}" is declared twice`);
268
+ names.add(_optionalChain([slot, 'optionalAccess', _14 => _14.name]));
269
+ checkSlot(id, slot, issues);
270
+ }
271
+ } catch (e) {
272
+ at(`describeTemplate failed: ${codeOf(e)}`);
273
+ continue;
274
+ }
275
+ try {
276
+ const result = await provider.instantiateTemplate(id);
277
+ if (!result.ok) at(`instantiateTemplate with the defaults failed: ${result.errors.join(" ")}`);
278
+ else {
279
+ for (const p of _chunk6RZVFYGJcjs.checkEffectSequence.call(void 0, result.sequence, list)) at(`with the defaults, ${p}`);
280
+ if (_optionalChain([result, 'access', _15 => _15.sequence, 'optionalAccess', _16 => _16.shots, 'optionalAccess', _17 => _17.length]) !== summary.shots) at(`listTemplates says ${summary.shots} shots; the sequence has ${_optionalChain([result, 'access', _18 => _18.sequence, 'optionalAccess', _19 => _19.shots, 'optionalAccess', _20 => _20.length])}`);
281
+ if (!Array.isArray(result.openSlots) || !Array.isArray(result.notes)) at("instantiateTemplate needs openSlots and notes lists");
282
+ else {
283
+ const open = Array.isArray(_optionalChain([result, 'access', _21 => _21.sequence, 'optionalAccess', _22 => _22.shots])) ? _chunk6RZVFYGJcjs.effectSequenceSlots.call(void 0, result.sequence) : [];
284
+ if (open.some((s) => !result.openSlots.includes(s))) at(`openSlots ${JSON.stringify(result.openSlots)} misses slots the sequence leaves open (${open.join(", ")})`);
285
+ }
286
+ }
287
+ } catch (e) {
288
+ at(`instantiateTemplate with the defaults failed: ${codeOf(e)}`);
289
+ }
290
+ const bad = { __no_such_slot__: "x", ...slots[0] ? { [slots[0].name]: wrongValue(slots[0]) } : {} };
291
+ try {
292
+ const result = await provider.instantiateTemplate(id, bad);
293
+ if (result.ok) at("instantiateTemplate accepted an unknown slot and a value of the wrong type");
294
+ else if (!result.errors.length || result.errors.some((e) => typeof e !== "string" || !e)) at("instantiateTemplate refused bad values without a sentence for each");
295
+ else if (slots[0] && result.errors.length < 2) at("instantiateTemplate should refuse every bad value at once (an unknown slot and a wrong type gave one error)");
296
+ } catch (e) {
297
+ at(`instantiateTemplate with bad values threw (${codeOf(e)}) instead of returning { ok: false, errors }`);
298
+ }
299
+ }
300
+ }
194
301
  async function checkEffectProvider(provider, options = {}) {
195
302
  const issues = [];
196
303
  const top = (message) => issues.push({ message });
197
304
  if (!provider.id) top("provider has no id");
198
305
  const caps = provider.capabilities;
199
306
  for (const k of ["supportsWorker", "supportsFloat", "supportsMask", "supportsHostImages", "supportsVector"]) {
200
- if (typeof _optionalChain([caps, 'optionalAccess', _12 => _12[k]]) !== "boolean") top(`capabilities.${k} is not a boolean`);
307
+ if (typeof _optionalChain([caps, 'optionalAccess', _23 => _23[k]]) !== "boolean") top(`capabilities.${k} is not a boolean`);
201
308
  }
202
- if (_optionalChain([caps, 'optionalAccess', _13 => _13.supportsAuthoring]) !== void 0 && typeof caps.supportsAuthoring !== "boolean") top("capabilities.supportsAuthoring is not a boolean");
203
- if (_optionalChain([caps, 'optionalAccess', _14 => _14.supportsVector]) && typeof provider.applyVectorEffect !== "function") top("supportsVector is set but applyVectorEffect is missing");
204
- if (_optionalChain([caps, 'optionalAccess', _15 => _15.supportsAuthoring]) && typeof provider.openAuthoring !== "function") top("supportsAuthoring is set but openAuthoring is missing");
205
- if (_optionalChain([caps, 'optionalAccess', _16 => _16.supportsCamera]) !== void 0 && typeof caps.supportsCamera !== "boolean") top("capabilities.supportsCamera is not a boolean");
206
- if (_optionalChain([caps, 'optionalAccess', _17 => _17.supportsCamera]) && typeof provider.cameraView !== "function") top("supportsCamera is set but cameraView is missing");
309
+ if (_optionalChain([caps, 'optionalAccess', _24 => _24.supportsAuthoring]) !== void 0 && typeof caps.supportsAuthoring !== "boolean") top("capabilities.supportsAuthoring is not a boolean");
310
+ if (_optionalChain([caps, 'optionalAccess', _25 => _25.supportsVector]) && typeof provider.applyVectorEffect !== "function") top("supportsVector is set but applyVectorEffect is missing");
311
+ if (_optionalChain([caps, 'optionalAccess', _26 => _26.supportsAuthoring]) && typeof provider.openAuthoring !== "function") top("supportsAuthoring is set but openAuthoring is missing");
312
+ if (_optionalChain([caps, 'optionalAccess', _27 => _27.supportsCamera]) !== void 0 && typeof caps.supportsCamera !== "boolean") top("capabilities.supportsCamera is not a boolean");
313
+ if (_optionalChain([caps, 'optionalAccess', _28 => _28.supportsCamera]) && typeof provider.cameraView !== "function") top("supportsCamera is set but cameraView is missing");
207
314
  if (provider.sampleCameraMove && typeof provider.cameraView !== "function") top("sampleCameraMove is present but cameraView is missing");
315
+ if (_optionalChain([caps, 'optionalAccess', _29 => _29.supportsTemplates]) !== void 0 && typeof caps.supportsTemplates !== "boolean") top("capabilities.supportsTemplates is not a boolean");
316
+ const templateMethods = ["listTemplates", "describeTemplate", "instantiateTemplate"];
317
+ if (_optionalChain([caps, 'optionalAccess', _30 => _30.supportsTemplates])) {
318
+ for (const m of templateMethods) if (typeof provider[m] !== "function") top(`supportsTemplates is set but ${m} is missing`);
319
+ }
320
+ if (!_optionalChain([caps, 'optionalAccess', _31 => _31.supportsTemplates]) && templateMethods.some((m) => typeof provider[m] === "function")) top("template methods are present but capabilities.supportsTemplates is not set");
208
321
  const list = await provider.list();
209
322
  const ids = /* @__PURE__ */ new Set();
210
323
  for (const e of list) {
@@ -212,10 +325,10 @@ async function checkEffectProvider(provider, options = {}) {
212
325
  ids.add(e.id);
213
326
  checkSummary(e, issues);
214
327
  }
215
- if (!_optionalChain([caps, 'optionalAccess', _18 => _18.supportsCamera]) && list.some((e) => e.kind === "camera")) top("the catalog lists camera effects but capabilities.supportsCamera is not set");
328
+ if (!_optionalChain([caps, 'optionalAccess', _32 => _32.supportsCamera]) && list.some((e) => e.kind === "camera")) top("the catalog lists camera effects but capabilities.supportsCamera is not set");
216
329
  const all = await provider.search("");
217
330
  if (all.length !== list.length) top(`search("") returned ${all.length} effects, list() ${list.length}`);
218
- const firstUse = _optionalChain([list, 'access', _19 => _19[0], 'optionalAccess', _20 => _20.uses, 'access', _21 => _21[0]]);
331
+ const firstUse = _optionalChain([list, 'access', _33 => _33[0], 'optionalAccess', _34 => _34.uses, 'access', _35 => _35[0]]);
219
332
  if (firstUse) {
220
333
  const filtered = await provider.search("", { use: firstUse });
221
334
  if (filtered.some((e) => !e.uses.includes(firstUse))) top(`search("", { use: "${firstUse}" }) returned effects without that use`);
@@ -224,7 +337,7 @@ async function checkEffectProvider(provider, options = {}) {
224
337
  if (unknown) top(`describe of an unknown id ${unknown}`);
225
338
  const unknownRenderer = await rejectsWith("unknown_effect", () => provider.createRenderer("__no_such_effect__", { width: 4, height: 4 }));
226
339
  if (unknownRenderer) top(`createRenderer of an unknown id ${unknownRenderer}`);
227
- if (_optionalChain([caps, 'optionalAccess', _22 => _22.supportsCamera]) && provider.cameraView) {
340
+ if (_optionalChain([caps, 'optionalAccess', _36 => _36.supportsCamera]) && provider.cameraView) {
228
341
  const probe = { from: WIDE, to: CLOSE, u: 0.5, ms: 1e3, stage: STAGE };
229
342
  const unknownCamera = await rejectsWith("unknown_effect", () => provider.cameraView("__no_such_effect__", probe));
230
343
  if (unknownCamera) top(`cameraView of an unknown id ${unknownCamera}`);
@@ -256,7 +369,7 @@ async function checkEffectProvider(provider, options = {}) {
256
369
  if (bad) issues.push({ effectId: id, message: `applyVectorEffect with an unknown control ${bad}` });
257
370
  }
258
371
  }
259
- if (_optionalChain([caps, 'optionalAccess', _23 => _23.supportsAuthoring]) && options.authoring !== false && typeof provider.openAuthoring === "function") {
372
+ if (_optionalChain([caps, 'optionalAccess', _37 => _37.supportsAuthoring]) && options.authoring !== false && typeof provider.openAuthoring === "function") {
260
373
  const targetEffect = (await Promise.all((_nullishCoalesce(options.ids, () => ( [...ids]))).map((id) => provider.describe(id)))).find(
261
374
  (d) => d.kind !== "motion" && d.kind !== "vector" && d.kind !== "camera"
262
375
  );
@@ -307,9 +420,125 @@ async function checkEffectProvider(provider, options = {}) {
307
420
  }
308
421
  }
309
422
  }
423
+ if (_optionalChain([caps, 'optionalAccess', _38 => _38.supportsTemplates]) && options.templates !== false && templateMethods.every((m) => typeof provider[m] === "function")) await checkTemplates(provider, list, issues);
310
424
  return issues;
311
425
  }
312
426
 
427
+ // src/effects/fake-templates.ts
428
+ var PLACEHOLDER = /\{\{([A-Za-z][\w-]*)\}\}/g;
429
+ var WHOLE = /^\{\{([A-Za-z][\w-]*)\}\}$/;
430
+ var picture = (label, tint) => `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 90" width="160" height="90"><rect width="160" height="90" fill="${tint}"/><text x="80" y="50" text-anchor="middle" font-family="sans-serif" font-size="14" fill="#fff">${label}</text></svg>`;
431
+ var TEMPLATES = [
432
+ {
433
+ summary: { id: "fake.title-sequence", name: "Title sequence", description: "A gradient behind a title with a lower-third bar, then a crossfade to a closing shot with a caption.", tags: ["title", "intro"], shots: 2, durationMs: 4600 },
434
+ slots: [
435
+ { name: "title", type: "text", label: "Title", default: "Hello", maxLength: 40 },
436
+ { name: "subtitle", type: "text", label: "Closing caption", default: "See you soon", maxLength: 60 },
437
+ { name: "accent", type: "color", label: "Accent colour", default: "#0ea5e9" },
438
+ { name: "holdMs", type: "number", label: "Time on each shot (ms)", default: 2e3, min: 500, max: 1e4, integer: true }
439
+ ],
440
+ sequence: {
441
+ name: "title-sequence",
442
+ title: "{{title}}",
443
+ stage: { width: 1280, height: 720 },
444
+ shots: [
445
+ {
446
+ hold: "{{holdMs}}",
447
+ title: "{{title}}",
448
+ layers: [
449
+ { id: "backdrop", effect: "fake.gradient", role: "background", values: { from: "{{accent}}" }, until: { shots: 1 } },
450
+ { id: "bar", effect: "fake.bar", role: "overlay", values: { color: "{{accent}}" }, from: 200 }
451
+ ]
452
+ },
453
+ {
454
+ hold: "{{holdMs}}",
455
+ caption: "{{subtitle}}",
456
+ transition: { effect: "fake.crossfade", ms: 600 },
457
+ layers: [{ id: "closing", effect: "fake.gradient", role: "background", values: { from: "#111827", to: "{{accent}}" } }]
458
+ }
459
+ ]
460
+ }
461
+ },
462
+ {
463
+ summary: { id: "fake.picture-reveal", name: "Picture reveal", description: "A tinted picture, then a crossfade to the picture in full colour with a logo over it and a caption.", tags: ["product", "reveal"], shots: 2, durationMs: 4800 },
464
+ slots: [
465
+ { name: "picture", type: "image", label: "Picture", description: "The picture to reveal.", hasDefault: true, subjectDefault: picture("Picture", "#64748b") },
466
+ { name: "logo", type: "image", label: "Logo", description: "A logo shown over the second shot; the host fills it when none is given.", hasDefault: false },
467
+ { name: "caption", type: "text", label: "Caption", default: "Now in colour", maxLength: 50 },
468
+ { name: "holdMs", type: "number", label: "Time on each shot (ms)", default: 2e3, min: 500, max: 1e4, integer: true }
469
+ ],
470
+ sequence: {
471
+ name: "picture-reveal",
472
+ stage: { width: 1280, height: 720 },
473
+ shots: [
474
+ { hold: "{{holdMs}}", layers: [{ id: "tinted", effect: "fake.tint", subject: { slot: "picture" }, values: { color: "#704214", amount: 0.6 } }] },
475
+ {
476
+ hold: "{{holdMs}}",
477
+ caption: "{{caption}}",
478
+ transition: { effect: "fake.crossfade", ms: 800 },
479
+ layers: [
480
+ { id: "picture", subject: { slot: "picture" }, role: "background" },
481
+ { id: "logo", subject: { slot: "logo" }, role: "overlay", rect: { x: 1040, y: 40, width: 200, height: 112 }, fade: 300 }
482
+ ]
483
+ }
484
+ ]
485
+ }
486
+ }
487
+ ];
488
+ var describeOf = (t) => ({
489
+ ...t.summary,
490
+ slots: t.slots.map(({ subjectDefault: _d, ...slot }) => slot)
491
+ });
492
+ function subjectOf(type, value) {
493
+ if (typeof value !== "string") return value;
494
+ if (value.trimStart().startsWith("<svg") || type === "svg") return { svg: value };
495
+ return type === "video" ? { video: value } : { image: value };
496
+ }
497
+ function fill(t, values) {
498
+ const slots = new Map(t.slots.map((s) => [s.name, s]));
499
+ const valueOf = (name) => {
500
+ const s = slots.get(name);
501
+ return _nullishCoalesce(values[name], () => ( (_chunk6RZVFYGJcjs.isSubjectTemplateSlot.call(void 0, s) ? s.subjectDefault : s.default)));
502
+ };
503
+ const walk = (v, key) => {
504
+ if (typeof v === "string") {
505
+ const whole = WHOLE.exec(v);
506
+ if (whole && slots.has(whole[1])) return valueOf(whole[1]);
507
+ return v.replace(PLACEHOLDER, (m, name) => slots.has(name) ? String(valueOf(name)) : m);
508
+ }
509
+ if (Array.isArray(v)) return v.map((x) => walk(x));
510
+ if (!v || typeof v !== "object") return v;
511
+ if (key === "subject" && typeof v.slot === "string") {
512
+ const s = slots.get(v.slot);
513
+ const value = s ? valueOf(s.name) : void 0;
514
+ return s && value !== void 0 ? subjectOf(s.type, value) : v;
515
+ }
516
+ return Object.fromEntries(Object.entries(v).map(([k, x]) => [k, walk(x, k)]));
517
+ };
518
+ return walk(t.sequence);
519
+ }
520
+ function fakeTemplateMethods() {
521
+ const byId = new Map(TEMPLATES.map((t) => [t.summary.id, t]));
522
+ const get = (id) => {
523
+ const t = byId.get(id);
524
+ if (!t) throw new (0, _chunkJAOSL334cjs.UnknownTemplateError)(id, "the fake provider");
525
+ return t;
526
+ };
527
+ return {
528
+ listTemplates: (options) => _chunk6RZVFYGJcjs.searchTemplateSummaries.call(void 0, TEMPLATES.map((t) => t.summary), options).map((s) => structuredClone(s)),
529
+ describeTemplate: (id) => structuredClone(describeOf(get(id))),
530
+ instantiateTemplate(id, values = {}, options = {}) {
531
+ const t = get(id);
532
+ const errors = _chunk6RZVFYGJcjs.checkTemplateValues.call(void 0, describeOf(t).slots, values);
533
+ if (options.name !== void 0 && (typeof options.name !== "string" || !_chunk6RZVFYGJcjs.EFFECT_SEQUENCE_NAME.test(options.name))) errors.push(`The sequence name is lowercase words and dashes (like "${t.summary.id.replace(/^fake\./, "")}").`);
534
+ if (errors.length) return { ok: false, errors };
535
+ const sequence = fill(t, values);
536
+ if (options.name) sequence.name = options.name;
537
+ return { ok: true, sequence, openSlots: _chunk6RZVFYGJcjs.effectSequenceSlots.call(void 0, sequence), notes: [] };
538
+ }
539
+ };
540
+ }
541
+
313
542
  // src/effects/fake.ts
314
543
  var HEX = "^#[0-9a-fA-F]{6}$";
315
544
  var colour = (description) => ({ type: "string", pattern: HEX, description });
@@ -550,16 +779,16 @@ var hexToRgb = (hex) => [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16));
550
779
  var smooth = (t) => t * t * (3 - 2 * t);
551
780
  var clamp01 = (v) => v < 0 ? 0 : v > 1 ? 1 : v;
552
781
  function input(request, name, id, width, height) {
553
- const src = _optionalChain([request, 'access', _24 => _24.inputs, 'optionalAccess', _25 => _25[name]]);
554
- if (!src) throw new (0, _chunkOPSK22DLcjs.EffectUnsupportedError)(`Effect "${id}" needs an input named "${name}".`, id);
555
- if (!_chunkOPSK22DLcjs.isEffectPixels.call(void 0, src)) throw new (0, _chunkOPSK22DLcjs.EffectUnsupportedError)(`The fake provider only takes EffectPixels inputs ("${name}").`, id);
782
+ const src = _optionalChain([request, 'access', _39 => _39.inputs, 'optionalAccess', _40 => _40[name]]);
783
+ if (!src) throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`Effect "${id}" needs an input named "${name}".`, id);
784
+ if (!_chunkJAOSL334cjs.isEffectPixels.call(void 0, src)) throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`The fake provider only takes EffectPixels inputs ("${name}").`, id);
556
785
  if (src.width !== width || src.height !== height) {
557
- throw new (0, _chunkOPSK22DLcjs.EffectUnsupportedError)(`Input "${name}" is ${src.width}\xD7${src.height}; the renderer is ${width}\xD7${height}.`, id);
786
+ throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`Input "${name}" is ${src.width}\xD7${src.height}; the renderer is ${width}\xD7${height}.`, id);
558
787
  }
559
788
  return src;
560
789
  }
561
790
  function renderPixels(d, v, request, width, height) {
562
- const out = _chunkOPSK22DLcjs.createEffectPixels.call(void 0, width, height);
791
+ const out = _chunkJAOSL334cjs.createEffectPixels.call(void 0, width, height);
563
792
  const o = out.data;
564
793
  switch (d.id) {
565
794
  case "fake.invert": {
@@ -625,7 +854,7 @@ function renderPixels(d, v, request, width, height) {
625
854
  break;
626
855
  }
627
856
  default:
628
- throw new (0, _chunkOPSK22DLcjs.EffectUnsupportedError)(`"${d.id}" is a ${d.kind} effect; use applyVectorEffect.`, d.id);
857
+ throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`"${d.id}" is a ${d.kind} effect; use applyVectorEffect.`, d.id);
629
858
  }
630
859
  return out;
631
860
  }
@@ -655,22 +884,22 @@ function cameraViewOf(d, ctx, v) {
655
884
  case "fake.drift":
656
885
  return viewAt(x0, y0, from.zoom * lerp(1, v.scale, smooth(u)), ctx);
657
886
  default:
658
- throw new (0, _chunkOPSK22DLcjs.EffectUnsupportedError)(`"${d.id}" is a ${d.kind} effect, not a camera move.`, d.id);
887
+ throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`"${d.id}" is a ${d.kind} effect, not a camera move.`, d.id);
659
888
  }
660
889
  }
661
890
  function toFloat(p) {
662
891
  const f = new Float32Array(p.data.length);
663
892
  for (let i = 0; i < f.length; i += 4) {
664
- f[i] = _chunkOPSK22DLcjs.srgbToLinear.call(void 0, p.data[i] / 255);
665
- f[i + 1] = _chunkOPSK22DLcjs.srgbToLinear.call(void 0, p.data[i + 1] / 255);
666
- f[i + 2] = _chunkOPSK22DLcjs.srgbToLinear.call(void 0, p.data[i + 2] / 255);
893
+ f[i] = _chunkJAOSL334cjs.srgbToLinear.call(void 0, p.data[i] / 255);
894
+ f[i + 1] = _chunkJAOSL334cjs.srgbToLinear.call(void 0, p.data[i + 1] / 255);
895
+ f[i + 2] = _chunkJAOSL334cjs.srgbToLinear.call(void 0, p.data[i + 2] / 255);
667
896
  f[i + 3] = p.data[i + 3] / 255;
668
897
  }
669
- return _chunkOPSK22DLcjs.encodeEffectFloat.call(void 0, { ...p, float: f });
898
+ return _chunkJAOSL334cjs.encodeEffectFloat.call(void 0, { ...p, float: f });
670
899
  }
671
900
  function maskResult(out, mask, source, id) {
672
- if (!_chunkOPSK22DLcjs.isEffectPixels.call(void 0, mask) || mask.width !== out.width || mask.height !== out.height) {
673
- throw new (0, _chunkOPSK22DLcjs.EffectUnsupportedError)("The mask must be EffectPixels the size of the renderer.", id);
901
+ if (!_chunkJAOSL334cjs.isEffectPixels.call(void 0, mask) || mask.width !== out.width || mask.height !== out.height) {
902
+ throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)("The mask must be EffectPixels the size of the renderer.", id);
674
903
  }
675
904
  const o = out.data;
676
905
  for (let i = 0; i < o.length; i += 4) {
@@ -689,6 +918,7 @@ function createFakeEffectProvider(options = {}) {
689
918
  supportsVector: true,
690
919
  supportsAuthoring,
691
920
  ...options.camera ? { supportsCamera: true } : {},
921
+ ...options.templates ? { supportsTemplates: true } : {},
692
922
  maxSize: 8192,
693
923
  ...options.capabilities
694
924
  };
@@ -696,32 +926,32 @@ function createFakeEffectProvider(options = {}) {
696
926
  const byId = new Map(all.map((d) => [d.id, d]));
697
927
  const get = (id) => {
698
928
  const d = byId.get(id);
699
- if (!d) throw new (0, _chunkOPSK22DLcjs.UnknownEffectError)(id, "the fake provider");
929
+ if (!d) throw new (0, _chunkJAOSL334cjs.UnknownEffectError)(id, "the fake provider");
700
930
  return d;
701
931
  };
702
932
  const summaries = all.map(summaryOf);
703
933
  const camera = (id, ctx, values) => {
704
934
  const d = get(id);
705
- if (d.kind !== "camera") throw new (0, _chunkOPSK22DLcjs.EffectUnsupportedError)(`"${id}" is a ${d.kind} effect, not a camera move.`, id);
706
- if (!(ctx.u >= 0 && ctx.u <= 1)) throw new (0, _chunkOPSK22DLcjs.EffectUnsupportedError)(`u must be 0\u20131 through the move, got ${ctx.u}.`, id);
707
- return cameraViewOf(d, ctx, _chunkOPSK22DLcjs.resolveEffectValues.call(void 0, d, values));
935
+ if (d.kind !== "camera") throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`"${id}" is a ${d.kind} effect, not a camera move.`, id);
936
+ if (!(ctx.u >= 0 && ctx.u <= 1)) throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`u must be 0\u20131 through the move, got ${ctx.u}.`, id);
937
+ return cameraViewOf(d, ctx, _chunkJAOSL334cjs.resolveEffectValues.call(void 0, d, values));
708
938
  };
709
939
  const provider = {
710
940
  id: "fake",
711
941
  name: "Fake effects",
712
942
  version: "1",
713
943
  capabilities,
714
- list: (o) => _chunkOPSK22DLcjs.searchEffectSummaries.call(void 0, summaries, "", o),
715
- search: (q, o) => _chunkOPSK22DLcjs.searchEffectSummaries.call(void 0, summaries, q, o),
944
+ list: (o) => _chunkJAOSL334cjs.searchEffectSummaries.call(void 0, summaries, "", o),
945
+ search: (q, o) => _chunkJAOSL334cjs.searchEffectSummaries.call(void 0, summaries, q, o),
716
946
  describe: (id) => structuredClone(get(id)),
717
947
  createRenderer(id, ro) {
718
948
  const d = get(id);
719
- if (d.kind === "camera") throw new (0, _chunkOPSK22DLcjs.EffectUnsupportedError)(`"${id}" is a camera move: it moves a scene's camera and draws no pixels. Use cameraView.`, id);
720
- if (d.kind !== "shader") throw new (0, _chunkOPSK22DLcjs.EffectUnsupportedError)(`"${id}" is a ${d.kind} effect; use applyVectorEffect.`, id);
949
+ if (d.kind === "camera") throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`"${id}" is a camera move: it moves a scene's camera and draws no pixels. Use cameraView.`, id);
950
+ if (d.kind !== "shader") throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`"${id}" is a ${d.kind} effect; use applyVectorEffect.`, id);
721
951
  const { width, height } = ro;
722
952
  const depth = _nullishCoalesce(ro.depth, () => ( 8));
723
953
  if (!(width > 0 && height > 0) || width > capabilities.maxSize || height > capabilities.maxSize) {
724
- throw new (0, _chunkOPSK22DLcjs.EffectUnsupportedError)(`Renderer size ${width}\xD7${height} is outside 1\u2013${capabilities.maxSize}.`, id);
954
+ throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`Renderer size ${width}\xD7${height} is outside 1\u2013${capabilities.maxSize}.`, id);
725
955
  }
726
956
  let disposed = false;
727
957
  return {
@@ -730,16 +960,16 @@ function createFakeEffectProvider(options = {}) {
730
960
  height,
731
961
  depth,
732
962
  async render(request) {
733
- if (disposed) throw new (0, _chunkOPSK22DLcjs.EffectDisposedError)(id);
963
+ if (disposed) throw new (0, _chunkJAOSL334cjs.EffectDisposedError)(id);
734
964
  if (!Number.isFinite(request.time) || request.time < 0) {
735
- throw new (0, _chunkOPSK22DLcjs.EffectUnsupportedError)(`time must be a finite number of ms \u2265 0, got ${request.time}.`, id);
965
+ throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`time must be a finite number of ms \u2265 0, got ${request.time}.`, id);
736
966
  }
737
- const values = _chunkOPSK22DLcjs.resolveEffectValues.call(void 0, d, request.values);
738
- _optionalChain([options, 'access', _26 => _26.onRender, 'optionalCall', _27 => _27(id, request)]);
967
+ const values = _chunkJAOSL334cjs.resolveEffectValues.call(void 0, d, request.values);
968
+ _optionalChain([options, 'access', _41 => _41.onRender, 'optionalCall', _42 => _42(id, request)]);
739
969
  const out = renderPixels(d, values, request, width, height);
740
970
  if (request.mask) {
741
- if (!capabilities.supportsMask) throw new (0, _chunkOPSK22DLcjs.EffectUnsupportedError)("This provider does not take masks.", id);
742
- const source = d.uses.includes("filter") ? _optionalChain([request, 'access', _28 => _28.inputs, 'optionalAccess', _29 => _29.source]) : void 0;
971
+ if (!capabilities.supportsMask) throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)("This provider does not take masks.", id);
972
+ const source = d.uses.includes("filter") ? _optionalChain([request, 'access', _43 => _43.inputs, 'optionalAccess', _44 => _44.source]) : void 0;
743
973
  maskResult(out, request.mask, source, id);
744
974
  }
745
975
  return depth > 8 && capabilities.supportsFloat ? toFloat(out) : out;
@@ -751,8 +981,8 @@ function createFakeEffectProvider(options = {}) {
751
981
  },
752
982
  applyVectorEffect(id, target, values) {
753
983
  const d = get(id);
754
- if (d.kind !== "motion" && d.kind !== "vector") throw new (0, _chunkOPSK22DLcjs.EffectUnsupportedError)(`"${id}" is a ${d.kind} effect, not a vector one.`, id);
755
- const v = _chunkOPSK22DLcjs.resolveEffectValues.call(void 0, d, values);
984
+ if (d.kind !== "motion" && d.kind !== "vector") throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`"${id}" is a ${d.kind} effect, not a vector one.`, id);
985
+ const v = _chunkJAOSL334cjs.resolveEffectValues.call(void 0, d, values);
756
986
  if (d.kind === "vector") {
757
987
  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 };
758
988
  }
@@ -772,11 +1002,12 @@ function createFakeEffectProvider(options = {}) {
772
1002
  sampleCameraMove: (id, request) => {
773
1003
  const d = get(id);
774
1004
  const { from, to, ms, stage, fps, values } = request;
775
- return _chunkOPSK22DLcjs.sampleCameraViews.call(void 0, (u) => camera(id, { from, to, u, ms, stage }, values), { ms, fps, cut: _optionalChain([d, 'access', _30 => _30.camera, 'optionalAccess', _31 => _31.cut]) });
1005
+ return _chunkJAOSL334cjs.sampleCameraViews.call(void 0, (u) => camera(id, { from, to, u, ms, stage }, values), { ms, fps, cut: _optionalChain([d, 'access', _45 => _45.camera, 'optionalAccess', _46 => _46.cut]) });
776
1006
  }
777
1007
  } : {},
1008
+ ...options.templates ? fakeTemplateMethods() : {},
778
1009
  ...supportsAuthoring ? {
779
- openAuthoring: (from) => _chunkC73U5UI3cjs.createEffectAuthoringSession.call(void 0, from, { provider })
1010
+ openAuthoring: (from) => _chunkA7PQNIBXcjs.createEffectAuthoringSession.call(void 0, from, { provider })
780
1011
  } : {}
781
1012
  };
782
1013
  return provider;
@@ -812,7 +1043,7 @@ function jsonTypeOf(value) {
812
1043
  function effectControlField(name, schema, fallback, options = {}) {
813
1044
  const base = { id: name, ...schema.title ? { label: schema.title } : {}, ...schema.description ? { description: schema.description } : {} };
814
1045
  const def = _nullishCoalesce(schema.default, () => ( fallback));
815
- const type = _nullishCoalesce(typeOf(schema), () => ( typeOf(_nullishCoalesce(_optionalChain([schema, 'access', _32 => _32.anyOf, 'optionalAccess', _33 => _33.find, 'call', _34 => _34((s) => typeOf(s) === jsonTypeOf(def))]), () => ( {})))));
1046
+ const type = _nullishCoalesce(typeOf(schema), () => ( typeOf(_nullishCoalesce(_optionalChain([schema, 'access', _47 => _47.anyOf, 'optionalAccess', _48 => _48.find, 'call', _49 => _49((s) => typeOf(s) === jsonTypeOf(def))]), () => ( {})))));
816
1047
  if (Array.isArray(schema.enum) && schema.enum.length) {
817
1048
  const options2 = schema.enum.filter((v) => typeof v === "string" || typeof v === "number");
818
1049
  return { ...base, type: "choice", options: options2, default: typeof def === "string" || typeof def === "number" ? def : options2[0], control: options2.length <= 4 ? "segmented" : "select" };
@@ -826,7 +1057,7 @@ function effectControlField(name, schema, fallback, options = {}) {
826
1057
  if (isEffectFontControl(schema)) {
827
1058
  const fonts = _nullishCoalesce(options.fonts, () => ( _chunk4XSBOGMKcjs.SYSTEM_FONT_CATALOG));
828
1059
  const opts = fonts.map((f) => ({ value: f.family, label: f.family, description: f.category }));
829
- const current = typeof def === "string" && def ? def : _nullishCoalesce(_optionalChain([opts, 'access', _35 => _35[0], 'optionalAccess', _36 => _36.value]), () => ( "sans-serif"));
1060
+ const current = typeof def === "string" && def ? def : _nullishCoalesce(_optionalChain([opts, 'access', _50 => _50[0], 'optionalAccess', _51 => _51.value]), () => ( "sans-serif"));
830
1061
  if (!opts.some((o) => o.value.toLowerCase() === current.toLowerCase())) opts.unshift({ value: current, label: current, description: "current" });
831
1062
  return { ...base, type: "choice", options: opts, default: opts.find((o) => o.value.toLowerCase() === current.toLowerCase()).value, control: "select" };
832
1063
  }
@@ -835,7 +1066,7 @@ function effectControlField(name, schema, fallback, options = {}) {
835
1066
  return { ...base, type: "text", default: typeof def === "string" ? def : "", ...schema.maxLength ? { maxLength: schema.maxLength } : {} };
836
1067
  }
837
1068
  if (type === "array" && Array.isArray(def) && def.length >= 2 && def.length <= 4 && def.every((n) => typeof n === "number")) {
838
- const items = _nullishCoalesce(_nullishCoalesce(schema.items, () => ( _optionalChain([schema, 'access', _37 => _37.anyOf, 'optionalAccess', _38 => _38.find, 'call', _39 => _39((s) => typeOf(s) === "array"), 'optionalAccess', _40 => _40.items]))), () => ( {}));
1069
+ const items = _nullishCoalesce(_nullishCoalesce(schema.items, () => ( _optionalChain([schema, 'access', _52 => _52.anyOf, 'optionalAccess', _53 => _53.find, 'call', _54 => _54((s) => typeOf(s) === "array"), 'optionalAccess', _55 => _55.items]))), () => ( {}));
839
1070
  return { ...base, type: "vector", size: def.length, default: [...def], ...items.minimum !== void 0 ? { min: items.minimum } : {}, ...items.maximum !== void 0 ? { max: items.maximum } : {} };
840
1071
  }
841
1072
  return null;
@@ -857,7 +1088,7 @@ var effectFieldValue = (field, value) => {
857
1088
  return value === void 0 || value === null || typeof value === "object" && !Array.isArray(value) ? field.default : value;
858
1089
  };
859
1090
  function effectSamplePicture(width, height, variant = 0) {
860
- const p = _chunkOPSK22DLcjs.createEffectPixels.call(void 0, width, height);
1091
+ const p = _chunkJAOSL334cjs.createEffectPixels.call(void 0, width, height);
861
1092
  for (let y = 0, i = 0; y < height; y++) {
862
1093
  for (let x = 0; x < width; x++, i += 4) {
863
1094
  const u = x / Math.max(1, width - 1);
@@ -948,11 +1179,11 @@ var EASING_SCHEMA = {
948
1179
  };
949
1180
  var NO_SESSION = "No effect authoring session is currently open. Open an effect using EffectProvider.openAuthoring() or in an authoring editor before calling effect authoring tools.";
950
1181
  function createEffectAuthoringToolProvider(host, options) {
951
- const id = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _41 => _41.id]), () => ( "effect-authoring"));
952
- const namespace = _optionalChain([options, 'optionalAccess', _42 => _42.namespace]);
953
- const title = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _43 => _43.title]), () => ( "Effect authoring"));
954
- const description = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _44 => _44.description]), () => ( "Author shaders and procedural effects, inspect parameters, adjust values, and manage keyframe animations."));
955
- const skill = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _45 => _45.skill]), () => ( "pixerate-effect-authoring"));
1182
+ const id = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _56 => _56.id]), () => ( "effect-authoring"));
1183
+ const namespace = _optionalChain([options, 'optionalAccess', _57 => _57.namespace]);
1184
+ const title = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _58 => _58.title]), () => ( "Effect authoring"));
1185
+ const description = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _59 => _59.description]), () => ( "Author shaders and procedural effects, inspect parameters, adjust values, and manage keyframe animations."));
1186
+ const skill = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _60 => _60.skill]), () => ( "pixerate-effect-authoring"));
956
1187
  const requireSession = () => {
957
1188
  const s = host.session();
958
1189
  if (!s) throw new Error(NO_SESSION);
@@ -973,7 +1204,7 @@ function createEffectAuthoringToolProvider(host, options) {
973
1204
  sourceLanguage: state.sourceLanguage,
974
1205
  controls: effectParameterFields(state.description),
975
1206
  values: state.values,
976
- presets: _nullishCoalesce(_optionalChain([state, 'access', _46 => _46.description, 'access', _47 => _47.presets, 'optionalAccess', _48 => _48.map, 'call', _49 => _49((p) => p.name)]), () => ( [])),
1207
+ presets: _nullishCoalesce(_optionalChain([state, 'access', _61 => _61.description, 'access', _62 => _62.presets, 'optionalAccess', _63 => _63.map, 'call', _64 => _64((p) => p.name)]), () => ( [])),
977
1208
  tracks: Object.entries(state.tracks).map(([control, track]) => ({
978
1209
  control,
979
1210
  keyframes: track.length
@@ -1280,7 +1511,7 @@ function createEffectAuthoringToolProvider(host, options) {
1280
1511
  const tools = [
1281
1512
  describeTool,
1282
1513
  getSourceTool,
1283
- ..._optionalChain([session, 'optionalAccess', _50 => _50.setSource]) ? [setSourceTool] : [],
1514
+ ..._optionalChain([session, 'optionalAccess', _65 => _65.setSource]) ? [setSourceTool] : [],
1284
1515
  setValuesTool,
1285
1516
  resetValuesTool,
1286
1517
  applyPresetTool,
@@ -1352,4 +1583,28 @@ function createEffectAuthoringToolProvider(host, options) {
1352
1583
 
1353
1584
 
1354
1585
 
1355
- exports.CAMERA_MOVE_MAX_MS = _chunkOPSK22DLcjs.CAMERA_MOVE_MAX_MS; exports.CAMERA_MOVE_ROLES = _chunkOPSK22DLcjs.CAMERA_MOVE_ROLES; exports.EFFECT_ERROR_CODES = _chunkOPSK22DLcjs.EFFECT_ERROR_CODES; exports.EFFECT_KINDS = _chunkOPSK22DLcjs.EFFECT_KINDS; exports.EFFECT_USES = _chunkOPSK22DLcjs.EFFECT_USES; exports.EFFECT_USE_LABELS = EFFECT_USE_LABELS; exports.EffectControlError = _chunkOPSK22DLcjs.EffectControlError; exports.EffectDisposedError = _chunkOPSK22DLcjs.EffectDisposedError; exports.EffectError = _chunkOPSK22DLcjs.EffectError; exports.EffectRendererPool = _chunkPY4GWSE2cjs.EffectRendererPool; exports.EffectUnsupportedError = _chunkOPSK22DLcjs.EffectUnsupportedError; exports.EffectsSlot = _chunkOPSK22DLcjs.EffectsSlot; exports.NoEffectsProviderError = _chunkOPSK22DLcjs.NoEffectsProviderError; exports.UnknownEffectError = _chunkOPSK22DLcjs.UnknownEffectError; exports.applyEffectMask = _chunkOPSK22DLcjs.applyEffectMask; exports.cameraBoxOfView = _chunkOPSK22DLcjs.cameraBoxOfView; exports.cameraMoveField = _chunkOPSK22DLcjs.cameraMoveField; exports.cameraMoveIdList = _chunkOPSK22DLcjs.cameraMoveIdList; exports.cameraMoveParts = _chunkOPSK22DLcjs.cameraMoveParts; exports.cameraMovesFor = _chunkOPSK22DLcjs.cameraMovesFor; exports.cameraViewOfBox = _chunkOPSK22DLcjs.cameraViewOfBox; exports.checkEffectProvider = checkEffectProvider; exports.countEffectTags = _chunkOPSK22DLcjs.countEffectTags; exports.createEffectAuthoringSession = _chunkC73U5UI3cjs.createEffectAuthoringSession; exports.createEffectAuthoringToolProvider = createEffectAuthoringToolProvider; exports.createEffectPixels = _chunkOPSK22DLcjs.createEffectPixels; exports.createEffectToolProvider = _chunkOPSK22DLcjs.createEffectToolProvider; exports.createFakeEffectProvider = createFakeEffectProvider; exports.effectControlField = effectControlField; exports.effectFieldValue = effectFieldValue; exports.effectFontFamilies = effectFontFamilies; exports.effectOffered = _chunkOPSK22DLcjs.effectOffered; exports.effectParameterFields = effectParameterFields; exports.effectSampleInputs = effectSampleInputs; exports.effectSamplePicture = effectSamplePicture; exports.effectValueErrors = _chunkOPSK22DLcjs.effectValueErrors; exports.encodeEffectFloat = _chunkOPSK22DLcjs.encodeEffectFloat; exports.groupEffectsByCategory = groupEffectsByCategory; exports.hasEffectTags = _chunkOPSK22DLcjs.hasEffectTags; exports.isCameraView = _chunkOPSK22DLcjs.isCameraView; exports.isEffectError = _chunkOPSK22DLcjs.isEffectError; exports.isEffectFontControl = isEffectFontControl; exports.isEffectPixels = _chunkOPSK22DLcjs.isEffectPixels; exports.linearToSrgb = _chunkOPSK22DLcjs.linearToSrgb; exports.normaliseEffectTag = _chunkOPSK22DLcjs.normaliseEffectTag; exports.renderEffectThumbnail = renderEffectThumbnail; exports.resolveCameraMoveSpec = _chunkOPSK22DLcjs.resolveCameraMoveSpec; exports.resolveEffectValues = _chunkOPSK22DLcjs.resolveEffectValues; exports.sampleCameraViews = _chunkOPSK22DLcjs.sampleCameraViews; exports.sampleEffectCameraMove = _chunkOPSK22DLcjs.sampleEffectCameraMove; exports.searchEffectSummaries = _chunkOPSK22DLcjs.searchEffectSummaries; exports.srgbToLinear = _chunkOPSK22DLcjs.srgbToLinear;
1586
+
1587
+
1588
+
1589
+
1590
+
1591
+
1592
+
1593
+
1594
+
1595
+
1596
+
1597
+
1598
+
1599
+
1600
+
1601
+
1602
+
1603
+
1604
+
1605
+
1606
+
1607
+
1608
+
1609
+
1610
+ exports.CAMERA_MOVE_MAX_MS = _chunkJAOSL334cjs.CAMERA_MOVE_MAX_MS; exports.CAMERA_MOVE_ROLES = _chunkJAOSL334cjs.CAMERA_MOVE_ROLES; exports.EFFECT_ERROR_CODES = _chunkJAOSL334cjs.EFFECT_ERROR_CODES; exports.EFFECT_KINDS = _chunkJAOSL334cjs.EFFECT_KINDS; exports.EFFECT_LAYER_ROLES = _chunkJAOSL334cjs.EFFECT_LAYER_ROLES; exports.EFFECT_LAYER_USES = _chunk6RZVFYGJcjs.EFFECT_LAYER_USES; exports.EFFECT_SEQUENCE_NAME = _chunk6RZVFYGJcjs.EFFECT_SEQUENCE_NAME; exports.EFFECT_SUBJECT_KINDS = _chunkJAOSL334cjs.EFFECT_SUBJECT_KINDS; exports.EFFECT_TEMPLATE_SLOT_TYPES = _chunkJAOSL334cjs.EFFECT_TEMPLATE_SLOT_TYPES; exports.EFFECT_TRANSITION_MS = _chunkJAOSL334cjs.EFFECT_TRANSITION_MS; exports.EFFECT_USES = _chunkJAOSL334cjs.EFFECT_USES; exports.EFFECT_USE_LABELS = EFFECT_USE_LABELS; exports.EffectControlError = _chunkJAOSL334cjs.EffectControlError; exports.EffectDisposedError = _chunkJAOSL334cjs.EffectDisposedError; exports.EffectError = _chunkJAOSL334cjs.EffectError; exports.EffectRendererPool = _chunkPY4GWSE2cjs.EffectRendererPool; exports.EffectUnsupportedError = _chunkJAOSL334cjs.EffectUnsupportedError; exports.EffectsSlot = _chunkJAOSL334cjs.EffectsSlot; exports.NoEffectsProviderError = _chunkJAOSL334cjs.NoEffectsProviderError; exports.UnknownEffectError = _chunkJAOSL334cjs.UnknownEffectError; exports.UnknownTemplateError = _chunkJAOSL334cjs.UnknownTemplateError; exports.applyEffectMask = _chunkJAOSL334cjs.applyEffectMask; exports.cameraBoxOfView = _chunkJAOSL334cjs.cameraBoxOfView; exports.cameraMoveField = _chunkJAOSL334cjs.cameraMoveField; exports.cameraMoveIdList = _chunkJAOSL334cjs.cameraMoveIdList; exports.cameraMoveParts = _chunkJAOSL334cjs.cameraMoveParts; exports.cameraMovesFor = _chunkJAOSL334cjs.cameraMovesFor; exports.cameraViewOfBox = _chunkJAOSL334cjs.cameraViewOfBox; exports.checkEffectProvider = checkEffectProvider; exports.checkEffectSequence = _chunk6RZVFYGJcjs.checkEffectSequence; exports.checkTemplateValues = _chunk6RZVFYGJcjs.checkTemplateValues; exports.countEffectTags = _chunkJAOSL334cjs.countEffectTags; exports.createEffectAuthoringSession = _chunkA7PQNIBXcjs.createEffectAuthoringSession; exports.createEffectAuthoringToolProvider = createEffectAuthoringToolProvider; exports.createEffectPixels = _chunkJAOSL334cjs.createEffectPixels; exports.createEffectToolProvider = _chunkJAOSL334cjs.createEffectToolProvider; exports.createFakeEffectProvider = createFakeEffectProvider; exports.effectControlField = effectControlField; exports.effectFieldValue = effectFieldValue; exports.effectFontFamilies = effectFontFamilies; exports.effectLayerInput = _chunk6RZVFYGJcjs.effectLayerInput; exports.effectLayerOffered = _chunk6RZVFYGJcjs.effectLayerOffered; exports.effectLayerRole = _chunk6RZVFYGJcjs.effectLayerRole; exports.effectOffered = _chunkJAOSL334cjs.effectOffered; exports.effectParameterFields = effectParameterFields; exports.effectSampleInputs = effectSampleInputs; exports.effectSamplePicture = effectSamplePicture; exports.effectSequenceEffects = _chunk6RZVFYGJcjs.effectSequenceEffects; exports.effectSequenceSlots = _chunk6RZVFYGJcjs.effectSequenceSlots; exports.effectSubjectKind = _chunk6RZVFYGJcjs.effectSubjectKind; exports.effectSubjectProblem = _chunk6RZVFYGJcjs.effectSubjectProblem; exports.effectValueErrors = _chunkJAOSL334cjs.effectValueErrors; exports.encodeEffectFloat = _chunkJAOSL334cjs.encodeEffectFloat; exports.groupEffectsByCategory = groupEffectsByCategory; exports.hasEffectTags = _chunkJAOSL334cjs.hasEffectTags; exports.isCameraView = _chunkJAOSL334cjs.isCameraView; exports.isEffectError = _chunkJAOSL334cjs.isEffectError; exports.isEffectFontControl = isEffectFontControl; exports.isEffectPixels = _chunkJAOSL334cjs.isEffectPixels; exports.isSubjectTemplateSlot = _chunk6RZVFYGJcjs.isSubjectTemplateSlot; exports.linearToSrgb = _chunkJAOSL334cjs.linearToSrgb; exports.normaliseEffectTag = _chunkJAOSL334cjs.normaliseEffectTag; exports.renderEffectThumbnail = renderEffectThumbnail; exports.resolveCameraMoveSpec = _chunkJAOSL334cjs.resolveCameraMoveSpec; exports.resolveEffectValues = _chunkJAOSL334cjs.resolveEffectValues; exports.sampleCameraViews = _chunkJAOSL334cjs.sampleCameraViews; exports.sampleEffectCameraMove = _chunkJAOSL334cjs.sampleEffectCameraMove; exports.searchEffectSummaries = _chunkJAOSL334cjs.searchEffectSummaries; exports.searchTemplateSummaries = _chunk6RZVFYGJcjs.searchTemplateSummaries; exports.srgbToLinear = _chunkJAOSL334cjs.srgbToLinear; exports.templateDefaultValues = _chunk6RZVFYGJcjs.templateDefaultValues; exports.templateSlotSchema = _chunk6RZVFYGJcjs.templateSlotSchema; exports.templateSlotSummary = _chunk6RZVFYGJcjs.templateSlotSummary; exports.templateSlotTakes = _chunk6RZVFYGJcjs.templateSlotTakes; exports.templateValueProblem = _chunk6RZVFYGJcjs.templateValueProblem; exports.templateValuesSchema = _chunk6RZVFYGJcjs.templateValuesSchema;