@cosmictraveler002/anim-kit 1.4.0 → 1.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.
Files changed (56) hide show
  1. package/README.md +256 -23
  2. package/dist/anim-kit.standalone.js +5 -5
  3. package/dist/anim-kit.standalone.js.map +1 -1
  4. package/dist/core/smooth-scroll.d.ts +29 -1
  5. package/dist/core/smooth-scroll.d.ts.map +1 -1
  6. package/dist/core/smooth-scroll.js +23 -3
  7. package/dist/core/smooth-scroll.js.map +1 -1
  8. package/dist/effects/horizontal-scroll.d.ts.map +1 -1
  9. package/dist/effects/horizontal-scroll.js +3 -0
  10. package/dist/effects/horizontal-scroll.js.map +1 -1
  11. package/dist/effects/ink-wipe.d.ts +41 -0
  12. package/dist/effects/ink-wipe.d.ts.map +1 -0
  13. package/dist/effects/ink-wipe.js +342 -0
  14. package/dist/effects/ink-wipe.js.map +1 -0
  15. package/dist/effects/scatter-text.d.ts.map +1 -1
  16. package/dist/effects/scatter-text.js +3 -0
  17. package/dist/effects/scatter-text.js.map +1 -1
  18. package/dist/effects/stacked-cards.d.ts.map +1 -1
  19. package/dist/effects/stacked-cards.js +3 -0
  20. package/dist/effects/stacked-cards.js.map +1 -1
  21. package/dist/index.d.ts +3 -0
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +2 -0
  24. package/dist/index.js.map +1 -1
  25. package/dist/three/coverflow-wheel.d.ts +26 -0
  26. package/dist/three/coverflow-wheel.d.ts.map +1 -0
  27. package/dist/three/coverflow-wheel.js +495 -0
  28. package/dist/three/coverflow-wheel.js.map +1 -0
  29. package/dist/three/dither-reveal.d.ts +36 -0
  30. package/dist/three/dither-reveal.d.ts.map +1 -0
  31. package/dist/three/dither-reveal.js +292 -0
  32. package/dist/three/dither-reveal.js.map +1 -0
  33. package/dist/three/index.d.ts +8 -0
  34. package/dist/three/index.d.ts.map +1 -1
  35. package/dist/three/index.js +4 -0
  36. package/dist/three/index.js.map +1 -1
  37. package/dist/three/tear-reveal.d.ts +54 -0
  38. package/dist/three/tear-reveal.d.ts.map +1 -0
  39. package/dist/three/tear-reveal.js +269 -0
  40. package/dist/three/tear-reveal.js.map +1 -0
  41. package/dist/three/wordmark-wave.d.ts +29 -0
  42. package/dist/three/wordmark-wave.d.ts.map +1 -0
  43. package/dist/three/wordmark-wave.js +461 -0
  44. package/dist/three/wordmark-wave.js.map +1 -0
  45. package/package.json +1 -1
  46. package/src/core/smooth-scroll.ts +44 -2
  47. package/src/effects/horizontal-scroll.ts +3 -0
  48. package/src/effects/ink-wipe.ts +409 -0
  49. package/src/effects/scatter-text.ts +3 -0
  50. package/src/effects/stacked-cards.ts +3 -0
  51. package/src/index.ts +3 -0
  52. package/src/three/coverflow-wheel.ts +569 -0
  53. package/src/three/dither-reveal.ts +365 -0
  54. package/src/three/index.ts +8 -0
  55. package/src/three/tear-reveal.ts +351 -0
  56. package/src/three/wordmark-wave.ts +517 -0
