@paper-design/shaders-react 0.0.54 → 0.0.56
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/color-props-are-equal.js +2 -15
- package/dist/color-props-are-equal.js.map +2 -2
- package/dist/fast-deep-equal.d.ts +1 -0
- package/dist/fast-deep-equal.js +33 -0
- package/dist/fast-deep-equal.js.map +7 -0
- package/dist/shader-mount.js +75 -45
- package/dist/shader-mount.js.map +2 -2
- package/dist/shaders/dithering.d.ts +2 -0
- package/dist/shaders/dithering.js +9 -8
- package/dist/shaders/dithering.js.map +2 -2
- package/dist/shaders/fluted-glass.js +13 -8
- package/dist/shaders/fluted-glass.js.map +2 -2
- package/dist/shaders/heatmap.js +26 -48
- package/dist/shaders/heatmap.js.map +2 -2
- package/dist/shaders/image-dithering.d.ts +2 -0
- package/dist/shaders/image-dithering.js +8 -7
- package/dist/shaders/image-dithering.js.map +2 -2
- package/dist/shaders/paper-texture.d.ts +8 -0
- package/dist/shaders/paper-texture.js +30 -25
- package/dist/shaders/paper-texture.js.map +2 -2
- package/dist/shaders/pulsing-border.js +56 -21
- package/dist/shaders/pulsing-border.js.map +2 -2
- package/dist/shaders/water.js +1 -1
- package/dist/shaders/water.js.map +1 -1
- package/package.json +2 -2
|
@@ -3,24 +3,11 @@
|
|
|
3
3
|
* https://github.com/paper-design/shaders *
|
|
4
4
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
5
5
|
|
|
6
|
+
import { fastDeepEqual } from "./fast-deep-equal.js";
|
|
6
7
|
function colorPropsAreEqual(prevProps, nextProps) {
|
|
7
8
|
for (const key in prevProps) {
|
|
8
9
|
if (key === "colors") {
|
|
9
|
-
|
|
10
|
-
const nextIsArray = Array.isArray(nextProps.colors);
|
|
11
|
-
if (!prevIsArray || !nextIsArray) {
|
|
12
|
-
if (Object.is(prevProps.colors, nextProps.colors) === false) {
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
|
-
continue;
|
|
16
|
-
}
|
|
17
|
-
if (prevProps.colors?.length !== nextProps.colors?.length) {
|
|
18
|
-
return false;
|
|
19
|
-
}
|
|
20
|
-
if (!prevProps.colors?.every((color, index) => color === nextProps.colors?.[index])) {
|
|
21
|
-
return false;
|
|
22
|
-
}
|
|
23
|
-
continue;
|
|
10
|
+
return fastDeepEqual(prevProps.colors, nextProps.colors);
|
|
24
11
|
}
|
|
25
12
|
if (Object.is(prevProps[key], nextProps[key]) === false) {
|
|
26
13
|
return false;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/color-props-are-equal.ts"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": ";;;;;
|
|
4
|
+
"sourcesContent": ["import { fastDeepEqual } from './fast-deep-equal.js';\n\ninterface PropsWithColors {\n colors?: string[];\n [key: string]: unknown;\n}\n\nexport function colorPropsAreEqual(prevProps: PropsWithColors, nextProps: PropsWithColors): boolean {\n for (const key in prevProps) {\n if (key === 'colors') {\n return fastDeepEqual(prevProps.colors, nextProps.colors);\n }\n\n if (Object.is(prevProps[key], nextProps[key]) === false) {\n return false;\n }\n }\n\n return true;\n}\n"],
|
|
5
|
+
"mappings": ";;;;;AAAA,SAAS,qBAAqB;AAOvB,SAAS,mBAAmB,WAA4B,WAAqC;AAClG,aAAW,OAAO,WAAW;AAC3B,QAAI,QAAQ,UAAU;AACpB,aAAO,cAAc,UAAU,QAAQ,UAAU,MAAM;AAAA,IACzD;AAEA,QAAI,OAAO,GAAG,UAAU,GAAG,GAAG,UAAU,GAAG,CAAC,MAAM,OAAO;AACvD,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function fastDeepEqual(a: any, b: any): boolean;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
2
|
+
* Paper Shaders *
|
|
3
|
+
* https://github.com/paper-design/shaders *
|
|
4
|
+
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
5
|
+
|
|
6
|
+
function fastDeepEqual(a, b) {
|
|
7
|
+
if (a === b) return true;
|
|
8
|
+
if (a && b && typeof a == "object" && typeof b == "object") {
|
|
9
|
+
if (a.constructor !== b.constructor) return false;
|
|
10
|
+
var length, i, keys;
|
|
11
|
+
if (Array.isArray(a)) {
|
|
12
|
+
length = a.length;
|
|
13
|
+
if (length != b.length) return false;
|
|
14
|
+
for (i = length; i-- !== 0; ) if (!fastDeepEqual(a[i], b[i])) return false;
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
if (a.constructor !== Object) return false;
|
|
18
|
+
keys = Object.keys(a);
|
|
19
|
+
length = keys.length;
|
|
20
|
+
if (length !== Object.keys(b).length) return false;
|
|
21
|
+
for (i = length; i-- !== 0; ) if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
|
|
22
|
+
for (i = length; i-- !== 0; ) {
|
|
23
|
+
var key = keys[i];
|
|
24
|
+
if (!fastDeepEqual(a[key], b[key])) return false;
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
return a !== a && b !== b;
|
|
29
|
+
}
|
|
30
|
+
export {
|
|
31
|
+
fastDeepEqual
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=fast-deep-equal.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/fast-deep-equal.ts"],
|
|
4
|
+
"sourcesContent": ["// Adapted from https://github.com/epoberezkin/fast-deep-equal\n\nexport function fastDeepEqual(a: any, b: any): boolean {\n if (a === b) return true;\n\n if (a && b && typeof a == 'object' && typeof b == 'object') {\n if (a.constructor !== b.constructor) return false;\n\n var length, i, keys;\n if (Array.isArray(a)) {\n length = a.length;\n if (length != b.length) return false;\n for (i = length; i-- !== 0; ) if (!fastDeepEqual(a[i], b[i])) return false;\n return true;\n }\n\n // Our change: compare Arrays (done above) and anonymous Objects only,\n // other objects will be compared by reference equality.\n if (a.constructor !== Object) return false;\n\n keys = Object.keys(a);\n length = keys.length;\n if (length !== Object.keys(b).length) return false;\n\n for (i = length; i-- !== 0; ) if (!Object.prototype.hasOwnProperty.call(b, keys[i]!)) return false;\n\n for (i = length; i-- !== 0; ) {\n var key = keys[i];\n\n if (!fastDeepEqual(a[key!], b[key!])) return false;\n }\n\n return true;\n }\n\n // true if both NaN, false otherwise\n return a !== a && b !== b;\n}\n"],
|
|
5
|
+
"mappings": ";;;;;AAEO,SAAS,cAAc,GAAQ,GAAiB;AACrD,MAAI,MAAM,EAAG,QAAO;AAEpB,MAAI,KAAK,KAAK,OAAO,KAAK,YAAY,OAAO,KAAK,UAAU;AAC1D,QAAI,EAAE,gBAAgB,EAAE,YAAa,QAAO;AAE5C,QAAI,QAAQ,GAAG;AACf,QAAI,MAAM,QAAQ,CAAC,GAAG;AACpB,eAAS,EAAE;AACX,UAAI,UAAU,EAAE,OAAQ,QAAO;AAC/B,WAAK,IAAI,QAAQ,QAAQ,IAAK,KAAI,CAAC,cAAc,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,EAAG,QAAO;AACrE,aAAO;AAAA,IACT;AAIA,QAAI,EAAE,gBAAgB,OAAQ,QAAO;AAErC,WAAO,OAAO,KAAK,CAAC;AACpB,aAAS,KAAK;AACd,QAAI,WAAW,OAAO,KAAK,CAAC,EAAE,OAAQ,QAAO;AAE7C,SAAK,IAAI,QAAQ,QAAQ,IAAK,KAAI,CAAC,OAAO,UAAU,eAAe,KAAK,GAAG,KAAK,CAAC,CAAE,EAAG,QAAO;AAE7F,SAAK,IAAI,QAAQ,QAAQ,KAAK;AAC5B,UAAI,MAAM,KAAK,CAAC;AAEhB,UAAI,CAAC,cAAc,EAAE,GAAI,GAAG,EAAE,GAAI,CAAC,EAAG,QAAO;AAAA,IAC/C;AAEA,WAAO;AAAA,EACT;AAGA,SAAO,MAAM,KAAK,MAAM;AAC1B;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/shader-mount.js
CHANGED
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
5
5
|
|
|
6
6
|
"use client";
|
|
7
|
-
import { useEffect, useRef, forwardRef, useState } from "react";
|
|
7
|
+
import { useEffect, useRef, forwardRef, useState, useLayoutEffect } from "react";
|
|
8
8
|
import {
|
|
9
9
|
ShaderMount as ShaderMountVanilla
|
|
10
10
|
} from "@paper-design/shaders";
|
|
11
11
|
import { useMergeRefs } from "./use-merge-refs.js";
|
|
12
|
+
import { transparentPixel } from "./transparent-pixel.js";
|
|
13
|
+
import { fastDeepEqual } from "./fast-deep-equal.js";
|
|
12
14
|
import { jsx } from "react/jsx-runtime";
|
|
13
15
|
async function processUniforms(uniformsProp) {
|
|
14
16
|
const processedUniforms = {};
|
|
@@ -50,7 +52,7 @@ async function processUniforms(uniformsProp) {
|
|
|
50
52
|
console.error(`Could not set uniforms. Failed to load image at ${value}`);
|
|
51
53
|
reject();
|
|
52
54
|
};
|
|
53
|
-
img.src = value;
|
|
55
|
+
img.src = value || transparentPixel;
|
|
54
56
|
});
|
|
55
57
|
imageLoadPromises.push(imagePromise);
|
|
56
58
|
} else {
|
|
@@ -62,7 +64,7 @@ async function processUniforms(uniformsProp) {
|
|
|
62
64
|
}
|
|
63
65
|
const ShaderMount = forwardRef(
|
|
64
66
|
function ShaderMountImpl({
|
|
65
|
-
fragmentShader,
|
|
67
|
+
fragmentShader: fragmentShaderProp,
|
|
66
68
|
uniforms: uniformsProp,
|
|
67
69
|
webGlContextAttributes,
|
|
68
70
|
speed = 0,
|
|
@@ -74,62 +76,90 @@ const ShaderMount = forwardRef(
|
|
|
74
76
|
style,
|
|
75
77
|
...divProps
|
|
76
78
|
}, forwardedRef) {
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
79
|
+
const containerRef = useRef(null);
|
|
80
|
+
const [shaderMount, setShaderMount] = useState(null);
|
|
81
|
+
const uniformsRegistered = useRef(null);
|
|
82
|
+
const [initialShaderFragment] = useState(fragmentShaderProp);
|
|
83
|
+
const [initialContextAttrs] = useState(webGlContextAttributes);
|
|
84
|
+
const initialFrame = useRef(frame);
|
|
85
|
+
const [documentVisible, setDocumentVisible] = useState(() => {
|
|
86
|
+
return typeof window === "undefined" || document.hidden === false;
|
|
87
|
+
});
|
|
88
|
+
useLayoutEffect(() => {
|
|
89
|
+
const uniformsDidChange = !fastDeepEqual(uniformsRegistered.current, uniformsProp);
|
|
90
|
+
if (uniformsDidChange) {
|
|
91
|
+
let cancelPromise = false;
|
|
92
|
+
processUniforms(uniformsProp).then((uniforms) => {
|
|
93
|
+
if (cancelPromise || !containerRef.current) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
uniformsRegistered.current = uniformsProp;
|
|
97
|
+
if (shaderMount) {
|
|
98
|
+
shaderMount.setUniforms(uniforms);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const canvas = new ShaderMountVanilla(
|
|
102
|
+
containerRef.current,
|
|
103
|
+
initialShaderFragment,
|
|
87
104
|
uniforms,
|
|
88
|
-
|
|
105
|
+
initialContextAttrs,
|
|
89
106
|
speed,
|
|
90
107
|
frame,
|
|
91
108
|
minPixelRatio,
|
|
92
109
|
maxPixelCount
|
|
93
110
|
);
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
|
|
111
|
+
setShaderMount(canvas);
|
|
112
|
+
});
|
|
113
|
+
return () => {
|
|
114
|
+
cancelPromise = true;
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
if (!shaderMount) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const targetSpeed = documentVisible ? speed : 0;
|
|
121
|
+
if (shaderMount.speed !== targetSpeed) {
|
|
122
|
+
shaderMount.setSpeed(targetSpeed);
|
|
123
|
+
}
|
|
124
|
+
if (initialFrame.current !== frame) {
|
|
125
|
+
initialFrame.current = frame;
|
|
126
|
+
shaderMount.setFrame(frame);
|
|
127
|
+
}
|
|
128
|
+
if (shaderMount.minPixelRatio !== minPixelRatio) {
|
|
129
|
+
shaderMount.setMinPixelRatio(minPixelRatio);
|
|
130
|
+
}
|
|
131
|
+
if (shaderMount.maxPixelCount !== maxPixelCount) {
|
|
132
|
+
shaderMount.setMaxPixelCount(maxPixelCount);
|
|
133
|
+
}
|
|
134
|
+
}, [
|
|
135
|
+
documentVisible,
|
|
136
|
+
frame,
|
|
137
|
+
initialContextAttrs,
|
|
138
|
+
initialShaderFragment,
|
|
139
|
+
maxPixelCount,
|
|
140
|
+
minPixelRatio,
|
|
141
|
+
shaderMount,
|
|
142
|
+
speed,
|
|
143
|
+
uniformsProp
|
|
144
|
+
]);
|
|
145
|
+
useEffect(() => {
|
|
98
146
|
return () => {
|
|
99
|
-
|
|
100
|
-
shaderMountRef.current = null;
|
|
147
|
+
shaderMount?.dispose();
|
|
101
148
|
};
|
|
102
|
-
}, [
|
|
149
|
+
}, [shaderMount]);
|
|
103
150
|
useEffect(() => {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
shaderMountRef.current?.setUniforms(uniforms);
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
updateUniforms();
|
|
151
|
+
function onVisibilityChange() {
|
|
152
|
+
setDocumentVisible(!document.hidden);
|
|
153
|
+
}
|
|
154
|
+
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
112
155
|
return () => {
|
|
113
|
-
|
|
156
|
+
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
114
157
|
};
|
|
115
|
-
}, [
|
|
116
|
-
useEffect(() => {
|
|
117
|
-
shaderMountRef.current?.setSpeed(speed);
|
|
118
|
-
}, [speed, isInitialized]);
|
|
119
|
-
useEffect(() => {
|
|
120
|
-
shaderMountRef.current?.setMaxPixelCount(maxPixelCount);
|
|
121
|
-
}, [maxPixelCount, isInitialized]);
|
|
122
|
-
useEffect(() => {
|
|
123
|
-
shaderMountRef.current?.setMinPixelRatio(minPixelRatio);
|
|
124
|
-
}, [minPixelRatio, isInitialized]);
|
|
125
|
-
useEffect(() => {
|
|
126
|
-
shaderMountRef.current?.setFrame(frame);
|
|
127
|
-
}, [frame, isInitialized]);
|
|
128
|
-
const mergedRef = useMergeRefs([divRef, forwardedRef]);
|
|
158
|
+
}, []);
|
|
129
159
|
return /* @__PURE__ */ jsx(
|
|
130
160
|
"div",
|
|
131
161
|
{
|
|
132
|
-
ref:
|
|
162
|
+
ref: useMergeRefs([containerRef, forwardedRef]),
|
|
133
163
|
style: width !== void 0 || height !== void 0 ? { width, height, ...style } : style,
|
|
134
164
|
...divProps
|
|
135
165
|
}
|
package/dist/shader-mount.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/shader-mount.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client';\n\nimport { useEffect, useRef, forwardRef, useState } from 'react';\nimport {\n ShaderMount as ShaderMountVanilla,\n type PaperShaderElement,\n type ShaderMotionParams,\n type ShaderMountUniforms,\n} from '@paper-design/shaders';\nimport { useMergeRefs } from './use-merge-refs.js';\n\n/**\n * React Shader Mount can also accept strings as uniform values, which will assumed to be URLs and loaded as images\n *\n * We accept undefined as a convenience for server rendering, when some things may be undefined\n * We just skip setting the uniform if it's undefined. This allows the shader mount to still take up space during server rendering\n */\ninterface ShaderMountUniformsReact {\n [key: string]: string | boolean | number | number[] | number[][] | HTMLImageElement | undefined;\n}\n\nexport interface ShaderMountProps extends Omit<React.ComponentProps<'div'>, 'color' | 'ref'>, ShaderMotionParams {\n ref?: React.Ref<PaperShaderElement>;\n fragmentShader: string;\n uniforms: ShaderMountUniformsReact;\n minPixelRatio?: number;\n maxPixelCount?: number;\n webGlContextAttributes?: WebGLContextAttributes;\n\n /** Inline CSS width style */\n width?: string | number;\n /** Inline CSS height style */\n height?: string | number;\n}\n\nexport interface ShaderComponentProps extends Omit<React.ComponentProps<'div'>, 'color' | 'ref'> {\n ref?: React.Ref<PaperShaderElement>;\n minPixelRatio?: number;\n maxPixelCount?: number;\n webGlContextAttributes?: WebGLContextAttributes;\n\n /** Inline CSS width style */\n width?: string | number;\n /** Inline CSS height style */\n height?: string | number;\n}\n\n/** Parse the provided uniforms, turning URL strings into loaded images */\nasync function processUniforms(uniformsProp: ShaderMountUniformsReact): Promise<ShaderMountUniforms> {\n const processedUniforms = {} as ShaderMountUniforms;\n const imageLoadPromises: Promise<void>[] = [];\n\n const isValidUrl = (url: string): boolean => {\n try {\n // Handle absolute paths\n if (url.startsWith('/')) return true;\n // Check if it's a valid URL\n new URL(url);\n return true;\n } catch {\n return false;\n }\n };\n\n const isExternalUrl = (url: string): boolean => {\n try {\n if (url.startsWith('/')) return false;\n const urlObject = new URL(url, window.location.origin);\n return urlObject.origin !== window.location.origin;\n } catch {\n return false;\n }\n };\n\n Object.entries(uniformsProp).forEach(([key, value]) => {\n if (typeof value === 'string') {\n // Make sure the provided string is a valid URL or just skip trying to set this uniform entirely\n if (!isValidUrl(value)) {\n console.warn(`Uniform \"${key}\" has invalid URL \"${value}\". Skipping image loading.`);\n return;\n }\n\n const imagePromise = new Promise<void>((resolve, reject) => {\n const img = new Image();\n if (isExternalUrl(value)) {\n img.crossOrigin = 'anonymous';\n }\n img.onload = () => {\n processedUniforms[key] = img;\n resolve();\n };\n img.onerror = () => {\n console.error(`Could not set uniforms. Failed to load image at ${value}`);\n reject();\n };\n img.src = value;\n });\n imageLoadPromises.push(imagePromise);\n } else {\n processedUniforms[key] = value;\n }\n });\n\n await Promise.all(imageLoadPromises);\n return processedUniforms;\n}\n\n/**\n * A React component that mounts a shader and updates its uniforms as the component's props change\n * If you pass a string as a uniform value, it will be assumed to be a URL and attempted to be loaded as an image\n */\nexport const ShaderMount: React.FC<ShaderMountProps> = forwardRef<PaperShaderElement, ShaderMountProps>(\n function ShaderMountImpl(\n {\n fragmentShader,\n uniforms: uniformsProp,\n webGlContextAttributes,\n speed = 0,\n frame = 0,\n width,\n height,\n minPixelRatio,\n maxPixelCount,\n style,\n ...divProps\n },\n forwardedRef\n ) {\n const [
|
|
5
|
-
"mappings": ";;;;;;AAEA,SAAS,WAAW,QAAQ,YAAY,
|
|
4
|
+
"sourcesContent": ["'use client';\n\nimport { useEffect, useRef, forwardRef, useState, useLayoutEffect } from 'react';\nimport {\n ShaderMount as ShaderMountVanilla,\n type PaperShaderElement,\n type ShaderMotionParams,\n type ShaderMountUniforms,\n} from '@paper-design/shaders';\nimport { useMergeRefs } from './use-merge-refs.js';\nimport { transparentPixel } from './transparent-pixel.js';\nimport { fastDeepEqual } from './fast-deep-equal.js';\n\n/**\n * React Shader Mount can also accept strings as uniform values, which will assumed to be URLs and loaded as images\n *\n * We accept undefined as a convenience for server rendering, when some things may be undefined\n * We just skip setting the uniform if it's undefined. This allows the shader mount to still take up space during server rendering\n */\ninterface ShaderMountUniformsReact {\n [key: string]: string | boolean | number | number[] | number[][] | HTMLImageElement | undefined;\n}\n\nexport interface ShaderMountProps extends Omit<React.ComponentProps<'div'>, 'color' | 'ref'>, ShaderMotionParams {\n ref?: React.Ref<PaperShaderElement>;\n fragmentShader: string;\n uniforms: ShaderMountUniformsReact;\n minPixelRatio?: number;\n maxPixelCount?: number;\n webGlContextAttributes?: WebGLContextAttributes;\n\n /** Inline CSS width style */\n width?: string | number;\n /** Inline CSS height style */\n height?: string | number;\n}\n\nexport interface ShaderComponentProps extends Omit<React.ComponentProps<'div'>, 'color' | 'ref'> {\n ref?: React.Ref<PaperShaderElement>;\n minPixelRatio?: number;\n maxPixelCount?: number;\n webGlContextAttributes?: WebGLContextAttributes;\n\n /** Inline CSS width style */\n width?: string | number;\n /** Inline CSS height style */\n height?: string | number;\n}\n\n/** Parse the provided uniforms, turning URL strings into loaded images */\nasync function processUniforms(uniformsProp: ShaderMountUniformsReact): Promise<ShaderMountUniforms> {\n const processedUniforms = {} as ShaderMountUniforms;\n const imageLoadPromises: Promise<void>[] = [];\n\n const isValidUrl = (url: string): boolean => {\n try {\n // Handle absolute paths\n if (url.startsWith('/')) return true;\n // Check if it's a valid URL\n new URL(url);\n return true;\n } catch {\n return false;\n }\n };\n\n const isExternalUrl = (url: string): boolean => {\n try {\n if (url.startsWith('/')) return false;\n const urlObject = new URL(url, window.location.origin);\n return urlObject.origin !== window.location.origin;\n } catch {\n return false;\n }\n };\n\n Object.entries(uniformsProp).forEach(([key, value]) => {\n if (typeof value === 'string') {\n // Make sure the provided string is a valid URL or just skip trying to set this uniform entirely\n if (!isValidUrl(value)) {\n console.warn(`Uniform \"${key}\" has invalid URL \"${value}\". Skipping image loading.`);\n return;\n }\n\n const imagePromise = new Promise<void>((resolve, reject) => {\n const img = new Image();\n if (isExternalUrl(value)) {\n img.crossOrigin = 'anonymous';\n }\n img.onload = () => {\n processedUniforms[key] = img;\n resolve();\n };\n img.onerror = () => {\n console.error(`Could not set uniforms. Failed to load image at ${value}`);\n reject();\n };\n // Use a transparent pixel for empty strings\n img.src = value || transparentPixel;\n });\n imageLoadPromises.push(imagePromise);\n } else {\n processedUniforms[key] = value;\n }\n });\n\n await Promise.all(imageLoadPromises);\n return processedUniforms;\n}\n\n/**\n * A React component that mounts a shader and updates its uniforms as the component's props change\n * If you pass a string as a uniform value, it will be assumed to be a URL and attempted to be loaded as an image\n */\nexport const ShaderMount: React.FC<ShaderMountProps> = forwardRef<PaperShaderElement, ShaderMountProps>(\n function ShaderMountImpl(\n {\n fragmentShader: fragmentShaderProp,\n uniforms: uniformsProp,\n webGlContextAttributes,\n speed = 0,\n frame = 0,\n width,\n height,\n minPixelRatio,\n maxPixelCount,\n style,\n ...divProps\n },\n forwardedRef\n ) {\n const containerRef = useRef<PaperShaderElement>(null);\n const [shaderMount, setShaderMount] = useState<ShaderMountVanilla | null>(null);\n\n // Uniforms that have been registered for processing or already processed\n const uniformsRegistered = useRef<ShaderMountUniformsReact>(null);\n\n // Save the initial shader fragment and context attributes, they are not allowed to change\n const [initialShaderFragment] = useState(fragmentShaderProp);\n const [initialContextAttrs] = useState(webGlContextAttributes);\n\n // Initial frame that the animation starts at\n const initialFrame = useRef(frame);\n\n const [documentVisible, setDocumentVisible] = useState(() => {\n return typeof window === 'undefined' || document.hidden === false;\n });\n\n useLayoutEffect(() => {\n // Check if uniforms have changed, if yes we'll schedule processing\n const uniformsDidChange = !fastDeepEqual(uniformsRegistered.current, uniformsProp);\n\n if (uniformsDidChange) {\n let cancelPromise = false;\n\n processUniforms(uniformsProp).then((uniforms) => {\n if (cancelPromise || !containerRef.current) {\n return;\n }\n\n uniformsRegistered.current = uniformsProp;\n\n // If shader mount already exists, we can update the uniforms\n if (shaderMount) {\n shaderMount.setUniforms(uniforms);\n return;\n }\n\n // Otherwise, initialize a new shader mount\n const canvas = new ShaderMountVanilla(\n containerRef.current,\n initialShaderFragment,\n uniforms,\n initialContextAttrs,\n speed,\n frame,\n minPixelRatio,\n maxPixelCount\n );\n\n setShaderMount(canvas);\n });\n\n return () => {\n cancelPromise = true;\n };\n }\n\n // Can't do granular updates if shader mount doesn't exist yet\n if (!shaderMount) {\n return;\n }\n\n // Pause when document is hidden\n const targetSpeed = documentVisible ? speed : 0;\n if (shaderMount.speed !== targetSpeed) {\n shaderMount.setSpeed(targetSpeed);\n }\n\n if (initialFrame.current !== frame) {\n initialFrame.current = frame;\n shaderMount.setFrame(frame);\n }\n\n if (shaderMount.minPixelRatio !== minPixelRatio) {\n shaderMount.setMinPixelRatio(minPixelRatio);\n }\n\n if (shaderMount.maxPixelCount !== maxPixelCount) {\n shaderMount.setMaxPixelCount(maxPixelCount);\n }\n }, [\n documentVisible,\n frame,\n initialContextAttrs,\n initialShaderFragment,\n maxPixelCount,\n minPixelRatio,\n shaderMount,\n speed,\n uniformsProp,\n ]);\n\n // Free up shader mount resources when the component unmounts\n useEffect(() => {\n return () => {\n shaderMount?.dispose();\n };\n }, [shaderMount]);\n\n useEffect(() => {\n function onVisibilityChange() {\n setDocumentVisible(!document.hidden);\n }\n\n document.addEventListener('visibilitychange', onVisibilityChange);\n\n return () => {\n document.removeEventListener('visibilitychange', onVisibilityChange);\n };\n }, []);\n\n return (\n <div\n ref={useMergeRefs([containerRef, forwardedRef]) as unknown as React.RefObject<HTMLDivElement>}\n style={width !== undefined || height !== undefined ? { width, height, ...style } : style}\n {...divProps}\n />\n );\n }\n);\n\nShaderMount.displayName = 'ShaderMount';\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type ShaderComponentProps } from '../shader-mount.js';
|
|
2
2
|
import { type DitheringParams, type ShaderPreset } from '@paper-design/shaders';
|
|
3
3
|
export interface DitheringProps extends ShaderComponentProps, DitheringParams {
|
|
4
|
+
/** @deprecated use `size` instead */
|
|
5
|
+
pxSize?: number;
|
|
4
6
|
}
|
|
5
7
|
type DitheringPreset = ShaderPreset<DitheringParams>;
|
|
6
8
|
export declare const defaultPreset: DitheringPreset;
|
|
@@ -26,7 +26,7 @@ const defaultPreset = {
|
|
|
26
26
|
colorFront: "#00b2ff",
|
|
27
27
|
shape: "sphere",
|
|
28
28
|
type: "4x4",
|
|
29
|
-
|
|
29
|
+
size: 2
|
|
30
30
|
}
|
|
31
31
|
};
|
|
32
32
|
const sinePreset = {
|
|
@@ -39,7 +39,7 @@ const sinePreset = {
|
|
|
39
39
|
colorFront: "#00becc",
|
|
40
40
|
shape: "wave",
|
|
41
41
|
type: "4x4",
|
|
42
|
-
|
|
42
|
+
size: 11,
|
|
43
43
|
scale: 1.2
|
|
44
44
|
}
|
|
45
45
|
};
|
|
@@ -53,7 +53,7 @@ const bugsPreset = {
|
|
|
53
53
|
colorFront: "#008000",
|
|
54
54
|
shape: "dots",
|
|
55
55
|
type: "random",
|
|
56
|
-
|
|
56
|
+
size: 9
|
|
57
57
|
}
|
|
58
58
|
};
|
|
59
59
|
const ripplePreset = {
|
|
@@ -66,7 +66,7 @@ const ripplePreset = {
|
|
|
66
66
|
colorFront: "#c67953",
|
|
67
67
|
shape: "ripple",
|
|
68
68
|
type: "2x2",
|
|
69
|
-
|
|
69
|
+
size: 3
|
|
70
70
|
}
|
|
71
71
|
};
|
|
72
72
|
const swirlPreset = {
|
|
@@ -79,7 +79,7 @@ const swirlPreset = {
|
|
|
79
79
|
colorFront: "#47a8e1",
|
|
80
80
|
shape: "swirl",
|
|
81
81
|
type: "8x8",
|
|
82
|
-
|
|
82
|
+
size: 2
|
|
83
83
|
}
|
|
84
84
|
};
|
|
85
85
|
const warpPreset = {
|
|
@@ -92,7 +92,7 @@ const warpPreset = {
|
|
|
92
92
|
colorFront: "#56ae6c",
|
|
93
93
|
shape: "warp",
|
|
94
94
|
type: "4x4",
|
|
95
|
-
|
|
95
|
+
size: 2.5
|
|
96
96
|
}
|
|
97
97
|
};
|
|
98
98
|
const ditheringPresets = [
|
|
@@ -111,7 +111,8 @@ const Dithering = memo(function DitheringImpl({
|
|
|
111
111
|
colorFront = defaultPreset.params.colorFront,
|
|
112
112
|
shape = defaultPreset.params.shape,
|
|
113
113
|
type = defaultPreset.params.type,
|
|
114
|
-
pxSize
|
|
114
|
+
pxSize,
|
|
115
|
+
size = pxSize === void 0 ? defaultPreset.params.size : pxSize,
|
|
115
116
|
// Sizing props
|
|
116
117
|
fit = defaultPreset.params.fit,
|
|
117
118
|
scale = defaultPreset.params.scale,
|
|
@@ -130,7 +131,7 @@ const Dithering = memo(function DitheringImpl({
|
|
|
130
131
|
u_colorFront: getShaderColorFromString(colorFront),
|
|
131
132
|
u_shape: DitheringShapes[shape],
|
|
132
133
|
u_type: DitheringTypes[type],
|
|
133
|
-
u_pxSize:
|
|
134
|
+
u_pxSize: size,
|
|
134
135
|
// Sizing uniforms
|
|
135
136
|
u_fit: ShaderFitOptions[fit],
|
|
136
137
|
u_scale: scale,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/shaders/dithering.tsx"],
|
|
4
|
-
"sourcesContent": ["import { memo } from 'react';\nimport { ShaderMount, type ShaderComponentProps } from '../shader-mount.js';\nimport {\n getShaderColorFromString,\n ditheringFragmentShader,\n ShaderFitOptions,\n type DitheringUniforms,\n type DitheringParams,\n type ShaderPreset,\n defaultPatternSizing,\n defaultObjectSizing,\n DitheringTypes,\n} from '@paper-design/shaders';\nimport { DitheringShapes } from '@paper-design/shaders';\n\nexport interface DitheringProps extends ShaderComponentProps, DitheringParams {}\n\ntype DitheringPreset = ShaderPreset<DitheringParams>;\n\nexport const defaultPreset: DitheringPreset = {\n name: 'Default',\n params: {\n ...defaultPatternSizing,\n speed: 1,\n frame: 0,\n scale: 0.6,\n colorBack: '#000000',\n colorFront: '#00b2ff',\n shape: 'sphere',\n type: '4x4',\n
|
|
5
|
-
"mappings": ";;;;;AAAA,SAAS,YAAY;AACrB,SAAS,mBAA8C;AACvD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EAIA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,uBAAuB;
|
|
4
|
+
"sourcesContent": ["import { memo } from 'react';\nimport { ShaderMount, type ShaderComponentProps } from '../shader-mount.js';\nimport {\n getShaderColorFromString,\n ditheringFragmentShader,\n ShaderFitOptions,\n type DitheringUniforms,\n type DitheringParams,\n type ShaderPreset,\n defaultPatternSizing,\n defaultObjectSizing,\n DitheringTypes,\n} from '@paper-design/shaders';\nimport { DitheringShapes } from '@paper-design/shaders';\n\nexport interface DitheringProps extends ShaderComponentProps, DitheringParams {\n /** @deprecated use `size` instead */\n pxSize?: number;\n}\n\ntype DitheringPreset = ShaderPreset<DitheringParams>;\n\nexport const defaultPreset: DitheringPreset = {\n name: 'Default',\n params: {\n ...defaultPatternSizing,\n speed: 1,\n frame: 0,\n scale: 0.6,\n colorBack: '#000000',\n colorFront: '#00b2ff',\n shape: 'sphere',\n type: '4x4',\n size: 2,\n },\n} as const;\n\nexport const sinePreset: DitheringPreset = {\n name: 'Sine Wave',\n params: {\n ...defaultPatternSizing,\n speed: 1,\n frame: 0,\n colorBack: '#730d54',\n colorFront: '#00becc',\n shape: 'wave',\n type: '4x4',\n size: 11,\n scale: 1.2,\n },\n} as const;\n\nexport const bugsPreset: DitheringPreset = {\n name: 'Bugs',\n params: {\n ...defaultPatternSizing,\n speed: 1,\n frame: 0,\n colorBack: '#000000',\n colorFront: '#008000',\n shape: 'dots',\n type: 'random',\n size: 9,\n },\n} as const;\n\nexport const ripplePreset: DitheringPreset = {\n name: 'Ripple',\n params: {\n ...defaultObjectSizing,\n speed: 1,\n frame: 0,\n colorBack: '#603520',\n colorFront: '#c67953',\n shape: 'ripple',\n type: '2x2',\n size: 3,\n },\n} as const;\n\nexport const swirlPreset: DitheringPreset = {\n name: 'Swirl',\n params: {\n ...defaultObjectSizing,\n speed: 1,\n frame: 0,\n colorBack: '#00000000',\n colorFront: '#47a8e1',\n shape: 'swirl',\n type: '8x8',\n size: 2,\n },\n} as const;\n\nexport const warpPreset: DitheringPreset = {\n name: 'Warp',\n params: {\n ...defaultObjectSizing,\n speed: 1,\n frame: 0,\n colorBack: '#301c2a',\n colorFront: '#56ae6c',\n shape: 'warp',\n type: '4x4',\n size: 2.5,\n },\n} as const;\n\nexport const ditheringPresets: DitheringPreset[] = [\n defaultPreset,\n warpPreset,\n sinePreset,\n ripplePreset,\n bugsPreset,\n swirlPreset,\n];\n\nexport const Dithering: React.FC<DitheringProps> = memo(function DitheringImpl({\n // Own props\n speed = defaultPreset.params.speed,\n frame = defaultPreset.params.frame,\n colorBack = defaultPreset.params.colorBack,\n colorFront = defaultPreset.params.colorFront,\n shape = defaultPreset.params.shape,\n type = defaultPreset.params.type,\n pxSize,\n size = pxSize === undefined ? defaultPreset.params.size : pxSize,\n\n // Sizing props\n fit = defaultPreset.params.fit,\n scale = defaultPreset.params.scale,\n rotation = defaultPreset.params.rotation,\n originX = defaultPreset.params.originX,\n originY = defaultPreset.params.originY,\n offsetX = defaultPreset.params.offsetX,\n offsetY = defaultPreset.params.offsetY,\n worldWidth = defaultPreset.params.worldWidth,\n worldHeight = defaultPreset.params.worldHeight,\n ...props\n}) {\n const uniforms = {\n // Own uniforms\n u_colorBack: getShaderColorFromString(colorBack),\n u_colorFront: getShaderColorFromString(colorFront),\n u_shape: DitheringShapes[shape],\n u_type: DitheringTypes[type],\n u_pxSize: size,\n\n // Sizing uniforms\n u_fit: ShaderFitOptions[fit],\n u_scale: scale,\n u_rotation: rotation,\n u_offsetX: offsetX,\n u_offsetY: offsetY,\n u_originX: originX,\n u_originY: originY,\n u_worldWidth: worldWidth,\n u_worldHeight: worldHeight,\n } satisfies DitheringUniforms;\n\n return (\n <ShaderMount {...props} speed={speed} frame={frame} fragmentShader={ditheringFragmentShader} uniforms={uniforms} />\n );\n});\n"],
|
|
5
|
+
"mappings": ";;;;;AAAA,SAAS,YAAY;AACrB,SAAS,mBAA8C;AACvD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EAIA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,uBAAuB;AAoJ5B;AA3IG,MAAM,gBAAiC;AAAA,EAC5C,MAAM;AAAA,EACN,QAAQ;AAAA,IACN,GAAG;AAAA,IACH,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AACF;AAEO,MAAM,aAA8B;AAAA,EACzC,MAAM;AAAA,EACN,QAAQ;AAAA,IACN,GAAG;AAAA,IACH,OAAO;AAAA,IACP,OAAO;AAAA,IACP,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AACF;AAEO,MAAM,aAA8B;AAAA,EACzC,MAAM;AAAA,EACN,QAAQ;AAAA,IACN,GAAG;AAAA,IACH,OAAO;AAAA,IACP,OAAO;AAAA,IACP,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AACF;AAEO,MAAM,eAAgC;AAAA,EAC3C,MAAM;AAAA,EACN,QAAQ;AAAA,IACN,GAAG;AAAA,IACH,OAAO;AAAA,IACP,OAAO;AAAA,IACP,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AACF;AAEO,MAAM,cAA+B;AAAA,EAC1C,MAAM;AAAA,EACN,QAAQ;AAAA,IACN,GAAG;AAAA,IACH,OAAO;AAAA,IACP,OAAO;AAAA,IACP,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AACF;AAEO,MAAM,aAA8B;AAAA,EACzC,MAAM;AAAA,EACN,QAAQ;AAAA,IACN,GAAG;AAAA,IACH,OAAO;AAAA,IACP,OAAO;AAAA,IACP,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AACF;AAEO,MAAM,mBAAsC;AAAA,EACjD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,MAAM,YAAsC,KAAK,SAAS,cAAc;AAAA;AAAA,EAE7E,QAAQ,cAAc,OAAO;AAAA,EAC7B,QAAQ,cAAc,OAAO;AAAA,EAC7B,YAAY,cAAc,OAAO;AAAA,EACjC,aAAa,cAAc,OAAO;AAAA,EAClC,QAAQ,cAAc,OAAO;AAAA,EAC7B,OAAO,cAAc,OAAO;AAAA,EAC5B;AAAA,EACA,OAAO,WAAW,SAAY,cAAc,OAAO,OAAO;AAAA;AAAA,EAG1D,MAAM,cAAc,OAAO;AAAA,EAC3B,QAAQ,cAAc,OAAO;AAAA,EAC7B,WAAW,cAAc,OAAO;AAAA,EAChC,UAAU,cAAc,OAAO;AAAA,EAC/B,UAAU,cAAc,OAAO;AAAA,EAC/B,UAAU,cAAc,OAAO;AAAA,EAC/B,UAAU,cAAc,OAAO;AAAA,EAC/B,aAAa,cAAc,OAAO;AAAA,EAClC,cAAc,cAAc,OAAO;AAAA,EACnC,GAAG;AACL,GAAG;AACD,QAAM,WAAW;AAAA;AAAA,IAEf,aAAa,yBAAyB,SAAS;AAAA,IAC/C,cAAc,yBAAyB,UAAU;AAAA,IACjD,SAAS,gBAAgB,KAAK;AAAA,IAC9B,QAAQ,eAAe,IAAI;AAAA,IAC3B,UAAU;AAAA;AAAA,IAGV,OAAO,iBAAiB,GAAG;AAAA,IAC3B,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,WAAW;AAAA,IACX,WAAW;AAAA,IACX,WAAW;AAAA,IACX,cAAc;AAAA,IACd,eAAe;AAAA,EACjB;AAEA,SACE,oBAAC,eAAa,GAAG,OAAO,OAAc,OAAc,gBAAgB,yBAAyB,UAAoB;AAErH,CAAC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -28,6 +28,7 @@ const defaultPreset = {
|
|
|
28
28
|
shift: 0,
|
|
29
29
|
blur: 3,
|
|
30
30
|
edges: 0,
|
|
31
|
+
margin: 0,
|
|
31
32
|
marginLeft: 0,
|
|
32
33
|
marginRight: 0,
|
|
33
34
|
marginTop: 0,
|
|
@@ -49,6 +50,7 @@ const wavesPreset = {
|
|
|
49
50
|
shift: 0,
|
|
50
51
|
blur: 0,
|
|
51
52
|
edges: 0,
|
|
53
|
+
margin: 0,
|
|
52
54
|
marginLeft: 0,
|
|
53
55
|
marginRight: 0,
|
|
54
56
|
marginTop: 0,
|
|
@@ -71,6 +73,7 @@ const irregularPreset = {
|
|
|
71
73
|
shift: 0,
|
|
72
74
|
blur: 25,
|
|
73
75
|
edges: 1,
|
|
76
|
+
margin: 0,
|
|
74
77
|
marginLeft: 0,
|
|
75
78
|
marginRight: 0,
|
|
76
79
|
marginTop: 0,
|
|
@@ -92,8 +95,9 @@ const foldsPreset = {
|
|
|
92
95
|
shift: 0,
|
|
93
96
|
blur: 0,
|
|
94
97
|
edges: 0,
|
|
95
|
-
|
|
96
|
-
|
|
98
|
+
margin: 0.2,
|
|
99
|
+
marginLeft: 0.2,
|
|
100
|
+
marginRight: 0.2,
|
|
97
101
|
marginTop: 0.2,
|
|
98
102
|
marginBottom: 0.2
|
|
99
103
|
}
|
|
@@ -103,21 +107,22 @@ const FlutedGlass = memo(function FlutedGlassImpl({
|
|
|
103
107
|
// Own props
|
|
104
108
|
speed = defaultPreset.params.speed,
|
|
105
109
|
frame = defaultPreset.params.frame,
|
|
106
|
-
image = "
|
|
110
|
+
image = "",
|
|
107
111
|
angle = defaultPreset.params.angle,
|
|
108
112
|
distortion = defaultPreset.params.distortion,
|
|
109
113
|
distortionShape = defaultPreset.params.distortionShape,
|
|
110
114
|
shape = defaultPreset.params.shape,
|
|
111
115
|
shift = defaultPreset.params.shift,
|
|
112
116
|
blur = defaultPreset.params.blur,
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
+
margin,
|
|
118
|
+
marginLeft = margin ?? defaultPreset.params.marginLeft,
|
|
119
|
+
marginRight = margin ?? defaultPreset.params.marginRight,
|
|
120
|
+
marginTop = margin ?? defaultPreset.params.marginTop,
|
|
121
|
+
marginBottom = margin ?? defaultPreset.params.marginBottom,
|
|
117
122
|
edges = defaultPreset.params.edges,
|
|
118
123
|
// integer `count` was deprecated in favor of the normalized `size` param
|
|
119
124
|
count,
|
|
120
|
-
size = count === void 0 ? defaultPreset.params.
|
|
125
|
+
size = count === void 0 ? defaultPreset.params.size : Math.pow(1 / (count * 1.6), 1 / 6) / 0.7 - 0.5,
|
|
121
126
|
// Sizing props
|
|
122
127
|
fit = defaultPreset.params.fit,
|
|
123
128
|
scale = defaultPreset.params.scale,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/shaders/fluted-glass.tsx"],
|
|
4
|
-
"sourcesContent": ["import { memo } from 'react';\nimport { ShaderMount, type ShaderComponentProps } from '../shader-mount.js';\nimport {\n flutedGlassFragmentShader,\n ShaderFitOptions,\n type FlutedGlassUniforms,\n type FlutedGlassParams,\n defaultObjectSizing,\n GlassDistortionShapes,\n GlassGridShapes,\n type ImageShaderPreset,\n} from '@paper-design/shaders';\n\nexport interface FlutedGlassProps extends ShaderComponentProps, FlutedGlassParams {\n /** @deprecated use `size` instead */\n count?: number;\n}\n\ntype FlutedGlassPreset = ImageShaderPreset<FlutedGlassParams>;\n\nexport const defaultPreset: FlutedGlassPreset = {\n name: 'Default',\n params: {\n ...defaultObjectSizing,\n fit: 'cover',\n speed: 0,\n frame: 0,\n size: 0.15,\n angle: 0,\n distortionShape: 'lens',\n shape: 'lines',\n distortion: 0.5,\n shift: 0,\n blur: 3,\n edges: 0,\n marginLeft: 0,\n marginRight: 0,\n marginTop: 0,\n marginBottom: 0,\n },\n};\n\nexport const wavesPreset: FlutedGlassPreset = {\n name: 'Waves',\n params: {\n ...defaultObjectSizing,\n fit: 'cover',\n speed: 0,\n frame: 0,\n size: 0.3,\n angle: 0,\n distortionShape: 'contour',\n shape: 'wave',\n distortion: 0.3,\n shift: 0,\n blur: 0,\n edges: 0,\n marginLeft: 0,\n marginRight: 0,\n marginTop: 0,\n marginBottom: 0,\n },\n};\n\nexport const irregularPreset: FlutedGlassPreset = {\n name: 'Irregular lines',\n params: {\n ...defaultObjectSizing,\n fit: 'cover',\n scale: 4,\n speed: 0,\n frame: 0,\n size: 0.3,\n angle: 150,\n distortionShape: 'facete',\n shape: 'linesIrregular',\n distortion: 1,\n shift: 0,\n blur: 25,\n edges: 1,\n marginLeft: 0,\n marginRight: 0,\n marginTop: 0,\n marginBottom: 0,\n },\n};\n\nexport const foldsPreset: FlutedGlassPreset = {\n name: 'Folds',\n params: {\n ...defaultObjectSizing,\n fit: 'cover',\n speed: 0,\n frame: 0,\n size: 0.25,\n angle: 0,\n distortionShape: 'cascade',\n shape: 'lines',\n distortion: 0.75,\n shift: 0,\n blur: 0,\n edges: 0,\n marginLeft: 0.
|
|
5
|
-
"mappings": ";;;;;AAAA,SAAS,YAAY;AACrB,SAAS,mBAA8C;AACvD;AAAA,EACE;AAAA,EACA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;
|
|
4
|
+
"sourcesContent": ["import { memo } from 'react';\nimport { ShaderMount, type ShaderComponentProps } from '../shader-mount.js';\nimport {\n flutedGlassFragmentShader,\n ShaderFitOptions,\n type FlutedGlassUniforms,\n type FlutedGlassParams,\n defaultObjectSizing,\n GlassDistortionShapes,\n GlassGridShapes,\n type ImageShaderPreset,\n} from '@paper-design/shaders';\n\nexport interface FlutedGlassProps extends ShaderComponentProps, FlutedGlassParams {\n /** @deprecated use `size` instead */\n count?: number;\n}\n\ntype FlutedGlassPreset = ImageShaderPreset<FlutedGlassParams>;\n\nexport const defaultPreset: FlutedGlassPreset = {\n name: 'Default',\n params: {\n ...defaultObjectSizing,\n fit: 'cover',\n speed: 0,\n frame: 0,\n size: 0.15,\n angle: 0,\n distortionShape: 'lens',\n shape: 'lines',\n distortion: 0.5,\n shift: 0,\n blur: 3,\n edges: 0,\n margin: 0,\n marginLeft: 0,\n marginRight: 0,\n marginTop: 0,\n marginBottom: 0,\n },\n};\n\nexport const wavesPreset: FlutedGlassPreset = {\n name: 'Waves',\n params: {\n ...defaultObjectSizing,\n fit: 'cover',\n speed: 0,\n frame: 0,\n size: 0.3,\n angle: 0,\n distortionShape: 'contour',\n shape: 'wave',\n distortion: 0.3,\n shift: 0,\n blur: 0,\n edges: 0,\n margin: 0,\n marginLeft: 0,\n marginRight: 0,\n marginTop: 0,\n marginBottom: 0,\n },\n};\n\nexport const irregularPreset: FlutedGlassPreset = {\n name: 'Irregular lines',\n params: {\n ...defaultObjectSizing,\n fit: 'cover',\n scale: 4,\n speed: 0,\n frame: 0,\n size: 0.3,\n angle: 150,\n distortionShape: 'facete',\n shape: 'linesIrregular',\n distortion: 1,\n shift: 0,\n blur: 25,\n edges: 1,\n margin: 0,\n marginLeft: 0,\n marginRight: 0,\n marginTop: 0,\n marginBottom: 0,\n },\n};\n\nexport const foldsPreset: FlutedGlassPreset = {\n name: 'Folds',\n params: {\n ...defaultObjectSizing,\n fit: 'cover',\n speed: 0,\n frame: 0,\n size: 0.25,\n angle: 0,\n distortionShape: 'cascade',\n shape: 'lines',\n distortion: 0.75,\n shift: 0,\n blur: 0,\n edges: 0,\n margin: 0.2,\n marginLeft: 0.2,\n marginRight: 0.2,\n marginTop: 0.2,\n marginBottom: 0.2,\n },\n};\n\nexport const flutedGlassPresets: FlutedGlassPreset[] = [defaultPreset, irregularPreset, wavesPreset, foldsPreset];\n\nexport const FlutedGlass: React.FC<FlutedGlassProps> = memo(function FlutedGlassImpl({\n // Own props\n speed = defaultPreset.params.speed,\n frame = defaultPreset.params.frame,\n image = '',\n angle = defaultPreset.params.angle,\n distortion = defaultPreset.params.distortion,\n distortionShape = defaultPreset.params.distortionShape,\n shape = defaultPreset.params.shape,\n shift = defaultPreset.params.shift,\n blur = defaultPreset.params.blur,\n margin,\n marginLeft = margin ?? defaultPreset.params.marginLeft,\n marginRight = margin ?? defaultPreset.params.marginRight,\n marginTop = margin ?? defaultPreset.params.marginTop,\n marginBottom = margin ?? defaultPreset.params.marginBottom,\n edges = defaultPreset.params.edges,\n\n // integer `count` was deprecated in favor of the normalized `size` param\n count,\n size = count === undefined ? defaultPreset.params.size : Math.pow(1 / (count * 1.6), 1 / 6) / 0.7 - 0.5,\n\n // Sizing props\n fit = defaultPreset.params.fit,\n scale = defaultPreset.params.scale,\n rotation = defaultPreset.params.rotation,\n originX = defaultPreset.params.originX,\n originY = defaultPreset.params.originY,\n offsetX = defaultPreset.params.offsetX,\n offsetY = defaultPreset.params.offsetY,\n worldWidth = defaultPreset.params.worldWidth,\n worldHeight = defaultPreset.params.worldHeight,\n ...props\n}: FlutedGlassProps) {\n const uniforms = {\n // Own uniforms\n u_image: image,\n u_size: size,\n u_angle: angle,\n u_distortion: distortion,\n u_shift: shift,\n u_blur: blur,\n u_edges: edges,\n u_distortionShape: GlassDistortionShapes[distortionShape],\n u_shape: GlassGridShapes[shape],\n u_marginLeft: marginLeft,\n u_marginRight: marginRight,\n u_marginTop: marginTop,\n u_marginBottom: marginBottom,\n\n // Sizing uniforms\n u_fit: ShaderFitOptions[fit],\n u_scale: scale,\n u_rotation: rotation,\n u_offsetX: offsetX,\n u_offsetY: offsetY,\n u_originX: originX,\n u_originY: originY,\n u_worldWidth: worldWidth,\n u_worldHeight: worldHeight,\n } satisfies FlutedGlassUniforms;\n\n return (\n <ShaderMount\n {...props}\n speed={speed}\n frame={frame}\n fragmentShader={flutedGlassFragmentShader}\n uniforms={uniforms}\n />\n );\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|