react-shadertoy 0.1.0 → 0.3.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/dist/index.d.mts +15 -3
- package/dist/index.d.ts +15 -3
- package/dist/index.js +287 -29
- package/dist/index.mjs +247 -14
- package/package.json +1 -1
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { CSSProperties, RefObject } from 'react';
|
|
3
3
|
|
|
4
|
+
/** Texture source: URL string, or an HTML element for dynamic textures */
|
|
5
|
+
type TextureSource = string | HTMLImageElement | HTMLVideoElement | HTMLCanvasElement;
|
|
6
|
+
/** Texture inputs mapped to Shadertoy channels */
|
|
7
|
+
type TextureInputs = {
|
|
8
|
+
iChannel0?: TextureSource;
|
|
9
|
+
iChannel1?: TextureSource;
|
|
10
|
+
iChannel2?: TextureSource;
|
|
11
|
+
iChannel3?: TextureSource;
|
|
12
|
+
};
|
|
4
13
|
interface ShadertoyProps {
|
|
5
14
|
/** Shadertoy-compatible GLSL fragment shader (must contain mainImage) */
|
|
6
15
|
fragmentShader: string;
|
|
16
|
+
/** Texture inputs for iChannel0-3 */
|
|
17
|
+
textures?: TextureInputs;
|
|
7
18
|
/** Container style */
|
|
8
19
|
style?: CSSProperties;
|
|
9
20
|
/** Container className */
|
|
@@ -23,6 +34,7 @@ interface ShadertoyProps {
|
|
|
23
34
|
}
|
|
24
35
|
interface UseShadertoyOptions {
|
|
25
36
|
fragmentShader: string;
|
|
37
|
+
textures?: TextureInputs;
|
|
26
38
|
paused?: boolean;
|
|
27
39
|
speed?: number;
|
|
28
40
|
pixelRatio?: number;
|
|
@@ -38,8 +50,8 @@ interface UseShadertoyReturn {
|
|
|
38
50
|
resume: () => void;
|
|
39
51
|
}
|
|
40
52
|
|
|
41
|
-
declare function Shadertoy({ fragmentShader, style, className, paused, speed, pixelRatio, mouse, onError, onLoad, }: ShadertoyProps): react_jsx_runtime.JSX.Element;
|
|
53
|
+
declare function Shadertoy({ fragmentShader, textures, style, className, paused, speed, pixelRatio, mouse, onError, onLoad, }: ShadertoyProps): react_jsx_runtime.JSX.Element;
|
|
42
54
|
|
|
43
|
-
declare function useShadertoy({ fragmentShader, paused, speed, pixelRatio, mouse: mouseEnabled, onError, onLoad, }: UseShadertoyOptions): UseShadertoyReturn;
|
|
55
|
+
declare function useShadertoy({ fragmentShader, textures: texturesProp, paused, speed, pixelRatio, mouse: mouseEnabled, onError, onLoad, }: UseShadertoyOptions): UseShadertoyReturn;
|
|
44
56
|
|
|
45
|
-
export { Shadertoy, type ShadertoyProps, type UseShadertoyOptions, type UseShadertoyReturn, useShadertoy };
|
|
57
|
+
export { Shadertoy, type ShadertoyProps, type TextureInputs, type UseShadertoyOptions, type UseShadertoyReturn, useShadertoy };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { CSSProperties, RefObject } from 'react';
|
|
3
3
|
|
|
4
|
+
/** Texture source: URL string, or an HTML element for dynamic textures */
|
|
5
|
+
type TextureSource = string | HTMLImageElement | HTMLVideoElement | HTMLCanvasElement;
|
|
6
|
+
/** Texture inputs mapped to Shadertoy channels */
|
|
7
|
+
type TextureInputs = {
|
|
8
|
+
iChannel0?: TextureSource;
|
|
9
|
+
iChannel1?: TextureSource;
|
|
10
|
+
iChannel2?: TextureSource;
|
|
11
|
+
iChannel3?: TextureSource;
|
|
12
|
+
};
|
|
4
13
|
interface ShadertoyProps {
|
|
5
14
|
/** Shadertoy-compatible GLSL fragment shader (must contain mainImage) */
|
|
6
15
|
fragmentShader: string;
|
|
16
|
+
/** Texture inputs for iChannel0-3 */
|
|
17
|
+
textures?: TextureInputs;
|
|
7
18
|
/** Container style */
|
|
8
19
|
style?: CSSProperties;
|
|
9
20
|
/** Container className */
|
|
@@ -23,6 +34,7 @@ interface ShadertoyProps {
|
|
|
23
34
|
}
|
|
24
35
|
interface UseShadertoyOptions {
|
|
25
36
|
fragmentShader: string;
|
|
37
|
+
textures?: TextureInputs;
|
|
26
38
|
paused?: boolean;
|
|
27
39
|
speed?: number;
|
|
28
40
|
pixelRatio?: number;
|
|
@@ -38,8 +50,8 @@ interface UseShadertoyReturn {
|
|
|
38
50
|
resume: () => void;
|
|
39
51
|
}
|
|
40
52
|
|
|
41
|
-
declare function Shadertoy({ fragmentShader, style, className, paused, speed, pixelRatio, mouse, onError, onLoad, }: ShadertoyProps): react_jsx_runtime.JSX.Element;
|
|
53
|
+
declare function Shadertoy({ fragmentShader, textures, style, className, paused, speed, pixelRatio, mouse, onError, onLoad, }: ShadertoyProps): react_jsx_runtime.JSX.Element;
|
|
42
54
|
|
|
43
|
-
declare function useShadertoy({ fragmentShader, paused, speed, pixelRatio, mouse: mouseEnabled, onError, onLoad, }: UseShadertoyOptions): UseShadertoyReturn;
|
|
55
|
+
declare function useShadertoy({ fragmentShader, textures: texturesProp, paused, speed, pixelRatio, mouse: mouseEnabled, onError, onLoad, }: UseShadertoyOptions): UseShadertoyReturn;
|
|
44
56
|
|
|
45
|
-
export { Shadertoy, type ShadertoyProps, type UseShadertoyOptions, type UseShadertoyReturn, useShadertoy };
|
|
57
|
+
export { Shadertoy, type ShadertoyProps, type TextureInputs, type UseShadertoyOptions, type UseShadertoyReturn, useShadertoy };
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,32 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
2
19
|
|
|
3
|
-
|
|
4
|
-
var
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
Shadertoy: () => Shadertoy,
|
|
24
|
+
useShadertoy: () => useShadertoy
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(index_exports);
|
|
5
27
|
|
|
6
28
|
// src/useShadertoy.ts
|
|
29
|
+
var import_react = require("react");
|
|
7
30
|
|
|
8
31
|
// src/renderer.ts
|
|
9
32
|
var QUAD_VERTICES = new Float32Array([
|
|
@@ -35,6 +58,14 @@ uniform float iTimeDelta;
|
|
|
35
58
|
uniform int iFrame;
|
|
36
59
|
uniform vec4 iMouse;
|
|
37
60
|
uniform vec4 iDate;
|
|
61
|
+
uniform sampler2D iChannel0;
|
|
62
|
+
uniform sampler2D iChannel1;
|
|
63
|
+
uniform sampler2D iChannel2;
|
|
64
|
+
uniform sampler2D iChannel3;
|
|
65
|
+
uniform vec3 iChannelResolution[4];
|
|
66
|
+
|
|
67
|
+
// Shadertoy compatibility: texture() is GLSL 300 es, WebGL1 uses texture2D()
|
|
68
|
+
#define texture texture2D
|
|
38
69
|
|
|
39
70
|
${shader}
|
|
40
71
|
|
|
@@ -90,13 +121,21 @@ function createRenderer(canvas, fragmentShader) {
|
|
|
90
121
|
iTimeDelta: gl.getUniformLocation(program, "iTimeDelta"),
|
|
91
122
|
iFrame: gl.getUniformLocation(program, "iFrame"),
|
|
92
123
|
iMouse: gl.getUniformLocation(program, "iMouse"),
|
|
93
|
-
iDate: gl.getUniformLocation(program, "iDate")
|
|
124
|
+
iDate: gl.getUniformLocation(program, "iDate"),
|
|
125
|
+
iChannel: [
|
|
126
|
+
gl.getUniformLocation(program, "iChannel0"),
|
|
127
|
+
gl.getUniformLocation(program, "iChannel1"),
|
|
128
|
+
gl.getUniformLocation(program, "iChannel2"),
|
|
129
|
+
gl.getUniformLocation(program, "iChannel3")
|
|
130
|
+
],
|
|
131
|
+
iChannelResolution: gl.getUniformLocation(program, "iChannelResolution")
|
|
94
132
|
};
|
|
95
133
|
gl.useProgram(program);
|
|
96
134
|
return {
|
|
97
135
|
gl,
|
|
98
136
|
program,
|
|
99
137
|
locations,
|
|
138
|
+
textures: [null, null, null, null],
|
|
100
139
|
time: 0,
|
|
101
140
|
frame: 0,
|
|
102
141
|
lastTime: 0
|
|
@@ -113,6 +152,178 @@ function dispose(state) {
|
|
|
113
152
|
gl.getExtension("WEBGL_lose_context")?.loseContext();
|
|
114
153
|
}
|
|
115
154
|
|
|
155
|
+
// src/textures.ts
|
|
156
|
+
function isPOT(v) {
|
|
157
|
+
return (v & v - 1) === 0 && v > 0;
|
|
158
|
+
}
|
|
159
|
+
function initTexture(gl, unit) {
|
|
160
|
+
const texture = gl.createTexture();
|
|
161
|
+
gl.activeTexture(gl.TEXTURE0 + unit);
|
|
162
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
163
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
164
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
165
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
166
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
167
|
+
return texture;
|
|
168
|
+
}
|
|
169
|
+
function uploadElement(gl, texture, unit, el) {
|
|
170
|
+
gl.activeTexture(gl.TEXTURE0 + unit);
|
|
171
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
172
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, el);
|
|
173
|
+
}
|
|
174
|
+
function createTexture(gl, source, unit) {
|
|
175
|
+
const texture = initTexture(gl, unit);
|
|
176
|
+
if (typeof source === "string") {
|
|
177
|
+
gl.texImage2D(
|
|
178
|
+
gl.TEXTURE_2D,
|
|
179
|
+
0,
|
|
180
|
+
gl.RGBA,
|
|
181
|
+
1,
|
|
182
|
+
1,
|
|
183
|
+
0,
|
|
184
|
+
gl.RGBA,
|
|
185
|
+
gl.UNSIGNED_BYTE,
|
|
186
|
+
new Uint8Array([255, 0, 255, 255])
|
|
187
|
+
);
|
|
188
|
+
const state2 = {
|
|
189
|
+
texture,
|
|
190
|
+
width: 1,
|
|
191
|
+
height: 1,
|
|
192
|
+
unit,
|
|
193
|
+
loaded: false,
|
|
194
|
+
needsUpdate: false,
|
|
195
|
+
source
|
|
196
|
+
};
|
|
197
|
+
const promise = new Promise((resolve, reject) => {
|
|
198
|
+
const img = new Image();
|
|
199
|
+
img.crossOrigin = "anonymous";
|
|
200
|
+
img.onload = () => {
|
|
201
|
+
if (gl.isContextLost()) {
|
|
202
|
+
resolve();
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
uploadElement(gl, texture, unit, img);
|
|
206
|
+
if (isPOT(img.width) && isPOT(img.height)) {
|
|
207
|
+
gl.generateMipmap(gl.TEXTURE_2D);
|
|
208
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
|
|
209
|
+
}
|
|
210
|
+
state2.width = img.width;
|
|
211
|
+
state2.height = img.height;
|
|
212
|
+
state2.loaded = true;
|
|
213
|
+
resolve();
|
|
214
|
+
};
|
|
215
|
+
img.onerror = () => reject(new Error(`Failed to load texture: ${source}`));
|
|
216
|
+
img.src = source;
|
|
217
|
+
});
|
|
218
|
+
return { state: state2, promise };
|
|
219
|
+
}
|
|
220
|
+
if (source instanceof HTMLImageElement) {
|
|
221
|
+
const state2 = {
|
|
222
|
+
texture,
|
|
223
|
+
width: source.naturalWidth || 1,
|
|
224
|
+
height: source.naturalHeight || 1,
|
|
225
|
+
unit,
|
|
226
|
+
loaded: source.complete,
|
|
227
|
+
needsUpdate: false,
|
|
228
|
+
source
|
|
229
|
+
};
|
|
230
|
+
if (source.complete && source.naturalWidth > 0) {
|
|
231
|
+
uploadElement(gl, texture, unit, source);
|
|
232
|
+
state2.width = source.naturalWidth;
|
|
233
|
+
state2.height = source.naturalHeight;
|
|
234
|
+
return { state: state2, promise: null };
|
|
235
|
+
}
|
|
236
|
+
const promise = new Promise((resolve, reject) => {
|
|
237
|
+
source.onload = () => {
|
|
238
|
+
if (gl.isContextLost()) {
|
|
239
|
+
resolve();
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
uploadElement(gl, texture, unit, source);
|
|
243
|
+
state2.width = source.naturalWidth;
|
|
244
|
+
state2.height = source.naturalHeight;
|
|
245
|
+
state2.loaded = true;
|
|
246
|
+
resolve();
|
|
247
|
+
};
|
|
248
|
+
source.onerror = () => reject(new Error("Failed to load image element"));
|
|
249
|
+
});
|
|
250
|
+
return { state: state2, promise };
|
|
251
|
+
}
|
|
252
|
+
if (source instanceof HTMLVideoElement) {
|
|
253
|
+
const w = source.videoWidth || 1;
|
|
254
|
+
const h = source.videoHeight || 1;
|
|
255
|
+
if (source.readyState >= 2) {
|
|
256
|
+
uploadElement(gl, texture, unit, source);
|
|
257
|
+
} else {
|
|
258
|
+
gl.texImage2D(
|
|
259
|
+
gl.TEXTURE_2D,
|
|
260
|
+
0,
|
|
261
|
+
gl.RGBA,
|
|
262
|
+
1,
|
|
263
|
+
1,
|
|
264
|
+
0,
|
|
265
|
+
gl.RGBA,
|
|
266
|
+
gl.UNSIGNED_BYTE,
|
|
267
|
+
new Uint8Array([0, 0, 0, 255])
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
const state2 = {
|
|
271
|
+
texture,
|
|
272
|
+
width: w,
|
|
273
|
+
height: h,
|
|
274
|
+
unit,
|
|
275
|
+
loaded: source.readyState >= 2,
|
|
276
|
+
needsUpdate: true,
|
|
277
|
+
source
|
|
278
|
+
};
|
|
279
|
+
return { state: state2, promise: null };
|
|
280
|
+
}
|
|
281
|
+
uploadElement(gl, texture, unit, source);
|
|
282
|
+
const state = {
|
|
283
|
+
texture,
|
|
284
|
+
width: source.width,
|
|
285
|
+
height: source.height,
|
|
286
|
+
unit,
|
|
287
|
+
loaded: true,
|
|
288
|
+
needsUpdate: true,
|
|
289
|
+
source
|
|
290
|
+
};
|
|
291
|
+
return { state, promise: null };
|
|
292
|
+
}
|
|
293
|
+
function updateDynamicTextures(gl, textures) {
|
|
294
|
+
for (const tex of textures) {
|
|
295
|
+
if (!tex || !tex.needsUpdate || !tex.source) continue;
|
|
296
|
+
if (tex.source instanceof HTMLVideoElement) {
|
|
297
|
+
const v = tex.source;
|
|
298
|
+
if (v.readyState < 2) continue;
|
|
299
|
+
uploadElement(gl, tex.texture, tex.unit, v);
|
|
300
|
+
tex.width = v.videoWidth;
|
|
301
|
+
tex.height = v.videoHeight;
|
|
302
|
+
tex.loaded = true;
|
|
303
|
+
} else if (tex.source instanceof HTMLCanvasElement) {
|
|
304
|
+
uploadElement(gl, tex.texture, tex.unit, tex.source);
|
|
305
|
+
tex.width = tex.source.width;
|
|
306
|
+
tex.height = tex.source.height;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
function bindTextures(gl, locations, textures) {
|
|
311
|
+
for (let i = 0; i < 4; i++) {
|
|
312
|
+
const tex = textures[i];
|
|
313
|
+
if (!tex) continue;
|
|
314
|
+
gl.activeTexture(gl.TEXTURE0 + tex.unit);
|
|
315
|
+
gl.bindTexture(gl.TEXTURE_2D, tex.texture);
|
|
316
|
+
if (locations[i]) {
|
|
317
|
+
gl.uniform1i(locations[i], tex.unit);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
function disposeTextures(gl, textures) {
|
|
322
|
+
for (const tex of textures) {
|
|
323
|
+
if (tex) gl.deleteTexture(tex.texture);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
116
327
|
// src/uniforms.ts
|
|
117
328
|
function updateUniforms(state, delta, speed, mouse) {
|
|
118
329
|
const { gl, locations } = state;
|
|
@@ -140,6 +351,18 @@ function updateUniforms(state, delta, speed, mouse) {
|
|
|
140
351
|
const mw = mouse.pressed ? mouse.clickY : -Math.abs(mouse.clickY);
|
|
141
352
|
gl.uniform4f(locations.iMouse, mouse.x, mouse.y, mz, mw);
|
|
142
353
|
}
|
|
354
|
+
if (locations.iChannelResolution) {
|
|
355
|
+
const res = new Float32Array(12);
|
|
356
|
+
for (let i = 0; i < 4; i++) {
|
|
357
|
+
const tex = state.textures[i];
|
|
358
|
+
if (tex) {
|
|
359
|
+
res[i * 3] = tex.width;
|
|
360
|
+
res[i * 3 + 1] = tex.height;
|
|
361
|
+
res[i * 3 + 2] = 1;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
gl.uniform3fv(locations.iChannelResolution, res);
|
|
365
|
+
}
|
|
143
366
|
if (locations.iDate) {
|
|
144
367
|
const now = /* @__PURE__ */ new Date();
|
|
145
368
|
const seconds = now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds() + now.getMilliseconds() / 1e3;
|
|
@@ -155,8 +378,10 @@ function updateUniforms(state, delta, speed, mouse) {
|
|
|
155
378
|
}
|
|
156
379
|
|
|
157
380
|
// src/useShadertoy.ts
|
|
381
|
+
var CHANNEL_KEYS = ["iChannel0", "iChannel1", "iChannel2", "iChannel3"];
|
|
158
382
|
function useShadertoy({
|
|
159
383
|
fragmentShader,
|
|
384
|
+
textures: texturesProp,
|
|
160
385
|
paused = false,
|
|
161
386
|
speed = 1,
|
|
162
387
|
pixelRatio,
|
|
@@ -164,14 +389,14 @@ function useShadertoy({
|
|
|
164
389
|
onError,
|
|
165
390
|
onLoad
|
|
166
391
|
}) {
|
|
167
|
-
const canvasRef =
|
|
168
|
-
const rendererRef =
|
|
169
|
-
const rafRef =
|
|
170
|
-
const pausedRef =
|
|
171
|
-
const speedRef =
|
|
172
|
-
const [isReady, setIsReady] =
|
|
173
|
-
const [error, setError] =
|
|
174
|
-
const mouseState =
|
|
392
|
+
const canvasRef = (0, import_react.useRef)(null);
|
|
393
|
+
const rendererRef = (0, import_react.useRef)(null);
|
|
394
|
+
const rafRef = (0, import_react.useRef)(0);
|
|
395
|
+
const pausedRef = (0, import_react.useRef)(paused);
|
|
396
|
+
const speedRef = (0, import_react.useRef)(speed);
|
|
397
|
+
const [isReady, setIsReady] = (0, import_react.useState)(false);
|
|
398
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
399
|
+
const mouseState = (0, import_react.useRef)({
|
|
175
400
|
x: 0,
|
|
176
401
|
y: 0,
|
|
177
402
|
clickX: 0,
|
|
@@ -180,7 +405,7 @@ function useShadertoy({
|
|
|
180
405
|
});
|
|
181
406
|
pausedRef.current = paused;
|
|
182
407
|
speedRef.current = speed;
|
|
183
|
-
|
|
408
|
+
(0, import_react.useEffect)(() => {
|
|
184
409
|
const canvas = canvasRef.current;
|
|
185
410
|
if (!canvas) return;
|
|
186
411
|
const result = createRenderer(canvas, fragmentShader);
|
|
@@ -190,16 +415,43 @@ function useShadertoy({
|
|
|
190
415
|
return;
|
|
191
416
|
}
|
|
192
417
|
rendererRef.current = result;
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
418
|
+
const texturePromises = [];
|
|
419
|
+
if (texturesProp) {
|
|
420
|
+
for (let i = 0; i < 4; i++) {
|
|
421
|
+
const src = texturesProp[CHANNEL_KEYS[i]];
|
|
422
|
+
if (src != null) {
|
|
423
|
+
const { state, promise } = createTexture(result.gl, src, i);
|
|
424
|
+
result.textures[i] = state;
|
|
425
|
+
if (promise) texturePromises.push(promise);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
const markReady = () => {
|
|
430
|
+
setIsReady(true);
|
|
431
|
+
setError(null);
|
|
432
|
+
onLoad?.();
|
|
433
|
+
};
|
|
434
|
+
if (texturePromises.length > 0) {
|
|
435
|
+
Promise.all(texturePromises).then(() => {
|
|
436
|
+
if (rendererRef.current) markReady();
|
|
437
|
+
}).catch((err) => {
|
|
438
|
+
const msg = err instanceof Error ? err.message : "Texture load failed";
|
|
439
|
+
setError(msg);
|
|
440
|
+
onError?.(msg);
|
|
441
|
+
});
|
|
442
|
+
} else {
|
|
443
|
+
markReady();
|
|
444
|
+
}
|
|
196
445
|
let lastTimestamp = 0;
|
|
197
446
|
const loop = (timestamp) => {
|
|
198
447
|
const delta = lastTimestamp ? (timestamp - lastTimestamp) / 1e3 : 0;
|
|
199
448
|
lastTimestamp = timestamp;
|
|
200
449
|
if (!pausedRef.current && rendererRef.current) {
|
|
201
|
-
|
|
202
|
-
|
|
450
|
+
const r = rendererRef.current;
|
|
451
|
+
updateDynamicTextures(r.gl, r.textures);
|
|
452
|
+
bindTextures(r.gl, r.locations.iChannel, r.textures);
|
|
453
|
+
updateUniforms(r, delta, speedRef.current, mouseState.current);
|
|
454
|
+
render(r);
|
|
203
455
|
}
|
|
204
456
|
rafRef.current = requestAnimationFrame(loop);
|
|
205
457
|
};
|
|
@@ -207,13 +459,14 @@ function useShadertoy({
|
|
|
207
459
|
return () => {
|
|
208
460
|
cancelAnimationFrame(rafRef.current);
|
|
209
461
|
if (rendererRef.current) {
|
|
462
|
+
disposeTextures(rendererRef.current.gl, rendererRef.current.textures);
|
|
210
463
|
dispose(rendererRef.current);
|
|
211
464
|
rendererRef.current = null;
|
|
212
465
|
}
|
|
213
466
|
setIsReady(false);
|
|
214
467
|
};
|
|
215
|
-
}, [fragmentShader, onError, onLoad]);
|
|
216
|
-
|
|
468
|
+
}, [fragmentShader, texturesProp, onError, onLoad]);
|
|
469
|
+
(0, import_react.useEffect)(() => {
|
|
217
470
|
const canvas = canvasRef.current;
|
|
218
471
|
if (!canvas) return;
|
|
219
472
|
const dpr = pixelRatio ?? (typeof window !== "undefined" ? window.devicePixelRatio : 1);
|
|
@@ -227,7 +480,7 @@ function useShadertoy({
|
|
|
227
480
|
observer.observe(canvas);
|
|
228
481
|
return () => observer.disconnect();
|
|
229
482
|
}, [pixelRatio]);
|
|
230
|
-
|
|
483
|
+
(0, import_react.useEffect)(() => {
|
|
231
484
|
if (!mouseEnabled) return;
|
|
232
485
|
const canvas = canvasRef.current;
|
|
233
486
|
if (!canvas) return;
|
|
@@ -282,16 +535,20 @@ function useShadertoy({
|
|
|
282
535
|
window.removeEventListener("touchend", te);
|
|
283
536
|
};
|
|
284
537
|
}, [mouseEnabled, pixelRatio]);
|
|
285
|
-
const pause =
|
|
538
|
+
const pause = (0, import_react.useCallback)(() => {
|
|
286
539
|
pausedRef.current = true;
|
|
287
540
|
}, []);
|
|
288
|
-
const resume =
|
|
541
|
+
const resume = (0, import_react.useCallback)(() => {
|
|
289
542
|
pausedRef.current = false;
|
|
290
543
|
}, []);
|
|
291
544
|
return { canvasRef, isReady, error, pause, resume };
|
|
292
545
|
}
|
|
546
|
+
|
|
547
|
+
// src/Shadertoy.tsx
|
|
548
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
293
549
|
function Shadertoy({
|
|
294
550
|
fragmentShader,
|
|
551
|
+
textures,
|
|
295
552
|
style,
|
|
296
553
|
className,
|
|
297
554
|
paused,
|
|
@@ -303,6 +560,7 @@ function Shadertoy({
|
|
|
303
560
|
}) {
|
|
304
561
|
const { canvasRef } = useShadertoy({
|
|
305
562
|
fragmentShader,
|
|
563
|
+
textures,
|
|
306
564
|
paused,
|
|
307
565
|
speed,
|
|
308
566
|
pixelRatio,
|
|
@@ -310,7 +568,7 @@ function Shadertoy({
|
|
|
310
568
|
onError,
|
|
311
569
|
onLoad
|
|
312
570
|
});
|
|
313
|
-
return /* @__PURE__ */
|
|
571
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
314
572
|
"canvas",
|
|
315
573
|
{
|
|
316
574
|
ref: canvasRef,
|
|
@@ -319,8 +577,8 @@ function Shadertoy({
|
|
|
319
577
|
}
|
|
320
578
|
);
|
|
321
579
|
}
|
|
322
|
-
|
|
323
|
-
exports
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
580
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
581
|
+
0 && (module.exports = {
|
|
582
|
+
Shadertoy,
|
|
583
|
+
useShadertoy
|
|
584
|
+
});
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { useRef, useState, useEffect, useCallback } from 'react';
|
|
2
|
-
import { jsx } from 'react/jsx-runtime';
|
|
3
|
-
|
|
4
1
|
// src/useShadertoy.ts
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
5
3
|
|
|
6
4
|
// src/renderer.ts
|
|
7
5
|
var QUAD_VERTICES = new Float32Array([
|
|
@@ -33,6 +31,14 @@ uniform float iTimeDelta;
|
|
|
33
31
|
uniform int iFrame;
|
|
34
32
|
uniform vec4 iMouse;
|
|
35
33
|
uniform vec4 iDate;
|
|
34
|
+
uniform sampler2D iChannel0;
|
|
35
|
+
uniform sampler2D iChannel1;
|
|
36
|
+
uniform sampler2D iChannel2;
|
|
37
|
+
uniform sampler2D iChannel3;
|
|
38
|
+
uniform vec3 iChannelResolution[4];
|
|
39
|
+
|
|
40
|
+
// Shadertoy compatibility: texture() is GLSL 300 es, WebGL1 uses texture2D()
|
|
41
|
+
#define texture texture2D
|
|
36
42
|
|
|
37
43
|
${shader}
|
|
38
44
|
|
|
@@ -88,13 +94,21 @@ function createRenderer(canvas, fragmentShader) {
|
|
|
88
94
|
iTimeDelta: gl.getUniformLocation(program, "iTimeDelta"),
|
|
89
95
|
iFrame: gl.getUniformLocation(program, "iFrame"),
|
|
90
96
|
iMouse: gl.getUniformLocation(program, "iMouse"),
|
|
91
|
-
iDate: gl.getUniformLocation(program, "iDate")
|
|
97
|
+
iDate: gl.getUniformLocation(program, "iDate"),
|
|
98
|
+
iChannel: [
|
|
99
|
+
gl.getUniformLocation(program, "iChannel0"),
|
|
100
|
+
gl.getUniformLocation(program, "iChannel1"),
|
|
101
|
+
gl.getUniformLocation(program, "iChannel2"),
|
|
102
|
+
gl.getUniformLocation(program, "iChannel3")
|
|
103
|
+
],
|
|
104
|
+
iChannelResolution: gl.getUniformLocation(program, "iChannelResolution")
|
|
92
105
|
};
|
|
93
106
|
gl.useProgram(program);
|
|
94
107
|
return {
|
|
95
108
|
gl,
|
|
96
109
|
program,
|
|
97
110
|
locations,
|
|
111
|
+
textures: [null, null, null, null],
|
|
98
112
|
time: 0,
|
|
99
113
|
frame: 0,
|
|
100
114
|
lastTime: 0
|
|
@@ -111,6 +125,178 @@ function dispose(state) {
|
|
|
111
125
|
gl.getExtension("WEBGL_lose_context")?.loseContext();
|
|
112
126
|
}
|
|
113
127
|
|
|
128
|
+
// src/textures.ts
|
|
129
|
+
function isPOT(v) {
|
|
130
|
+
return (v & v - 1) === 0 && v > 0;
|
|
131
|
+
}
|
|
132
|
+
function initTexture(gl, unit) {
|
|
133
|
+
const texture = gl.createTexture();
|
|
134
|
+
gl.activeTexture(gl.TEXTURE0 + unit);
|
|
135
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
136
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
137
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
138
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
139
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
140
|
+
return texture;
|
|
141
|
+
}
|
|
142
|
+
function uploadElement(gl, texture, unit, el) {
|
|
143
|
+
gl.activeTexture(gl.TEXTURE0 + unit);
|
|
144
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
145
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, el);
|
|
146
|
+
}
|
|
147
|
+
function createTexture(gl, source, unit) {
|
|
148
|
+
const texture = initTexture(gl, unit);
|
|
149
|
+
if (typeof source === "string") {
|
|
150
|
+
gl.texImage2D(
|
|
151
|
+
gl.TEXTURE_2D,
|
|
152
|
+
0,
|
|
153
|
+
gl.RGBA,
|
|
154
|
+
1,
|
|
155
|
+
1,
|
|
156
|
+
0,
|
|
157
|
+
gl.RGBA,
|
|
158
|
+
gl.UNSIGNED_BYTE,
|
|
159
|
+
new Uint8Array([255, 0, 255, 255])
|
|
160
|
+
);
|
|
161
|
+
const state2 = {
|
|
162
|
+
texture,
|
|
163
|
+
width: 1,
|
|
164
|
+
height: 1,
|
|
165
|
+
unit,
|
|
166
|
+
loaded: false,
|
|
167
|
+
needsUpdate: false,
|
|
168
|
+
source
|
|
169
|
+
};
|
|
170
|
+
const promise = new Promise((resolve, reject) => {
|
|
171
|
+
const img = new Image();
|
|
172
|
+
img.crossOrigin = "anonymous";
|
|
173
|
+
img.onload = () => {
|
|
174
|
+
if (gl.isContextLost()) {
|
|
175
|
+
resolve();
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
uploadElement(gl, texture, unit, img);
|
|
179
|
+
if (isPOT(img.width) && isPOT(img.height)) {
|
|
180
|
+
gl.generateMipmap(gl.TEXTURE_2D);
|
|
181
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
|
|
182
|
+
}
|
|
183
|
+
state2.width = img.width;
|
|
184
|
+
state2.height = img.height;
|
|
185
|
+
state2.loaded = true;
|
|
186
|
+
resolve();
|
|
187
|
+
};
|
|
188
|
+
img.onerror = () => reject(new Error(`Failed to load texture: ${source}`));
|
|
189
|
+
img.src = source;
|
|
190
|
+
});
|
|
191
|
+
return { state: state2, promise };
|
|
192
|
+
}
|
|
193
|
+
if (source instanceof HTMLImageElement) {
|
|
194
|
+
const state2 = {
|
|
195
|
+
texture,
|
|
196
|
+
width: source.naturalWidth || 1,
|
|
197
|
+
height: source.naturalHeight || 1,
|
|
198
|
+
unit,
|
|
199
|
+
loaded: source.complete,
|
|
200
|
+
needsUpdate: false,
|
|
201
|
+
source
|
|
202
|
+
};
|
|
203
|
+
if (source.complete && source.naturalWidth > 0) {
|
|
204
|
+
uploadElement(gl, texture, unit, source);
|
|
205
|
+
state2.width = source.naturalWidth;
|
|
206
|
+
state2.height = source.naturalHeight;
|
|
207
|
+
return { state: state2, promise: null };
|
|
208
|
+
}
|
|
209
|
+
const promise = new Promise((resolve, reject) => {
|
|
210
|
+
source.onload = () => {
|
|
211
|
+
if (gl.isContextLost()) {
|
|
212
|
+
resolve();
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
uploadElement(gl, texture, unit, source);
|
|
216
|
+
state2.width = source.naturalWidth;
|
|
217
|
+
state2.height = source.naturalHeight;
|
|
218
|
+
state2.loaded = true;
|
|
219
|
+
resolve();
|
|
220
|
+
};
|
|
221
|
+
source.onerror = () => reject(new Error("Failed to load image element"));
|
|
222
|
+
});
|
|
223
|
+
return { state: state2, promise };
|
|
224
|
+
}
|
|
225
|
+
if (source instanceof HTMLVideoElement) {
|
|
226
|
+
const w = source.videoWidth || 1;
|
|
227
|
+
const h = source.videoHeight || 1;
|
|
228
|
+
if (source.readyState >= 2) {
|
|
229
|
+
uploadElement(gl, texture, unit, source);
|
|
230
|
+
} else {
|
|
231
|
+
gl.texImage2D(
|
|
232
|
+
gl.TEXTURE_2D,
|
|
233
|
+
0,
|
|
234
|
+
gl.RGBA,
|
|
235
|
+
1,
|
|
236
|
+
1,
|
|
237
|
+
0,
|
|
238
|
+
gl.RGBA,
|
|
239
|
+
gl.UNSIGNED_BYTE,
|
|
240
|
+
new Uint8Array([0, 0, 0, 255])
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
const state2 = {
|
|
244
|
+
texture,
|
|
245
|
+
width: w,
|
|
246
|
+
height: h,
|
|
247
|
+
unit,
|
|
248
|
+
loaded: source.readyState >= 2,
|
|
249
|
+
needsUpdate: true,
|
|
250
|
+
source
|
|
251
|
+
};
|
|
252
|
+
return { state: state2, promise: null };
|
|
253
|
+
}
|
|
254
|
+
uploadElement(gl, texture, unit, source);
|
|
255
|
+
const state = {
|
|
256
|
+
texture,
|
|
257
|
+
width: source.width,
|
|
258
|
+
height: source.height,
|
|
259
|
+
unit,
|
|
260
|
+
loaded: true,
|
|
261
|
+
needsUpdate: true,
|
|
262
|
+
source
|
|
263
|
+
};
|
|
264
|
+
return { state, promise: null };
|
|
265
|
+
}
|
|
266
|
+
function updateDynamicTextures(gl, textures) {
|
|
267
|
+
for (const tex of textures) {
|
|
268
|
+
if (!tex || !tex.needsUpdate || !tex.source) continue;
|
|
269
|
+
if (tex.source instanceof HTMLVideoElement) {
|
|
270
|
+
const v = tex.source;
|
|
271
|
+
if (v.readyState < 2) continue;
|
|
272
|
+
uploadElement(gl, tex.texture, tex.unit, v);
|
|
273
|
+
tex.width = v.videoWidth;
|
|
274
|
+
tex.height = v.videoHeight;
|
|
275
|
+
tex.loaded = true;
|
|
276
|
+
} else if (tex.source instanceof HTMLCanvasElement) {
|
|
277
|
+
uploadElement(gl, tex.texture, tex.unit, tex.source);
|
|
278
|
+
tex.width = tex.source.width;
|
|
279
|
+
tex.height = tex.source.height;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
function bindTextures(gl, locations, textures) {
|
|
284
|
+
for (let i = 0; i < 4; i++) {
|
|
285
|
+
const tex = textures[i];
|
|
286
|
+
if (!tex) continue;
|
|
287
|
+
gl.activeTexture(gl.TEXTURE0 + tex.unit);
|
|
288
|
+
gl.bindTexture(gl.TEXTURE_2D, tex.texture);
|
|
289
|
+
if (locations[i]) {
|
|
290
|
+
gl.uniform1i(locations[i], tex.unit);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
function disposeTextures(gl, textures) {
|
|
295
|
+
for (const tex of textures) {
|
|
296
|
+
if (tex) gl.deleteTexture(tex.texture);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
114
300
|
// src/uniforms.ts
|
|
115
301
|
function updateUniforms(state, delta, speed, mouse) {
|
|
116
302
|
const { gl, locations } = state;
|
|
@@ -138,6 +324,18 @@ function updateUniforms(state, delta, speed, mouse) {
|
|
|
138
324
|
const mw = mouse.pressed ? mouse.clickY : -Math.abs(mouse.clickY);
|
|
139
325
|
gl.uniform4f(locations.iMouse, mouse.x, mouse.y, mz, mw);
|
|
140
326
|
}
|
|
327
|
+
if (locations.iChannelResolution) {
|
|
328
|
+
const res = new Float32Array(12);
|
|
329
|
+
for (let i = 0; i < 4; i++) {
|
|
330
|
+
const tex = state.textures[i];
|
|
331
|
+
if (tex) {
|
|
332
|
+
res[i * 3] = tex.width;
|
|
333
|
+
res[i * 3 + 1] = tex.height;
|
|
334
|
+
res[i * 3 + 2] = 1;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
gl.uniform3fv(locations.iChannelResolution, res);
|
|
338
|
+
}
|
|
141
339
|
if (locations.iDate) {
|
|
142
340
|
const now = /* @__PURE__ */ new Date();
|
|
143
341
|
const seconds = now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds() + now.getMilliseconds() / 1e3;
|
|
@@ -153,8 +351,10 @@ function updateUniforms(state, delta, speed, mouse) {
|
|
|
153
351
|
}
|
|
154
352
|
|
|
155
353
|
// src/useShadertoy.ts
|
|
354
|
+
var CHANNEL_KEYS = ["iChannel0", "iChannel1", "iChannel2", "iChannel3"];
|
|
156
355
|
function useShadertoy({
|
|
157
356
|
fragmentShader,
|
|
357
|
+
textures: texturesProp,
|
|
158
358
|
paused = false,
|
|
159
359
|
speed = 1,
|
|
160
360
|
pixelRatio,
|
|
@@ -188,16 +388,43 @@ function useShadertoy({
|
|
|
188
388
|
return;
|
|
189
389
|
}
|
|
190
390
|
rendererRef.current = result;
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
391
|
+
const texturePromises = [];
|
|
392
|
+
if (texturesProp) {
|
|
393
|
+
for (let i = 0; i < 4; i++) {
|
|
394
|
+
const src = texturesProp[CHANNEL_KEYS[i]];
|
|
395
|
+
if (src != null) {
|
|
396
|
+
const { state, promise } = createTexture(result.gl, src, i);
|
|
397
|
+
result.textures[i] = state;
|
|
398
|
+
if (promise) texturePromises.push(promise);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
const markReady = () => {
|
|
403
|
+
setIsReady(true);
|
|
404
|
+
setError(null);
|
|
405
|
+
onLoad?.();
|
|
406
|
+
};
|
|
407
|
+
if (texturePromises.length > 0) {
|
|
408
|
+
Promise.all(texturePromises).then(() => {
|
|
409
|
+
if (rendererRef.current) markReady();
|
|
410
|
+
}).catch((err) => {
|
|
411
|
+
const msg = err instanceof Error ? err.message : "Texture load failed";
|
|
412
|
+
setError(msg);
|
|
413
|
+
onError?.(msg);
|
|
414
|
+
});
|
|
415
|
+
} else {
|
|
416
|
+
markReady();
|
|
417
|
+
}
|
|
194
418
|
let lastTimestamp = 0;
|
|
195
419
|
const loop = (timestamp) => {
|
|
196
420
|
const delta = lastTimestamp ? (timestamp - lastTimestamp) / 1e3 : 0;
|
|
197
421
|
lastTimestamp = timestamp;
|
|
198
422
|
if (!pausedRef.current && rendererRef.current) {
|
|
199
|
-
|
|
200
|
-
|
|
423
|
+
const r = rendererRef.current;
|
|
424
|
+
updateDynamicTextures(r.gl, r.textures);
|
|
425
|
+
bindTextures(r.gl, r.locations.iChannel, r.textures);
|
|
426
|
+
updateUniforms(r, delta, speedRef.current, mouseState.current);
|
|
427
|
+
render(r);
|
|
201
428
|
}
|
|
202
429
|
rafRef.current = requestAnimationFrame(loop);
|
|
203
430
|
};
|
|
@@ -205,12 +432,13 @@ function useShadertoy({
|
|
|
205
432
|
return () => {
|
|
206
433
|
cancelAnimationFrame(rafRef.current);
|
|
207
434
|
if (rendererRef.current) {
|
|
435
|
+
disposeTextures(rendererRef.current.gl, rendererRef.current.textures);
|
|
208
436
|
dispose(rendererRef.current);
|
|
209
437
|
rendererRef.current = null;
|
|
210
438
|
}
|
|
211
439
|
setIsReady(false);
|
|
212
440
|
};
|
|
213
|
-
}, [fragmentShader, onError, onLoad]);
|
|
441
|
+
}, [fragmentShader, texturesProp, onError, onLoad]);
|
|
214
442
|
useEffect(() => {
|
|
215
443
|
const canvas = canvasRef.current;
|
|
216
444
|
if (!canvas) return;
|
|
@@ -288,8 +516,12 @@ function useShadertoy({
|
|
|
288
516
|
}, []);
|
|
289
517
|
return { canvasRef, isReady, error, pause, resume };
|
|
290
518
|
}
|
|
519
|
+
|
|
520
|
+
// src/Shadertoy.tsx
|
|
521
|
+
import { jsx } from "react/jsx-runtime";
|
|
291
522
|
function Shadertoy({
|
|
292
523
|
fragmentShader,
|
|
524
|
+
textures,
|
|
293
525
|
style,
|
|
294
526
|
className,
|
|
295
527
|
paused,
|
|
@@ -301,6 +533,7 @@ function Shadertoy({
|
|
|
301
533
|
}) {
|
|
302
534
|
const { canvasRef } = useShadertoy({
|
|
303
535
|
fragmentShader,
|
|
536
|
+
textures,
|
|
304
537
|
paused,
|
|
305
538
|
speed,
|
|
306
539
|
pixelRatio,
|
|
@@ -317,7 +550,7 @@ function Shadertoy({
|
|
|
317
550
|
}
|
|
318
551
|
);
|
|
319
552
|
}
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
553
|
+
export {
|
|
554
|
+
Shadertoy,
|
|
555
|
+
useShadertoy
|
|
556
|
+
};
|
package/package.json
CHANGED
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/renderer.ts","../src/uniforms.ts","../src/useShadertoy.ts","../src/Shadertoy.tsx"],"names":["useRef","useState","useEffect","useCallback","jsx"],"mappings":"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","file":"index.js","sourcesContent":["import type { RendererState, UniformLocations } from './types'\n\n// Full-screen quad: two triangles covering clip space\nconst QUAD_VERTICES = new Float32Array([\n -1, -1,\n 1, -1,\n -1, 1,\n -1, 1,\n 1, -1,\n 1, 1,\n])\n\nconst VERTEX_SHADER = `\nattribute vec2 position;\nvoid main() {\n gl_Position = vec4(position, 0.0, 1.0);\n}\n`\n\n/**\n * Wrap Shadertoy GLSL: prepend uniform declarations + main() bridge.\n */\nfunction wrapFragmentShader(shader: string): string {\n return `precision highp float;\n\nuniform vec3 iResolution;\nuniform float iTime;\nuniform float iTimeDelta;\nuniform int iFrame;\nuniform vec4 iMouse;\nuniform vec4 iDate;\n\n${shader}\n\nvoid main() {\n mainImage(gl_FragColor, gl_FragCoord.xy);\n}\n`\n}\n\nfunction compileShader(\n gl: WebGLRenderingContext,\n type: number,\n source: string,\n): WebGLShader | string {\n const shader = gl.createShader(type)\n if (!shader) return 'Failed to create shader'\n\n gl.shaderSource(shader, source)\n gl.compileShader(shader)\n\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const log = gl.getShaderInfoLog(shader) || 'Unknown compile error'\n gl.deleteShader(shader)\n return log\n }\n\n return shader\n}\n\n/**\n * Initialize WebGL: compile shaders, link program, setup quad.\n * Returns RendererState on success or error string on failure.\n */\nexport function createRenderer(\n canvas: HTMLCanvasElement,\n fragmentShader: string,\n): RendererState | string {\n const gl = canvas.getContext('webgl', {\n antialias: false,\n alpha: true,\n premultipliedAlpha: false,\n })\n if (!gl) return 'WebGL not supported'\n\n // Compile vertex shader\n const vert = compileShader(gl, gl.VERTEX_SHADER, VERTEX_SHADER)\n if (typeof vert === 'string') return vert\n\n // Compile fragment shader (wrapped)\n const frag = compileShader(gl, gl.FRAGMENT_SHADER, wrapFragmentShader(fragmentShader))\n if (typeof frag === 'string') return frag\n\n // Link program\n const program = gl.createProgram()\n if (!program) return 'Failed to create program'\n\n gl.attachShader(program, vert)\n gl.attachShader(program, frag)\n gl.linkProgram(program)\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n const log = gl.getProgramInfoLog(program) || 'Unknown link error'\n gl.deleteProgram(program)\n return log\n }\n\n // Clean up individual shaders (attached to program)\n gl.deleteShader(vert)\n gl.deleteShader(frag)\n\n // Setup quad geometry\n const buffer = gl.createBuffer()\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n gl.bufferData(gl.ARRAY_BUFFER, QUAD_VERTICES, gl.STATIC_DRAW)\n\n const positionLoc = gl.getAttribLocation(program, 'position')\n gl.enableVertexAttribArray(positionLoc)\n gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0)\n\n // Get uniform locations\n const locations: UniformLocations = {\n iResolution: gl.getUniformLocation(program, 'iResolution'),\n iTime: gl.getUniformLocation(program, 'iTime'),\n iTimeDelta: gl.getUniformLocation(program, 'iTimeDelta'),\n iFrame: gl.getUniformLocation(program, 'iFrame'),\n iMouse: gl.getUniformLocation(program, 'iMouse'),\n iDate: gl.getUniformLocation(program, 'iDate'),\n }\n\n gl.useProgram(program)\n\n return {\n gl,\n program,\n locations,\n time: 0,\n frame: 0,\n lastTime: 0,\n }\n}\n\n/**\n * Render one frame.\n */\nexport function render(state: RendererState): void {\n const { gl } = state\n gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight)\n gl.drawArrays(gl.TRIANGLES, 0, 6)\n}\n\n/**\n * Clean up WebGL resources.\n */\nexport function dispose(state: RendererState): void {\n const { gl, program } = state\n gl.deleteProgram(program)\n gl.getExtension('WEBGL_lose_context')?.loseContext()\n}\n","import type { MouseState, RendererState } from './types'\n\n/**\n * Update all Shadertoy standard uniforms for one frame.\n */\nexport function updateUniforms(\n state: RendererState,\n delta: number,\n speed: number,\n mouse: MouseState,\n): void {\n const { gl, locations } = state\n\n // iTime\n state.time += delta * speed\n if (locations.iTime) {\n gl.uniform1f(locations.iTime, state.time)\n }\n\n // iTimeDelta\n if (locations.iTimeDelta) {\n gl.uniform1f(locations.iTimeDelta, delta)\n }\n\n // iFrame\n state.frame++\n if (locations.iFrame) {\n gl.uniform1i(locations.iFrame, state.frame)\n }\n\n // iResolution\n if (locations.iResolution) {\n gl.uniform3f(\n locations.iResolution,\n gl.drawingBufferWidth,\n gl.drawingBufferHeight,\n 1.0,\n )\n }\n\n // iMouse — Shadertoy convention:\n // xy: current position (if pressed)\n // zw: click position (positive when pressed, negative when released)\n if (locations.iMouse) {\n const mz = mouse.pressed ? mouse.clickX : -Math.abs(mouse.clickX)\n const mw = mouse.pressed ? mouse.clickY : -Math.abs(mouse.clickY)\n gl.uniform4f(locations.iMouse, mouse.x, mouse.y, mz, mw)\n }\n\n // iDate — vec4(year, month, day, seconds_since_midnight)\n if (locations.iDate) {\n const now = new Date()\n const seconds =\n now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds() + now.getMilliseconds() / 1000\n gl.uniform4f(\n locations.iDate,\n now.getFullYear(),\n now.getMonth(), // 0-based, matches Shadertoy\n now.getDate(),\n seconds,\n )\n }\n}\n","import { useCallback, useEffect, useRef, useState } from 'react'\nimport { createRenderer, dispose, render } from './renderer'\nimport type { MouseState, RendererState, UseShadertoyOptions, UseShadertoyReturn } from './types'\nimport { updateUniforms } from './uniforms'\n\nexport function useShadertoy({\n fragmentShader,\n paused = false,\n speed = 1.0,\n pixelRatio,\n mouse: mouseEnabled = true,\n onError,\n onLoad,\n}: UseShadertoyOptions): UseShadertoyReturn {\n const canvasRef = useRef<HTMLCanvasElement | null>(null)\n const rendererRef = useRef<RendererState | null>(null)\n const rafRef = useRef<number>(0)\n const pausedRef = useRef(paused)\n const speedRef = useRef(speed)\n\n const [isReady, setIsReady] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const mouseState = useRef<MouseState>({\n x: 0, y: 0,\n clickX: 0, clickY: 0,\n pressed: false,\n })\n\n // Keep refs in sync\n pausedRef.current = paused\n speedRef.current = speed\n\n // Initialize WebGL\n useEffect(() => {\n const canvas = canvasRef.current\n if (!canvas) return\n\n const result = createRenderer(canvas, fragmentShader)\n if (typeof result === 'string') {\n setError(result)\n onError?.(result)\n return\n }\n\n rendererRef.current = result\n setIsReady(true)\n setError(null)\n onLoad?.()\n\n // Render loop\n let lastTimestamp = 0\n\n const loop = (timestamp: number) => {\n const delta = lastTimestamp ? (timestamp - lastTimestamp) / 1000 : 0\n lastTimestamp = timestamp\n\n if (!pausedRef.current && rendererRef.current) {\n updateUniforms(rendererRef.current, delta, speedRef.current, mouseState.current)\n render(rendererRef.current)\n }\n\n rafRef.current = requestAnimationFrame(loop)\n }\n\n rafRef.current = requestAnimationFrame(loop)\n\n return () => {\n cancelAnimationFrame(rafRef.current)\n if (rendererRef.current) {\n dispose(rendererRef.current)\n rendererRef.current = null\n }\n setIsReady(false)\n }\n }, [fragmentShader, onError, onLoad])\n\n // Canvas resize\n useEffect(() => {\n const canvas = canvasRef.current\n if (!canvas) return\n\n const dpr = pixelRatio ?? (typeof window !== 'undefined' ? window.devicePixelRatio : 1)\n\n const observer = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height } = entry.contentRect\n canvas.width = Math.round(width * dpr)\n canvas.height = Math.round(height * dpr)\n }\n })\n\n observer.observe(canvas)\n return () => observer.disconnect()\n }, [pixelRatio])\n\n // Mouse / touch events\n useEffect(() => {\n if (!mouseEnabled) return\n const canvas = canvasRef.current\n if (!canvas) return\n\n const toPixel = (cx: number, cy: number) => {\n const r = canvas.getBoundingClientRect()\n const dpr = pixelRatio ?? window.devicePixelRatio\n return {\n x: (cx - r.left) * dpr,\n y: (r.height - (cy - r.top)) * dpr, // flip Y\n }\n }\n\n const onMove = (cx: number, cy: number) => {\n if (!mouseState.current.pressed) return\n const { x, y } = toPixel(cx, cy)\n mouseState.current.x = x\n mouseState.current.y = y\n }\n\n const onDown = (cx: number, cy: number) => {\n const { x, y } = toPixel(cx, cy)\n mouseState.current.x = x\n mouseState.current.y = y\n mouseState.current.clickX = x\n mouseState.current.clickY = y\n mouseState.current.pressed = true\n }\n\n const onUp = () => {\n mouseState.current.pressed = false\n }\n\n const mm = (e: MouseEvent) => onMove(e.clientX, e.clientY)\n const md = (e: MouseEvent) => onDown(e.clientX, e.clientY)\n const mu = () => onUp()\n const tm = (e: TouchEvent) => {\n if (e.touches[0]) onMove(e.touches[0].clientX, e.touches[0].clientY)\n }\n const ts = (e: TouchEvent) => {\n if (e.touches[0]) onDown(e.touches[0].clientX, e.touches[0].clientY)\n }\n const te = () => onUp()\n\n window.addEventListener('mousemove', mm)\n canvas.addEventListener('mousedown', md)\n window.addEventListener('mouseup', mu)\n window.addEventListener('touchmove', tm, { passive: true })\n canvas.addEventListener('touchstart', ts, { passive: true })\n window.addEventListener('touchend', te)\n\n return () => {\n window.removeEventListener('mousemove', mm)\n canvas.removeEventListener('mousedown', md)\n window.removeEventListener('mouseup', mu)\n window.removeEventListener('touchmove', tm)\n canvas.removeEventListener('touchstart', ts)\n window.removeEventListener('touchend', te)\n }\n }, [mouseEnabled, pixelRatio])\n\n const pause = useCallback(() => { pausedRef.current = true }, [])\n const resume = useCallback(() => { pausedRef.current = false }, [])\n\n return { canvasRef, isReady, error, pause, resume }\n}\n","import type { ShadertoyProps } from './types'\nimport { useShadertoy } from './useShadertoy'\n\nexport function Shadertoy({\n fragmentShader,\n style,\n className,\n paused,\n speed,\n pixelRatio,\n mouse,\n onError,\n onLoad,\n}: ShadertoyProps) {\n const { canvasRef } = useShadertoy({\n fragmentShader,\n paused,\n speed,\n pixelRatio,\n mouse,\n onError,\n onLoad,\n })\n\n return (\n <canvas\n ref={canvasRef}\n className={className}\n style={{ width: '100%', height: '100%', display: 'block', ...style }}\n />\n )\n}\n"]}
|
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/renderer.ts","../src/uniforms.ts","../src/useShadertoy.ts","../src/Shadertoy.tsx"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import type { RendererState, UniformLocations } from './types'\n\n// Full-screen quad: two triangles covering clip space\nconst QUAD_VERTICES = new Float32Array([\n -1, -1,\n 1, -1,\n -1, 1,\n -1, 1,\n 1, -1,\n 1, 1,\n])\n\nconst VERTEX_SHADER = `\nattribute vec2 position;\nvoid main() {\n gl_Position = vec4(position, 0.0, 1.0);\n}\n`\n\n/**\n * Wrap Shadertoy GLSL: prepend uniform declarations + main() bridge.\n */\nfunction wrapFragmentShader(shader: string): string {\n return `precision highp float;\n\nuniform vec3 iResolution;\nuniform float iTime;\nuniform float iTimeDelta;\nuniform int iFrame;\nuniform vec4 iMouse;\nuniform vec4 iDate;\n\n${shader}\n\nvoid main() {\n mainImage(gl_FragColor, gl_FragCoord.xy);\n}\n`\n}\n\nfunction compileShader(\n gl: WebGLRenderingContext,\n type: number,\n source: string,\n): WebGLShader | string {\n const shader = gl.createShader(type)\n if (!shader) return 'Failed to create shader'\n\n gl.shaderSource(shader, source)\n gl.compileShader(shader)\n\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const log = gl.getShaderInfoLog(shader) || 'Unknown compile error'\n gl.deleteShader(shader)\n return log\n }\n\n return shader\n}\n\n/**\n * Initialize WebGL: compile shaders, link program, setup quad.\n * Returns RendererState on success or error string on failure.\n */\nexport function createRenderer(\n canvas: HTMLCanvasElement,\n fragmentShader: string,\n): RendererState | string {\n const gl = canvas.getContext('webgl', {\n antialias: false,\n alpha: true,\n premultipliedAlpha: false,\n })\n if (!gl) return 'WebGL not supported'\n\n // Compile vertex shader\n const vert = compileShader(gl, gl.VERTEX_SHADER, VERTEX_SHADER)\n if (typeof vert === 'string') return vert\n\n // Compile fragment shader (wrapped)\n const frag = compileShader(gl, gl.FRAGMENT_SHADER, wrapFragmentShader(fragmentShader))\n if (typeof frag === 'string') return frag\n\n // Link program\n const program = gl.createProgram()\n if (!program) return 'Failed to create program'\n\n gl.attachShader(program, vert)\n gl.attachShader(program, frag)\n gl.linkProgram(program)\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n const log = gl.getProgramInfoLog(program) || 'Unknown link error'\n gl.deleteProgram(program)\n return log\n }\n\n // Clean up individual shaders (attached to program)\n gl.deleteShader(vert)\n gl.deleteShader(frag)\n\n // Setup quad geometry\n const buffer = gl.createBuffer()\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n gl.bufferData(gl.ARRAY_BUFFER, QUAD_VERTICES, gl.STATIC_DRAW)\n\n const positionLoc = gl.getAttribLocation(program, 'position')\n gl.enableVertexAttribArray(positionLoc)\n gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0)\n\n // Get uniform locations\n const locations: UniformLocations = {\n iResolution: gl.getUniformLocation(program, 'iResolution'),\n iTime: gl.getUniformLocation(program, 'iTime'),\n iTimeDelta: gl.getUniformLocation(program, 'iTimeDelta'),\n iFrame: gl.getUniformLocation(program, 'iFrame'),\n iMouse: gl.getUniformLocation(program, 'iMouse'),\n iDate: gl.getUniformLocation(program, 'iDate'),\n }\n\n gl.useProgram(program)\n\n return {\n gl,\n program,\n locations,\n time: 0,\n frame: 0,\n lastTime: 0,\n }\n}\n\n/**\n * Render one frame.\n */\nexport function render(state: RendererState): void {\n const { gl } = state\n gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight)\n gl.drawArrays(gl.TRIANGLES, 0, 6)\n}\n\n/**\n * Clean up WebGL resources.\n */\nexport function dispose(state: RendererState): void {\n const { gl, program } = state\n gl.deleteProgram(program)\n gl.getExtension('WEBGL_lose_context')?.loseContext()\n}\n","import type { MouseState, RendererState } from './types'\n\n/**\n * Update all Shadertoy standard uniforms for one frame.\n */\nexport function updateUniforms(\n state: RendererState,\n delta: number,\n speed: number,\n mouse: MouseState,\n): void {\n const { gl, locations } = state\n\n // iTime\n state.time += delta * speed\n if (locations.iTime) {\n gl.uniform1f(locations.iTime, state.time)\n }\n\n // iTimeDelta\n if (locations.iTimeDelta) {\n gl.uniform1f(locations.iTimeDelta, delta)\n }\n\n // iFrame\n state.frame++\n if (locations.iFrame) {\n gl.uniform1i(locations.iFrame, state.frame)\n }\n\n // iResolution\n if (locations.iResolution) {\n gl.uniform3f(\n locations.iResolution,\n gl.drawingBufferWidth,\n gl.drawingBufferHeight,\n 1.0,\n )\n }\n\n // iMouse — Shadertoy convention:\n // xy: current position (if pressed)\n // zw: click position (positive when pressed, negative when released)\n if (locations.iMouse) {\n const mz = mouse.pressed ? mouse.clickX : -Math.abs(mouse.clickX)\n const mw = mouse.pressed ? mouse.clickY : -Math.abs(mouse.clickY)\n gl.uniform4f(locations.iMouse, mouse.x, mouse.y, mz, mw)\n }\n\n // iDate — vec4(year, month, day, seconds_since_midnight)\n if (locations.iDate) {\n const now = new Date()\n const seconds =\n now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds() + now.getMilliseconds() / 1000\n gl.uniform4f(\n locations.iDate,\n now.getFullYear(),\n now.getMonth(), // 0-based, matches Shadertoy\n now.getDate(),\n seconds,\n )\n }\n}\n","import { useCallback, useEffect, useRef, useState } from 'react'\nimport { createRenderer, dispose, render } from './renderer'\nimport type { MouseState, RendererState, UseShadertoyOptions, UseShadertoyReturn } from './types'\nimport { updateUniforms } from './uniforms'\n\nexport function useShadertoy({\n fragmentShader,\n paused = false,\n speed = 1.0,\n pixelRatio,\n mouse: mouseEnabled = true,\n onError,\n onLoad,\n}: UseShadertoyOptions): UseShadertoyReturn {\n const canvasRef = useRef<HTMLCanvasElement | null>(null)\n const rendererRef = useRef<RendererState | null>(null)\n const rafRef = useRef<number>(0)\n const pausedRef = useRef(paused)\n const speedRef = useRef(speed)\n\n const [isReady, setIsReady] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const mouseState = useRef<MouseState>({\n x: 0, y: 0,\n clickX: 0, clickY: 0,\n pressed: false,\n })\n\n // Keep refs in sync\n pausedRef.current = paused\n speedRef.current = speed\n\n // Initialize WebGL\n useEffect(() => {\n const canvas = canvasRef.current\n if (!canvas) return\n\n const result = createRenderer(canvas, fragmentShader)\n if (typeof result === 'string') {\n setError(result)\n onError?.(result)\n return\n }\n\n rendererRef.current = result\n setIsReady(true)\n setError(null)\n onLoad?.()\n\n // Render loop\n let lastTimestamp = 0\n\n const loop = (timestamp: number) => {\n const delta = lastTimestamp ? (timestamp - lastTimestamp) / 1000 : 0\n lastTimestamp = timestamp\n\n if (!pausedRef.current && rendererRef.current) {\n updateUniforms(rendererRef.current, delta, speedRef.current, mouseState.current)\n render(rendererRef.current)\n }\n\n rafRef.current = requestAnimationFrame(loop)\n }\n\n rafRef.current = requestAnimationFrame(loop)\n\n return () => {\n cancelAnimationFrame(rafRef.current)\n if (rendererRef.current) {\n dispose(rendererRef.current)\n rendererRef.current = null\n }\n setIsReady(false)\n }\n }, [fragmentShader, onError, onLoad])\n\n // Canvas resize\n useEffect(() => {\n const canvas = canvasRef.current\n if (!canvas) return\n\n const dpr = pixelRatio ?? (typeof window !== 'undefined' ? window.devicePixelRatio : 1)\n\n const observer = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height } = entry.contentRect\n canvas.width = Math.round(width * dpr)\n canvas.height = Math.round(height * dpr)\n }\n })\n\n observer.observe(canvas)\n return () => observer.disconnect()\n }, [pixelRatio])\n\n // Mouse / touch events\n useEffect(() => {\n if (!mouseEnabled) return\n const canvas = canvasRef.current\n if (!canvas) return\n\n const toPixel = (cx: number, cy: number) => {\n const r = canvas.getBoundingClientRect()\n const dpr = pixelRatio ?? window.devicePixelRatio\n return {\n x: (cx - r.left) * dpr,\n y: (r.height - (cy - r.top)) * dpr, // flip Y\n }\n }\n\n const onMove = (cx: number, cy: number) => {\n if (!mouseState.current.pressed) return\n const { x, y } = toPixel(cx, cy)\n mouseState.current.x = x\n mouseState.current.y = y\n }\n\n const onDown = (cx: number, cy: number) => {\n const { x, y } = toPixel(cx, cy)\n mouseState.current.x = x\n mouseState.current.y = y\n mouseState.current.clickX = x\n mouseState.current.clickY = y\n mouseState.current.pressed = true\n }\n\n const onUp = () => {\n mouseState.current.pressed = false\n }\n\n const mm = (e: MouseEvent) => onMove(e.clientX, e.clientY)\n const md = (e: MouseEvent) => onDown(e.clientX, e.clientY)\n const mu = () => onUp()\n const tm = (e: TouchEvent) => {\n if (e.touches[0]) onMove(e.touches[0].clientX, e.touches[0].clientY)\n }\n const ts = (e: TouchEvent) => {\n if (e.touches[0]) onDown(e.touches[0].clientX, e.touches[0].clientY)\n }\n const te = () => onUp()\n\n window.addEventListener('mousemove', mm)\n canvas.addEventListener('mousedown', md)\n window.addEventListener('mouseup', mu)\n window.addEventListener('touchmove', tm, { passive: true })\n canvas.addEventListener('touchstart', ts, { passive: true })\n window.addEventListener('touchend', te)\n\n return () => {\n window.removeEventListener('mousemove', mm)\n canvas.removeEventListener('mousedown', md)\n window.removeEventListener('mouseup', mu)\n window.removeEventListener('touchmove', tm)\n canvas.removeEventListener('touchstart', ts)\n window.removeEventListener('touchend', te)\n }\n }, [mouseEnabled, pixelRatio])\n\n const pause = useCallback(() => { pausedRef.current = true }, [])\n const resume = useCallback(() => { pausedRef.current = false }, [])\n\n return { canvasRef, isReady, error, pause, resume }\n}\n","import type { ShadertoyProps } from './types'\nimport { useShadertoy } from './useShadertoy'\n\nexport function Shadertoy({\n fragmentShader,\n style,\n className,\n paused,\n speed,\n pixelRatio,\n mouse,\n onError,\n onLoad,\n}: ShadertoyProps) {\n const { canvasRef } = useShadertoy({\n fragmentShader,\n paused,\n speed,\n pixelRatio,\n mouse,\n onError,\n onLoad,\n })\n\n return (\n <canvas\n ref={canvasRef}\n className={className}\n style={{ width: '100%', height: '100%', display: 'block', ...style }}\n />\n )\n}\n"]}
|