@pixerate/flair 0.21.1 → 0.23.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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # @pixerate/flair
2
2
 
3
+ ## 0.23.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 69cdb60: `effectInputs(effect)` says what an effect takes and how it answers the pointer: what it `accepts` (image, video, svg, text, mask, path), its image controls and whether each wants a picture, a mask or text, its text controls (copy, font, path, glyphs), its video use, its `interactions` (hover, press, click, trail, pointer) and whether it is a transparent overlay. It is worked out from the effect's controls, source and fields, so it never drifts. `findEffects` and the `catalog.search` command filter on `accepts`, `interaction` and `transparent`, and the search lists each effect's inputs. `silhouette-morph` now says `video: "none"` (it takes silhouettes, not photos), and the fireworks, explosion and bullet-time effects are tagged `interactive`.
8
+
9
+ ## 0.22.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 4eb5f23: `image-duotone` is now only a duotone: it maps the picture onto two colours by brightness, still and without its built-in light sweep (the `uSweep` control is gone). For the glare, lay the `shine-sweep` overlay over it.
14
+
3
15
  ## 0.21.1
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -150,6 +150,33 @@ new SvgPlayer(host, motion, { loop: false });
150
150
 
151
151
  Find effects with `findEffects({ text: "glow", category: "light", kind: "shader" })`. Each effect has an `id`, `name`, `description`, `category`, `tags` and optional `presets`. Image effects default to built-in sample pictures, so they look right before you set `uImage` to your own URL.
152
152
 