@@ -0,0 +1,461 @@
1
+ /**
2
+ * Wordmark wave — the giant wordmark that ripples under the pointer and
3
+ * throws red/cyan chromatic fringes while it deforms.
4
+ *
5
+ * The whole effect is one deformable plane textured with the wordmark drawn
6
+ * from the target's own text and font — no bundled typeface, no baked mesh:
7
+ *
8
+ * - **The sim runs on the CPU, per vertex** (a ~5 k-vertex grid is nothing
9
+ * at 60 Hz), stepping the reference's frame constants verbatim: pointer
10
+ * falloff `1/(1 + d/0.05) − 0.1`, a `0.02` pointer-velocity "drag" term,
11
+ * a `0.1` spring back to rest, `0.9` damping, `0.1` integration scale.
12
+ * The step is fixed at 1/60 s (accumulated, max 4 per frame) so the
13
+ * physics are identical on 60/120/144 Hz displays; pointer velocity is
14
+ * measured per frame, folded to 1/60 s after a stall and zeroed above
15
+ * 10 units/s (teleport guard).
16
+ * - **The chroma is three additive draws, not a post effect.** The same
17
+ * geometry renders once per channel with the displacement scaled
18
+ * 0.9 / 1.0 / 1.1 — at rest the passes coincide and the wordmark is solid;
19
+ * wherever the mesh moves the channels separate into red/cyan fringes.
20
+ * (Light base colours only — a saturated colour kills its own channels.)
21
+ * - **Normalized space.** Positions, cursor and falloff live in half-width
22
+ * units (x ∈ [−1, 1], y ∈ [−h/w, h/w]) so waves stay circles on screen at
23
+ * any element aspect; the vertex shader converts y to NDC with one aspect
24
+ * multiply.
25
+ * - **Silent no-op ladder.** Missing target / empty text → no-op. No WebGL
26
+ * (SSR, jsdom, disabled) → no-op before any context is requested.
27
+ * Renderer construction throws → no-op. Off-screen → the ticker idles
28
+ * (IntersectionObserver) and a settled wordmark stops stepping entirely.
29
+ * Under `prefers-reduced-motion` nothing mounts — the real text simply
30
+ * stays visible (it is only hidden while the effect owns it).
31
+ * - **Fidelity.** `destroy()` restores the text colour and the inline
32
+ * position, removes the canvas, listeners and observers, and disposes
33
+ * geometry, materials, texture and renderer.
34
+ *
35
+ * wordmarkWave("[data-wordmark]", { outline: 3, tracking: 8 });
36
+ *
37
+ * CSS: the target holds a single line of text; it is hidden (colour
38
+ * transparent) while mounted and re-drawn centred in its own box. Style the
39
+ * font there — the effect inherits it.
40
+ */
41
+ import * as THREE from "three";
42
+ import { gsap, initGSAP } from "../core/gsap.js";
43
+ import { guard } from "../core/guard.js";
44
+ import { one } from "../core/util.js";
45
+ /* Reference frame constants — the sim is stepped at a fixed 60 Hz so these
46
+ stay exactly as measured, whatever the display's refresh rate. */
47
+ const FALLOFF = 0.05; // pointer falloff radius, half-width units
48
+ const FLOOR = 0.1; // strength = 1/(1+d/FALLOFF) − FLOOR, clamped
49
+ const REACH = FALLOFF * (1 / FLOOR - 1); // where strength hits 0 → 0.45
50
+ const DRAG_K = 0.02; // pointer-velocity term
51
+ const SPRING = 0.1; // return-to-rest term
52
+ const DAMP = 0.9; // velocity damping per step
53
+ const INTEG = 0.1; // displacement per velocity per step
54
+ const STEP = 1 / 60; // fixed sim step, seconds
55
+ const MAX_STEPS = 4; // accumulated steps allowed per frame
56
+ const V_CLAMP = 10; // pointer speed above which the delta is discarded
57
+ const SETTLE_EPS = 1e-4; // |disp|/|vel| below which the sim sleeps
58
+ const VERT = /* glsl */ `
59
+ attribute vec2 aDisp; // sim displacement, half-width units
60
+ uniform float uDispScale; // chroma pass multiplier: 0.9 / 1.0 / 1.1
61
+ uniform float uAspect; // w/h — sim y to NDC (y extent is h/w)
62
+ varying vec2 vUv;
63
+
64
+ void main() {
65
+ vUv = uv;
66
+ vec2 p = position.xy + aDisp * uDispScale;
67
+ gl_Position = vec4(p.x, p.y * uAspect, 0.0, 1.0);
68
+ }
69
+ `;
70
+ /* Chroma pass: premultiplied rgb, alpha = opacity/3. The three passes add up
71
+ to base * coverage * opacity at rest; where only one channel reaches, the
72
+ fringe sits at a third of the coverage — brighter than its alpha says,
73
+ which is exactly the additive look the reference has. */
74
+ const CHROMA_FRAG = /* glsl */ `
75
+ precision highp float;
76
+ uniform sampler2D uMap;
77
+ uniform vec3 uPass; // channel * base colour
78
+ uniform float uOpacity;
79
+ varying vec2 vUv;
80
+
81
+ void main() {
82
+ float a = texture2D(uMap, vUv).a;
83
+ if (a <= 0.002) discard;
84
+ gl_FragColor = vec4(uPass * a * uOpacity, a * uOpacity / 3.0);
85
+ }
86
+ `;
87
+ /* Single pass (chroma: false): straight alpha, like every other overlay. */
88
+ const PLAIN_FRAG = /* glsl */ `
89
+ precision highp float;
90
+ uniform sampler2D uMap;
91
+ uniform vec3 uPass;
92
+ uniform float uOpacity;
93
+ varying vec2 vUv;
94
+
95
+ void main() {
96
+ float a = texture2D(uMap, vUv).a;
97
+ if (a <= 0.002) discard;
98
+ gl_FragColor = vec4(uPass, a * uOpacity);
99
+ }
100
+ `;
101
+ export function wordmarkWave(target, options = {}) {
102
+ initGSAP();
103
+ const host = one(target);
104
+ if (!host)
105
+ return () => { };
106
+ const text = (options.text ?? host.textContent ?? "").trim().replace(/\s+/g, " ");
107
+ if (!text)
108
+ return () => { };
109
+ const { color, opacity = 1, outline = 0, tracking = 0, drag = 1, push = 0, chroma = true, dpr = 2, segments = 0, z = 1, } = options;
110
+ return guard(options, () => {
111
+ /* ---------------- availability ladder (silent, no probes) ---------------- */
112
+ if (typeof window === "undefined" || !("WebGLRenderingContext" in window))
113
+ return () => { };
114
+ let renderer;
115
+ try {
116
+ renderer = new THREE.WebGLRenderer({ alpha: true, antialias: false });
117
+ }
118
+ catch {
119
+ return () => { }; // context refused — the plain text simply stays
120
+ }
121
+ /* --------------- the font + colour live on the element ------------------ */
122
+ const computed = getComputedStyle(host);
123
+ const family = computed.fontFamily;
124
+ const weight = computed.fontWeight;
125
+ const style = computed.fontStyle;
126
+ const variant = computed.fontVariant;
127
+ const size0 = parseFloat(computed.fontSize) || 16;
128
+ const baseColor = color || computed.color || "#ffffff";
129
+ const pass = new THREE.Color(baseColor);
130
+ /* ---------------- layout + styles we must restore ---------------- */
131
+ const prevPosition = host.style.position;
132
+ if (!prevPosition && computed.position === "static")
133
+ host.style.position = "relative";
134
+ const prevColor = host.style.color;
135
+ host.style.color = "transparent"; // the canvas owns the pixels now
136
+ let w = Math.max(1, host.clientWidth);
137
+ let h = Math.max(1, host.clientHeight);
138
+ renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, dpr));
139
+ renderer.setSize(w, h, false);
140
+ renderer.setClearColor(0x000000, 0);
141
+ const canvas = renderer.domElement;
142
+ canvas.style.cssText = `position:absolute;inset:0;width:100%;height:100%;display:block;pointer-events:none;z-index:${z};`;
143
+ const scene = new THREE.Scene();
144
+ const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, -1, 1);
145
+ /* ---------------- the wordmark texture ---------------- */
146
+ const texCanvas = document.createElement("canvas");
147
+ const ctx = texCanvas.getContext("2d");
148
+ let texture = null;
149
+ /* The font: the target's computed shorthand by default; options.font
150
+ verbatim when the canvas accepts it (px sizes are never rewritten —
151
+ a rejected value falls back to the computed one). */
152
+ const applyFont = () => {
153
+ const fallback = `${style} ${variant} ${weight} ${size0}px ${family}`;
154
+ const cand = options.font || fallback;
155
+ ctx.font = "1px monospace"; // sentinel: survives a rejected assignment
156
+ ctx.font = cand;
157
+ if (ctx.font === "1px monospace")
158
+ ctx.font = fallback;
159
+ };
160
+ const drawText = () => {
161
+ const capDpr = Math.min(window.devicePixelRatio || 1, dpr);
162
+ texCanvas.width = Math.max(1, Math.round(w * capDpr));
163
+ texCanvas.height = Math.max(1, Math.round(h * capDpr));
164
+ ctx.setTransform(capDpr, 0, 0, capDpr, 0, 0);
165
+ ctx.clearRect(0, 0, w, h);
166
+ applyFont();
167
+ ctx.textBaseline = "middle";
168
+ ctx.fillStyle = "#ffffff";
169
+ ctx.strokeStyle = "#ffffff";
170
+ ctx.lineWidth = outline;
171
+ /* Letter spacing: native where it exists (Chromium 99+, FF 128+),
172
+ manual elsewhere. typeof keeps this a runtime probe — an `in` check
173
+ would narrow ctx to never (the property is in the type lib). */
174
+ const canTrack = typeof ctx.letterSpacing === "string";
175
+ if (tracking && canTrack)
176
+ ctx.letterSpacing = `${tracking}px`;
177
+ const chars = [...text];
178
+ const manual = tracking > 0 && !canTrack;
179
+ const trackW = manual ? tracking * (chars.length - 1) : 0;
180
+ const m = ctx.measureText(text);
181
+ const inkH = isFinite(m.actualBoundingBoxAscent) && isFinite(m.actualBoundingBoxDescent)
182
+ ? m.actualBoundingBoxAscent + m.actualBoundingBoxDescent
183
+ : size0 * 1.2;
184
+ /* Fit-to-box on both axes: scale the whole drawing (font, stroke,
185
+ tracking) rather than parsing sizes out of arbitrary shorthands.
186
+ Padding leaves the stroke room to breathe at the edges. */
187
+ const padW = Math.min(16, w * 0.06) + outline;
188
+ const padH = Math.min(12, h * 0.06) + outline;
189
+ const fw = m.width + trackW > 0 ? (w - padW) / (m.width + trackW) : 1;
190
+ const fh = inkH > 0 ? (h - padH) / inkH : 1;
191
+ const f = Math.max(0.05, Math.min(1, fw, fh));
192
+ ctx.save();
193
+ ctx.translate(w / 2, h / 2);
194
+ ctx.scale(f, f);
195
+ const paint = () => (outline > 0 ? ctx.strokeText(text, 0, 0) : ctx.fillText(text, 0, 0));
196
+ if (!manual) {
197
+ ctx.textAlign = "center";
198
+ paint();
199
+ }
200
+ else {
201
+ /* Manual tracking: left-align each glyph on a running cursor. */
202
+ const widths = chars.map((c) => ctx.measureText(c).width);
203
+ const total = widths.reduce((a, b) => a + b, 0) + trackW;
204
+ ctx.textAlign = "left";
205
+ let x = -total / 2;
206
+ chars.forEach((c, i) => {
207
+ if (outline > 0)
208
+ ctx.strokeText(c, x, 0);
209
+ else
210
+ ctx.fillText(c, x, 0);
211
+ x += widths[i] + tracking;
212
+ });
213
+ }
214
+ ctx.restore();
215
+ };
216
+ const buildTexture = () => {
217
+ drawText();
218
+ if (texture)
219
+ texture.dispose();
220
+ texture = new THREE.CanvasTexture(texCanvas);
221
+ texture.minFilter = THREE.LinearFilter;
222
+ texture.magFilter = THREE.LinearFilter;
223
+ texture.generateMipmaps = false;
224
+ /* Uniform values are read every render — no material.needsUpdate,
225
+ which would recompile the program on every resize. */
226
+ for (const m of materials) {
227
+ m.uniforms.uMap.value = texture;
228
+ m.uniforms.uAspect.value = w / Math.max(1, h);
229
+ }
230
+ };
231
+ /* ---------------- materials + the three chroma passes ---------------- */
232
+ const passColors = chroma
233
+ ? [new THREE.Color(pass.r, 0, 0), new THREE.Color(0, pass.g, 0), new THREE.Color(0, 0, pass.b)]
234
+ : [pass];
235
+ const passScales = chroma ? [0.9, 1, 1.1] : [1];
236
+ const materials = passColors.map((pc, i) => new THREE.ShaderMaterial({
237
+ vertexShader: VERT,
238
+ fragmentShader: chroma ? CHROMA_FRAG : PLAIN_FRAG,
239
+ uniforms: {
240
+ uMap: { value: null },
241
+ uPass: { value: pc },
242
+ uOpacity: { value: opacity },
243
+ uDispScale: { value: passScales[i] },
244
+ uAspect: { value: w / Math.max(1, h) },
245
+ },
246
+ transparent: true,
247
+ depthTest: false,
248
+ depthWrite: false,
249
+ blending: chroma ? THREE.CustomBlending : THREE.NormalBlending,
250
+ blendSrc: THREE.OneFactor,
251
+ blendDst: THREE.OneFactor,
252
+ blendEquation: THREE.AddEquation,
253
+ }));
254
+ /* ---------------- grid + sim state ---------------- */
255
+ let geometry;
256
+ let meshes = [];
257
+ let disp = new Float32Array(0); // x,y displacement
258
+ let vel = new Float32Array(0); // x,y velocity
259
+ let verts = 0;
260
+ const buildGrid = () => {
261
+ geometry?.dispose();
262
+ for (const m of meshes)
263
+ scene.remove(m);
264
+ const cols = segments > 0 ? Math.round(segments) : Math.min(160, Math.max(40, Math.round(w / 10)));
265
+ const cell = w / cols;
266
+ const rows = Math.min(96, Math.max(8, Math.round(h / cell)));
267
+ /* Half-width space: x spans ±1, y spans ±h/w (isotropic units). */
268
+ geometry = new THREE.PlaneGeometry(2, (2 * h) / w, cols, rows);
269
+ verts = geometry.attributes.position.count;
270
+ disp = new Float32Array(verts * 2);
271
+ vel = new Float32Array(verts * 2);
272
+ const attr = new THREE.BufferAttribute(disp, 2);
273
+ attr.setUsage(THREE.DynamicDrawUsage);
274
+ geometry.setAttribute("aDisp", attr);
275
+ meshes = passColors.map((_, i) => {
276
+ const mesh = new THREE.Mesh(geometry, materials[i]);
277
+ mesh.frustumCulled = false; // the shader moves the verts
278
+ scene.add(mesh);
279
+ return mesh;
280
+ });
281
+ };
282
+ buildTexture();
283
+ buildGrid();
284
+ host.appendChild(canvas);
285
+ /* ---------------- pointer + sim ---------------- */
286
+ const cursor = { x: 0, y: 0 };
287
+ const prevCursor = { x: 0, y: 0 };
288
+ let hasCursor = false;
289
+ let settled = true;
290
+ let needsRender = true;
291
+ let acc = 0;
292
+ const toSim = (cx, cy, rect) => {
293
+ const rw = Math.max(1, rect.width);
294
+ const rh = Math.max(1, rect.height);
295
+ return { x: (cx / rw) * 2 - 1, y: (1 - (cy / rh) * 2) * (rh / rw) };
296
+ };
297
+ const onMove = (e) => {
298
+ const rect = host.getBoundingClientRect();
299
+ const p = toSim(e.clientX - rect.left, e.clientY - rect.top, rect);
300
+ if (!hasCursor) {
301
+ prevCursor.x = p.x; // first sighting: no delta from the origin
302
+ prevCursor.y = p.y;
303
+ hasCursor = true;
304
+ }
305
+ cursor.x = p.x;
306
+ cursor.y = p.y;
307
+ /* Outside the box + reach nothing can move — don't wake the sim. */
308
+ const dx = Math.max(0, Math.abs(p.x) - 1);
309
+ const dy = Math.max(0, Math.abs(p.y) - h / Math.max(1, w));
310
+ if (Math.hypot(dx, dy) < REACH + 0.05)
311
+ settled = false;
312
+ };
313
+ window.addEventListener("pointermove", onMove, { passive: true });
314
+ /* One fixed 1/60 s step — mirrors the reference's transform-feedback
315
+ shader: velocity += drag + spring + push, damping, integrate, clamp. */
316
+ const step = (vx, vy) => {
317
+ const rest = geometry.attributes.position.array;
318
+ const stride = geometry.attributes.position.itemSize; // 3: x,y,z
319
+ let maxD = 0;
320
+ let maxV = 0;
321
+ for (let i = 0; i < verts; i++) {
322
+ const ix = i * 2;
323
+ const iy = ix + 1;
324
+ const rx = i * stride;
325
+ /* cursorToPos: from the cursor to the vertex's current position */
326
+ const ox = rest[rx] + disp[ix] - cursor.x;
327
+ const oy = rest[rx + 1] + disp[iy] - cursor.y;
328
+ const dist = Math.hypot(ox, oy);
329
+ let strength = 1 / (1 + dist / FALLOFF) - FLOOR;
330
+ if (strength <= 0)
331
+ strength = 0;
332
+ else if (strength > 1)
333
+ strength = 1;
334
+ vel[ix] =
335
+ (vel[ix] + vx * DRAG_K * strength * drag - disp[ix] * SPRING + ox * strength * push) * DAMP;
336
+ vel[iy] =
337
+ (vel[iy] + vy * DRAG_K * strength * drag - disp[iy] * SPRING + oy * strength * push) * DAMP;
338
+ disp[ix] += vel[ix] * INTEG;
339
+ disp[iy] += vel[iy] * INTEG;
340
+ disp[ix] = disp[ix] > 1 ? 1 : disp[ix] < -1 ? -1 : disp[ix];
341
+ disp[iy] = disp[iy] > 1 ? 1 : disp[iy] < -1 ? -1 : disp[iy];
342
+ vel[ix] = vel[ix] > 1 ? 1 : vel[ix] < -1 ? -1 : vel[ix];
343
+ vel[iy] = vel[iy] > 1 ? 1 : vel[iy] < -1 ? -1 : vel[iy];
344
+ const ad = Math.abs(disp[ix]) + Math.abs(disp[iy]);
345
+ const av = Math.abs(vel[ix]) + Math.abs(vel[iy]);
346
+ if (ad > maxD)
347
+ maxD = ad;
348
+ if (av > maxV)
349
+ maxV = av;
350
+ }
351
+ /* Asleep only when every vertex is back at rest: strength is 0 beyond
352
+ REACH anyway, so a pointer moving elsewhere can't wake it — onMove
353
+ does that when it comes back within reach. */
354
+ if (maxD < SETTLE_EPS && maxV < SETTLE_EPS)
355
+ settled = true;
356
+ };
357
+ const render = () => {
358
+ geometry.attributes.aDisp.needsUpdate = true;
359
+ renderer.render(scene, camera);
360
+ needsRender = false;
361
+ };
362
+ /* ---------------- visibility gate ---------------- */
363
+ let visible = true;
364
+ let io = null;
365
+ if (typeof IntersectionObserver === "function") {
366
+ io = new IntersectionObserver(([entry]) => {
367
+ const was = visible;
368
+ visible = entry.isIntersecting;
369
+ if (visible && !was)
370
+ needsRender = true;
371
+ }, { rootMargin: "80px" });
372
+ io.observe(host);
373
+ }
374
+ /* ---------------- ticker: frame velocity + fixed-step sim ---------------- */
375
+ const tick = (_t, deltaMs) => {
376
+ let dt = deltaMs / 1000;
377
+ if (!(dt > 0))
378
+ dt = STEP;
379
+ if (dt > 0.2)
380
+ dt = STEP; // a stalled tab folds into one clean step
381
+ /* Pointer velocity is a per-frame quantity: cursor - last frame's.
382
+ Consumed every frame — even off-screen — so a delta accumulated
383
+ while hidden never lands as one phantom impulse on re-entry. */
384
+ let vx = 0;
385
+ let vy = 0;
386
+ if (hasCursor) {
387
+ vx = (cursor.x - prevCursor.x) / dt;
388
+ vy = (cursor.y - prevCursor.y) / dt;
389
+ if (Math.hypot(vx, vy) > V_CLAMP) {
390
+ vx = 0;
391
+ vy = 0;
392
+ }
393
+ prevCursor.x = cursor.x;
394
+ prevCursor.y = cursor.y;
395
+ }
396
+ if (!visible) {
397
+ needsRender = true;
398
+ return;
399
+ }
400
+ if (settled) {
401
+ if (needsRender)
402
+ render();
403
+ return;
404
+ }
405
+ acc += dt;
406
+ let n = Math.floor(acc / STEP);
407
+ if (n > MAX_STEPS)
408
+ n = MAX_STEPS;
409
+ acc -= n * STEP;
410
+ if (n <= 0) {
411
+ if (needsRender)
412
+ render();
413
+ return;
414
+ }
415
+ for (let i = 0; i < n; i++)
416
+ step(vx, vy);
417
+ render();
418
+ };
419
+ gsap.ticker.add(tick);
420
+ /* ---------------- resize ---------------- */
421
+ let ro = null;
422
+ const resize = () => {
423
+ const rw = Math.max(1, host.clientWidth);
424
+ const rh = Math.max(1, host.clientHeight);
425
+ if (rw === w && rh === h)
426
+ return;
427
+ w = rw;
428
+ h = rh;
429
+ renderer.setSize(w, h, false);
430
+ buildTexture();
431
+ buildGrid();
432
+ settled = false;
433
+ needsRender = true;
434
+ };
435
+ /* ResizeObserver alone: a vw-sized host reflows on window resize too,
436
+ so the box change is always what actually needs the rebuild. */
437
+ if (typeof ResizeObserver === "function") {
438
+ ro = new ResizeObserver(resize);
439
+ ro.observe(host);
440
+ }
441
+ render(); // the rest state, before the pointer ever arrives
442
+ /* ---------------- teardown ---------------- */
443
+ return () => {
444
+ gsap.ticker.remove(tick);
445
+ window.removeEventListener("pointermove", onMove);
446
+ io?.disconnect();
447
+ ro?.disconnect();
448
+ for (const m of meshes)
449
+ scene.remove(m);
450
+ geometry.dispose();
451
+ for (const m of materials)
452
+ m.dispose();
453
+ texture?.dispose();
454
+ renderer.dispose();
455
+ canvas.remove();
456
+ host.style.color = prevColor;
457
+ host.style.position = prevPosition;
458
+ };
459
+ });
460
+ }
461
+ //# sourceMappingURL=wordmark-wave.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wordmark-wave.js","sourceRoot":"","sources":["../../src/three/wordmark-wave.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmictraveler002/anim-kit",
3
- "version": "1.4.0",
3
+ "version": "1.6.0",
4
4
  "description": "Modular, framework-agnostic animation library — GSAP + ScrollTrigger + Lenis effects packaged as composable ES modules.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -4,10 +4,14 @@
