@waveso/ui 0.0.10 → 0.1.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/accordion.d.ts +24 -8
- package/dist/accordion.d.ts.map +1 -0
- package/dist/accordion.js +50 -73
- package/dist/accordion.js.map +1 -1
- package/dist/action-bar.d.ts +83 -0
- package/dist/action-bar.d.ts.map +1 -0
- package/dist/action-bar.js +264 -0
- package/dist/action-bar.js.map +1 -0
- package/dist/alert-dialog.d.ts +56 -21
- package/dist/alert-dialog.d.ts.map +1 -0
- package/dist/alert-dialog.js +75 -127
- package/dist/alert-dialog.js.map +1 -1
- package/dist/alert.d.ts +26 -11
- package/dist/alert.d.ts.map +1 -0
- package/dist/alert.js +37 -68
- package/dist/alert.js.map +1 -1
- package/dist/animate.d.ts +117 -75
- package/dist/animate.d.ts.map +1 -0
- package/dist/animate.js +259 -223
- package/dist/animate.js.map +1 -1
- package/dist/aspect-ratio.d.ts +11 -6
- package/dist/aspect-ratio.d.ts.map +1 -0
- package/dist/aspect-ratio.js +12 -14
- package/dist/aspect-ratio.js.map +1 -1
- package/dist/autocomplete.d.ts +91 -25
- package/dist/autocomplete.d.ts.map +1 -0
- package/dist/autocomplete.js +119 -181
- package/dist/autocomplete.js.map +1 -1
- package/dist/avatar.d.ts +32 -11
- package/dist/avatar.d.ts.map +1 -0
- package/dist/avatar.js +42 -89
- package/dist/avatar.js.map +1 -1
- package/dist/badge.d.ts +15 -8
- package/dist/badge.d.ts.map +1 -0
- package/dist/badge.js +34 -48
- package/dist/badge.js.map +1 -1
- package/dist/breadcrumb.d.ts +35 -11
- package/dist/breadcrumb.d.ts.map +1 -0
- package/dist/breadcrumb.js +60 -110
- package/dist/breadcrumb.js.map +1 -1
- package/dist/button-group.d.ts +26 -13
- package/dist/button-group.d.ts.map +1 -0
- package/dist/button-group.js +38 -76
- package/dist/button-group.js.map +1 -1
- package/dist/button.d.ts +17 -10
- package/dist/button.d.ts.map +1 -0
- package/dist/button.js +50 -3
- package/dist/button.js.map +1 -1
- package/dist/card.d.ts +35 -11
- package/dist/card.d.ts.map +1 -0
- package/dist/card.js +43 -82
- package/dist/card.js.map +1 -1
- package/dist/checkbox.d.ts +6 -4
- package/dist/checkbox.d.ts.map +1 -0
- package/dist/checkbox.js +21 -29
- package/dist/checkbox.js.map +1 -1
- package/dist/collapsible.d.ts +15 -7
- package/dist/collapsible.d.ts.map +1 -0
- package/dist/collapsible.js +19 -8
- package/dist/collapsible.js.map +1 -1
- package/dist/combobox.d.ts +83 -23
- package/dist/combobox.d.ts.map +1 -0
- package/dist/combobox.js +149 -247
- package/dist/combobox.js.map +1 -1
- package/dist/context-menu.d.ts +80 -26
- package/dist/context-menu.d.ts.map +1 -0
- package/dist/context-menu.js +108 -164
- package/dist/context-menu.js.map +1 -1
- package/dist/count.d.ts +45 -31
- package/dist/count.d.ts.map +1 -0
- package/dist/count.js +170 -165
- package/dist/count.js.map +1 -1
- package/dist/dialog.d.ts +61 -28
- package/dist/dialog.d.ts.map +1 -0
- package/dist/dialog.js +77 -120
- package/dist/dialog.js.map +1 -1
- package/dist/direction.d.ts +2 -1
- package/dist/direction.js +3 -3
- package/dist/drawer.d.ts +45 -15
- package/dist/drawer.d.ts.map +1 -0
- package/dist/drawer.js +93 -5
- package/dist/drawer.js.map +1 -1
- package/dist/encrypted-text.d.ts +25 -12
- package/dist/encrypted-text.d.ts.map +1 -0
- package/dist/encrypted-text.js +102 -134
- package/dist/encrypted-text.js.map +1 -1
- package/dist/field.d.ts +37 -21
- package/dist/field.d.ts.map +1 -0
- package/dist/field.js +52 -3
- package/dist/field.js.map +1 -1
- package/dist/film-grain-shader.d.ts +6 -0
- package/dist/film-grain-shader.d.ts.map +1 -0
- package/dist/film-grain-shader.js +88 -0
- package/dist/film-grain-shader.js.map +1 -0
- package/dist/film-grain-webgl.d.ts +20 -0
- package/dist/film-grain-webgl.d.ts.map +1 -0
- package/dist/film-grain-webgl.js +306 -0
- package/dist/film-grain-webgl.js.map +1 -0
- package/dist/film-grain.d.ts +21 -11
- package/dist/film-grain.d.ts.map +1 -0
- package/dist/film-grain.js +28 -420
- package/dist/film-grain.js.map +1 -1
- package/dist/form.d.ts +64 -49
- package/dist/form.d.ts.map +1 -0
- package/dist/form.js +112 -91
- package/dist/form.js.map +1 -1
- package/dist/gradient-reveal-text.d.ts +35 -22
- package/dist/gradient-reveal-text.d.ts.map +1 -0
- package/dist/gradient-reveal-text.js +238 -205
- package/dist/gradient-reveal-text.js.map +1 -1
- package/dist/hooks/use-mobile.d.ts +3 -1
- package/dist/hooks/use-mobile.d.ts.map +1 -0
- package/dist/hooks/use-mobile.js +28 -2
- package/dist/hooks/use-mobile.js.map +1 -1
- package/dist/infinite-scroll.d.ts +29 -15
- package/dist/infinite-scroll.d.ts.map +1 -0
- package/dist/infinite-scroll.js +69 -99
- package/dist/infinite-scroll.js.map +1 -1
- package/dist/input-group.d.ts +41 -18
- package/dist/input-group.d.ts.map +1 -0
- package/dist/input-group.js +80 -6
- package/dist/input-group.js.map +1 -1
- package/dist/input-otp.d.ts +26 -10
- package/dist/input-otp.d.ts.map +1 -0
- package/dist/input-otp.js +40 -70
- package/dist/input-otp.js.map +1 -1
- package/dist/input.d.ts +10 -4
- package/dist/input.d.ts.map +1 -0
- package/dist/input.js +16 -3
- package/dist/input.js.map +1 -1
- package/dist/item.d.ts +58 -23
- package/dist/item.d.ts.map +1 -0
- package/dist/item.js +102 -160
- package/dist/item.js.map +1 -1
- package/dist/kbd.d.ts +12 -4
- package/dist/kbd.d.ts.map +1 -0
- package/dist/kbd.js +15 -24
- package/dist/kbd.js.map +1 -1
- package/dist/label.d.ts +9 -4
- package/dist/label.d.ts.map +1 -0
- package/dist/label.js +12 -16
- package/dist/label.js.map +1 -1
- package/dist/lib/focus.d.ts +42 -0
- package/dist/lib/focus.d.ts.map +1 -0
- package/dist/lib/focus.js +21 -0
- package/dist/lib/focus.js.map +1 -0
- package/dist/lib/internal-icons.d.ts +32 -0
- package/dist/lib/internal-icons.d.ts.map +1 -0
- package/dist/lib/internal-icons.js +222 -0
- package/dist/lib/internal-icons.js.map +1 -0
- package/dist/lib/utils.d.ts +4 -2
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +12 -2
- package/dist/lib/utils.js.map +1 -1
- package/dist/masonry.d.ts +25 -11
- package/dist/masonry.d.ts.map +1 -0
- package/dist/masonry.js +188 -229
- package/dist/masonry.js.map +1 -1
- package/dist/menu.d.ts +84 -26
- package/dist/menu.d.ts.map +1 -0
- package/dist/menu.js +141 -4
- package/dist/menu.js.map +1 -1
- package/dist/menubar.d.ts +60 -22
- package/dist/menubar.d.ts.map +1 -0
- package/dist/menubar.js +80 -52
- package/dist/menubar.js.map +1 -1
- package/dist/pagination.d.ts +38 -17
- package/dist/pagination.d.ts.map +1 -0
- package/dist/pagination.js +68 -107
- package/dist/pagination.js.map +1 -1
- package/dist/popover.d.ts +56 -14
- package/dist/popover.d.ts.map +1 -0
- package/dist/popover.js +62 -87
- package/dist/popover.js.map +1 -1
- package/dist/preview-card.d.ts +28 -9
- package/dist/preview-card.d.ts.map +1 -0
- package/dist/preview-card.js +40 -60
- package/dist/preview-card.js.map +1 -1
- package/dist/progress.d.ts +28 -9
- package/dist/progress.d.ts.map +1 -0
- package/dist/progress.js +35 -60
- package/dist/progress.js.map +1 -1
- package/dist/radio-group.d.ts +14 -8
- package/dist/radio-group.d.ts.map +1 -0
- package/dist/radio-group.js +18 -22
- package/dist/radio-group.js.map +1 -1
- package/dist/radio.d.ts +14 -6
- package/dist/radio.d.ts.map +1 -0
- package/dist/radio.js +24 -3
- package/dist/radio.js.map +1 -1
- package/dist/scroll-area.d.ts +16 -6
- package/dist/scroll-area.d.ts.map +1 -0
- package/dist/scroll-area.js +34 -55
- package/dist/scroll-area.js.map +1 -1
- package/dist/select.d.ts +66 -18
- package/dist/select.d.ts.map +1 -0
- package/dist/select.js +105 -185
- package/dist/select.js.map +1 -1
- package/dist/separator.d.ts +11 -5
- package/dist/separator.d.ts.map +1 -0
- package/dist/separator.js +17 -3
- package/dist/separator.js.map +1 -1
- package/dist/sidebar.d.ts +172 -79
- package/dist/sidebar.d.ts.map +1 -0
- package/dist/sidebar.js +363 -585
- package/dist/sidebar.js.map +1 -1
- package/dist/skeleton.d.ts +8 -3
- package/dist/skeleton.d.ts.map +1 -0
- package/dist/skeleton.js +13 -3
- package/dist/skeleton.js.map +1 -1
- package/dist/slider.d.ts +16 -6
- package/dist/slider.d.ts.map +1 -0
- package/dist/slider.js +40 -67
- package/dist/slider.js.map +1 -1
- package/dist/spinner.d.ts +8 -3
- package/dist/spinner.d.ts.map +1 -0
- package/dist/spinner.js +15 -4
- package/dist/spinner.js.map +1 -1
- package/dist/switch.d.ts +12 -6
- package/dist/switch.d.ts.map +1 -0
- package/dist/switch.js +18 -25
- package/dist/switch.js.map +1 -1
- package/dist/table.d.ts +37 -11
- package/dist/table.d.ts.map +1 -0
- package/dist/table.js +51 -88
- package/dist/table.js.map +1 -1
- package/dist/tabs.d.ts +28 -12
- package/dist/tabs.d.ts.map +1 -0
- package/dist/tabs.js +40 -74
- package/dist/tabs.js.map +1 -1
- package/dist/textarea.d.ts +13 -6
- package/dist/textarea.d.ts.map +1 -0
- package/dist/textarea.js +19 -3
- package/dist/textarea.js.map +1 -1
- package/dist/toast.d.ts +63 -39
- package/dist/toast.d.ts.map +1 -0
- package/dist/toast.js +177 -215
- package/dist/toast.js.map +1 -1
- package/dist/toggle-group.d.ts +26 -12
- package/dist/toggle-group.d.ts.map +1 -0
- package/dist/toggle-group.js +49 -73
- package/dist/toggle-group.js.map +1 -1
- package/dist/toggle.d.ts +17 -10
- package/dist/toggle.d.ts.map +1 -0
- package/dist/toggle.js +38 -3
- package/dist/toggle.js.map +1 -1
- package/dist/tooltip.d.ts +35 -14
- package/dist/tooltip.d.ts.map +1 -0
- package/dist/tooltip.js +52 -3
- package/dist/tooltip.js.map +1 -1
- package/dist/typewriter.d.ts +44 -31
- package/dist/typewriter.d.ts.map +1 -0
- package/dist/typewriter.js +185 -185
- package/dist/typewriter.js.map +1 -1
- package/package.json +6 -6
- package/dist/chunk-45VQAWIM.js +0 -228
- package/dist/chunk-45VQAWIM.js.map +0 -1
- package/dist/chunk-6Y7LPQMO.js +0 -11
- package/dist/chunk-6Y7LPQMO.js.map +0 -1
- package/dist/chunk-76UQO56T.js +0 -19
- package/dist/chunk-76UQO56T.js.map +0 -1
- package/dist/chunk-7F4MPMLJ.js +0 -17
- package/dist/chunk-7F4MPMLJ.js.map +0 -1
- package/dist/chunk-BKTJYX4M.js +0 -143
- package/dist/chunk-BKTJYX4M.js.map +0 -1
- package/dist/chunk-D5XPEJ6T.js +0 -36
- package/dist/chunk-D5XPEJ6T.js.map +0 -1
- package/dist/chunk-DIGOLJIR.js +0 -105
- package/dist/chunk-DIGOLJIR.js.map +0 -1
- package/dist/chunk-IQ7YQ5XA.js +0 -141
- package/dist/chunk-IQ7YQ5XA.js.map +0 -1
- package/dist/chunk-NCHHHWTB.js +0 -85
- package/dist/chunk-NCHHHWTB.js.map +0 -1
- package/dist/chunk-OUFYQLVN.js +0 -56
- package/dist/chunk-OUFYQLVN.js.map +0 -1
- package/dist/chunk-QFSEK4M6.js +0 -22
- package/dist/chunk-QFSEK4M6.js.map +0 -1
- package/dist/chunk-QRW37LRP.js +0 -25
- package/dist/chunk-QRW37LRP.js.map +0 -1
- package/dist/chunk-RPQHL6C5.js +0 -26
- package/dist/chunk-RPQHL6C5.js.map +0 -1
- package/dist/chunk-V4ZX4YCP.js +0 -66
- package/dist/chunk-V4ZX4YCP.js.map +0 -1
- package/dist/chunk-YTSQQTSF.js +0 -44
- package/dist/chunk-YTSQQTSF.js.map +0 -1
- package/dist/chunk-ZZZH3JGW.js +0 -23
- package/dist/chunk-ZZZH3JGW.js.map +0 -1
- package/dist/direction.js.map +0 -1
package/dist/film-grain.js
CHANGED
|
@@ -1,422 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return fract(sin(dot(p + seed, vec2(127.1, 311.7))) * 43758.5453123);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Film response curve (soft toe + shoulder rolloff)
|
|
32
|
-
float filmCurve(float x) {
|
|
33
|
-
return smoothstep(0.0, 0.2, x) * (1.0 - smoothstep(0.8, 1.0, x));
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
void main() {
|
|
37
|
-
vec2 uv = gl_FragCoord.xy;
|
|
38
|
-
vec2 p = floor(uv);
|
|
39
|
-
|
|
40
|
-
// Temporal coherence: blend between current and next frame seed
|
|
41
|
-
float frame = floor(uTime * uFps);
|
|
42
|
-
float t = fract(uTime * uFps);
|
|
43
|
-
float seed = frame * 0.1731;
|
|
44
|
-
|
|
45
|
-
// Multi-scale grain with inter-frame blending on fine layer
|
|
46
|
-
float fineA = hash(p, seed);
|
|
47
|
-
float fineB = hash(p, seed + 0.1731);
|
|
48
|
-
float fine = mix(fineA, fineB, t);
|
|
49
|
-
|
|
50
|
-
float medium = hash(floor(uv * 0.5), seed + 3.1);
|
|
51
|
-
float coarse = hash(floor(uv * 0.25), seed + 7.93);
|
|
52
|
-
|
|
53
|
-
float grain = fine * 0.65 + medium * 0.25 + coarse * 0.10;
|
|
54
|
-
|
|
55
|
-
// Emulsion clumping (organic structure)
|
|
56
|
-
float cluster = hash(floor(uv * 0.18), seed + 9.2);
|
|
57
|
-
grain *= mix(0.75, 1.35, cluster);
|
|
58
|
-
|
|
59
|
-
// Density threshold
|
|
60
|
-
grain = smoothstep(1.0 - uDensity, 1.0, grain);
|
|
61
|
-
|
|
62
|
-
// Film response curve (replaces raw pow gamma)
|
|
63
|
-
grain = filmCurve(grain);
|
|
64
|
-
|
|
65
|
-
// Micro-blur: sample neighbors for optical diffusion
|
|
66
|
-
float n1 = hash(p + vec2(1.0, 0.0), seed);
|
|
67
|
-
float n2 = hash(p - vec2(1.0, 0.0), seed);
|
|
68
|
-
float n3 = hash(p + vec2(0.0, 1.0), seed);
|
|
69
|
-
float n4 = hash(p - vec2(0.0, 1.0), seed);
|
|
70
|
-
float neighbors = (n1 + n2 + n3 + n4) * 0.25;
|
|
71
|
-
grain = mix(grain, neighbors, 0.15);
|
|
72
|
-
|
|
73
|
-
// Chromatic aberration (reuse neighbor hashes)
|
|
74
|
-
float rShift = n1 * 0.015;
|
|
75
|
-
float bShift = n2 * 0.015;
|
|
76
|
-
|
|
77
|
-
vec3 color = uColor * vec3(
|
|
78
|
-
grain + rShift,
|
|
79
|
-
grain,
|
|
80
|
-
grain + bShift
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
color = clamp(color, 0.0, 1.0);
|
|
84
|
-
|
|
85
|
-
gl_FragColor = vec4(color, grain * uOpacity);
|
|
86
|
-
}
|
|
87
|
-
`;
|
|
88
|
-
|
|
89
|
-
// src/film-grain-webgl.ts
|
|
90
|
-
function parseHex(hex) {
|
|
91
|
-
if (!/^#([0-9a-f]{3,8})$/i.test(hex)) return [255, 255, 255, 255];
|
|
92
|
-
let h = hex.replace("#", "");
|
|
93
|
-
if (h.length === 3) h = h.split("").map((c) => c + c).join("");
|
|
94
|
-
if (h.length === 6) h += "ff";
|
|
95
|
-
const n = parseInt(h, 16);
|
|
96
|
-
return [n >> 24 & 255, n >> 16 & 255, n >> 8 & 255, n & 255];
|
|
97
|
-
}
|
|
98
|
-
function initWebGL(gl) {
|
|
99
|
-
const createShader = (type, source) => {
|
|
100
|
-
const shader = gl.createShader(type);
|
|
101
|
-
if (!shader) return null;
|
|
102
|
-
gl.shaderSource(shader, source);
|
|
103
|
-
gl.compileShader(shader);
|
|
104
|
-
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
105
|
-
gl.deleteShader(shader);
|
|
106
|
-
return null;
|
|
107
|
-
}
|
|
108
|
-
return shader;
|
|
109
|
-
};
|
|
110
|
-
const vs = createShader(gl.VERTEX_SHADER, vertexShader);
|
|
111
|
-
const fs = createShader(gl.FRAGMENT_SHADER, fragmentShader);
|
|
112
|
-
if (!vs || !fs) return null;
|
|
113
|
-
const program = gl.createProgram();
|
|
114
|
-
if (!program) return null;
|
|
115
|
-
gl.attachShader(program, vs);
|
|
116
|
-
gl.attachShader(program, fs);
|
|
117
|
-
gl.linkProgram(program);
|
|
118
|
-
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
119
|
-
gl.deleteProgram(program);
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
|
-
gl.useProgram(program);
|
|
123
|
-
const buffer = gl.createBuffer();
|
|
124
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
125
|
-
gl.bufferData(
|
|
126
|
-
gl.ARRAY_BUFFER,
|
|
127
|
-
new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]),
|
|
128
|
-
gl.STATIC_DRAW
|
|
129
|
-
);
|
|
130
|
-
const position = gl.getAttribLocation(program, "position");
|
|
131
|
-
gl.enableVertexAttribArray(position);
|
|
132
|
-
gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0);
|
|
133
|
-
return {
|
|
134
|
-
uTime: gl.getUniformLocation(program, "uTime"),
|
|
135
|
-
uResolution: gl.getUniformLocation(program, "uResolution"),
|
|
136
|
-
uDensity: gl.getUniformLocation(program, "uDensity"),
|
|
137
|
-
uOpacity: gl.getUniformLocation(program, "uOpacity"),
|
|
138
|
-
uFps: gl.getUniformLocation(program, "uFps"),
|
|
139
|
-
uColor: gl.getUniformLocation(program, "uColor"),
|
|
140
|
-
program,
|
|
141
|
-
vs,
|
|
142
|
-
fs,
|
|
143
|
-
buffer
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
function setUniform1f(gl, loc, val) {
|
|
147
|
-
if (loc) gl.uniform1f(loc, val);
|
|
148
|
-
}
|
|
149
|
-
function setUniform2f(gl, loc, x, y) {
|
|
150
|
-
if (loc) gl.uniform2f(loc, x, y);
|
|
151
|
-
}
|
|
152
|
-
function setUniform3f(gl, loc, x, y, z) {
|
|
153
|
-
if (loc) gl.uniform3f(loc, x, y, z);
|
|
154
|
-
}
|
|
155
|
-
function generateGrainTexture(width, height, density, color) {
|
|
156
|
-
const offscreen = document.createElement("canvas");
|
|
157
|
-
offscreen.width = width;
|
|
158
|
-
offscreen.height = height;
|
|
159
|
-
const ctx = offscreen.getContext("2d");
|
|
160
|
-
if (!ctx) return offscreen;
|
|
161
|
-
const [r, g, b, a] = parseHex(color);
|
|
162
|
-
const imageData = ctx.createImageData(width, height);
|
|
163
|
-
const pixels = new Uint32Array(imageData.data.buffer);
|
|
164
|
-
for (let i = 0; i < pixels.length; i++) {
|
|
165
|
-
if (Math.random() < density) {
|
|
166
|
-
const variation = Math.round(a * (0.4 + Math.random() * 0.6));
|
|
167
|
-
pixels[i] = (variation << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
ctx.putImageData(imageData, 0, 0);
|
|
171
|
-
return offscreen;
|
|
172
|
-
}
|
|
173
|
-
function useFilmGrain({
|
|
174
|
-
density,
|
|
175
|
-
opacity,
|
|
176
|
-
fps = 18,
|
|
177
|
-
color = "#ffffff"
|
|
178
|
-
}) {
|
|
179
|
-
const canvasRef = useRef(null);
|
|
180
|
-
const rafRef = useRef(0);
|
|
181
|
-
const visibleRef = useRef(true);
|
|
182
|
-
const grainTextureRef = useRef(null);
|
|
183
|
-
const resizeTimerRef = useRef(null);
|
|
184
|
-
const interval = useMemo(() => 1e3 / fps, [fps]);
|
|
185
|
-
useEffect(() => {
|
|
186
|
-
const canvas = canvasRef.current;
|
|
187
|
-
if (!canvas) return;
|
|
188
|
-
const container = canvas.parentElement;
|
|
189
|
-
if (!container) return;
|
|
190
|
-
const prefersReducedMotion = window.matchMedia(
|
|
191
|
-
"(prefers-reduced-motion: reduce)"
|
|
192
|
-
).matches;
|
|
193
|
-
const intersectionObs = new IntersectionObserver(
|
|
194
|
-
(entries) => {
|
|
195
|
-
const entry = entries[0];
|
|
196
|
-
if (entry) visibleRef.current = entry.isIntersecting;
|
|
197
|
-
},
|
|
198
|
-
{ threshold: 0.01 }
|
|
199
|
-
);
|
|
200
|
-
intersectionObs.observe(container);
|
|
201
|
-
const getDimensions = () => {
|
|
202
|
-
const dpr = window.devicePixelRatio || 1;
|
|
203
|
-
return {
|
|
204
|
-
w: Math.round(canvas.clientWidth * dpr),
|
|
205
|
-
h: Math.round(canvas.clientHeight * dpr),
|
|
206
|
-
dpr
|
|
207
|
-
};
|
|
208
|
-
};
|
|
209
|
-
const gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
|
|
210
|
-
const uniforms = gl ? initWebGL(gl) : null;
|
|
211
|
-
if (gl && uniforms) {
|
|
212
|
-
let contextLost = false;
|
|
213
|
-
const [cr, cg, cb] = parseHex(color);
|
|
214
|
-
const setUniforms = () => {
|
|
215
|
-
setUniform1f(gl, uniforms.uDensity, density);
|
|
216
|
-
setUniform1f(gl, uniforms.uOpacity, opacity);
|
|
217
|
-
setUniform1f(gl, uniforms.uFps, fps);
|
|
218
|
-
setUniform3f(gl, uniforms.uColor, cr / 255, cg / 255, cb / 255);
|
|
219
|
-
};
|
|
220
|
-
const onContextLost = (e) => {
|
|
221
|
-
e.preventDefault();
|
|
222
|
-
contextLost = true;
|
|
223
|
-
cancelAnimationFrame(rafRef.current);
|
|
224
|
-
};
|
|
225
|
-
const onContextRestored = () => {
|
|
226
|
-
contextLost = false;
|
|
227
|
-
const newUniforms = initWebGL(gl);
|
|
228
|
-
if (newUniforms) {
|
|
229
|
-
uniforms.uTime = newUniforms.uTime;
|
|
230
|
-
uniforms.uResolution = newUniforms.uResolution;
|
|
231
|
-
uniforms.uDensity = newUniforms.uDensity;
|
|
232
|
-
uniforms.uOpacity = newUniforms.uOpacity;
|
|
233
|
-
uniforms.uFps = newUniforms.uFps;
|
|
234
|
-
uniforms.uColor = newUniforms.uColor;
|
|
235
|
-
uniforms.program = newUniforms.program;
|
|
236
|
-
uniforms.vs = newUniforms.vs;
|
|
237
|
-
uniforms.fs = newUniforms.fs;
|
|
238
|
-
uniforms.buffer = newUniforms.buffer;
|
|
239
|
-
resize();
|
|
240
|
-
setUniforms();
|
|
241
|
-
if (!prefersReducedMotion)
|
|
242
|
-
rafRef.current = requestAnimationFrame(render);
|
|
243
|
-
}
|
|
244
|
-
};
|
|
245
|
-
canvas.addEventListener("webglcontextlost", onContextLost);
|
|
246
|
-
canvas.addEventListener("webglcontextrestored", onContextRestored);
|
|
247
|
-
const resize = () => {
|
|
248
|
-
const { w: w2, h: h2 } = getDimensions();
|
|
249
|
-
if (w2 === 0 || h2 === 0) return;
|
|
250
|
-
canvas.width = w2;
|
|
251
|
-
canvas.height = h2;
|
|
252
|
-
gl.viewport(0, 0, w2, h2);
|
|
253
|
-
setUniform2f(gl, uniforms.uResolution, w2, h2);
|
|
254
|
-
};
|
|
255
|
-
resize();
|
|
256
|
-
setUniforms();
|
|
257
|
-
gl.clearColor(0, 0, 0, 0);
|
|
258
|
-
const start = performance.now();
|
|
259
|
-
let lastSeed = -1;
|
|
260
|
-
const render = (now) => {
|
|
261
|
-
if (contextLost) return;
|
|
262
|
-
if (!document.hidden && visibleRef.current && canvas.width > 0 && canvas.height > 0) {
|
|
263
|
-
const time = (now - start) / 1e3;
|
|
264
|
-
const seed = Math.floor(time * fps);
|
|
265
|
-
if (seed !== lastSeed) {
|
|
266
|
-
lastSeed = seed;
|
|
267
|
-
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
268
|
-
setUniform1f(gl, uniforms.uTime, time);
|
|
269
|
-
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
rafRef.current = requestAnimationFrame(render);
|
|
273
|
-
};
|
|
274
|
-
if (prefersReducedMotion) {
|
|
275
|
-
setUniform1f(gl, uniforms.uTime, 0);
|
|
276
|
-
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
277
|
-
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
278
|
-
} else {
|
|
279
|
-
rafRef.current = requestAnimationFrame(render);
|
|
280
|
-
}
|
|
281
|
-
const onResize2 = () => {
|
|
282
|
-
if (resizeTimerRef.current) clearTimeout(resizeTimerRef.current);
|
|
283
|
-
resizeTimerRef.current = setTimeout(resize, 150);
|
|
284
|
-
};
|
|
285
|
-
window.addEventListener("resize", onResize2);
|
|
286
|
-
return () => {
|
|
287
|
-
cancelAnimationFrame(rafRef.current);
|
|
288
|
-
if (resizeTimerRef.current) clearTimeout(resizeTimerRef.current);
|
|
289
|
-
window.removeEventListener("resize", onResize2);
|
|
290
|
-
canvas.removeEventListener("webglcontextlost", onContextLost);
|
|
291
|
-
canvas.removeEventListener("webglcontextrestored", onContextRestored);
|
|
292
|
-
intersectionObs.disconnect();
|
|
293
|
-
gl.deleteBuffer(uniforms.buffer);
|
|
294
|
-
gl.deleteShader(uniforms.vs);
|
|
295
|
-
gl.deleteShader(uniforms.fs);
|
|
296
|
-
gl.deleteProgram(uniforms.program);
|
|
297
|
-
};
|
|
298
|
-
}
|
|
299
|
-
const ctx = canvas.getContext("2d");
|
|
300
|
-
if (!ctx) {
|
|
301
|
-
intersectionObs.disconnect();
|
|
302
|
-
return;
|
|
303
|
-
}
|
|
304
|
-
const padFactor = 0.3;
|
|
305
|
-
const getPad = (w2, h2) => Math.round(Math.max(w2, h2) * padFactor);
|
|
306
|
-
const setup = () => {
|
|
307
|
-
const { w: w2, h: h2 } = getDimensions();
|
|
308
|
-
if (w2 === 0 || h2 === 0) return { w: 0, h: 0, pad: 0 };
|
|
309
|
-
const pad2 = getPad(w2, h2);
|
|
310
|
-
canvas.width = w2;
|
|
311
|
-
canvas.height = h2;
|
|
312
|
-
if (!grainTextureRef.current || grainTextureRef.current.width < w2 + pad2 || grainTextureRef.current.height < h2 + pad2) {
|
|
313
|
-
grainTextureRef.current = generateGrainTexture(
|
|
314
|
-
w2 + pad2,
|
|
315
|
-
h2 + pad2,
|
|
316
|
-
density,
|
|
317
|
-
color
|
|
318
|
-
);
|
|
319
|
-
}
|
|
320
|
-
return { w: w2, h: h2, pad: pad2 };
|
|
321
|
-
};
|
|
322
|
-
let { w, h, pad } = setup();
|
|
323
|
-
let offsetX = 0;
|
|
324
|
-
let offsetY = 0;
|
|
325
|
-
const drawFrame = () => {
|
|
326
|
-
const grain = grainTextureRef.current;
|
|
327
|
-
if (!grain || w === 0 || h === 0) return;
|
|
328
|
-
const dpr = window.devicePixelRatio || 1;
|
|
329
|
-
ctx.clearRect(0, 0, w, h);
|
|
330
|
-
ctx.filter = `blur(${0.3 * dpr}px)`;
|
|
331
|
-
offsetX = (offsetX + 0.7) % pad;
|
|
332
|
-
offsetY = (offsetY + 0.5) % pad;
|
|
333
|
-
ctx.drawImage(grain, -offsetX, -offsetY, w + pad, h + pad);
|
|
334
|
-
ctx.filter = "none";
|
|
335
|
-
};
|
|
336
|
-
if (prefersReducedMotion) {
|
|
337
|
-
drawFrame();
|
|
338
|
-
intersectionObs.disconnect();
|
|
339
|
-
grainTextureRef.current = null;
|
|
340
|
-
return;
|
|
341
|
-
}
|
|
342
|
-
let lastFrame = performance.now();
|
|
343
|
-
const tick = (now) => {
|
|
344
|
-
if (!document.hidden && visibleRef.current && w > 0 && h > 0) {
|
|
345
|
-
while (now - lastFrame >= interval) {
|
|
346
|
-
lastFrame += interval;
|
|
347
|
-
drawFrame();
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
rafRef.current = requestAnimationFrame(tick);
|
|
351
|
-
};
|
|
352
|
-
rafRef.current = requestAnimationFrame(tick);
|
|
353
|
-
const onResize = () => {
|
|
354
|
-
if (resizeTimerRef.current) clearTimeout(resizeTimerRef.current);
|
|
355
|
-
resizeTimerRef.current = setTimeout(() => {
|
|
356
|
-
const m = getDimensions();
|
|
357
|
-
const newPad = getPad(m.w, m.h);
|
|
358
|
-
if (grainTextureRef.current && grainTextureRef.current.width >= m.w + newPad && grainTextureRef.current.height >= m.h + newPad) {
|
|
359
|
-
w = m.w;
|
|
360
|
-
h = m.h;
|
|
361
|
-
pad = newPad;
|
|
362
|
-
canvas.width = w;
|
|
363
|
-
canvas.height = h;
|
|
364
|
-
return;
|
|
365
|
-
}
|
|
366
|
-
w = m.w;
|
|
367
|
-
h = m.h;
|
|
368
|
-
pad = newPad;
|
|
369
|
-
canvas.width = w;
|
|
370
|
-
canvas.height = h;
|
|
371
|
-
grainTextureRef.current = generateGrainTexture(
|
|
372
|
-
w + pad,
|
|
373
|
-
h + pad,
|
|
374
|
-
density,
|
|
375
|
-
color
|
|
376
|
-
);
|
|
377
|
-
}, 150);
|
|
378
|
-
};
|
|
379
|
-
window.addEventListener("resize", onResize);
|
|
380
|
-
return () => {
|
|
381
|
-
cancelAnimationFrame(rafRef.current);
|
|
382
|
-
if (resizeTimerRef.current) clearTimeout(resizeTimerRef.current);
|
|
383
|
-
window.removeEventListener("resize", onResize);
|
|
384
|
-
intersectionObs.disconnect();
|
|
385
|
-
grainTextureRef.current = null;
|
|
386
|
-
};
|
|
387
|
-
}, [density, opacity, fps, interval, color]);
|
|
388
|
-
return canvasRef;
|
|
389
|
-
}
|
|
390
|
-
function FilmGrain({
|
|
391
|
-
density = 0.6,
|
|
392
|
-
opacity = 0.08,
|
|
393
|
-
blendMode = "overlay",
|
|
394
|
-
fps = 18,
|
|
395
|
-
color = "#ffffff",
|
|
396
|
-
className,
|
|
397
|
-
style
|
|
398
|
-
}) {
|
|
399
|
-
const canvasRef = useFilmGrain({ density, opacity, fps, color });
|
|
400
|
-
return /* @__PURE__ */ jsx(
|
|
401
|
-
"div",
|
|
402
|
-
{
|
|
403
|
-
"aria-hidden": "true",
|
|
404
|
-
className: [
|
|
405
|
-
"absolute inset-0 z-0 pointer-events-none select-none overflow-hidden",
|
|
406
|
-
className
|
|
407
|
-
].filter(Boolean).join(" "),
|
|
408
|
-
style: { mixBlendMode: blendMode, opacity, ...style },
|
|
409
|
-
children: /* @__PURE__ */ jsx(
|
|
410
|
-
"canvas",
|
|
411
|
-
{
|
|
412
|
-
ref: canvasRef,
|
|
413
|
-
className: "w-full h-full will-change-transform"
|
|
414
|
-
}
|
|
415
|
-
)
|
|
416
|
-
}
|
|
417
|
-
);
|
|
418
|
-
}
|
|
419
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
import { useFilmGrain } from "./film-grain-webgl.js";
|
|
3
|
+
import "react";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
//#region src/film-grain.tsx
|
|
6
|
+
function FilmGrain({ density = .6, opacity = .08, blendMode = "overlay", fps = 18, color = "#ffffff", className, style }) {
|
|
7
|
+
const canvasRef = useFilmGrain({
|
|
8
|
+
density,
|
|
9
|
+
opacity,
|
|
10
|
+
fps,
|
|
11
|
+
color
|
|
12
|
+
});
|
|
13
|
+
return /* @__PURE__ */ jsx("div", {
|
|
14
|
+
"aria-hidden": "true",
|
|
15
|
+
className: ["absolute inset-0 z-0 pointer-events-none select-none overflow-hidden", className].filter(Boolean).join(" "),
|
|
16
|
+
style: {
|
|
17
|
+
mixBlendMode: blendMode,
|
|
18
|
+
opacity,
|
|
19
|
+
...style
|
|
20
|
+
},
|
|
21
|
+
children: /* @__PURE__ */ jsx("canvas", {
|
|
22
|
+
ref: canvasRef,
|
|
23
|
+
className: "w-full h-full will-change-transform"
|
|
24
|
+
})
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
420
28
|
export { FilmGrain };
|
|
421
|
-
|
|
29
|
+
|
|
422
30
|
//# sourceMappingURL=film-grain.js.map
|
package/dist/film-grain.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/film-grain-shader.ts","../src/film-grain-webgl.ts","../src/film-grain.tsx"],"names":["w","h","onResize","pad"],"mappings":"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","file":"film-grain.js","sourcesContent":["export const vertexShader = `\nattribute vec2 position;\nvarying vec2 vUv;\n\nvoid main() {\n vUv = position * 0.5 + 0.5;\n gl_Position = vec4(position, 0.0, 1.0);\n}\n`\n\nexport const fragmentShader = `\nprecision highp float;\n\nuniform float uTime;\nuniform vec2 uResolution;\nuniform float uDensity;\nuniform float uOpacity;\nuniform float uFps;\nuniform vec3 uColor;\n\nvarying vec2 vUv;\n\n// Stable hash\nfloat hash(vec2 p, float seed) {\n return fract(sin(dot(p + seed, vec2(127.1, 311.7))) * 43758.5453123);\n}\n\n// Film response curve (soft toe + shoulder rolloff)\nfloat filmCurve(float x) {\n return smoothstep(0.0, 0.2, x) * (1.0 - smoothstep(0.8, 1.0, x));\n}\n\nvoid main() {\n vec2 uv = gl_FragCoord.xy;\n vec2 p = floor(uv);\n\n // Temporal coherence: blend between current and next frame seed\n float frame = floor(uTime * uFps);\n float t = fract(uTime * uFps);\n float seed = frame * 0.1731;\n\n // Multi-scale grain with inter-frame blending on fine layer\n float fineA = hash(p, seed);\n float fineB = hash(p, seed + 0.1731);\n float fine = mix(fineA, fineB, t);\n\n float medium = hash(floor(uv * 0.5), seed + 3.1);\n float coarse = hash(floor(uv * 0.25), seed + 7.93);\n\n float grain = fine * 0.65 + medium * 0.25 + coarse * 0.10;\n\n // Emulsion clumping (organic structure)\n float cluster = hash(floor(uv * 0.18), seed + 9.2);\n grain *= mix(0.75, 1.35, cluster);\n\n // Density threshold\n grain = smoothstep(1.0 - uDensity, 1.0, grain);\n\n // Film response curve (replaces raw pow gamma)\n grain = filmCurve(grain);\n\n // Micro-blur: sample neighbors for optical diffusion\n float n1 = hash(p + vec2(1.0, 0.0), seed);\n float n2 = hash(p - vec2(1.0, 0.0), seed);\n float n3 = hash(p + vec2(0.0, 1.0), seed);\n float n4 = hash(p - vec2(0.0, 1.0), seed);\n float neighbors = (n1 + n2 + n3 + n4) * 0.25;\n grain = mix(grain, neighbors, 0.15);\n\n // Chromatic aberration (reuse neighbor hashes)\n float rShift = n1 * 0.015;\n float bShift = n2 * 0.015;\n\n vec3 color = uColor * vec3(\n grain + rShift,\n grain,\n grain + bShift\n );\n\n color = clamp(color, 0.0, 1.0);\n\n gl_FragColor = vec4(color, grain * uOpacity);\n}\n`\n","import { useEffect, useRef, useMemo } from \"react\"\nimport { vertexShader, fragmentShader } from \"./film-grain-shader\"\n\ninterface UseFilmGrainOptions {\n density: number\n opacity: number\n /** Target FPS for both WebGL and canvas fallback. Default 18 */\n fps?: number\n /** Hex color for canvas fallback grain. Default '#ffffff' */\n color?: string\n}\n\n/** Parse hex color safely */\nfunction parseHex(hex: string): [number, number, number, number] {\n if (!/^#([0-9a-f]{3,8})$/i.test(hex)) return [255, 255, 255, 255]\n let h = hex.replace(\"#\", \"\")\n if (h.length === 3) h = h.split(\"\").map((c) => c + c).join(\"\")\n if (h.length === 6) h += \"ff\"\n const n = parseInt(h, 16)\n return [(n >> 24) & 0xff, (n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff]\n}\n\n// ── WebGL renderer ──────────────────────────────────────────────────\n\ninterface WebGLUniforms {\n uTime: WebGLUniformLocation | null\n uResolution: WebGLUniformLocation | null\n uDensity: WebGLUniformLocation | null\n uOpacity: WebGLUniformLocation | null\n uFps: WebGLUniformLocation | null\n uColor: WebGLUniformLocation | null\n program: WebGLProgram\n vs: WebGLShader\n fs: WebGLShader\n buffer: WebGLBuffer | null\n}\n\nfunction initWebGL(gl: WebGLRenderingContext): WebGLUniforms | null {\n const createShader = (type: number, source: string) => {\n const shader = gl.createShader(type)\n if (!shader) return null\n gl.shaderSource(shader, source)\n gl.compileShader(shader)\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n gl.deleteShader(shader)\n return null\n }\n return shader\n }\n\n const vs = createShader(gl.VERTEX_SHADER, vertexShader)\n const fs = createShader(gl.FRAGMENT_SHADER, fragmentShader)\n if (!vs || !fs) return null\n\n const program = gl.createProgram()\n if (!program) return null\n\n gl.attachShader(program, vs)\n gl.attachShader(program, fs)\n gl.linkProgram(program)\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n gl.deleteProgram(program)\n return null\n }\n\n gl.useProgram(program)\n\n const buffer = gl.createBuffer()\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n gl.bufferData(\n gl.ARRAY_BUFFER,\n new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]),\n gl.STATIC_DRAW\n )\n\n const position = gl.getAttribLocation(program, \"position\")\n gl.enableVertexAttribArray(position)\n gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0)\n\n return {\n uTime: gl.getUniformLocation(program, \"uTime\"),\n uResolution: gl.getUniformLocation(program, \"uResolution\"),\n uDensity: gl.getUniformLocation(program, \"uDensity\"),\n uOpacity: gl.getUniformLocation(program, \"uOpacity\"),\n uFps: gl.getUniformLocation(program, \"uFps\"),\n uColor: gl.getUniformLocation(program, \"uColor\"),\n program,\n vs,\n fs,\n buffer,\n }\n}\n\n/** Safe uniform setters */\nfunction setUniform1f(\n gl: WebGLRenderingContext,\n loc: WebGLUniformLocation | null,\n val: number\n) {\n if (loc) gl.uniform1f(loc, val)\n}\n\nfunction setUniform2f(\n gl: WebGLRenderingContext,\n loc: WebGLUniformLocation | null,\n x: number,\n y: number\n) {\n if (loc) gl.uniform2f(loc, x, y)\n}\n\nfunction setUniform3f(\n gl: WebGLRenderingContext,\n loc: WebGLUniformLocation | null,\n x: number,\n y: number,\n z: number\n) {\n if (loc) gl.uniform3f(loc, x, y, z)\n}\n\n// ── Canvas 2D fallback renderer ─────────────────────────────────────\n\nfunction generateGrainTexture(\n width: number,\n height: number,\n density: number,\n color: string\n): HTMLCanvasElement {\n const offscreen = document.createElement(\"canvas\")\n offscreen.width = width\n offscreen.height = height\n const ctx = offscreen.getContext(\"2d\")\n if (!ctx) return offscreen\n\n const [r, g, b, a] = parseHex(color)\n const imageData = ctx.createImageData(width, height)\n const pixels = new Uint32Array(imageData.data.buffer)\n\n for (let i = 0; i < pixels.length; i++) {\n if (Math.random() < density) {\n const variation = Math.round(a * (0.4 + Math.random() * 0.6))\n pixels[i] = ((variation << 24) | (b << 16) | (g << 8) | r) >>> 0\n }\n }\n\n ctx.putImageData(imageData, 0, 0)\n return offscreen\n}\n\n// ── Hook ────────────────────────────────────────────────────────────\n\nexport function useFilmGrain({\n density,\n opacity,\n fps = 18,\n color = \"#ffffff\",\n}: UseFilmGrainOptions) {\n const canvasRef = useRef<HTMLCanvasElement | null>(null)\n const rafRef = useRef<number>(0)\n const visibleRef = useRef(true)\n const grainTextureRef = useRef<HTMLCanvasElement | null>(null)\n const resizeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n const interval = useMemo(() => 1000 / fps, [fps])\n\n useEffect(() => {\n const canvas = canvasRef.current\n if (!canvas) return\n\n const container = canvas.parentElement\n if (!container) return\n\n const prefersReducedMotion = window.matchMedia(\n \"(prefers-reduced-motion: reduce)\"\n ).matches\n\n // Pause when offscreen\n const intersectionObs = new IntersectionObserver(\n (entries) => {\n const entry = entries[0]\n if (entry) visibleRef.current = entry.isIntersecting\n },\n { threshold: 0.01 }\n )\n intersectionObs.observe(container)\n\n const getDimensions = () => {\n const dpr = window.devicePixelRatio || 1\n return {\n w: Math.round(canvas.clientWidth * dpr),\n h: Math.round(canvas.clientHeight * dpr),\n dpr,\n }\n }\n\n // ── Try WebGL ──\n\n const gl =\n canvas.getContext(\"webgl\") ||\n (canvas.getContext(\"experimental-webgl\") as WebGLRenderingContext | null)\n const uniforms = gl ? initWebGL(gl) : null\n\n if (gl && uniforms) {\n let contextLost = false\n\n const [cr, cg, cb] = parseHex(color)\n const setUniforms = () => {\n setUniform1f(gl, uniforms.uDensity, density)\n setUniform1f(gl, uniforms.uOpacity, opacity)\n setUniform1f(gl, uniforms.uFps, fps)\n setUniform3f(gl, uniforms.uColor, cr / 255, cg / 255, cb / 255)\n }\n\n const onContextLost = (e: Event) => {\n e.preventDefault()\n contextLost = true\n cancelAnimationFrame(rafRef.current)\n }\n\n const onContextRestored = () => {\n contextLost = false\n const newUniforms = initWebGL(gl)\n if (newUniforms) {\n uniforms.uTime = newUniforms.uTime\n uniforms.uResolution = newUniforms.uResolution\n uniforms.uDensity = newUniforms.uDensity\n uniforms.uOpacity = newUniforms.uOpacity\n uniforms.uFps = newUniforms.uFps\n uniforms.uColor = newUniforms.uColor\n uniforms.program = newUniforms.program\n uniforms.vs = newUniforms.vs\n uniforms.fs = newUniforms.fs\n uniforms.buffer = newUniforms.buffer\n resize()\n setUniforms()\n if (!prefersReducedMotion)\n rafRef.current = requestAnimationFrame(render)\n }\n }\n\n canvas.addEventListener(\"webglcontextlost\", onContextLost)\n canvas.addEventListener(\"webglcontextrestored\", onContextRestored)\n\n const resize = () => {\n const { w, h } = getDimensions()\n if (w === 0 || h === 0) return\n canvas.width = w\n canvas.height = h\n gl.viewport(0, 0, w, h)\n setUniform2f(gl, uniforms.uResolution, w, h)\n }\n\n resize()\n setUniforms()\n\n gl.clearColor(0, 0, 0, 0)\n\n const start = performance.now()\n let lastSeed = -1\n\n const render = (now: number) => {\n if (contextLost) return\n\n if (\n !document.hidden &&\n visibleRef.current &&\n canvas.width > 0 &&\n canvas.height > 0\n ) {\n const time = (now - start) / 1000\n\n // Skip draw if grain seed hasn't changed\n const seed = Math.floor(time * fps)\n if (seed !== lastSeed) {\n lastSeed = seed\n gl.clear(gl.COLOR_BUFFER_BIT)\n setUniform1f(gl, uniforms.uTime, time)\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)\n }\n }\n\n rafRef.current = requestAnimationFrame(render)\n }\n\n if (prefersReducedMotion) {\n setUniform1f(gl, uniforms.uTime, 0)\n gl.clear(gl.COLOR_BUFFER_BIT)\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)\n } else {\n rafRef.current = requestAnimationFrame(render)\n }\n\n const onResize = () => {\n if (resizeTimerRef.current) clearTimeout(resizeTimerRef.current)\n resizeTimerRef.current = setTimeout(resize, 150)\n }\n\n window.addEventListener(\"resize\", onResize)\n\n return () => {\n cancelAnimationFrame(rafRef.current)\n if (resizeTimerRef.current) clearTimeout(resizeTimerRef.current)\n window.removeEventListener(\"resize\", onResize)\n canvas.removeEventListener(\"webglcontextlost\", onContextLost)\n canvas.removeEventListener(\"webglcontextrestored\", onContextRestored)\n intersectionObs.disconnect()\n\n gl.deleteBuffer(uniforms.buffer)\n gl.deleteShader(uniforms.vs)\n gl.deleteShader(uniforms.fs)\n gl.deleteProgram(uniforms.program)\n }\n }\n\n // ── Canvas 2D fallback ──\n\n const ctx = canvas.getContext(\"2d\")\n if (!ctx) {\n intersectionObs.disconnect()\n return\n }\n\n const padFactor = 0.3\n const getPad = (w: number, h: number) =>\n Math.round(Math.max(w, h) * padFactor)\n\n const setup = () => {\n const { w, h } = getDimensions()\n if (w === 0 || h === 0) return { w: 0, h: 0, pad: 0 }\n\n const pad = getPad(w, h)\n canvas.width = w\n canvas.height = h\n\n if (\n !grainTextureRef.current ||\n grainTextureRef.current.width < w + pad ||\n grainTextureRef.current.height < h + pad\n ) {\n grainTextureRef.current = generateGrainTexture(\n w + pad,\n h + pad,\n density,\n color\n )\n }\n\n return { w, h, pad }\n }\n\n let { w, h, pad } = setup()\n\n // Drifting offset for temporal coherence (not teleporting)\n let offsetX = 0\n let offsetY = 0\n\n const drawFrame = () => {\n const grain = grainTextureRef.current\n if (!grain || w === 0 || h === 0) return\n\n const dpr = window.devicePixelRatio || 1\n\n ctx.clearRect(0, 0, w, h)\n ctx.filter = `blur(${0.3 * dpr}px)`\n\n offsetX = (offsetX + 0.7) % pad\n offsetY = (offsetY + 0.5) % pad\n\n ctx.drawImage(grain, -offsetX, -offsetY, w + pad, h + pad)\n ctx.filter = \"none\"\n }\n\n if (prefersReducedMotion) {\n drawFrame()\n intersectionObs.disconnect()\n grainTextureRef.current = null\n return\n }\n\n let lastFrame = performance.now()\n\n const tick = (now: number) => {\n if (\n !document.hidden &&\n visibleRef.current &&\n w > 0 &&\n h > 0\n ) {\n while (now - lastFrame >= interval) {\n lastFrame += interval\n drawFrame()\n }\n }\n rafRef.current = requestAnimationFrame(tick)\n }\n\n rafRef.current = requestAnimationFrame(tick)\n\n const onResize = () => {\n if (resizeTimerRef.current) clearTimeout(resizeTimerRef.current)\n resizeTimerRef.current = setTimeout(() => {\n const m = getDimensions()\n const newPad = getPad(m.w, m.h)\n\n if (\n grainTextureRef.current &&\n grainTextureRef.current.width >= m.w + newPad &&\n grainTextureRef.current.height >= m.h + newPad\n ) {\n w = m.w\n h = m.h\n pad = newPad\n canvas.width = w\n canvas.height = h\n return\n }\n\n w = m.w\n h = m.h\n pad = newPad\n canvas.width = w\n canvas.height = h\n grainTextureRef.current = generateGrainTexture(\n w + pad,\n h + pad,\n density,\n color\n )\n }, 150)\n }\n\n window.addEventListener(\"resize\", onResize)\n\n return () => {\n cancelAnimationFrame(rafRef.current)\n if (resizeTimerRef.current) clearTimeout(resizeTimerRef.current)\n window.removeEventListener(\"resize\", onResize)\n intersectionObs.disconnect()\n grainTextureRef.current = null\n }\n }, [density, opacity, fps, interval, color])\n\n return canvasRef\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { useFilmGrain } from \"./film-grain-webgl\"\n\ninterface FilmGrainProps {\n density?: number\n opacity?: number\n blendMode?: React.CSSProperties[\"mixBlendMode\"]\n fps?: number\n color?: string\n className?: string\n style?: React.CSSProperties\n}\n\nfunction FilmGrain({\n density = 0.6,\n opacity = 0.08,\n blendMode = \"overlay\",\n fps = 18,\n color = \"#ffffff\",\n className,\n style,\n}: FilmGrainProps) {\n const canvasRef = useFilmGrain({ density, opacity, fps, color })\n\n return (\n <div\n aria-hidden=\"true\"\n className={[\n \"absolute inset-0 z-0 pointer-events-none select-none overflow-hidden\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n style={{ mixBlendMode: blendMode, opacity, ...style }}\n >\n <canvas\n ref={canvasRef}\n className=\"w-full h-full will-change-transform\"\n />\n </div>\n )\n}\n\nexport { FilmGrain }\nexport type { FilmGrainProps }\n"]}
|
|
1
|
+
{"version":3,"file":"film-grain.js","names":[],"sources":["../src/film-grain.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { useFilmGrain } from \"./film-grain-webgl\"\n\ninterface FilmGrainProps {\n density?: number\n opacity?: number\n blendMode?: React.CSSProperties[\"mixBlendMode\"]\n fps?: number\n color?: string\n className?: string\n style?: React.CSSProperties\n}\n\nfunction FilmGrain({\n density = 0.6,\n opacity = 0.08,\n blendMode = \"overlay\",\n fps = 18,\n color = \"#ffffff\",\n className,\n style,\n}: FilmGrainProps) {\n const canvasRef = useFilmGrain({ density, opacity, fps, color })\n\n return (\n <div\n aria-hidden=\"true\"\n className={[\n \"absolute inset-0 z-0 pointer-events-none select-none overflow-hidden\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n style={{ mixBlendMode: blendMode, opacity, ...style }}\n >\n <canvas\n ref={canvasRef}\n className=\"w-full h-full will-change-transform\"\n />\n </div>\n )\n}\n\nexport { FilmGrain }\nexport type { FilmGrainProps }\n"],"mappings":";;;;;AAeA,SAAS,UAAU,EACjB,UAAU,IACV,UAAU,KACV,YAAY,WACZ,MAAM,IACN,QAAQ,WACR,WACA,SACiB;CACjB,MAAM,YAAY,aAAa;EAAE;EAAS;EAAS;EAAK;EAAO,CAAC;AAEhE,QACE,oBAAC,OAAD;EACE,eAAY;EACZ,WAAW,CACT,wEACA,UACD,CACE,OAAO,QAAQ,CACf,KAAK,IAAI;EACZ,OAAO;GAAE,cAAc;GAAW;GAAS,GAAG;GAAO;YAErD,oBAAC,UAAD;GACE,KAAK;GACL,WAAU;GACV,CAAA;EACE,CAAA"}
|
package/dist/form.d.ts
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
import * as
|
|
5
|
-
import
|
|
6
|
-
import { Field } from './field.js';
|
|
7
|
-
import '@base-ui/react';
|
|
8
|
-
import '@base-ui/react/field';
|
|
1
|
+
import { Field } from "./field.js";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
4
|
+
import * as _$react_hook_form0 from "react-hook-form";
|
|
5
|
+
import { ControllerFieldState, ControllerRenderProps, FieldPath, FieldValues, RegisterOptions, SubmitHandler, UseFormReturn, useForm, useWatch } from "react-hook-form";
|
|
9
6
|
|
|
7
|
+
//#region src/form.d.ts
|
|
10
8
|
type FormProps<TFieldValues extends FieldValues> = {
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
form: UseFormReturn<TFieldValues>;
|
|
10
|
+
onSubmit: SubmitHandler<TFieldValues>;
|
|
13
11
|
} & Omit<React.ComponentProps<"form">, "onSubmit">;
|
|
14
12
|
type FormRootProps = React.ComponentProps<"form">;
|
|
15
13
|
type FormErrorProps = React.ComponentProps<"p">;
|
|
16
14
|
type FormActionsProps = React.ComponentProps<"div">;
|
|
17
15
|
type FormMessageProps = React.ComponentProps<"p">;
|
|
18
|
-
declare function Form<TFieldValues extends FieldValues>({
|
|
16
|
+
declare function Form<TFieldValues extends FieldValues>({
|
|
17
|
+
form,
|
|
18
|
+
onSubmit,
|
|
19
|
+
...props
|
|
20
|
+
}: FormProps<TFieldValues>): _$react_jsx_runtime0.JSX.Element;
|
|
19
21
|
/**
|
|
20
22
|
* Plain `<form>` element with RHF integration.
|
|
21
23
|
*
|
|
@@ -25,28 +27,31 @@ declare function Form<TFieldValues extends FieldValues>({ form, onSubmit, ...pro
|
|
|
25
27
|
* provides validation, error handling, and submit management, the Base UI
|
|
26
28
|
* Form wrapper adds no value at the moment.
|
|
27
29
|
*/
|
|
28
|
-
declare function FormRoot({
|
|
30
|
+
declare function FormRoot({
|
|
31
|
+
className,
|
|
32
|
+
...props
|
|
33
|
+
}: FormRootProps): _$react_jsx_runtime0.JSX.Element;
|
|
29
34
|
type FormFieldRenderArgs<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues>> = {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
id: string;
|
|
36
|
+
field: ControllerRenderProps<TFieldValues, TName>;
|
|
37
|
+
fieldState: ControllerFieldState;
|
|
33
38
|
};
|
|
34
39
|
type FormFieldProps<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues>> = {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
40
|
+
name: TName;
|
|
41
|
+
id?: string;
|
|
42
|
+
required?: boolean;
|
|
43
|
+
label?: React.ReactNode;
|
|
44
|
+
description?: React.ReactNode;
|
|
45
|
+
rules?: RegisterOptions<TFieldValues, TName>;
|
|
46
|
+
/**
|
|
47
|
+
* Render the actual control.
|
|
48
|
+
*
|
|
49
|
+
* - For Base UI controls, prefer `onValueChange`.
|
|
50
|
+
* - For native/standard inputs, use `onChange`.
|
|
51
|
+
*
|
|
52
|
+
* Use `fieldControlProps(field)` to get both.
|
|
53
|
+
*/
|
|
54
|
+
render: (args: FormFieldRenderArgs<TFieldValues, TName>) => React.ReactNode;
|
|
50
55
|
} & Omit<React.ComponentProps<typeof Field>, "children" | "name" | "invalid" | "touched" | "dirty" | "render">;
|
|
51
56
|
/**
|
|
52
57
|
* Base UI + React Hook Form field helper.
|
|
@@ -54,30 +59,40 @@ type FormFieldProps<TFieldValues extends FieldValues, TName extends FieldPath<TF
|
|
|
54
59
|
* It maps RHF Controller state onto Base UI's <Field> state so styling can
|
|
55
60
|
* rely on `data-[invalid]`, `data-[touched]`, `data-[dirty]`, etc.
|
|
56
61
|
*/
|
|
57
|
-
declare function FormField<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues>>(props: FormFieldProps<TFieldValues, TName>):
|
|
58
|
-
declare function FormError({
|
|
59
|
-
|
|
60
|
-
|
|
62
|
+
declare function FormField<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues>>(props: FormFieldProps<TFieldValues, TName>): _$react_jsx_runtime0.JSX.Element;
|
|
63
|
+
declare function FormError({
|
|
64
|
+
className,
|
|
65
|
+
...props
|
|
66
|
+
}: FormErrorProps): _$react_jsx_runtime0.JSX.Element | null;
|
|
67
|
+
declare function FormActions({
|
|
68
|
+
className,
|
|
69
|
+
...props
|
|
70
|
+
}: FormActionsProps): _$react_jsx_runtime0.JSX.Element;
|
|
71
|
+
declare function FormMessage({
|
|
72
|
+
className,
|
|
73
|
+
...props
|
|
74
|
+
}: FormMessageProps): _$react_jsx_runtime0.JSX.Element;
|
|
61
75
|
/**
|
|
62
76
|
* Convenience helper for mapping RHF field props onto either:
|
|
63
77
|
* - Base UI controls (use `onValueChange`)
|
|
64
78
|
* - Native/standard inputs (use `onChange`)
|
|
65
79
|
*/
|
|
66
80
|
declare function fieldControlProps<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues>>(field: ControllerRenderProps<TFieldValues, TName>, opts?: {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
81
|
+
id?: string;
|
|
82
|
+
describedBy?: string;
|
|
83
|
+
invalid?: boolean;
|
|
84
|
+
native?: boolean;
|
|
71
85
|
}): {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
86
|
+
"aria-describedby": string | undefined;
|
|
87
|
+
"aria-invalid": boolean | undefined;
|
|
88
|
+
onValueChange?: ((...event: any[]) => void) | undefined;
|
|
89
|
+
id: string | undefined;
|
|
90
|
+
name: TName;
|
|
91
|
+
ref: _$react_hook_form0.RefCallBack;
|
|
92
|
+
value: string;
|
|
93
|
+
onBlur: _$react_hook_form0.Noop;
|
|
94
|
+
onChange: (...event: any[]) => void;
|
|
81
95
|
};
|
|
82
|
-
|
|
83
|
-
export { Form, FormActions, FormError, FormField, type FormFieldProps, type FormFieldRenderArgs, FormMessage, FormRoot, fieldControlProps };
|
|
96
|
+
//#endregion
|
|
97
|
+
export { Form, FormActions, FormError, FormField, type FormFieldProps, type FormFieldRenderArgs, FormMessage, FormRoot, fieldControlProps, useForm, useWatch };
|
|
98
|
+
//# sourceMappingURL=form.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form.d.ts","names":[],"sources":["../src/form.tsx"],"mappings":";;;;;;;KAsBK,SAAA,sBAA+B,WAAA;EAClC,IAAA,EAAM,aAAA,CAAc,YAAA;EACpB,QAAA,EAAU,aAAA,CAAc,YAAA;AAAA,IACtB,IAAA,CAAK,KAAA,CAAM,cAAA;AAAA,KAEV,aAAA,GAAgB,KAAA,CAAM,cAAA;AAAA,KACtB,cAAA,GAAiB,KAAA,CAAM,cAAA;AAAA,KACvB,gBAAA,GAAmB,KAAA,CAAM,cAAA;AAAA,KACzB,gBAAA,GAAmB,KAAA,CAAM,cAAA;AAAA,iBAErB,IAAA,sBAA0B,WAAA,CAAA,CAAA;EAAe,IAAA;EAAM,QAAA;EAAA,GAAa;AAAA,GAAS,SAAA,CAAU,YAAA,IAAa,oBAAA,CAAA,GAAA,CAAA,OAAA;;;;;;;;;;iBAiB5F,QAAA,CAAA;EAAW,SAAA;EAAA,GAAc;AAAA,GAAS,aAAA,GAAa,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,KAMnD,mBAAA,sBACkB,WAAA,gBACP,SAAA,CAAU,YAAA;EAExB,EAAA;EACA,KAAA,EAAO,qBAAA,CAAsB,YAAA,EAAc,KAAA;EAC3C,UAAA,EAAY,oBAAA;AAAA;AAAA,KAGT,cAAA,sBACkB,WAAA,gBACP,SAAA,CAAU,YAAA;EAExB,IAAA,EAAM,KAAA;EACN,EAAA;EACA,QAAA;EACA,KAAA,GAAQ,KAAA,CAAM,SAAA;EACd,WAAA,GAAc,KAAA,CAAM,SAAA;EACpB,KAAA,GAAQ,eAAA,CAAgB,YAAA,EAAc,KAAA;;;;AA9CC;;;;;EAuDvC,MAAA,GAAS,IAAA,EAAM,mBAAA,CAAoB,YAAA,EAAc,KAAA,MAAW,KAAA,CAAM,SAAA;AAAA,IAChE,IAAA,CACF,KAAA,CAAM,cAAA,QAAsB,KAAA;;;;AAvDc;;;iBAiEnC,SAAA,sBACc,WAAA,gBACP,SAAA,CAAU,YAAA,EAAA,CACxB,KAAA,EAAO,cAAA,CAAe,YAAA,EAAc,KAAA,IAAM,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBAyDnC,SAAA,CAAA;EAAY,SAAA;EAAA,GAAc;AAAA,GAAS,cAAA,GAAc,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBA2BjD,WAAA,CAAA;EAAc,SAAA;EAAA,GAAc;AAAA,GAAS,gBAAA,GAAgB,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBAUrD,WAAA,CAAA;EAAc,SAAA;EAAA,GAAc;AAAA,GAAS,gBAAA,GAAgB,oBAAA,CAAA,GAAA,CAAA,OAAA;;;;;;iBAWrD,iBAAA,sBACc,WAAA,gBACP,SAAA,CAAU,YAAA,EAAA,CAExB,KAAA,EAAO,qBAAA,CAAsB,YAAA,EAAc,KAAA,GAC3C,IAAA;EACE,EAAA;EACA,WAAA;EACA,OAAA;EACA,MAAA;AAAA"}
|