@lovo/matter 0.4.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/README.md +3 -3
- package/dist/index.cjs +563 -126
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +104 -58
- package/dist/index.d.ts +104 -58
- package/dist/index.js +547 -111
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,13 +1,51 @@
|
|
|
1
1
|
// src/runtime/create-renderer/create-renderer.ts
|
|
2
|
-
import { Color } from "three";
|
|
2
|
+
import { Color, Vector2 } from "three";
|
|
3
3
|
import { WebGPURenderer } from "three/webgpu";
|
|
4
|
+
|
|
5
|
+
// src/runtime/create-renderer/gamut.ts
|
|
6
|
+
import { ColorManagement, SRGBColorSpace } from "three";
|
|
7
|
+
import {
|
|
8
|
+
DisplayP3ColorSpace,
|
|
9
|
+
DisplayP3ColorSpaceImpl,
|
|
10
|
+
LinearDisplayP3ColorSpace,
|
|
11
|
+
LinearDisplayP3ColorSpaceImpl
|
|
12
|
+
} from "three/examples/jsm/math/ColorSpaces.js";
|
|
13
|
+
ColorManagement.define({
|
|
14
|
+
[DisplayP3ColorSpace]: DisplayP3ColorSpaceImpl,
|
|
15
|
+
[LinearDisplayP3ColorSpace]: LinearDisplayP3ColorSpaceImpl
|
|
16
|
+
});
|
|
17
|
+
function gamutToColorSpace(gamut) {
|
|
18
|
+
return gamut === "p3" ? DisplayP3ColorSpace : SRGBColorSpace;
|
|
19
|
+
}
|
|
20
|
+
function hasWebGpuBackendInternals(backend) {
|
|
21
|
+
if (typeof backend !== "object" || backend === null) return false;
|
|
22
|
+
if (!("device" in backend) || !("context" in backend)) return false;
|
|
23
|
+
const { device, context } = backend;
|
|
24
|
+
return typeof device === "object" && device !== null && typeof context === "object" && context !== null && "configure" in context && typeof context.configure === "function";
|
|
25
|
+
}
|
|
26
|
+
function applyCanvasGamut(renderer, backend, gamut) {
|
|
27
|
+
if (gamut !== "p3" || backend !== "webgpu") return;
|
|
28
|
+
if (typeof navigator === "undefined" || !("gpu" in navigator)) return;
|
|
29
|
+
const webGpuBackend = renderer.backend;
|
|
30
|
+
if (!hasWebGpuBackendInternals(webGpuBackend)) return;
|
|
31
|
+
webGpuBackend.context.configure({
|
|
32
|
+
device: webGpuBackend.device,
|
|
33
|
+
format: navigator.gpu.getPreferredCanvasFormat(),
|
|
34
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
|
|
35
|
+
alphaMode: "premultiplied",
|
|
36
|
+
colorSpace: "display-p3"
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// src/runtime/create-renderer/create-renderer.ts
|
|
4
41
|
async function createRenderer(canvas, opts = {}) {
|
|
5
42
|
const {
|
|
6
43
|
antialias = true,
|
|
7
44
|
forceWebGL = false,
|
|
8
45
|
clearColor = 0,
|
|
9
46
|
clearAlpha = 0,
|
|
10
|
-
maxDPR = 2
|
|
47
|
+
maxDPR = 2,
|
|
48
|
+
gamut = "srgb"
|
|
11
49
|
} = opts;
|
|
12
50
|
const three = new WebGPURenderer({
|
|
13
51
|
canvas,
|
|
@@ -15,19 +53,24 @@ async function createRenderer(canvas, opts = {}) {
|
|
|
15
53
|
forceWebGL
|
|
16
54
|
});
|
|
17
55
|
await three.init();
|
|
56
|
+
three.outputColorSpace = gamutToColorSpace(gamut);
|
|
18
57
|
three.setPixelRatio(Math.min(window.devicePixelRatio, maxDPR));
|
|
19
58
|
const resolvedClearColor = clearColor instanceof Color ? clearColor : new Color(clearColor);
|
|
20
59
|
three.setClearColor(resolvedClearColor, clearAlpha);
|
|
60
|
+
const rendererSize = new Vector2();
|
|
21
61
|
const resize = () => {
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
if (
|
|
25
|
-
|
|
62
|
+
const canvasWidth = canvas.clientWidth;
|
|
63
|
+
const canvasHeight = canvas.clientHeight;
|
|
64
|
+
if (canvasWidth === 0 || canvasHeight === 0) return;
|
|
65
|
+
three.getSize(rendererSize);
|
|
66
|
+
if (rendererSize.width !== canvasWidth || rendererSize.height !== canvasHeight) {
|
|
67
|
+
three.setSize(canvasWidth, canvasHeight, false);
|
|
26
68
|
}
|
|
27
69
|
};
|
|
28
70
|
resize();
|
|
29
71
|
const isWebGL = "isWebGLBackend" in three.backend && three.backend.isWebGLBackend === true;
|
|
30
72
|
const backend = forceWebGL || isWebGL ? "webgl2" : "webgpu";
|
|
73
|
+
applyCanvasGamut(three, backend, gamut);
|
|
31
74
|
return {
|
|
32
75
|
three,
|
|
33
76
|
backend,
|
|
@@ -56,16 +99,19 @@ var CursorInput = class {
|
|
|
56
99
|
this.element = element;
|
|
57
100
|
this.handleMouseMove = (e) => {
|
|
58
101
|
if (!(e instanceof MouseEvent)) return;
|
|
59
|
-
const
|
|
102
|
+
const mouseEvent = e;
|
|
60
103
|
if (this.element) {
|
|
61
|
-
const
|
|
62
|
-
const
|
|
63
|
-
const
|
|
64
|
-
this.target = [
|
|
104
|
+
const elementRect = this.element.getBoundingClientRect();
|
|
105
|
+
const elementWidth = elementRect.width || 1;
|
|
106
|
+
const elementHeight = elementRect.height || 1;
|
|
107
|
+
this.target = [
|
|
108
|
+
(mouseEvent.clientX - elementRect.left) / elementWidth,
|
|
109
|
+
(mouseEvent.clientY - elementRect.top) / elementHeight
|
|
110
|
+
];
|
|
65
111
|
} else {
|
|
66
|
-
const
|
|
67
|
-
const
|
|
68
|
-
this.target = [
|
|
112
|
+
const viewportWidth = typeof window !== "undefined" && window.innerWidth || 1;
|
|
113
|
+
const viewportHeight = typeof window !== "undefined" && window.innerHeight || 1;
|
|
114
|
+
this.target = [mouseEvent.clientX / viewportWidth, mouseEvent.clientY / viewportHeight];
|
|
69
115
|
}
|
|
70
116
|
this.targetDirty = true;
|
|
71
117
|
};
|
|
@@ -76,9 +122,9 @@ var CursorInput = class {
|
|
|
76
122
|
return this.value;
|
|
77
123
|
}
|
|
78
124
|
/** Subscribe to change events. Returns an unsubscribe function. */
|
|
79
|
-
on(
|
|
80
|
-
this.listeners.add(
|
|
81
|
-
return () => this.listeners.delete(
|
|
125
|
+
on(_eventType, changeListener) {
|
|
126
|
+
this.listeners.add(changeListener);
|
|
127
|
+
return () => this.listeners.delete(changeListener);
|
|
82
128
|
}
|
|
83
129
|
/**
|
|
84
130
|
* Advance the smoothing one tick. Called by the host scheduler; not
|
|
@@ -107,51 +153,387 @@ var CursorInput = class {
|
|
|
107
153
|
this.listeners.clear();
|
|
108
154
|
}
|
|
109
155
|
};
|
|
110
|
-
var clamp01 = (
|
|
111
|
-
var lerp = (
|
|
156
|
+
var clamp01 = (value) => Math.max(0, Math.min(1, value));
|
|
157
|
+
var lerp = (startValue, endValue, blendFactor) => startValue + (endValue - startValue) * blendFactor;
|
|
112
158
|
|
|
113
159
|
// src/primitives/color-ramp/color-ramp.ts
|
|
114
|
-
import {
|
|
115
|
-
|
|
116
|
-
|
|
160
|
+
import { clamp as clamp3, div, sub, vec3 as vec37 } from "three/tsl";
|
|
161
|
+
|
|
162
|
+
// src/primitives/color-space/hue.ts
|
|
163
|
+
import { mod, sign, step } from "three/tsl";
|
|
164
|
+
var EQUAL_HUE_EPSILON = 1e-6;
|
|
165
|
+
var shortestArcHue = (h1, h2, t, period) => {
|
|
166
|
+
const half = period / 2;
|
|
167
|
+
const delta = mod(h2.sub(h1).add(half), period).sub(half);
|
|
168
|
+
return h1.add(delta.mul(t));
|
|
169
|
+
};
|
|
170
|
+
var longestArcHue = (h1, h2, t, period) => {
|
|
171
|
+
const half = period / 2;
|
|
172
|
+
const short = mod(h2.sub(h1).add(half), period).sub(half);
|
|
173
|
+
const delta = short.sub(sign(short).mul(period));
|
|
174
|
+
return h1.add(delta.mul(t));
|
|
175
|
+
};
|
|
176
|
+
var increasingArcHue = (h1, h2, t, period) => {
|
|
177
|
+
const delta = mod(h2.sub(h1), period);
|
|
178
|
+
return h1.add(delta.mul(t));
|
|
179
|
+
};
|
|
180
|
+
var decreasingArcHue = (h1, h2, t, period) => {
|
|
181
|
+
const up = mod(h2.sub(h1), period);
|
|
182
|
+
const delta = up.sub(step(EQUAL_HUE_EPSILON, up).mul(period));
|
|
183
|
+
return h1.add(delta.mul(t));
|
|
184
|
+
};
|
|
185
|
+
var hueArcInterpolators = {
|
|
186
|
+
shorter: shortestArcHue,
|
|
187
|
+
longer: longestArcHue,
|
|
188
|
+
increasing: increasingArcHue,
|
|
189
|
+
decreasing: decreasingArcHue
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// src/primitives/color-space/hsl.ts
|
|
193
|
+
import { abs, clamp, fract, max, min, mix as mix2, step as step3, vec3, vec4 } from "three/tsl";
|
|
194
|
+
|
|
195
|
+
// src/primitives/color-space/transfer.ts
|
|
196
|
+
import { mix, pow, step as step2 } from "three/tsl";
|
|
197
|
+
function srgbChannelToLinear(channel) {
|
|
198
|
+
return channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4;
|
|
199
|
+
}
|
|
200
|
+
function srgbToLinear(srgb) {
|
|
201
|
+
const value = pow(srgb, 1);
|
|
202
|
+
const lowSegment = value.div(12.92);
|
|
203
|
+
const highSegment = pow(value.add(0.055).div(1.055), 2.4);
|
|
204
|
+
return mix(lowSegment, highSegment, step2(0.04045, value));
|
|
205
|
+
}
|
|
206
|
+
function linearToSrgb(linear) {
|
|
207
|
+
const value = pow(linear, 1);
|
|
208
|
+
const lowSegment = value.mul(12.92);
|
|
209
|
+
const highSegment = pow(value, 1 / 2.4).mul(1.055).sub(0.055);
|
|
210
|
+
return mix(lowSegment, highSegment, step2(31308e-7, value));
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// src/primitives/color-space/hsl.ts
|
|
214
|
+
var EPSILON = 1e-10;
|
|
215
|
+
function gammaRgbHue(c) {
|
|
216
|
+
const p = mix2(vec4(c.b, c.g, -1 / 3, 2 / 3), vec4(c.g, c.b, 0, -1 / 3), step3(c.b, c.g));
|
|
217
|
+
const q = mix2(vec4(p.x, p.y, p.w, c.r), vec4(c.r, p.y, p.z, p.x), step3(p.x, c.r));
|
|
218
|
+
const chroma = q.x.sub(min(q.w, q.y));
|
|
219
|
+
return abs(q.z.add(q.w.sub(q.y).div(chroma.mul(6).add(EPSILON))));
|
|
220
|
+
}
|
|
221
|
+
function gammaRgbToHsl(c) {
|
|
222
|
+
const maxChannel = max(c.r, max(c.g, c.b));
|
|
223
|
+
const minChannel = min(c.r, min(c.g, c.b));
|
|
224
|
+
const lightness = maxChannel.add(minChannel).mul(0.5);
|
|
225
|
+
const chroma = maxChannel.sub(minChannel);
|
|
226
|
+
const saturation = chroma.div(abs(lightness.mul(2).sub(1)).oneMinus().add(EPSILON));
|
|
227
|
+
return vec3(gammaRgbHue(c), saturation, lightness);
|
|
228
|
+
}
|
|
229
|
+
function hslToGammaRgb(hsl) {
|
|
230
|
+
const hue = hsl.x;
|
|
231
|
+
const saturation = hsl.y;
|
|
232
|
+
const lightness = hsl.z;
|
|
233
|
+
const chroma = abs(lightness.mul(2).sub(1)).oneMinus().mul(saturation);
|
|
234
|
+
const ramp = abs(
|
|
235
|
+
fract(vec3(hue).add(vec3(1, 2 / 3, 1 / 3))).mul(6).sub(vec3(3))
|
|
236
|
+
);
|
|
237
|
+
const hueRgb = clamp(ramp.sub(vec3(1)), 0, 1);
|
|
238
|
+
return hueRgb.sub(0.5).mul(chroma).add(lightness);
|
|
239
|
+
}
|
|
240
|
+
var hslSpace = {
|
|
241
|
+
// Clamp into sRGB before the gamma transfer: HSL is an sRGB-gamut concept, and
|
|
242
|
+
// the sRGB OETF's pow() can't be WGSL const-evaluated on the negative channels
|
|
243
|
+
// of an out-of-sRGB (wide-gamut) stop color — that crashed the shader compile.
|
|
244
|
+
fromLinear: (rgb) => gammaRgbToHsl(linearToSrgb(clamp(rgb, 0, 1))),
|
|
245
|
+
toLinear: (hsl) => srgbToLinear(hslToGammaRgb(hsl)),
|
|
246
|
+
lerp: (a, b, t, hue) => vec3(hue(a.x, b.x, t, 1), mix2(a.y, b.y, t), mix2(a.z, b.z, t))
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// src/primitives/color-space/hsv.ts
|
|
250
|
+
import { abs as abs2, clamp as clamp2, fract as fract2, min as min2, mix as mix3, step as step4, vec3 as vec32, vec4 as vec42 } from "three/tsl";
|
|
251
|
+
var EPSILON2 = 1e-10;
|
|
252
|
+
function gammaRgbToHsv(c) {
|
|
253
|
+
const p = mix3(vec42(c.b, c.g, -1 / 3, 2 / 3), vec42(c.g, c.b, 0, -1 / 3), step4(c.b, c.g));
|
|
254
|
+
const q = mix3(vec42(p.x, p.y, p.w, c.r), vec42(c.r, p.y, p.z, p.x), step4(p.x, c.r));
|
|
255
|
+
const chroma = q.x.sub(min2(q.w, q.y));
|
|
256
|
+
const hue = abs2(q.z.add(q.w.sub(q.y).div(chroma.mul(6).add(EPSILON2))));
|
|
257
|
+
const saturation = chroma.div(q.x.add(EPSILON2));
|
|
258
|
+
return vec32(hue, saturation, q.x);
|
|
259
|
+
}
|
|
260
|
+
function hsvToGammaRgb(hsv) {
|
|
261
|
+
const hue = hsv.x;
|
|
262
|
+
const saturation = hsv.y;
|
|
263
|
+
const value = hsv.z;
|
|
264
|
+
const ramp = abs2(
|
|
265
|
+
fract2(vec32(hue).add(vec32(1, 2 / 3, 1 / 3))).mul(6).sub(vec32(3))
|
|
266
|
+
);
|
|
267
|
+
return mix3(vec32(1), clamp2(ramp.sub(vec32(1)), 0, 1), saturation).mul(value);
|
|
268
|
+
}
|
|
269
|
+
var hsvSpace = {
|
|
270
|
+
// Clamp into sRGB before the gamma transfer: HSV is an sRGB-gamut concept, and
|
|
271
|
+
// the sRGB OETF's pow() can't be WGSL const-evaluated on the negative channels
|
|
272
|
+
// of an out-of-sRGB (wide-gamut) stop color — that crashed the shader compile.
|
|
273
|
+
fromLinear: (rgb) => gammaRgbToHsv(linearToSrgb(clamp2(rgb, 0, 1))),
|
|
274
|
+
toLinear: (hsv) => srgbToLinear(hsvToGammaRgb(hsv)),
|
|
275
|
+
lerp: (a, b, t, hue) => vec32(hue(a.x, b.x, t, 1), mix3(a.y, b.y, t), mix3(a.z, b.z, t))
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
// src/primitives/color-space/lch.ts
|
|
279
|
+
import { atan2, cbrt, cos, length, mix as mix4, sin, step as step5, vec2, vec3 as vec33 } from "three/tsl";
|
|
280
|
+
var TWO_PI = Math.PI * 2;
|
|
281
|
+
var WHITE_X = 0.95047;
|
|
282
|
+
var WHITE_Y = 1;
|
|
283
|
+
var WHITE_Z = 1.08883;
|
|
284
|
+
var EPSILON3 = 216 / 24389;
|
|
285
|
+
var KAPPA = 24389 / 27;
|
|
286
|
+
function labForward(ratio) {
|
|
287
|
+
const linearPart = ratio.mul(KAPPA).add(16).div(116);
|
|
288
|
+
const cubeRootPart = cbrt(ratio);
|
|
289
|
+
return mix4(linearPart, cubeRootPart, step5(EPSILON3, ratio));
|
|
290
|
+
}
|
|
291
|
+
function labInverse(f) {
|
|
292
|
+
const cubed = f.mul(f).mul(f);
|
|
293
|
+
const linearPart = f.mul(116).sub(16).div(KAPPA);
|
|
294
|
+
return mix4(linearPart, cubed, step5(EPSILON3, cubed));
|
|
295
|
+
}
|
|
296
|
+
function linearToLch(rgb) {
|
|
297
|
+
const r = rgb.r;
|
|
298
|
+
const g = rgb.g;
|
|
299
|
+
const b = rgb.b;
|
|
300
|
+
const x = r.mul(0.4123907993).add(g.mul(0.3575843394)).add(b.mul(0.1804807884));
|
|
301
|
+
const y = r.mul(0.2126390059).add(g.mul(0.7151686788)).add(b.mul(0.0721923154));
|
|
302
|
+
const z = r.mul(0.0193308187).add(g.mul(0.1191947798)).add(b.mul(0.9505321522));
|
|
303
|
+
const fx = labForward(x.div(WHITE_X));
|
|
304
|
+
const fy = labForward(y.div(WHITE_Y));
|
|
305
|
+
const fz = labForward(z.div(WHITE_Z));
|
|
306
|
+
const lightness = fy.mul(116).sub(16);
|
|
307
|
+
const greenRed = fx.sub(fy).mul(500);
|
|
308
|
+
const blueYellow = fy.sub(fz).mul(200);
|
|
309
|
+
const chroma = length(vec2(greenRed, blueYellow));
|
|
310
|
+
const hue = atan2(blueYellow, greenRed);
|
|
311
|
+
return vec33(lightness, chroma, hue);
|
|
312
|
+
}
|
|
313
|
+
function lchToLinear(lch) {
|
|
314
|
+
const lightness = lch.x;
|
|
315
|
+
const chroma = lch.y;
|
|
316
|
+
const hue = lch.z;
|
|
317
|
+
const greenRed = chroma.mul(cos(hue));
|
|
318
|
+
const blueYellow = chroma.mul(sin(hue));
|
|
319
|
+
const fy = lightness.add(16).div(116);
|
|
320
|
+
const fx = fy.add(greenRed.div(500));
|
|
321
|
+
const fz = fy.sub(blueYellow.div(200));
|
|
322
|
+
const x = labInverse(fx).mul(WHITE_X);
|
|
323
|
+
const y = labInverse(fy).mul(WHITE_Y);
|
|
324
|
+
const z = labInverse(fz).mul(WHITE_Z);
|
|
325
|
+
const r = x.mul(3.2409699419).sub(y.mul(1.5373831776)).sub(z.mul(0.4986107603));
|
|
326
|
+
const g = x.mul(-0.9692436363).add(y.mul(1.8759675015)).add(z.mul(0.0415550574));
|
|
327
|
+
const b = x.mul(0.0556300797).sub(y.mul(0.2039769589)).add(z.mul(1.0569715142));
|
|
328
|
+
return vec33(r, g, b);
|
|
329
|
+
}
|
|
330
|
+
var lchSpace = {
|
|
331
|
+
fromLinear: linearToLch,
|
|
332
|
+
toLinear: lchToLinear,
|
|
333
|
+
lerp: (a, b, t, hue) => vec33(mix4(a.x, b.x, t), mix4(a.y, b.y, t), hue(a.z, b.z, t, TWO_PI))
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
// src/primitives/color-space/linear.ts
|
|
337
|
+
import { mix as mix5, vec3 as vec34 } from "three/tsl";
|
|
338
|
+
var linearSpace = {
|
|
339
|
+
fromLinear: (rgb) => vec34(rgb),
|
|
340
|
+
toLinear: (coords) => vec34(coords),
|
|
341
|
+
lerp: (a, b, t) => mix5(a, b, t)
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
// src/primitives/color-space/oklab.ts
|
|
345
|
+
import { cbrt as cbrt2, mix as mix6, vec3 as vec35 } from "three/tsl";
|
|
346
|
+
function linearToOklab(rgb) {
|
|
347
|
+
const r = rgb.r;
|
|
348
|
+
const g = rgb.g;
|
|
349
|
+
const b = rgb.b;
|
|
350
|
+
const longCone = r.mul(0.4122214708).add(g.mul(0.5363325363)).add(b.mul(0.0514459929));
|
|
351
|
+
const mediumCone = r.mul(0.2119034982).add(g.mul(0.6806995451)).add(b.mul(0.1073969566));
|
|
352
|
+
const shortCone = r.mul(0.0883024619).add(g.mul(0.2817188376)).add(b.mul(0.6299787005));
|
|
353
|
+
const longRoot = cbrt2(longCone);
|
|
354
|
+
const mediumRoot = cbrt2(mediumCone);
|
|
355
|
+
const shortRoot = cbrt2(shortCone);
|
|
356
|
+
const lightness = longRoot.mul(0.2104542553).add(mediumRoot.mul(0.793617785)).sub(shortRoot.mul(0.0040720468));
|
|
357
|
+
const greenRed = longRoot.mul(1.9779984951).sub(mediumRoot.mul(2.428592205)).add(shortRoot.mul(0.4505937099));
|
|
358
|
+
const blueYellow = longRoot.mul(0.0259040371).add(mediumRoot.mul(0.7827717662)).sub(shortRoot.mul(0.808675766));
|
|
359
|
+
return vec35(lightness, greenRed, blueYellow);
|
|
360
|
+
}
|
|
361
|
+
function oklabToLinear(lab) {
|
|
362
|
+
const lightness = lab.x;
|
|
363
|
+
const greenRed = lab.y;
|
|
364
|
+
const blueYellow = lab.z;
|
|
365
|
+
const longRoot = lightness.add(greenRed.mul(0.3963377774)).add(blueYellow.mul(0.2158037573));
|
|
366
|
+
const mediumRoot = lightness.sub(greenRed.mul(0.1055613458)).sub(blueYellow.mul(0.0638541728));
|
|
367
|
+
const shortRoot = lightness.sub(greenRed.mul(0.0894841775)).sub(blueYellow.mul(1.291485548));
|
|
368
|
+
const longCone = longRoot.mul(longRoot).mul(longRoot);
|
|
369
|
+
const mediumCone = mediumRoot.mul(mediumRoot).mul(mediumRoot);
|
|
370
|
+
const shortCone = shortRoot.mul(shortRoot).mul(shortRoot);
|
|
371
|
+
const r = longCone.mul(4.0767416621).sub(mediumCone.mul(3.3077115913)).add(shortCone.mul(0.2309699292));
|
|
372
|
+
const g = longCone.mul(-1.2684380046).add(mediumCone.mul(2.6097574011)).sub(shortCone.mul(0.3413193965));
|
|
373
|
+
const b = longCone.mul(-0.0041960863).sub(mediumCone.mul(0.7034186147)).add(shortCone.mul(1.707614701));
|
|
374
|
+
return vec35(r, g, b);
|
|
375
|
+
}
|
|
376
|
+
var oklabSpace = {
|
|
377
|
+
fromLinear: linearToOklab,
|
|
378
|
+
toLinear: oklabToLinear,
|
|
379
|
+
lerp: (a, b, t) => mix6(a, b, t)
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
// src/primitives/color-space/oklch.ts
|
|
383
|
+
import { atan2 as atan22, cos as cos2, length as length2, mix as mix7, sin as sin2, vec2 as vec22, vec3 as vec36 } from "three/tsl";
|
|
384
|
+
var TWO_PI2 = Math.PI * 2;
|
|
385
|
+
function linearToOklch(rgb) {
|
|
386
|
+
const lab = linearToOklab(rgb);
|
|
387
|
+
const lightness = lab.x;
|
|
388
|
+
const greenRed = lab.y;
|
|
389
|
+
const blueYellow = lab.z;
|
|
390
|
+
const chroma = length2(vec22(greenRed, blueYellow));
|
|
391
|
+
const hue = atan22(blueYellow, greenRed);
|
|
392
|
+
return vec36(lightness, chroma, hue);
|
|
393
|
+
}
|
|
394
|
+
function oklchToLinear(lch) {
|
|
395
|
+
const lightness = lch.x;
|
|
396
|
+
const chroma = lch.y;
|
|
397
|
+
const hue = lch.z;
|
|
398
|
+
const greenRed = chroma.mul(cos2(hue));
|
|
399
|
+
const blueYellow = chroma.mul(sin2(hue));
|
|
400
|
+
return oklabToLinear(vec36(lightness, greenRed, blueYellow));
|
|
401
|
+
}
|
|
402
|
+
var oklchSpace = {
|
|
403
|
+
fromLinear: linearToOklch,
|
|
404
|
+
toLinear: oklchToLinear,
|
|
405
|
+
lerp: (a, b, t, hue) => vec36(mix7(a.x, b.x, t), mix7(a.y, b.y, t), hue(a.z, b.z, t, TWO_PI2))
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
// src/primitives/color-space/registry.ts
|
|
409
|
+
var colorSpaces = {
|
|
410
|
+
linear: linearSpace,
|
|
411
|
+
oklab: oklabSpace,
|
|
412
|
+
oklch: oklchSpace,
|
|
413
|
+
lch: lchSpace,
|
|
414
|
+
hsl: hslSpace,
|
|
415
|
+
hsv: hsvSpace
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
// src/primitives/color-ramp/color-ramp.ts
|
|
419
|
+
function colorRamp(t, stops, colorSpace = "linear", hueInterpolation = "shorter") {
|
|
420
|
+
const space = colorSpaces[colorSpace];
|
|
421
|
+
const hue = hueArcInterpolators[hueInterpolation];
|
|
117
422
|
const first = stops[0];
|
|
118
|
-
if (first === void 0) return
|
|
119
|
-
|
|
120
|
-
|
|
423
|
+
if (first === void 0) return vec37(0, 0, 0);
|
|
424
|
+
const firstCoords = space.fromLinear(vec37(first.color));
|
|
425
|
+
if (stops.length === 1) return space.toLinear(firstCoords);
|
|
426
|
+
let resultCoords = firstCoords;
|
|
121
427
|
for (let i = 1; i < stops.length; i += 1) {
|
|
122
|
-
const
|
|
428
|
+
const previousStop = stops[i - 1];
|
|
123
429
|
const next = stops[i];
|
|
124
|
-
if (
|
|
125
|
-
const
|
|
126
|
-
if (
|
|
127
|
-
const localT =
|
|
128
|
-
|
|
430
|
+
if (previousStop === void 0 || next === void 0) continue;
|
|
431
|
+
const positionSpan = next.position - previousStop.position;
|
|
432
|
+
if (positionSpan <= 0) continue;
|
|
433
|
+
const localT = clamp3(div(sub(t, previousStop.position), positionSpan), 0, 1);
|
|
434
|
+
const nextCoords = space.fromLinear(vec37(next.color));
|
|
435
|
+
resultCoords = space.lerp(resultCoords, nextCoords, localT, hue);
|
|
436
|
+
}
|
|
437
|
+
return space.toLinear(resultCoords);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// src/primitives/color-space/mix-color.ts
|
|
441
|
+
import { vec3 as vec38 } from "three/tsl";
|
|
442
|
+
function mixColor(colorA, colorB, t, colorSpace = "oklab", hueInterpolation = "shorter") {
|
|
443
|
+
const space = colorSpaces[colorSpace];
|
|
444
|
+
const hue = hueArcInterpolators[hueInterpolation];
|
|
445
|
+
const a = space.fromLinear(vec38(colorA));
|
|
446
|
+
const b = space.fromLinear(vec38(colorB));
|
|
447
|
+
return space.toLinear(space.lerp(a, b, t, hue));
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// src/primitives/color-space/cpu-convert.ts
|
|
451
|
+
function oklabToLinearSrgb(lightness, greenRed, blueYellow) {
|
|
452
|
+
const longRoot = lightness + 0.3963377774 * greenRed + 0.2158037573 * blueYellow;
|
|
453
|
+
const mediumRoot = lightness - 0.1055613458 * greenRed - 0.0638541728 * blueYellow;
|
|
454
|
+
const shortRoot = lightness - 0.0894841775 * greenRed - 1.291485548 * blueYellow;
|
|
455
|
+
const longCone = longRoot * longRoot * longRoot;
|
|
456
|
+
const mediumCone = mediumRoot * mediumRoot * mediumRoot;
|
|
457
|
+
const shortCone = shortRoot * shortRoot * shortRoot;
|
|
458
|
+
const red = 4.0767416621 * longCone - 3.3077115913 * mediumCone + 0.2309699292 * shortCone;
|
|
459
|
+
const green = -1.2684380046 * longCone + 2.6097574011 * mediumCone - 0.3413193965 * shortCone;
|
|
460
|
+
const blue = -0.0041960863 * longCone - 0.7034186147 * mediumCone + 1.707614701 * shortCone;
|
|
461
|
+
return [red, green, blue];
|
|
462
|
+
}
|
|
463
|
+
function oklchToLinearSrgb(lightness, chroma, hueDegrees) {
|
|
464
|
+
const hueRadians = hueDegrees * Math.PI / 180;
|
|
465
|
+
const greenRed = chroma * Math.cos(hueRadians);
|
|
466
|
+
const blueYellow = chroma * Math.sin(hueRadians);
|
|
467
|
+
return oklabToLinearSrgb(lightness, greenRed, blueYellow);
|
|
468
|
+
}
|
|
469
|
+
function parseComponent(token, scale) {
|
|
470
|
+
const trimmed = token.trim();
|
|
471
|
+
if (trimmed.endsWith("%")) {
|
|
472
|
+
return parseFloat(trimmed.slice(0, -1)) / 100 * scale;
|
|
129
473
|
}
|
|
130
|
-
return
|
|
474
|
+
return parseFloat(trimmed);
|
|
475
|
+
}
|
|
476
|
+
function functionArgs(input, prefix) {
|
|
477
|
+
const inner = input.slice(prefix.length, input.lastIndexOf(")"));
|
|
478
|
+
const beforeAlpha = inner.split("/")[0] ?? "";
|
|
479
|
+
return beforeAlpha.trim().split(/[\s,]+/).filter((token) => token.length > 0);
|
|
480
|
+
}
|
|
481
|
+
function parseColorString(input) {
|
|
482
|
+
const value = input.trim();
|
|
483
|
+
if (value.startsWith("#")) {
|
|
484
|
+
const hex = value.slice(1);
|
|
485
|
+
return [
|
|
486
|
+
srgbChannelToLinear(parseInt(hex.slice(0, 2), 16) / 255),
|
|
487
|
+
srgbChannelToLinear(parseInt(hex.slice(2, 4), 16) / 255),
|
|
488
|
+
srgbChannelToLinear(parseInt(hex.slice(4, 6), 16) / 255)
|
|
489
|
+
];
|
|
490
|
+
}
|
|
491
|
+
if (value.startsWith("oklch(")) {
|
|
492
|
+
const [lightnessToken, chromaToken, hueToken] = functionArgs(value, "oklch(");
|
|
493
|
+
if (lightnessToken === void 0 || chromaToken === void 0 || hueToken === void 0) {
|
|
494
|
+
throw new Error(`Invalid oklch() color: "${input}"`);
|
|
495
|
+
}
|
|
496
|
+
const lightness = parseComponent(lightnessToken, 1);
|
|
497
|
+
const chroma = parseComponent(chromaToken, 0.4);
|
|
498
|
+
const hueDegrees = parseFloat(hueToken.replace(/deg$/, ""));
|
|
499
|
+
return oklchToLinearSrgb(lightness, chroma, hueDegrees);
|
|
500
|
+
}
|
|
501
|
+
if (value.startsWith("oklab(")) {
|
|
502
|
+
const [lightnessToken, aToken, bToken] = functionArgs(value, "oklab(");
|
|
503
|
+
if (lightnessToken === void 0 || aToken === void 0 || bToken === void 0) {
|
|
504
|
+
throw new Error(`Invalid oklab() color: "${input}"`);
|
|
505
|
+
}
|
|
506
|
+
return oklabToLinearSrgb(
|
|
507
|
+
parseComponent(lightnessToken, 1),
|
|
508
|
+
parseComponent(aToken, 0.4),
|
|
509
|
+
parseComponent(bToken, 0.4)
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
throw new Error(`Unsupported color syntax: "${input}". Use #rrggbb, oklch(...), or oklab(...).`);
|
|
131
513
|
}
|
|
132
514
|
|
|
133
515
|
// src/primitives/noise/noise.ts
|
|
134
516
|
import { mx_noise_float } from "three/tsl";
|
|
135
|
-
function
|
|
517
|
+
function simplexNoise(p) {
|
|
136
518
|
return mx_noise_float(p);
|
|
137
519
|
}
|
|
138
520
|
|
|
139
521
|
// src/primitives/fbm/fbm.ts
|
|
140
522
|
import { add, mul } from "three/tsl";
|
|
141
|
-
function
|
|
523
|
+
function fractalNoise(p, opts = {}) {
|
|
142
524
|
const octaves = opts.octaves ?? 4;
|
|
143
525
|
const lacunarity = opts.lacunarity ?? 2;
|
|
144
526
|
const gain = opts.gain ?? 0.5;
|
|
145
|
-
let sum =
|
|
146
|
-
let
|
|
147
|
-
let
|
|
148
|
-
let total =
|
|
527
|
+
let sum = simplexNoise(p);
|
|
528
|
+
let amplitude = 1;
|
|
529
|
+
let frequency = 1;
|
|
530
|
+
let total = amplitude;
|
|
149
531
|
for (let i = 1; i < octaves; i += 1) {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
total +=
|
|
153
|
-
const pAtFreq = add(mul(p,
|
|
154
|
-
const layer =
|
|
532
|
+
frequency *= lacunarity;
|
|
533
|
+
amplitude *= gain;
|
|
534
|
+
total += amplitude;
|
|
535
|
+
const pAtFreq = add(mul(p, frequency), i * 100);
|
|
536
|
+
const layer = simplexNoise(pAtFreq).mul(amplitude);
|
|
155
537
|
sum = sum.add(layer);
|
|
156
538
|
}
|
|
157
539
|
return sum.div(total);
|
|
@@ -168,14 +550,14 @@ function quantize(t, steps) {
|
|
|
168
550
|
if (steps <= 1) {
|
|
169
551
|
return t.mul(0);
|
|
170
552
|
}
|
|
171
|
-
const
|
|
172
|
-
return t.mul(
|
|
553
|
+
const denominator = steps - 1;
|
|
554
|
+
return t.mul(denominator).add(0.5).floor().div(denominator);
|
|
173
555
|
}
|
|
174
556
|
|
|
175
557
|
// src/primitives/sdf-circle/sdf-circle.ts
|
|
176
|
-
import { length } from "three/tsl";
|
|
177
|
-
function
|
|
178
|
-
return
|
|
558
|
+
import { length as length3 } from "three/tsl";
|
|
559
|
+
function signedDistanceFieldCircle(p, radius) {
|
|
560
|
+
return length3(p).sub(radius);
|
|
179
561
|
}
|
|
180
562
|
|
|
181
563
|
// src/primitives/displace/displace.ts
|
|
@@ -185,7 +567,7 @@ function displace(p, by) {
|
|
|
185
567
|
}
|
|
186
568
|
|
|
187
569
|
// src/primitives/cursor-ripple/cursor-ripple.ts
|
|
188
|
-
import { length as
|
|
570
|
+
import { length as length4, sin as sin3, smoothstep, sub as sub2 } from "three/tsl";
|
|
189
571
|
|
|
190
572
|
// src/primitives/time/time.ts
|
|
191
573
|
import { time as _builtinTime } from "three/tsl";
|
|
@@ -199,7 +581,7 @@ var state = {
|
|
|
199
581
|
function setReducedMotionPolicy(policy) {
|
|
200
582
|
if (state.policy === policy) return;
|
|
201
583
|
state.policy = policy;
|
|
202
|
-
for (const
|
|
584
|
+
for (const watcher of state.watchers) watcher.recompute();
|
|
203
585
|
}
|
|
204
586
|
function getReducedMotionPolicy() {
|
|
205
587
|
return state.policy;
|
|
@@ -220,8 +602,8 @@ function createReducedMotionWatcher() {
|
|
|
220
602
|
if (typeof matchMedia !== "function") {
|
|
221
603
|
return {
|
|
222
604
|
scale: () => computeScale(false),
|
|
223
|
-
subscribe: (
|
|
224
|
-
void
|
|
605
|
+
subscribe: (listener) => {
|
|
606
|
+
void listener;
|
|
225
607
|
return () => {
|
|
226
608
|
};
|
|
227
609
|
},
|
|
@@ -230,33 +612,33 @@ function createReducedMotionWatcher() {
|
|
|
230
612
|
}
|
|
231
613
|
};
|
|
232
614
|
}
|
|
233
|
-
const
|
|
234
|
-
const
|
|
235
|
-
let
|
|
615
|
+
const mediaQueryList = matchMedia("(prefers-reduced-motion: reduce)");
|
|
616
|
+
const subscriptions = /* @__PURE__ */ new Set();
|
|
617
|
+
let lastComputedScale = computeScale(mediaQueryList.matches);
|
|
236
618
|
const onChange = () => {
|
|
237
|
-
const next = computeScale(
|
|
238
|
-
if (next !==
|
|
239
|
-
|
|
240
|
-
for (const
|
|
619
|
+
const next = computeScale(mediaQueryList.matches);
|
|
620
|
+
if (next !== lastComputedScale) {
|
|
621
|
+
lastComputedScale = next;
|
|
622
|
+
for (const listener of subscriptions) listener(next);
|
|
241
623
|
}
|
|
242
624
|
};
|
|
243
|
-
|
|
625
|
+
mediaQueryList.addEventListener("change", onChange);
|
|
244
626
|
const watcher = {
|
|
245
|
-
scale: () =>
|
|
246
|
-
subscribe(
|
|
247
|
-
|
|
248
|
-
return () =>
|
|
627
|
+
scale: () => lastComputedScale,
|
|
628
|
+
subscribe(listener) {
|
|
629
|
+
subscriptions.add(listener);
|
|
630
|
+
return () => subscriptions.delete(listener);
|
|
249
631
|
},
|
|
250
632
|
recompute() {
|
|
251
|
-
const next = computeScale(
|
|
252
|
-
if (next !==
|
|
253
|
-
|
|
254
|
-
for (const
|
|
633
|
+
const next = computeScale(mediaQueryList.matches);
|
|
634
|
+
if (next !== lastComputedScale) {
|
|
635
|
+
lastComputedScale = next;
|
|
636
|
+
for (const listener of subscriptions) listener(next);
|
|
255
637
|
}
|
|
256
638
|
},
|
|
257
639
|
dispose() {
|
|
258
|
-
|
|
259
|
-
|
|
640
|
+
mediaQueryList.removeEventListener("change", onChange);
|
|
641
|
+
subscriptions.clear();
|
|
260
642
|
state.watchers.delete(watcher);
|
|
261
643
|
}
|
|
262
644
|
};
|
|
@@ -278,7 +660,7 @@ function getReducedMotionTimeScale() {
|
|
|
278
660
|
}
|
|
279
661
|
|
|
280
662
|
// src/primitives/time/time.ts
|
|
281
|
-
var
|
|
663
|
+
var elapsedTime = _builtinTime.mul(getReducedMotionTimeScale());
|
|
282
664
|
|
|
283
665
|
// src/primitives/cursor-ripple/cursor-ripple.ts
|
|
284
666
|
function cursorRipple(p, center, opts = {}) {
|
|
@@ -286,20 +668,31 @@ function cursorRipple(p, center, opts = {}) {
|
|
|
286
668
|
const frequency = opts.frequency ?? 30;
|
|
287
669
|
const speed = opts.speed ?? 6;
|
|
288
670
|
const amplitude = opts.amplitude ?? 0.5;
|
|
289
|
-
const d =
|
|
290
|
-
const wave =
|
|
671
|
+
const d = length4(sub2(p, center));
|
|
672
|
+
const wave = sin3(d.mul(frequency).sub(elapsedTime.mul(speed)));
|
|
291
673
|
const decay = smoothstep(reach, 0, d);
|
|
292
674
|
return wave.mul(amplitude).mul(decay);
|
|
293
675
|
}
|
|
294
676
|
|
|
295
677
|
// src/primitives/film-grain/film-grain.ts
|
|
296
|
-
import {
|
|
297
|
-
function filmGrain(
|
|
298
|
-
const
|
|
299
|
-
const
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
678
|
+
import { hash, mul as mul2, screenCoordinate } from "three/tsl";
|
|
679
|
+
function filmGrain(intensity, timeOffset = 0) {
|
|
680
|
+
const pixel = screenCoordinate.xy.floor();
|
|
681
|
+
const seed = pixel.x.toUint().mul(1973).add(pixel.y.toUint().mul(9277)).add(mul2(timeOffset, 26699).toUint());
|
|
682
|
+
return hash(seed).sub(0.5).mul(intensity);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
// src/primitives/dither/dither.ts
|
|
686
|
+
import { dot, fract as fract3, sin as sin4, vec2 as vec23, vec3 as vec39 } from "three/tsl";
|
|
687
|
+
function hash21(coord) {
|
|
688
|
+
return fract3(sin4(dot(coord, vec23(12.9898, 78.233))).mul(43758.5453));
|
|
689
|
+
}
|
|
690
|
+
function dither(color, coord, amount = 1 / 255) {
|
|
691
|
+
const pixelCoord = vec23(coord);
|
|
692
|
+
const firstHash = hash21(pixelCoord);
|
|
693
|
+
const secondHash = hash21(pixelCoord.add(vec23(0.5, 0.5)));
|
|
694
|
+
const triangularNoise = firstHash.sub(secondHash).mul(0.5);
|
|
695
|
+
return vec39(color).add(triangularNoise.mul(amount));
|
|
303
696
|
}
|
|
304
697
|
|
|
305
698
|
// src/runtime/visibility/visibility.ts
|
|
@@ -313,21 +706,21 @@ function createVisibilityWatcher() {
|
|
|
313
706
|
}
|
|
314
707
|
};
|
|
315
708
|
}
|
|
316
|
-
const
|
|
709
|
+
const subscriptions = /* @__PURE__ */ new Set();
|
|
317
710
|
const onChange = () => {
|
|
318
|
-
const
|
|
319
|
-
for (const
|
|
711
|
+
const isVisible = document.visibilityState === "visible";
|
|
712
|
+
for (const listener of subscriptions) listener(isVisible);
|
|
320
713
|
};
|
|
321
714
|
document.addEventListener("visibilitychange", onChange);
|
|
322
715
|
return {
|
|
323
716
|
isVisible: () => document.visibilityState === "visible",
|
|
324
|
-
subscribe(
|
|
325
|
-
|
|
326
|
-
return () =>
|
|
717
|
+
subscribe(listener) {
|
|
718
|
+
subscriptions.add(listener);
|
|
719
|
+
return () => subscriptions.delete(listener);
|
|
327
720
|
},
|
|
328
721
|
dispose() {
|
|
329
722
|
document.removeEventListener("visibilitychange", onChange);
|
|
330
|
-
|
|
723
|
+
subscriptions.clear();
|
|
331
724
|
}
|
|
332
725
|
};
|
|
333
726
|
}
|
|
@@ -343,27 +736,27 @@ function createIntersectionWatcher(canvas) {
|
|
|
343
736
|
}
|
|
344
737
|
};
|
|
345
738
|
}
|
|
346
|
-
const
|
|
739
|
+
const subscriptions = /* @__PURE__ */ new Set();
|
|
347
740
|
let inView = true;
|
|
348
|
-
const
|
|
741
|
+
const observer = new IntersectionObserver(
|
|
349
742
|
(entries) => {
|
|
350
|
-
const next = entries.some((
|
|
743
|
+
const next = entries.some((entry) => entry.isIntersecting);
|
|
351
744
|
if (next === inView) return;
|
|
352
745
|
inView = next;
|
|
353
|
-
for (const
|
|
746
|
+
for (const listener of subscriptions) listener(inView);
|
|
354
747
|
},
|
|
355
748
|
{ threshold: 0 }
|
|
356
749
|
);
|
|
357
|
-
|
|
750
|
+
observer.observe(canvas);
|
|
358
751
|
return {
|
|
359
752
|
isInView: () => inView,
|
|
360
|
-
subscribe(
|
|
361
|
-
|
|
362
|
-
return () =>
|
|
753
|
+
subscribe(listener) {
|
|
754
|
+
subscriptions.add(listener);
|
|
755
|
+
return () => subscriptions.delete(listener);
|
|
363
756
|
},
|
|
364
757
|
dispose() {
|
|
365
|
-
|
|
366
|
-
|
|
758
|
+
observer.disconnect();
|
|
759
|
+
subscriptions.clear();
|
|
367
760
|
}
|
|
368
761
|
};
|
|
369
762
|
}
|
|
@@ -374,10 +767,19 @@ var FrameScheduler = class {
|
|
|
374
767
|
rafId = null;
|
|
375
768
|
running = false;
|
|
376
769
|
paused = false;
|
|
377
|
-
idle = false;
|
|
378
770
|
flushPending = false;
|
|
379
771
|
startedAt = 0;
|
|
380
772
|
lastTickAt = 0;
|
|
773
|
+
// Reference-counted idle voting. The scheduler is idle only when at least
|
|
774
|
+
// one component has voted idle AND no component has voted animated. This
|
|
775
|
+
// prevents a static component (e.g. LinearGradient speed=0) from halting
|
|
776
|
+
// the loop while an animated overlay (e.g. FilmGrain) is still running.
|
|
777
|
+
idleVotes = 0;
|
|
778
|
+
animatedVotes = 0;
|
|
779
|
+
/** True when all participating components prefer idle and none need animation. */
|
|
780
|
+
get idle() {
|
|
781
|
+
return this.idleVotes > 0 && this.animatedVotes === 0;
|
|
782
|
+
}
|
|
381
783
|
/** Activate the scheduler. The rAF loop starts on the first client added. */
|
|
382
784
|
start() {
|
|
383
785
|
this.running = true;
|
|
@@ -413,19 +815,39 @@ var FrameScheduler = class {
|
|
|
413
815
|
this.clients.clear();
|
|
414
816
|
}
|
|
415
817
|
/**
|
|
416
|
-
*
|
|
417
|
-
*
|
|
418
|
-
*
|
|
818
|
+
* Cast a vote on whether the scheduler should be idle.
|
|
819
|
+
*
|
|
820
|
+
* `setIdle(true)` increments the idle-vote count; the returned cleanup
|
|
821
|
+
* decrements it. `setIdle(false)` increments the animated-vote count;
|
|
822
|
+
* its cleanup decrements that. The scheduler halts (after one flush tick)
|
|
823
|
+
* only when `idleVotes > 0 && animatedVotes === 0`.
|
|
824
|
+
*
|
|
825
|
+
* Callers are responsible for calling the returned cleanup on unmount.
|
|
826
|
+
* Use `requestRender()` or cast a `setIdle(false)` vote to wake the loop
|
|
827
|
+
* without permanently registering an animated preference.
|
|
419
828
|
*/
|
|
420
829
|
setIdle(idle) {
|
|
421
|
-
if (this.idle === idle) return;
|
|
422
|
-
this.idle = idle;
|
|
423
830
|
if (idle) {
|
|
424
|
-
|
|
425
|
-
this.
|
|
831
|
+
const wasIdle = this.idle;
|
|
832
|
+
this.idleVotes += 1;
|
|
833
|
+
const nowIdle = this.idle;
|
|
834
|
+
if (!wasIdle && nowIdle) this.onBecameIdle();
|
|
835
|
+
return () => {
|
|
836
|
+
const prevIdle = this.idle;
|
|
837
|
+
this.idleVotes = Math.max(0, this.idleVotes - 1);
|
|
838
|
+
const afterIdle = this.idle;
|
|
839
|
+
if (prevIdle && !afterIdle) this.onBecameAnimated();
|
|
840
|
+
};
|
|
426
841
|
} else {
|
|
427
|
-
|
|
428
|
-
this.
|
|
842
|
+
const wasIdle = this.idle;
|
|
843
|
+
this.animatedVotes += 1;
|
|
844
|
+
if (wasIdle) this.onBecameAnimated();
|
|
845
|
+
return () => {
|
|
846
|
+
const prevIdle = this.idle;
|
|
847
|
+
this.animatedVotes = Math.max(0, this.animatedVotes - 1);
|
|
848
|
+
const nowIdle = this.idle;
|
|
849
|
+
if (!prevIdle && nowIdle) this.onBecameIdle();
|
|
850
|
+
};
|
|
429
851
|
}
|
|
430
852
|
}
|
|
431
853
|
/** Force a single tick while idle. Useful for prop-change invalidation. */
|
|
@@ -434,6 +856,14 @@ var FrameScheduler = class {
|
|
|
434
856
|
this.flushPending = true;
|
|
435
857
|
this.maybeQueue();
|
|
436
858
|
}
|
|
859
|
+
onBecameIdle() {
|
|
860
|
+
this.flushPending = true;
|
|
861
|
+
this.maybeQueue();
|
|
862
|
+
}
|
|
863
|
+
onBecameAnimated() {
|
|
864
|
+
this.flushPending = false;
|
|
865
|
+
this.maybeQueue();
|
|
866
|
+
}
|
|
437
867
|
maybeQueue() {
|
|
438
868
|
if (this.rafId !== null) return;
|
|
439
869
|
if (!this.running) return;
|
|
@@ -475,15 +905,21 @@ export {
|
|
|
475
905
|
createVisibilityWatcher,
|
|
476
906
|
cursorRipple,
|
|
477
907
|
displace,
|
|
478
|
-
|
|
908
|
+
dither,
|
|
909
|
+
elapsedTime,
|
|
479
910
|
filmGrain,
|
|
911
|
+
fractalNoise,
|
|
480
912
|
getReducedMotionPolicy,
|
|
481
913
|
getReducedMotionTimeScale,
|
|
482
|
-
|
|
914
|
+
mixColor,
|
|
915
|
+
oklabToLinearSrgb,
|
|
916
|
+
oklchToLinearSrgb,
|
|
917
|
+
parseColorString,
|
|
483
918
|
quantize,
|
|
484
|
-
sdfCircle,
|
|
485
919
|
setReducedMotionPolicy,
|
|
486
|
-
|
|
920
|
+
signedDistanceFieldCircle,
|
|
921
|
+
simplexNoise,
|
|
922
|
+
srgbChannelToLinear,
|
|
487
923
|
voronoi
|
|
488
924
|
};
|
|
489
925
|
//# sourceMappingURL=index.js.map
|