4
4
  * Uses the canonical Lenis + GSAP recipe:
5
5
  * lenis.on("scroll", ScrollTrigger.update)
6
6
  * gsap.ticker.add(t => lenis.raf(t * 1000))
7
- * gsap.ticker.lagSmoothing(0)
8
7
  *
9
8
  * Driving Lenis from GSAP's ticker (rather than its own rAF) keeps both
10
9
  * clocks on the same frame, which is what stops ScrollTrigger from stuttering.
10
+ * Those ticker callbacks receive the *same* adjusted clock the tweens run on,
11
+ * so GSAP's lag smoothing is deliberately left on: a stalled frame (GC pause,
12
+ * buffer tick) advances one short step everywhere instead of snapping the
13
+ * scroll and every scroll-linked tween to a new time at once. See
14
+ * SmoothScrollOptions.lagSmoothing to retune it or restore the old opt-out.
11
15
  *
12
16
  * `useScrollerProxy: true` additionally proxies `document.documentElement`,
13
17
  * matching kalakritico.in's setup — only needed if you scroll a nested
@@ -31,6 +35,27 @@ export interface SmoothScrollOptions extends CommonOptions {
31
35
  initialScroll?: number;
32
36
  /** Proxy documentElement through ScrollTrigger (nested scrollers). @default false */
33
37
  useScrollerProxy?: boolean;
38
+ /** Touch-drag sensitivity — forwarded to Lenis `touchMultiplier`. @default 1 */
39
+ touchMultiplier?: number;
40
+ /** Mouse-wheel sensitivity — forwarded to Lenis `wheelMultiplier`. @default 1 */
41
+ wheelMultiplier?: number;
42
+ /**
43
+ * GSAP lag smoothing on the shared ticker: a frame longer than `threshold`
44
+ * advances only `adjustedLag` ms, so a hitch can't teleport the scroll and
45
+ * every scroll-linked tween in one jump.
46
+ *
47
+ * - `undefined` — leave GSAP's setup alone; its built-in compensation
48
+ * (500ms → 33ms) stays active.
49
+ * - `false` — disable lag smoothing (anim-kit ≤1.4 behaviour, what the
50
+ * Lenis README recipe asks for): timing stays exactly wall-clock, but
51
+ * every frame longer than the threshold snaps.
52
+ * - `{ threshold, adjustedLag }` — retune it. Lower the threshold (e.g.
53
+ * `150`) to smooth short mobile hitches; raise it if slow devices should
54
+ * keep real-time speed instead of briefly running slow-motion.
55
+ *
56
+ * `destroy()` restores GSAP's default (500/33) whenever this was set.
57
+ */
58
+ lagSmoothing?: false | { threshold?: number; adjustedLag?: number };
34
59
  }
