@instantshader/react 0.5.0 → 0.6.1
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/README.md +42 -5
- package/dist/index.d.ts +55 -29
- package/dist/index.js +53 -17
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
React bindings for [instantshader](https://www.npmjs.com/package/instantshader), a
|
|
6
6
|
zero-dependency animated WebGL gradient engine. Drop a `<Flow>`, `<Beam>`, `<Bloom>`, `<Halo>`, `<Strata>`, `<Dune>` or
|
|
7
|
-
`<Whorl>` component into any sized wrapper to mount a live, animated gradient
|
|
8
|
-
|
|
7
|
+
`<Whorl>` component into any sized wrapper to mount a live, animated gradient, and
|
|
8
|
+
add dither, pixelate, halftone or ASCII effects over it or over your own image.
|
|
9
|
+
Built by [InstantGradient](https://instantgradient.com/app).
|
|
9
10
|
|
|
10
11
|
## Install
|
|
11
12
|
|
|
@@ -56,7 +57,43 @@ import { Bloom } from "@instantshader/react";
|
|
|
56
57
|
|
|
57
58
|
See the [`instantshader` README](https://www.npmjs.com/package/instantshader)
|
|
58
59
|
for what each param does and for the shader defs themselves (re-exported from
|
|
59
|
-
here as `flow`, `beam` and `
|
|
60
|
+
here as `flow`, `beam`, `bloom`, `halo`, `strata`, `dune` and `whorl`).
|
|
61
|
+
|
|
62
|
+
## Effects
|
|
63
|
+
|
|
64
|
+
Every shader component takes an `effects` prop: a list of layers, bottom
|
|
65
|
+
first, each an effect def with its params.
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import { Bloom, dither } from "@instantshader/react";
|
|
69
|
+
|
|
70
|
+
<Bloom
|
|
71
|
+
colors={["#140f30", "#9c2168", "#eb6a4e", "#fcd87c"]}
|
|
72
|
+
effects={[{ effect: dither, params: { pattern: "blueNoise", colorMode: "palette", levels: 4 } }]}
|
|
73
|
+
style={{ width: "100%", height: "100%" }}
|
|
74
|
+
/>;
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`<ShaderStack>` takes a `source` instead of a fixed shader, which is how you
|
|
78
|
+
put effects over an image. Any `<img>`, `<canvas>` or `<video>` element works
|
|
79
|
+
as `media`:
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
import { ShaderStack, halftone } from "@instantshader/react";
|
|
83
|
+
|
|
84
|
+
<ShaderStack
|
|
85
|
+
source={{ kind: "media", media: img, fit: "cover" }}
|
|
86
|
+
colors={["#111111", "#f4f1ea"]}
|
|
87
|
+
effects={[{ effect: halftone, params: { size: 20, angle: 30 } }]}
|
|
88
|
+
style={{ width: "100%", height: "100%" }}
|
|
89
|
+
/>;
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Changing `effects` or their params updates the canvas in place. A new
|
|
93
|
+
`source`, `seed`, `background` or `fontFamily` remounts it. The four effect
|
|
94
|
+
defs (`pixelate`, `dither`, `halftone`, `ascii`) are re-exported from here,
|
|
95
|
+
and the [repository README](https://github.com/ugolbck/instantshader#effects)
|
|
96
|
+
lists every param with its range.
|
|
60
97
|
|
|
61
98
|
## Seamless loops
|
|
62
99
|
|
|
@@ -67,7 +104,7 @@ at the wrap:
|
|
|
67
104
|
<Flow colors={colors} loopSeconds={30} style={{ width: "100%", height: "100%" }} />
|
|
68
105
|
```
|
|
69
106
|
|
|
70
|
-
15
|
|
71
|
-
seconds
|
|
107
|
+
15 to 60s is the comfortable range, and the period is measured in animation
|
|
108
|
+
seconds, so it interacts with `speed`. See the
|
|
72
109
|
[`instantshader` README](https://www.npmjs.com/package/instantshader) for the
|
|
73
110
|
full details.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,53 +1,79 @@
|
|
|
1
1
|
import { CSSProperties, ReactElement } from "react";
|
|
2
|
-
import { ParamDef, ShaderDef, ShaderDef as ShaderDef$1, beam, bloom, dune, flow, halo, strata, whorl } from "instantshader";
|
|
2
|
+
import { EffectDef, EffectLayer, EffectLayer as EffectLayer$1, EffectParamDef, ParamDef, ParamValue, ShaderDef, ShaderDef as ShaderDef$1, Source, Source as Source$1, ascii, beam, bloom, dither, dune, flow, halftone, halo, pixelate, strata, whorl } from "instantshader";
|
|
3
3
|
|
|
4
|
-
//#region src/
|
|
5
|
-
interface
|
|
6
|
-
|
|
4
|
+
//#region src/ShaderStack.d.ts
|
|
5
|
+
interface ShaderStackProps {
|
|
6
|
+
source: Source$1;
|
|
7
|
+
/** Effect layers, bottom to top. A new array with the same content does
|
|
8
|
+
* not recompile anything. */
|
|
9
|
+
effects?: EffectLayer$1[];
|
|
10
|
+
/** Palette. Generators draw with it; effects in "palette" color mode map
|
|
11
|
+
* tone through it. */
|
|
7
12
|
colors: string[];
|
|
8
13
|
/**
|
|
9
|
-
* Merged into the shader's current params (removed/omitted keys are NOT
|
|
10
|
-
* reset to their default — they keep whatever value was last applied).
|
|
11
|
-
* Setting this prop back to `undefined` does not revert to defaults
|
|
12
|
-
* either: the underlying MountHandle is only updated when `params` is
|
|
13
|
-
* truthy, so the last applied values simply stick.
|
|
14
|
-
*/
|
|
15
|
-
params?: Record<string, number>;
|
|
16
|
-
/**
|
|
17
14
|
* Setting this prop back to `undefined` does NOT revert playback to the
|
|
18
|
-
* default speed — the underlying
|
|
19
|
-
*
|
|
15
|
+
* default speed — the underlying handle is only updated when `speed` is
|
|
16
|
+
* not `undefined`, so whatever speed was last applied keeps playing.
|
|
20
17
|
*/
|
|
21
18
|
speed?: number;
|
|
22
19
|
seed?: number;
|
|
23
|
-
/**
|
|
24
|
-
*
|
|
25
|
-
* seconds. Unlike `params` and `speed`, setting this back to `undefined`
|
|
26
|
-
* DOES take effect — it turns looping off — because "no loop" is a real
|
|
27
|
-
* state the underlying handle can be put into.
|
|
28
|
-
*/
|
|
20
|
+
/** Makes the animation repeat seamlessly every `loopSeconds` animation
|
|
21
|
+
* seconds. Setting it back to `undefined` turns looping off. */
|
|
29
22
|
loopSeconds?: number;
|
|
30
23
|
paused?: boolean;
|
|
24
|
+
/** Shown behind contain-fit media and under media alpha. Mount-time only. */
|
|
25
|
+
background?: string;
|
|
26
|
+
/** CSS font-family for effects that draw text (ASCII). Load it first with
|
|
27
|
+
* `document.fonts.load`. Mount-time only. */
|
|
28
|
+
fontFamily?: string;
|
|
31
29
|
className?: string;
|
|
32
30
|
style?: CSSProperties;
|
|
33
31
|
}
|
|
34
32
|
/**
|
|
35
|
-
* Mounts a live
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* `position: relative`.
|
|
33
|
+
* Mounts a live stack into a wrapper `<div>`. The canvas fills that div at
|
|
34
|
+
* 100%/100%, so the consumer MUST give the wrapper an explicit size (via
|
|
35
|
+
* `style`, `className`, or a sized parent) — this component does not impose
|
|
36
|
+
* one beyond `position: relative`.
|
|
40
37
|
*/
|
|
41
|
-
declare function
|
|
42
|
-
|
|
38
|
+
declare function ShaderStack({
|
|
39
|
+
source,
|
|
40
|
+
effects,
|
|
43
41
|
colors,
|
|
44
|
-
params,
|
|
45
42
|
speed,
|
|
46
43
|
seed,
|
|
47
44
|
loopSeconds,
|
|
48
45
|
paused,
|
|
46
|
+
background,
|
|
47
|
+
fontFamily,
|
|
49
48
|
className,
|
|
50
49
|
style
|
|
50
|
+
}: ShaderStackProps): ReactElement;
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region src/ShaderCanvas.d.ts
|
|
53
|
+
interface ShaderCanvasProps extends Omit<ShaderStackProps, "source" | "effects" | "background"> {
|
|
54
|
+
shader: ShaderDef$1;
|
|
55
|
+
/**
|
|
56
|
+
* Merged into the shader's current params (removed/omitted keys are NOT
|
|
57
|
+
* reset to their default — they keep whatever value was last applied).
|
|
58
|
+
* Setting this prop back to `undefined` does not revert to defaults
|
|
59
|
+
* either: the underlying handle is only updated when `params` is truthy,
|
|
60
|
+
* so the last applied values simply stick.
|
|
61
|
+
*/
|
|
62
|
+
params?: Record<string, number>;
|
|
63
|
+
/** Effect layers drawn over the gradient, bottom to top:
|
|
64
|
+
* `[{ effect: dither, params: { size: 4, colorMode: "palette" } }]`. */
|
|
65
|
+
effects?: EffectLayer$1[];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Mounts a live InstantShader gradient, optionally with effects over it. See
|
|
69
|
+
* ShaderStack for sizing: the consumer MUST give the wrapper an explicit size.
|
|
70
|
+
* Remounts only when `shader` or `seed` changes.
|
|
71
|
+
*/
|
|
72
|
+
declare function ShaderCanvas({
|
|
73
|
+
shader,
|
|
74
|
+
params,
|
|
75
|
+
effects,
|
|
76
|
+
...rest
|
|
51
77
|
}: ShaderCanvasProps): ReactElement;
|
|
52
78
|
//#endregion
|
|
53
79
|
//#region src/shaders.d.ts
|
|
@@ -59,4 +85,4 @@ declare function Strata(props: Omit<ShaderCanvasProps, "shader">): ReactElement;
|
|
|
59
85
|
declare function Dune(props: Omit<ShaderCanvasProps, "shader">): ReactElement;
|
|
60
86
|
declare function Whorl(props: Omit<ShaderCanvasProps, "shader">): ReactElement;
|
|
61
87
|
//#endregion
|
|
62
|
-
export { Beam, Bloom, Dune, Flow, Halo, type ParamDef, ShaderCanvas, type ShaderCanvasProps, type ShaderDef, Strata, Whorl, beam, bloom, dune, flow, halo, strata, whorl };
|
|
88
|
+
export { Beam, Bloom, Dune, type EffectDef, type EffectLayer, type EffectParamDef, Flow, Halo, type ParamDef, type ParamValue, ShaderCanvas, type ShaderCanvasProps, type ShaderDef, ShaderStack, type ShaderStackProps, type Source, Strata, Whorl, ascii, beam, bloom, dither, dune, flow, halftone, halo, pixelate, strata, whorl };
|
package/dist/index.js
CHANGED
|
@@ -1,30 +1,38 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useEffect, useMemo, useRef } from "react";
|
|
3
|
-
import { beam, beam as beam$1, bloom, bloom as bloom$1, dune, dune as dune$1, flow, flow as flow$1, halo, halo as halo$1,
|
|
3
|
+
import { ascii, beam, beam as beam$1, bloom, bloom as bloom$1, dither, dune, dune as dune$1, flow, flow as flow$1, halftone, halo, halo as halo$1, mountStack, pixelate, strata, strata as strata$1, whorl, whorl as whorl$1 } from "instantshader";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
5
|
|
|
6
|
-
//#region src/
|
|
6
|
+
//#region src/ShaderStack.tsx
|
|
7
|
+
function sortedSig(o) {
|
|
8
|
+
if (!o) return "";
|
|
9
|
+
return Object.keys(o).sort().map((k) => `${k}:${String(o[k])}`).join(",");
|
|
10
|
+
}
|
|
7
11
|
/**
|
|
8
|
-
* Mounts a live
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* `position: relative`.
|
|
12
|
+
* Mounts a live stack into a wrapper `<div>`. The canvas fills that div at
|
|
13
|
+
* 100%/100%, so the consumer MUST give the wrapper an explicit size (via
|
|
14
|
+
* `style`, `className`, or a sized parent) — this component does not impose
|
|
15
|
+
* one beyond `position: relative`.
|
|
13
16
|
*/
|
|
14
|
-
function
|
|
17
|
+
function ShaderStack({ source, effects, colors, speed, seed, loopSeconds, paused, background, fontFamily, className, style }) {
|
|
15
18
|
const containerRef = useRef(null);
|
|
16
19
|
const handleRef = useRef(null);
|
|
17
|
-
const
|
|
20
|
+
const sourceIdentity = source.kind === "generator" ? source.shader : source.media;
|
|
21
|
+
const fit = source.kind === "media" ? source.fit : void 0;
|
|
22
|
+
const sourceParams = useMemo(() => source.kind === "generator" ? source.params : void 0, [source.kind === "generator" ? sortedSig(source.params) : ""]);
|
|
23
|
+
const layers = useMemo(() => effects ?? [], [(effects ?? []).map((l) => `${l.effect.id}|${l.enabled ?? true}|${sortedSig(l.params)}`).join(";")]);
|
|
18
24
|
useEffect(() => {
|
|
19
25
|
const container = containerRef.current;
|
|
20
26
|
if (!container) return;
|
|
21
|
-
const handle =
|
|
22
|
-
|
|
27
|
+
const handle = mountStack(container, {
|
|
28
|
+
source,
|
|
29
|
+
effects: layers,
|
|
23
30
|
colors,
|
|
24
|
-
params: p,
|
|
25
31
|
speed,
|
|
26
32
|
seed,
|
|
27
|
-
loopSeconds
|
|
33
|
+
loopSeconds,
|
|
34
|
+
background,
|
|
35
|
+
fontFamily
|
|
28
36
|
});
|
|
29
37
|
handleRef.current = handle;
|
|
30
38
|
if (paused) handle.pause();
|
|
@@ -32,13 +40,22 @@ function ShaderCanvas({ shader, colors, params, speed, seed, loopSeconds, paused
|
|
|
32
40
|
handle.dispose();
|
|
33
41
|
handleRef.current = null;
|
|
34
42
|
};
|
|
35
|
-
}, [
|
|
43
|
+
}, [
|
|
44
|
+
sourceIdentity,
|
|
45
|
+
fit,
|
|
46
|
+
seed,
|
|
47
|
+
background,
|
|
48
|
+
fontFamily
|
|
49
|
+
]);
|
|
36
50
|
useEffect(() => {
|
|
37
51
|
handleRef.current?.setColors(colors);
|
|
38
52
|
}, [colors]);
|
|
39
53
|
useEffect(() => {
|
|
40
|
-
if (
|
|
41
|
-
}, [
|
|
54
|
+
if (sourceParams) handleRef.current?.setSourceParams(sourceParams);
|
|
55
|
+
}, [sourceParams]);
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
handleRef.current?.setEffects(layers);
|
|
58
|
+
}, [layers]);
|
|
42
59
|
useEffect(() => {
|
|
43
60
|
if (speed !== void 0) handleRef.current?.setSpeed(speed);
|
|
44
61
|
}, [speed]);
|
|
@@ -59,6 +76,25 @@ function ShaderCanvas({ shader, colors, params, speed, seed, loopSeconds, paused
|
|
|
59
76
|
});
|
|
60
77
|
}
|
|
61
78
|
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region src/ShaderCanvas.tsx
|
|
81
|
+
/**
|
|
82
|
+
* Mounts a live InstantShader gradient, optionally with effects over it. See
|
|
83
|
+
* ShaderStack for sizing: the consumer MUST give the wrapper an explicit size.
|
|
84
|
+
* Remounts only when `shader` or `seed` changes.
|
|
85
|
+
*/
|
|
86
|
+
function ShaderCanvas({ shader, params, effects,...rest }) {
|
|
87
|
+
return /* @__PURE__ */ jsx(ShaderStack, {
|
|
88
|
+
source: {
|
|
89
|
+
kind: "generator",
|
|
90
|
+
shader,
|
|
91
|
+
params
|
|
92
|
+
},
|
|
93
|
+
effects,
|
|
94
|
+
...rest
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
62
98
|
//#endregion
|
|
63
99
|
//#region src/shaders.tsx
|
|
64
100
|
function Flow(props) {
|
|
@@ -105,4 +141,4 @@ function Whorl(props) {
|
|
|
105
141
|
}
|
|
106
142
|
|
|
107
143
|
//#endregion
|
|
108
|
-
export { Beam, Bloom, Dune, Flow, Halo, ShaderCanvas, Strata, Whorl, beam, bloom, dune, flow, halo, strata, whorl };
|
|
144
|
+
export { Beam, Bloom, Dune, Flow, Halo, ShaderCanvas, ShaderStack, Strata, Whorl, ascii, beam, bloom, dither, dune, flow, halftone, halo, pixelate, strata, whorl };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@instantshader/react",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "React
|
|
3
|
+
"version": "0.6.1",
|
|
4
|
+
"description": "React components for InstantShader: animated WebGL gradients and image effects.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"react"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"instantshader": "0.
|
|
39
|
+
"instantshader": "0.6.1"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"react": "^18 || ^19",
|