153
+ #### What an effect takes
154
+
155
+ `effectInputs(effect)` says what you can give an effect and how it answers the pointer, worked out from the effect itself:
156
+
157
+ ```ts
158
+ import { effectInputs, findEffects, getEffect, textImage } from "@pixerate/flair/catalog";
159
+
160
+ effectInputs(getEffect("image-duotone")!);
161
+ // { accepts: ["image", "video", "svg"], images: [{ name: "uImage", wants: "picture" }], video: "filter", interactions: [], transparent: false, … }
162
+ effectInputs(getEffect("typewriter")!);
163
+ // { accepts: ["text"], texts: [{ name: "text", holds: "copy" }, { name: "font", holds: "font" }], interactions: [], … }
164
+ effectInputs(getEffect("click-ripple")!).interactions; // ["click"]
165
+
166
+ findEffects({ accepts: ["video"] }); // effects that run on video
167
+ findEffects({ accepts: ["text"], kind: "vector" }); // animated titles and labels
168
+ findEffects({ accepts: ["image"], interaction: ["hover"] }); // pictures that react to hovering
169
+ findEffects({ transparent: true }); // overlays to lay over a page, picture or video
170
+ ```
171
+
172
+ - `accepts`: `image` (any picture URL), `video` (a live `<video>`, with `setLiveSource`), `svg` (an SVG URL, drawn with its transparency), `text` (words for a text control, or for a text mask through `textImage("…")`), `mask` (a shape with transparency whose silhouette the effect uses: an icon, a logo, a word), `path` (SVG path data for a shape control).
173
+ - `images`: each image control's name, and whether it `wants` a `picture`, a `mask` or `text`.
174
+ - `texts`: each text control's name, and whether it `holds` `copy`, a `font`, a `path` or `glyphs`.
175
+ - `interactions`: `hover`, `press`, `click`, `trail` (follows where the pointer has been) or `pointer` (follows where it is), from the pointer built-ins a shader reads or a vector effect's `trigger`.
176
+ - `transparent`, `video` and `trigger`, as on the effect.
177
+
178
+ `findEffects` filters on `accepts` (all of them), `interaction` (any of them; `[]` for effects that don't answer the pointer) and `transparent`, and the `catalog.search` command takes the same filters and lists each effect's `accepts` and `interactions`. The `interactive` tag is kept in step with `interactions`.
179
+
153
180
  Effects that show a picture (image, transition, morph, time-warp and the like) take transparent pictures too, such as SVG icons (Lucide and similar sets draw black `currentColor` strokes on a clear background). They lay the picture over a backdrop: `uBackdrop` (white by default) shows through its clear parts. Set `uBackdropAlpha` to 0 to keep the picture's alpha instead, and render with `{ alpha: true }` to lay the result over the page. `SAMPLE_IMAGES.icon` is a Lucide-style sample icon. SVGs are rasterised at 2048 px on the long edge, so icons stay sharp.
154
181
 
155
182
  #### Effects on video
@@ -1,7 +1,76 @@
1
1
  import { a as ControlDef, C as ControlValue } from '../controls-Ec6P0Vpy.js';
2
- import { E as EffectDefinition, a as EffectCategory, b as VideoUse, S as ShaderEffect } from '../types-Cy5EihZ8.js';
3
- export { C as CURRENT_COLOR, c as EFFECT_CATEGORIES, d as EffectPreset, e as VECTOR_CONTROL_TYPES, f as VIDEO_USES, g as VectorControl, V as VectorEffect, h as colorControl, i as isCurrentColor, n as numberControl, r as renderVectorEffect, v as vectorControlDef, j as vectorControlIssues, k as vectorControls, l as vectorEffectControls } from '../types-Cy5EihZ8.js';
4
- import '../svg-BEOJriIW.js';
2
+ import { a as SvgTrigger } from '../svg-BhRboN9q.js';
3
+ import { a as VideoUse, E as EffectDefinition, b as EffectCategory, S as ShaderEffect } from '../types-DLkbOX8d.js';
4
+ export { C as CURRENT_COLOR, c as EFFECT_CATEGORIES, d as EffectPreset, e as VECTOR_CONTROL_TYPES, f as VIDEO_USES, g as VectorControl, V as VectorEffect, h as colorControl, i as isCurrentColor, n as numberControl, r as renderVectorEffect, v as vectorControlDef, j as vectorControlIssues, k as vectorControls, l as vectorEffectControls } from '../types-DLkbOX8d.js';
5
+
6
+ /**
7
+ * What an effect takes and how it answers the pointer, worked out from the
8
+ * effect itself (its controls, its `video` use, the pointer built-ins its
9
+ * source reads, its `trigger`), so a consumer can pair a picture, a video,
10
+ * an SVG, a word or a path with effects that suit it.
11
+ */
12
+
13
+ /**
14
+ * Something you can give an effect:
15
+ * - `image`: a photo or picture (any URL or `data:` image) for an image control.
16
+ * - `video`: a live `<video>` (or canvas) for an image control, with `setLiveSource`.
17
+ * - `svg`: an SVG file or `data:` URL for an image control (drawn as a picture, keeping its transparency).
18
+ * - `text`: words, for a text control, or for a text mask through `textImage`.
19
+ * - `mask`: a shape with transparency (an icon, a logo, `textImage`) whose silhouette the effect uses.
20
+ * - `path`: SVG path data (`d`), for a shape control.
21
+ */
22
+ type EffectInput = "image" | "video" | "svg" | "text" | "mask" | "path";
23
+ /** Every {@link EffectInput}. */
24
+ declare const EFFECT_INPUTS: readonly EffectInput[];
25
+ /**
26
+ * How an effect answers the pointer:
27
+ * - `hover`: changes while the pointer is over it.
28
+ * - `press`: changes while the pointer is held down (or dragged).
29
+ * - `click`: answers each click or tap.
30
+ * - `trail`: follows where the pointer has just been.
31
+ * - `pointer`: follows where the pointer is.
32
+ */
33
+ type EffectInteraction = "hover" | "press" | "click" | "trail" | "pointer";
34
+ /** Every {@link EffectInteraction}. */
35
+ declare const EFFECT_INTERACTIONS: readonly EffectInteraction[];
36
+ /** A shader's image control and what it wants. */
37
+ interface ImageSlot {
38
+ /** The control's name (a `sampler2D` uniform): set it with `setValues` or `setLiveSource`. */
39
+ name: string;
40
+ label: string;
41
+ /**
42
+ * What it is for: `picture` (a photo, video or SVG shown as it is), `mask`
43
+ * (a shape whose transparency the effect uses: an icon, a logo, a
44
+ * silhouette), or `text` (a word drawn by `textImage`).
45
+ */
46
+ wants: "picture" | "mask" | "text";
47
+ }
48
+ /** A vector effect's text control and what it holds. */
49
+ interface TextSlot {
50
+ /** The control's name: set it with `renderVectorEffect(effect, { [name]: … })`. */
51
+ name: string;
52
+ label: string;
53
+ /** `copy` (words shown), `font` (a CSS font family), `path` (SVG path data) or `glyphs` (characters to draw from). */
54
+ holds: "copy" | "font" | "path" | "glyphs";
55
+ default: string;
56
+ }
57
+ /** What an effect takes and how it answers the pointer (see {@link effectInputs}). */
58
+ interface EffectInputs {
59
+ /** Everything it can be given, from its image and text controls. Empty: it makes its picture from nothing. */
60
+ accepts: EffectInput[];
61
+ /** Its image controls (shader effects). */
62
+ images: ImageSlot[];
63
+ /** Its text controls (vector effects). */
64
+ texts: TextSlot[];
65
+ /** How it suits video, for shaders with an image control (see `VideoUse`). */
66
+ video?: VideoUse;
67
+ /** How it answers the pointer; empty when it does not. */
68
+ interactions: EffectInteraction[];
69
+ /** A vector effect's trigger: what makes it play. */
70
+ trigger?: SvgTrigger;
71
+ /** Draws over other content (render it with `alpha: true`, over a page or picture). */
72
+ transparent: boolean;
73
+ }
5
74
 
6
75
  /**
7
76
  * Sample pictures for the catalog's image effects: small SVGs as `data:` URLs,
@@ -71,6 +140,7 @@ declare function glsl(...parts: string[]): string;
71
140
  * - Video: shader effects with image controls say how they suit video
72
141
  * (`video`, see `VideoUse`); `findEffects({ video: ["filter"] })` finds them.
73
142
  * - Controls: `effectControls`, `effectDefaults`.
143
+ * - Inputs: `effectInputs` (what an effect takes, how it answers the pointer).
74
144
  * - Vector effects: their pictures declare their controls (`vectorControls`),
75
145
  * and `renderVectorEffect` fills them in.
76
146
  *
@@ -83,6 +153,17 @@ declare const SHADER_EFFECTS: readonly ShaderEffect[];
83
153
  declare const EFFECTS: readonly EffectDefinition[];
84
154
  /** The effect with this id, or undefined. */
85
155
  declare function getEffect(id: string): EffectDefinition | undefined;
156
+
157
+ /**
158
+ * What an effect takes and how it answers the pointer: what you can give it
159
+ * (`accepts`: image, video, svg, text, mask, path), its image controls and
160
+ * whether each wants a picture, a mask or text, its text controls (copy,
161
+ * font, path, glyphs), how it suits video, how it answers the pointer
162
+ * (`interactions`: hover, press, click, trail, pointer) and whether it draws
163
+ * over other content. Worked out from the effect itself, so it always agrees
164
+ * with its controls and source.
165
+ */
166
+ declare function effectInputs(effect: EffectDefinition): EffectInputs;
86
167
  interface EffectQuery {
87
168
  /** Words to look for in the name, description, tags and id (all must match). */
88
169
  text?: string;
@@ -92,6 +173,12 @@ interface EffectQuery {
92
173
  tags?: readonly string[];
93
174
  /** Effects that suit video in one of these ways (shader effects with image controls only). */
94
175
  video?: readonly VideoUse[];
176
+ /** Effects that can be given every one of these (see {@link effectInputs}): `["image"]`, `["text"]`, `["svg"]`… */
177
+ accepts?: readonly EffectInput[];
178
+ /** Effects that answer the pointer in at least one of these ways; `[]` for effects that don't answer it at all. */
179
+ interaction?: readonly EffectInteraction[];
180
+ /** Overlays (`true`), which draw over other content, or effects that fill their frame (`false`). */
181
+ transparent?: boolean;
95
182
  }
96
183
  /** Effects matching a query, in catalog order. */
97
184
  declare function findEffects(query?: EffectQuery): EffectDefinition[];
@@ -103,4 +190,4 @@ declare function effectDefaults(effect: EffectDefinition, options?: {
103
190
  values?: Record<string, ControlValue>;
104
191
  }): Record<string, ControlValue>;
105
192
 
106
- export { EFFECTS, EffectCategory, EffectDefinition, type EffectQuery, FBM, HASH, NOISE, OKLAB_MIX, PALETTE, ROTATE, SAMPLE_IMAGES, SHADER_EFFECTS, ShaderEffect, VideoUse, effectControls, effectDefaults, findEffects, getEffect, glsl, svgDataUrl, textImage };
193
+ export { EFFECTS, EFFECT_INPUTS, EFFECT_INTERACTIONS, EffectCategory, EffectDefinition, type EffectInput, type EffectInputs, type EffectInteraction, type EffectQuery, FBM, HASH, type ImageSlot, NOISE, OKLAB_MIX, PALETTE, ROTATE, SAMPLE_IMAGES, SHADER_EFFECTS, ShaderEffect, type TextSlot, VideoUse, effectControls, effectDefaults, effectInputs, findEffects, getEffect, glsl, svgDataUrl, textImage };
@@ -2,6 +2,8 @@ import {
2
2
  CURRENT_COLOR,
3
3
  EFFECTS,
4
4
  EFFECT_CATEGORIES,
5
+ EFFECT_INPUTS,
6
+ EFFECT_INTERACTIONS,
5
7
  FBM,
6
8
  HASH,
7
9
  NOISE,
@@ -15,6 +17,7 @@ import {
15
17
  colorControl,
16
18
  effectControls,
17
19
  effectDefaults,
20
+ effectInputs,
18
21
  findEffects,
19
22
  getEffect,
20
23
  glsl,
@@ -27,7 +30,7 @@ import {
27
30
  vectorControlIssues,
28
31
  vectorControls,
29
32
  vectorEffectControls
30
- } from "../chunk-ECBG5K6E.js";
33
+ } from "../chunk-4F4KL4KU.js";
31
34
  import "../chunk-OHW7UG6D.js";
32
35
  import "../chunk-EHDJ3CPJ.js";
33
36
  import "../chunk-VYOMXE6I.js";
@@ -35,6 +38,8 @@ export {
35
38
  CURRENT_COLOR,
36
39
  EFFECTS,
37
40
  EFFECT_CATEGORIES,
41
+ EFFECT_INPUTS,
42
+ EFFECT_INTERACTIONS,
38
43
  FBM,
39
44
  HASH,
40
45
  NOISE,
@@ -48,6 +53,7 @@ export {
48
53
  colorControl,
49
54
  effectControls,
50
55
  effectDefaults,
56
+ effectInputs,
51
57
  findEffects,
52
58
  getEffect,
53
59
  glsl,
@@ -14,6 +14,68 @@ import {
14
14
  rgbToHex
15
15
  } from "./chunk-VYOMXE6I.js";
16
16
 
17
+ // src/catalog/inputs.ts
18
+ var EFFECT_INPUTS = ["image", "video", "svg", "text", "mask", "path"];
19
+ var EFFECT_INTERACTIONS = ["hover", "press", "click", "trail", "pointer"];
20
+ function isTextImage(url) {
21
+ if (!url.startsWith("data:image/svg+xml;charset=utf-8,")) return false;
22
+ try {
23
+ return decodeURIComponent(url.slice(url.indexOf(",") + 1)).includes("<text");
24
+ } catch {
25
+ return false;
26
+ }
27
+ }
28
+ var PATH_DATA = /^\s*[Mm]\s*[-+.\d]/;
29
+ function textSlot(control) {
30
+ const value = String(control.default);
31
+ const holds2 = control.name === "font" || /\bfont\b/i.test(control.label) ? "font" : PATH_DATA.test(value) ? "path" : control.name === "glyphs" ? "glyphs" : "copy";
32
+ return { name: control.name, label: control.label, holds: holds2, default: value };
33
+ }
34
+ function shaderInteractions(source) {
35
+ const code = source.replace(/\/\*[\s\S]*?\*\/|\/\/[^\n]*/g, "");
36
+ const found = /* @__PURE__ */ new Set();
37
+ if (/\biClicks\b/.test(code)) found.add("click");
38
+ if (/\biTrail\b/.test(code)) found.add("trail");
39
+ if (/\biPointer\s*\.\s*z\b/.test(code)) found.add("hover");
40
+ if (/\biPointer\s*\.\s*w\b/.test(code) || /\biMouse\s*\.\s*z\b/.test(code)) found.add("press");
41
+ if (/\biPointer\s*\.\s*xy?\b/.test(code) || /\biMouse\s*\.\s*xy?\b/.test(code)) found.add("pointer");
42
+ return EFFECT_INTERACTIONS.filter((i) => found.has(i));
43
+ }
44
+ function inputsOf(effect, controls) {
45
+ const accepts = /* @__PURE__ */ new Set();
46
+ const images = [];
47
+ const texts = [];
48
+ for (const control of controls) {
49
+ if (control.type === "sampler2D") {
50
+ const value = String(control.default);
51
+ const video = effect.kind === "shader" ? effect.video : void 0;
52
+ const wants = isTextImage(value) ? "text" : video === "none" ? "mask" : "picture";
53
+ images.push({ name: control.name, label: control.label, wants });
54
+ if (wants === "picture") {
55
+ accepts.add("image").add("svg");
56
+ if (video && video !== "none") accepts.add("video");
57
+ } else {
58
+ accepts.add("mask").add("svg").add("text").add("image");
59
+ }
60
+ } else if (control.type === "text") {
61
+ const slot = textSlot(control);
62
+ texts.push(slot);
63
+ if (slot.holds === "copy") accepts.add("text");
64
+ if (slot.holds === "path") accepts.add("path");
65
+ }
66
+ }
67
+ const interactions = effect.kind === "vector" ? effect.trigger ? [effect.trigger] : [] : shaderInteractions(effect.source);
68
+ return {
69
+ accepts: EFFECT_INPUTS.filter((i) => accepts.has(i)),
70
+ images,
71
+ texts,
72
+ ...effect.kind === "shader" && effect.video ? { video: effect.video } : {},
73
+ interactions,
74
+ ...effect.kind === "vector" && effect.trigger ? { trigger: effect.trigger } : {},
75
+ transparent: effect.kind === "shader" ? Boolean(effect.transparent) : false
76
+ };
77
+ }
78
+
17
79
  // src/catalog/glsl.ts
18
80
  var HASH = `
19
81
  float hash12(vec2 p) {
@@ -456,17 +518,16 @@ var imageDuotone = {
456
518
  kind: "shader",
457
519
  id: "image-duotone",
458
520
  name: "Duotone",
459
- description: "An image mapped onto two colours, with a slow light sweep.",
521
+ description: "An image mapped onto two colours, from its shadows to its highlights. For a passing glare, lay `shine-sweep` over it.",
460
522
  category: "image",
461
523
  video: "filter",
462
524
  tags: ["image", "brand", "editorial", "colour"],
463
525
  source: glsl(
464
- `// Duotone: an image mapped onto two colours, with a light sweep.
526
+ `// Duotone: an image mapped onto two colours by its brightness.
465
527
  uniform sampler2D uImage; // @control filter=linear wrap=clamp default=${SAMPLE_IMAGES.landscape} label="Image"
466
528
  uniform vec3 uShadow; // @control color default=#1E1B4B label="Shadows"
467
529
  uniform vec3 uHighlight; // @control color default=#FB7185 label="Highlights"
468
530
  uniform float uContrast; // @control min=0.5 max=3 default=1.2 label="Contrast"
469
- uniform float uSweep; // @control min=0 max=1 default=0.3 label="Light sweep"
470
531
  ${BACKDROP_CONTROLS}`,
471
532
  PICTURE,
472
533
  `void mainImage(out vec4 fragColor, in vec2 fragCoord) {
@@ -474,9 +535,7 @@ ${BACKDROP_CONTROLS}`,
474
535
  vec4 src = pictureRGBA(uImage, uv);
475
536
  float l = dot(src.rgb, vec3(0.2126, 0.7152, 0.0722));
476
537
  l = clamp((l - 0.5) * uContrast + 0.5, 0.0, 1.0);
477
- float sweep = exp(-pow((uv.x + uv.y * 0.4 - fract(iTime * 0.15) * 2.0 + 0.4) * 6.0, 2.0));
478
- vec3 col = mix(uShadow, uHighlight, l) + sweep * uSweep;
479
- fragColor = vec4(col, src.a);
538
+ fragColor = vec4(mix(uShadow, uHighlight, l), src.a);
480
539
  }`
481
540
  ),
482
541
  presets: [
@@ -10245,7 +10304,7 @@ var fireworks = {
10245
10304
  name: "Fireworks",
10246
10305
  description: "Shells rising on faint trails and bursting into peonies, chrysanthemums, gold willows and rings that droop and twinkle out; clicks fire more.",
10247
10306
  category: "pyrotechnics",
10248
- tags: ["pyro", "overlay", "fireworks", "celebration", "festive", "night", "click"],
10307
+ tags: ["pyro", "overlay", "fireworks", "celebration", "festive", "night", "click", "interactive"],
10249
10308
  transparent: true,
10250
10309
  source: glsl(
10251
10310
  `// Fireworks: staggered shells rising and bursting into peony, chrysanthemum, willow and ring patterns.
@@ -10464,7 +10523,7 @@ var explosion = {
10464
10523
  name: "Explosion",
10465
10524
  description: "A fireball cooling from white-hot to orange to rolling dark smoke, with a shockwave ring and flying debris; it loops and also goes off at each click.",
10466
10525
  category: "pyrotechnics",
10467
- tags: ["pyro", "overlay", "explosion", "fire", "smoke", "action", "click"],
10526
+ tags: ["pyro", "overlay", "explosion", "fire", "smoke", "action", "click", "interactive"],
10468
10527
  transparent: true,
10469
10528
  loop: 3,
10470
10529
  source: glsl(
@@ -11311,7 +11370,7 @@ var bulletTime = {
11311
11370
  description: "A shockwave sweeping out from the centre or a click, freezing the picture grey and zoomed behind it while the rest moves on.",
11312
11371
  category: "timewarp",
11313
11372
  video: "stills",
11314
- tags: ["time", "image", "freeze", "shockwave", "click", "cinematic"],
11373
+ tags: ["time", "image", "freeze", "shockwave", "click", "cinematic", "interactive"],
11315
11374
  loop: 8,
11316
11375
  source: glsl(
11317
11376
  `// Bullet time: every 4 s (or on a click) a wave freezes the picture behind it, then lets go.
@@ -11662,7 +11721,7 @@ var silhouetteMorph = {
11662
11721
  name: "Silhouette morph",
11663
11722
  description: "One silhouette or logo flowing into another as a gooey blob, its colour blending from the first shape's to the second's.",
11664
11723
  category: "morph",
11665
- video: "stills",
11724
+ video: "none",
11666
11725
  tags: ["morph", "shape", "logo", "goo", "blob", "text"],
11667
11726
  loop: 4,
11668
11727
  source: glsl(
@@ -20131,6 +20190,12 @@ var byId = new Map(EFFECTS.map((e) => [e.id, e]));
20131
20190
  function getEffect(id) {
20132
20191
  return byId.get(id);
20133
20192
  }
20193
+ var inputsCache = /* @__PURE__ */ new WeakMap();
20194
+ function effectInputs(effect) {
20195
+ let inputs = inputsCache.get(effect);
20196
+ if (!inputs) inputsCache.set(effect, inputs = inputsOf(effect, effectControls(effect)));
20197
+ return inputs;
20198
+ }
20134
20199
  function findEffects(query = {}) {
20135
20200
  const words = (query.text ?? "").toLowerCase().split(/\s+/).filter(Boolean);
20136
20201
  return EFFECTS.filter((e) => {
@@ -20138,6 +20203,15 @@ function findEffects(query = {}) {
20138
20203
  if (query.kind && e.kind !== query.kind) return false;
20139
20204
  if (query.tags && !query.tags.every((t) => e.tags.includes(t))) return false;
20140
20205
  if (query.video && !(e.kind === "shader" && e.video && query.video.includes(e.video))) return false;
20206
+ if (query.accepts || query.interaction || query.transparent !== void 0) {
20207
+ const inputs = effectInputs(e);
20208
+ if (query.accepts && !query.accepts.every((i) => inputs.accepts.includes(i))) return false;
20209
+ if (query.interaction) {
20210
+ const answers = query.interaction.length === 0 ? inputs.interactions.length === 0 : query.interaction.some((i) => inputs.interactions.includes(i));
20211
+ if (!answers) return false;
20212
+ }
20213
+ if (query.transparent !== void 0 && inputs.transparent !== query.transparent) return false;
20214
+ }
20141
20215
  const haystack = [e.id, e.name, e.description, e.category, ...e.tags].join(" ").toLowerCase();
20142
20216
  return words.every((w) => haystack.includes(w));
20143
20217
  });
@@ -20153,6 +20227,8 @@ function effectDefaults(effect, options = {}) {
20153
20227
  }
20154
20228
 
20155
20229
  export {
20230
+ EFFECT_INPUTS,
20231
+ EFFECT_INTERACTIONS,
20156
20232
  HASH,
20157
20233
  NOISE,
20158
20234
  FBM,
@@ -20178,8 +20254,9 @@ export {
20178
20254
  SHADER_EFFECTS,
20179
20255
  EFFECTS,
20180
20256
  getEffect,
20257
+ effectInputs,
20181
20258
  findEffects,
20182
20259
  effectControls,
20183
20260
  effectDefaults
20184
20261
  };
20185
- //# sourceMappingURL=chunk-ECBG5K6E.js.map
20262
+ //# sourceMappingURL=chunk-4F4KL4KU.js.map