35
60
 
36
61
  export interface SmoothScrollHandle {
@@ -61,6 +86,9 @@ export function smoothScroll(options: SmoothScrollOptions = {}): SmoothScrollHan
61
86
  orientation = "vertical",
62
87
  initialScroll = 0,
63
88
  useScrollerProxy = false,
89
+ touchMultiplier,
90
+ wheelMultiplier,
91
+ lagSmoothing,
64
92
  } = options;
65
93
 
66
94
  if (typeof window === "undefined") return INERT;
@@ -74,6 +102,9 @@ export function smoothScroll(options: SmoothScrollOptions = {}): SmoothScrollHan
74
102
  syncTouch: smoothTouch,
75
103
  orientation,
76
104
  autoRaf: false,
105
+ // undefined falls through to Lenis's own defaults (1 / 1).
106
+ touchMultiplier,
107
+ wheelMultiplier,
77
108
  });
78
109
 
79
110
  if (initialScroll) lenis.scrollTo(initialScroll, { immediate: true });
@@ -85,7 +116,17 @@ export function smoothScroll(options: SmoothScrollOptions = {}): SmoothScrollHan
85
116
  // 2. Run Lenis off GSAP's ticker so both share one frame clock.
86
117
  const tick = (time: number) => lenis.raf(time * 1000);
