@pixerate/flair 0.34.0 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +20 -2
- package/dist/{chunk-ZULFHADW.js → chunk-OLTY4APV.js} +33 -5
- package/dist/{chunk-ZULFHADW.js.map → chunk-OLTY4APV.js.map} +1 -1
- package/dist/cli.js +1 -1
- package/dist/editor/index.d.ts +13 -11
- package/dist/editor/index.js +75 -23
- package/dist/editor/index.js.map +1 -1
- package/dist/index.d.ts +24 -4
- package/dist/index.js +288 -165
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/editor/index.js
CHANGED
|
@@ -234,6 +234,12 @@ var easingSchema = {
|
|
|
234
234
|
var valueSchema = {
|
|
235
235
|
description: 'A control value: a number (float, int), true/false (bool), an array of numbers (vec2\u2013vec4; colours 0\u20131), a "#RRGGBB" colour, an image URL (sampler2D), or a string (text).'
|
|
236
236
|
};
|
|
237
|
+
var CATALOG_SEARCH_LIMIT = 20;
|
|
238
|
+
function compileStatus(editor) {
|
|
239
|
+
const state = editor.getState();
|
|
240
|
+
if (state.document.effect.kind !== "shader") return void 0;
|
|
241
|
+
return state.compile ?? "not compiled yet: no renderer has compiled this source, so compile errors are unknown";
|
|
242
|
+
}
|
|
237
243
|
function describeEditor(editor) {
|
|
238
244
|
const state = editor.getState();
|
|
239
245
|
const doc = state.document;
|
|
@@ -255,7 +261,7 @@ function describeEditor(editor) {
|
|
|
255
261
|
presets: doc.presets.map((p) => p.name),
|
|
256
262
|
timeline: { duration: doc.duration, loop: doc.loop, time: state.time, playing: state.playing, recording: state.recording },
|
|
257
263
|
issues: state.issues,
|
|
258
|
-
compile:
|
|
264
|
+
...doc.effect.kind === "shader" && { compile: compileStatus(editor) },
|
|
259
265
|
history: { canUndo: state.history.canUndo, canRedo: state.history.canRedo }
|
|
260
266
|
};
|
|
261
267
|
}
|
|
@@ -273,7 +279,7 @@ function effectCommands() {
|
|
|
273
279
|
id: "catalog.search",
|
|
274
280
|
label: "Search effects",
|
|
275
281
|
group: "Catalog",
|
|
276
|
-
description:
|
|
282
|
+
description: `Searches the built-in effect catalog: {total, effects}, at most \`limit\` effects (default ${CATALOG_SEARCH_LIMIT}). Narrow with words and filters rather than raising the limit. Load one with effect.load to start from it.`,
|
|
277
283
|
readOnly: true,
|
|
278
284
|
params: {
|
|
279
285
|
type: "object",
|
|
@@ -301,25 +307,37 @@ function effectCommands() {
|
|
|
301
307
|
items: { type: "string", enum: EFFECT_INTERACTIONS },
|
|
302
308
|
description: "Only effects that answer the pointer in one of these ways: hover, press, click, trail (follows where it has been), pointer (follows where it is). An empty list finds effects that don't answer it."
|
|
303
309
|
},
|
|
304
|
-
transparent: { type: "boolean", description: "Only overlays (true), drawn over other content, or only effects that fill their frame (false)." }
|
|
310
|
+
transparent: { type: "boolean", description: "Only overlays (true), drawn over other content, or only effects that fill their frame (false)." },
|
|
311
|
+
limit: { type: "integer", minimum: 1, description: `Most effects to return (default ${CATALOG_SEARCH_LIMIT}).` },
|
|
312
|
+
offset: { type: "integer", minimum: 0, description: "Effects to skip first, to page through more (default 0)." }
|
|
305
313
|
},
|
|
306
314
|
additionalProperties: false
|
|
307
315
|
},
|
|
308
|
-
run: (_, params) =>
|
|
309
|
-
const
|
|
316
|
+
run: (_, params) => {
|
|
317
|
+
const { limit = CATALOG_SEARCH_LIMIT, offset = 0, ...filters } = params ?? {};
|
|
318
|
+
const found = findEffects(filters);
|
|
319
|
+
const effects = found.slice(offset, offset + limit).map((e) => {
|
|
320
|
+
const inputs = effectInputs(e);
|
|
321
|
+
return {
|
|
322
|
+
id: e.id,
|
|
323
|
+
name: e.name,
|
|
324
|
+
kind: e.kind,
|
|
325
|
+
category: e.category,
|
|
326
|
+
description: e.description,
|
|
327
|
+
...e.kind === "shader" && e.video ? { video: e.video } : {},
|
|
328
|
+
accepts: inputs.accepts,
|
|
329
|
+
...inputs.interactions.length ? { interactions: inputs.interactions } : {},
|
|
330
|
+
...inputs.transparent ? { transparent: true } : {},
|
|
331
|
+
presets: e.presets?.map((p) => p.name) ?? []
|
|
332
|
+
};
|
|
333
|
+
});
|
|
334
|
+
const more = found.length - offset - effects.length;
|
|
310
335
|
return {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
category: e.category,
|
|
315
|
-
description: e.description,
|
|
316
|
-
...e.kind === "shader" && e.video ? { video: e.video } : {},
|
|
317
|
-
accepts: inputs.accepts,
|
|
318
|
-
...inputs.interactions.length ? { interactions: inputs.interactions } : {},
|
|
319
|
-
...inputs.transparent ? { transparent: true } : {},
|
|
320
|
-
presets: e.presets?.map((p) => p.name) ?? []
|
|
336
|
+
total: found.length,
|
|
337
|
+
effects,
|
|
338
|
+
...more > 0 && { more: `${more} more match; narrow the search, or pass offset ${offset + effects.length} for the next ones.` }
|
|
321
339
|
};
|
|
322
|
-
}
|
|
340
|
+
}
|
|
323
341
|
},
|
|
324
342
|
{
|
|
325
343
|
id: "effect.load",
|
|
@@ -342,9 +360,40 @@ function effectCommands() {
|
|
|
342
360
|
id: "effect.setSource",
|
|
343
361
|
label: "Set shader source",
|
|
344
362
|
group: "Effect",
|
|
345
|
-
description: "Replaces
|
|
363
|
+
description: "Replaces a shader effect's GLSL ES 3.00 source (Shadertoy-style mainImage; controls are uniforms annotated `// @control`). Returns the compile report when a preview compiled it (errors carry your source's line numbers), and the document's issues.",
|
|
346
364
|
params: { type: "object", properties: { source: { type: "string" } }, required: ["source"], additionalProperties: false },
|
|
347
|
-
run: (editor, p) =>
|
|
365
|
+
run: (editor, p) => {
|
|
366
|
+
done(editor.setSource(p.source));
|
|
367
|
+
return { ok: true, compile: compileStatus(editor), issues: editor.getState().issues };
|
|
368
|
+
}
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
id: "effect.setMotion",
|
|
372
|
+
label: "Set vector picture",
|
|
373
|
+
group: "Effect",
|
|
374
|
+
description: "Replaces a vector effect's picture: {svg, animate?}. `svg` is one self-contained <svg> with a viewBox (no scripts); `{{name: type \u2026}}` placeholders in it declare controls and `{{name}}` fills them. `animate` lists changes to elements by id: {id, step?, delay?, ms?, ease?, attrs?: {name: [from, to]}, draw?, view?, along?, count?, write?}. Returns the document's issues.",
|
|
375
|
+
params: {
|
|
376
|
+
type: "object",
|
|
377
|
+
properties: {
|
|
378
|
+
motion: {
|
|
379
|
+
type: "object",
|
|
380
|
+
properties: { svg: { type: "string" }, animate: { type: "array", items: { type: "object" } } },
|
|
381
|
+
required: ["svg"],
|
|
382
|
+
description: "The picture and its animation."
|
|
383
|
+
},
|
|
384
|
+
controls: {
|
|
385
|
+
type: "array",
|
|
386
|
+
items: { type: "object" },
|
|
387
|
+
description: "Controls declared outside the picture, for older pictures: {name, type, default, label?, color?, min?, max?, step?}. Leave out to keep the current list."
|
|
388
|
+
}
|
|
389
|
+
},
|
|
390
|
+
required: ["motion"],
|
|
391
|
+
additionalProperties: false
|
|
392
|
+
},
|
|
393
|
+
run: (editor, p) => {
|
|
394
|
+
done(editor.setMotion(p.motion, p.controls));
|
|
395
|
+
return { ok: true, issues: editor.getState().issues };
|
|
396
|
+
}
|
|
348
397
|
},
|
|
349
398
|
{
|
|
350
399
|
id: "effect.rename",
|
|
@@ -621,14 +670,16 @@ var EffectEditor = class {
|
|
|
621
670
|
// ── The effect itself ───────────────────────────────────────────────
|
|
622
671
|
/** Replaces a shader's source. Compile errors arrive later, from the renderer (see `reportCompile`). */
|
|
623
672
|
setSource(source) {
|
|
624
|
-
if (this.doc.effect.kind !== "shader") return fail("This is a vector effect;
|
|
673
|
+
if (this.doc.effect.kind !== "shader") return fail("This is a vector effect; change its picture with setMotion (the effect.setMotion command).");
|
|
625
674
|
if (source === this.doc.effect.source) return ok;
|
|
626
675
|
this.commit("Edit source", { ...this.doc, effect: { kind: "shader", source } }, "source");
|
|
627
676
|
return ok;
|
|
628
677
|
}
|
|
629
678
|
/** Replaces a vector effect's picture, whose `{{name: type …}}` placeholders declare its controls (and optionally a `controls` list). */
|
|
630
679
|
setMotion(motion, controls) {
|
|
631
|
-
if (this.doc.effect.kind !== "vector") return fail("This is a shader effect;
|
|
680
|
+
if (this.doc.effect.kind !== "vector") return fail("This is a shader effect; change its source with setSource (the effect.setSource command).");
|
|
681
|
+
if (!motion || typeof motion.svg !== "string" || !motion.svg.trim()) return fail("The picture needs `svg`: one <svg>\u2026</svg> element with a viewBox.");
|
|
682
|
+
if (motion.animate !== void 0 && !Array.isArray(motion.animate)) return fail("`animate` must be a list of changes to the picture's elements.");
|
|
632
683
|
this.commit("Edit picture", { ...this.doc, effect: { ...this.doc.effect, motion, controls: controls ?? this.doc.effect.controls } });
|
|
633
684
|
return ok;
|
|
634
685
|
}
|
|
@@ -958,7 +1009,7 @@ async function callTool(provider, name, args = {}) {
|
|
|
958
1009
|
}
|
|
959
1010
|
var EFFECT_AGENT_INSTRUCTIONS = `You design web visual effects in an effect editor. Work through its tools: \`list_commands\` shows every command with its parameters; \`run_command\` runs one; \`run_commands\` runs several in order.
|
|
960
1011
|
|
|
961
|
-
Start with \`effect.describe\` to see what is being edited. To start from something close, use \`catalog.search\` then \`effect.load\` (with a preset if one fits). Every change is one undo step; \`history.undo\` reverts a step.
|
|
1012
|
+
Start with \`effect.describe\` to see what is being edited. To start from something close, use \`catalog.search\` (it returns the first matches and a \`total\`; narrow it with words and filters) then \`effect.load\` (with a preset if one fits). Every change is one undo step; \`history.undo\` reverts a step.
|
|
962
1013
|
|
|
963
1014
|
Shader effects are GLSL ES 3.00 fragment shaders written Shadertoy-style:
|
|
964
1015
|
- Define \`void mainImage(out vec4 fragColor, in vec2 fragCoord)\`; the output is opaque unless the host renders with \`alpha: true\` (overlays), when \`fragColor.a\` is coverage.
|
|
@@ -970,11 +1021,11 @@ Shader effects are GLSL ES 3.00 fragment shaders written Shadertoy-style:
|
|
|
970
1021
|
uniform sampler2D uPhoto; // @control filter=linear wrap=clamp label="Photo"
|
|
971
1022
|
Types: float, int, bool, vec2, vec3, vec4, sampler2D. Every uniform you declare should be a control.
|
|
972
1023
|
- Write float literals with a decimal point (1.0, not 1); GLSL does not convert int to float implicitly. Use \`texture()\`, not \`texture2D()\`.
|
|
973
|
-
-
|
|
1024
|
+
- \`effect.setSource\` returns \`compile\`: fix any errors (their line numbers match your source) before going on. When it says the source is not compiled yet, no preview is attached; check again with \`effect.describe\` or \`view_effect\` later.
|
|
974
1025
|
|
|
975
1026
|
Vector effects are animated SVG pictures that declare their controls in themselves, like shader uniforms: the first \`{{name: type \u2026}}\` declares a control (types: float, int, bool, color, text; attributes as for \`@control\`, values with spaces in single quotes), and every \`{{name}}\` is replaced by its value, e.g.
|
|
976
1027
|
<!-- {{title: text default='Hello' label='Title'}} {{accent: color default=#6366F1}} --><text fill="{{accent}}">{{title}}</text>
|
|
977
|
-
Change their controls' values freely (a text control takes any words)
|
|
1028
|
+
Change their controls' values freely (a text control takes any words). Replace the picture with \`effect.setMotion\` ({svg, animate}), with care: keep the viewBox and the element ids that animations refer to, and read the issues it returns.
|
|
978
1029
|
|
|
979
1030
|
Make effects that loop smoothly and read well behind content: keep motion calm unless asked otherwise, keep contrast where text may sit, and expose the few controls a designer would actually want (colours, speed, scale, intensity) with sensible ranges. Use keyframes (\`keyframe.set\`, in ms) for changes over the timeline. When you can, look at the result with \`view_effect\` and refine it.`;
|
|
980
1031
|
|
|
@@ -1119,6 +1170,7 @@ function bindEffectParameters(editor, options = {}) {
|
|
|
1119
1170
|
};
|
|
1120
1171
|
}
|
|
1121
1172
|
export {
|
|
1173
|
+
CATALOG_SEARCH_LIMIT,
|
|
1122
1174
|
EASING_PRESETS,
|
|
1123
1175
|
EFFECT_AGENT_INSTRUCTIONS,
|
|
1124
1176
|
EffectEditor,
|