87
118
  gsap.ticker.add(tick);
88
- gsap.ticker.lagSmoothing(0);
119
+
120
+ // Lag smoothing drives *one* clock — the tweens' and this ticker's alike —
121
+ // so leaving GSAP's compensation on turns a stalled frame into one short
122
+ // step everywhere instead of a snap. Only touch the ticker when asked, so a
123
+ // host page's own setup is never clobbered.
124
+ let lagTouched = false;
125
+ if (lagSmoothing !== undefined) {
126
+ lagTouched = true;
127
+ if (lagSmoothing === false) gsap.ticker.lagSmoothing(0);
128
+ else gsap.ticker.lagSmoothing(lagSmoothing.threshold ?? 500, lagSmoothing.adjustedLag ?? 33);
129
+ }
89
130
 
90
131
  // 3. Optional: proxy the scroller (for nested/element scrollers).
91
132
  if (useScrollerProxy) {
@@ -126,6 +167,7 @@ export function smoothScroll(options: SmoothScrollOptions = {}): SmoothScrollHan
126
167
  window.removeEventListener("resize", onResize);
127
168
  window.removeEventListener("load", refresh);
128
169
  gsap.ticker.remove(tick);
170
+ if (lagTouched) gsap.ticker.lagSmoothing(500, 33); // undo our change — GSAP's default
129
171
  lenis.off("scroll", onScroll);
130
172
  if (useScrollerProxy) {
131
173
  ScrollTrigger.scrollerProxy(document.documentElement, {} as never);
@@ -68,6 +68,9 @@ export function horizontalScroll(
68
68
  scrollTrigger: {
69
69
  trigger: section,
70
70
  pin: true,
71
+ // Refresh pins first (creation order ≠ document order): our spacer must
72
+ // exist before triggers below us measure, or they start ~9k px early.
73
+ refreshPriority: 1,
71
74
  scrub,
72
75
  end: () => "+=" + travel(),
73
76
  invalidateOnRefresh: true,