solid-drift 0.2.0 → 0.7.1
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/README.md +735 -10
- package/dist/animate.d.ts +2 -2
- package/dist/animate.js +2 -2
- package/dist/cartoon.d.ts +190 -0
- package/dist/cartoon.js +334 -0
- package/dist/color.d.ts +53 -0
- package/dist/color.js +391 -0
- package/dist/directive.d.ts +5 -5
- package/dist/directive.js +15 -7
- package/dist/easing.d.ts +22 -1
- package/dist/easing.js +49 -1
- package/dist/flip.d.ts +44 -0
- package/dist/flip.js +108 -0
- package/dist/horizontal.d.ts +107 -0
- package/dist/horizontal.js +208 -0
- package/dist/index.d.ts +16 -3
- package/dist/index.js +15 -3
- package/dist/inview.d.ts +4 -4
- package/dist/inview.js +5 -5
- package/dist/motion.d.ts +327 -0
- package/dist/motion.js +729 -0
- package/dist/physics.d.ts +146 -0
- package/dist/physics.js +352 -0
- package/dist/pointer.d.ts +76 -0
- package/dist/pointer.js +123 -0
- package/dist/reduced-motion.d.ts +3 -3
- package/dist/reduced-motion.js +5 -4
- package/dist/scroll.d.ts +3 -3
- package/dist/scroll.js +5 -5
- package/dist/scrollfx.d.ts +156 -0
- package/dist/scrollfx.js +148 -0
- package/dist/scrub.d.ts +51 -0
- package/dist/scrub.js +67 -0
- package/dist/spring.d.ts +39 -4
- package/dist/spring.js +26 -7
- package/dist/stagger.d.ts +4 -4
- package/dist/stagger.js +4 -4
- package/dist/timeline.d.ts +45 -0
- package/dist/timeline.js +93 -0
- package/dist/trail.d.ts +27 -0
- package/dist/trail.js +75 -0
- package/dist/tween.d.ts +3 -3
- package/dist/tween.js +3 -3
- package/dist/typography.d.ts +241 -0
- package/dist/typography.js +812 -0
- package/dist/velocity.d.ts +44 -0
- package/dist/velocity.js +88 -0
- package/package.json +1 -1
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type Accessor } from "solid-js";
|
|
2
|
+
import { type AnimateOptions } from "./animate.js";
|
|
3
|
+
export interface TimelineStep extends AnimateOptions {
|
|
4
|
+
/** Start value of this step. */
|
|
5
|
+
from: number;
|
|
6
|
+
/** End value of this step. */
|
|
7
|
+
to: number;
|
|
8
|
+
}
|
|
9
|
+
export type TimelineStatus = "idle" | "running" | "done";
|
|
10
|
+
export interface TimelineControls {
|
|
11
|
+
/** Play every step in order. Resolves when the last step completes. */
|
|
12
|
+
start: () => Promise<void>;
|
|
13
|
+
/** Stop the timeline wherever it is. The start() promise resolves. */
|
|
14
|
+
stop: () => void;
|
|
15
|
+
/** Stop and play again from the first step. */
|
|
16
|
+
replay: () => Promise<void>;
|
|
17
|
+
/** Reactive status: "idle" | "running" | "done". */
|
|
18
|
+
status: Accessor<TimelineStatus>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Plays a sequence of one-shot animations back to back.
|
|
22
|
+
*
|
|
23
|
+
* Each step is an `animate()` call: `from`/`to` plus duration, delay,
|
|
24
|
+
* easing, and `onUpdate`. Steps run strictly in order, so one step's
|
|
25
|
+
* `onUpdate` can drive one element while the next step drives another,
|
|
26
|
+
* building choreographed entrances without nested callbacks.
|
|
27
|
+
*
|
|
28
|
+
* `stop()` halts mid-step and resolves the in-flight `start()` promise.
|
|
29
|
+
* `replay()` restarts from the first step. The timeline also stops
|
|
30
|
+
* itself on cleanup.
|
|
31
|
+
*
|
|
32
|
+
* Under reduced motion every step jumps straight to its end value (each
|
|
33
|
+
* step's `onUpdate(to)` still runs, so the final state is always
|
|
34
|
+
* correct). SSR-safe: steps apply their end values instantly.
|
|
35
|
+
*
|
|
36
|
+
* ```ts
|
|
37
|
+
* const intro = createTimeline([
|
|
38
|
+
* { from: 0, to: 1, duration: 400, onUpdate: (v) => (title.style.opacity = String(v)) },
|
|
39
|
+
* { from: 24, to: 0, duration: 500, easing: "easeOutExpo", onUpdate: (v) => (title.style.transform = `translateY(${v}px)`) },
|
|
40
|
+
* { from: 0, to: 1, duration: 300, onUpdate: (v) => (cta.style.opacity = String(v)) },
|
|
41
|
+
* ])
|
|
42
|
+
* await intro.start()
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function createTimeline(steps: TimelineStep[]): TimelineControls;
|
package/dist/timeline.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { createSignal, onCleanup } from "solid-js";
|
|
2
|
+
import { animate, } from "./animate.js";
|
|
3
|
+
/**
|
|
4
|
+
* Plays a sequence of one-shot animations back to back.
|
|
5
|
+
*
|
|
6
|
+
* Each step is an `animate()` call: `from`/`to` plus duration, delay,
|
|
7
|
+
* easing, and `onUpdate`. Steps run strictly in order, so one step's
|
|
8
|
+
* `onUpdate` can drive one element while the next step drives another,
|
|
9
|
+
* building choreographed entrances without nested callbacks.
|
|
10
|
+
*
|
|
11
|
+
* `stop()` halts mid-step and resolves the in-flight `start()` promise.
|
|
12
|
+
* `replay()` restarts from the first step. The timeline also stops
|
|
13
|
+
* itself on cleanup.
|
|
14
|
+
*
|
|
15
|
+
* Under reduced motion every step jumps straight to its end value (each
|
|
16
|
+
* step's `onUpdate(to)` still runs, so the final state is always
|
|
17
|
+
* correct). SSR-safe: steps apply their end values instantly.
|
|
18
|
+
*
|
|
19
|
+
* ```ts
|
|
20
|
+
* const intro = createTimeline([
|
|
21
|
+
* { from: 0, to: 1, duration: 400, onUpdate: (v) => (title.style.opacity = String(v)) },
|
|
22
|
+
* { from: 24, to: 0, duration: 500, easing: "easeOutExpo", onUpdate: (v) => (title.style.transform = `translateY(${v}px)`) },
|
|
23
|
+
* { from: 0, to: 1, duration: 300, onUpdate: (v) => (cta.style.opacity = String(v)) },
|
|
24
|
+
* ])
|
|
25
|
+
* await intro.start()
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export function createTimeline(steps) {
|
|
29
|
+
const [status, setStatus] = createSignal("idle");
|
|
30
|
+
let current = null;
|
|
31
|
+
let runToken = 0;
|
|
32
|
+
const play = async () => {
|
|
33
|
+
const token = ++runToken;
|
|
34
|
+
const alive = () => token === runToken;
|
|
35
|
+
setStatus("running");
|
|
36
|
+
for (const step of steps) {
|
|
37
|
+
if (!alive())
|
|
38
|
+
break;
|
|
39
|
+
const { from, to, ...options } = step;
|
|
40
|
+
if (typeof window === "undefined") {
|
|
41
|
+
options.onUpdate?.(to);
|
|
42
|
+
options.onComplete?.();
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
await new Promise((resolve) => {
|
|
46
|
+
// Declared before animate() runs: under reduced motion animate()
|
|
47
|
+
// calls onComplete synchronously, before its return value exists.
|
|
48
|
+
// The completed flag keeps `current` from pointing at a control
|
|
49
|
+
// that already finished in that synchronous path.
|
|
50
|
+
let stepControls = null;
|
|
51
|
+
let completed = false;
|
|
52
|
+
stepControls = animate(from, to, {
|
|
53
|
+
...options,
|
|
54
|
+
onComplete: () => {
|
|
55
|
+
completed = true;
|
|
56
|
+
options.onComplete?.();
|
|
57
|
+
if (current === stepControls)
|
|
58
|
+
current = null;
|
|
59
|
+
resolve();
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
if (!completed)
|
|
63
|
+
current = stepControls;
|
|
64
|
+
// `finished` also resolves when the step is stopped, which
|
|
65
|
+
// unblocks the chain, the alive() check then ends the run.
|
|
66
|
+
void stepControls.finished.then(() => {
|
|
67
|
+
if (current === stepControls)
|
|
68
|
+
current = null;
|
|
69
|
+
resolve();
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
if (alive())
|
|
74
|
+
setStatus("done");
|
|
75
|
+
};
|
|
76
|
+
const stop = () => {
|
|
77
|
+
runToken++;
|
|
78
|
+
current?.stop();
|
|
79
|
+
current = null;
|
|
80
|
+
setStatus("idle");
|
|
81
|
+
};
|
|
82
|
+
const controls = {
|
|
83
|
+
start: () => play(),
|
|
84
|
+
stop,
|
|
85
|
+
replay: () => {
|
|
86
|
+
stop();
|
|
87
|
+
return play();
|
|
88
|
+
},
|
|
89
|
+
status,
|
|
90
|
+
};
|
|
91
|
+
onCleanup(stop);
|
|
92
|
+
return controls;
|
|
93
|
+
}
|
package/dist/trail.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type Accessor } from "solid-js";
|
|
2
|
+
export interface TrailOptions {
|
|
3
|
+
/** How far behind the source the trail follows, in ms. Default 120. */
|
|
4
|
+
delay?: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* A signal that replays another signal's past: it returns the value the
|
|
8
|
+
* source had `delay` milliseconds ago, interpolated between samples.
|
|
9
|
+
*
|
|
10
|
+
* Chain trails off one source for follower effects (a cursor with a
|
|
11
|
+
* comet tail, cascading highlights), or trail a scroll progress for a
|
|
12
|
+
* delayed echo of the page. The trail catches up and parks exactly on
|
|
13
|
+
* the latest value when the source rests.
|
|
14
|
+
*
|
|
15
|
+
* The follow loop runs on the shared clock only while the trail is
|
|
16
|
+
* behind: it starts when the source changes and stops once caught up.
|
|
17
|
+
*
|
|
18
|
+
* SSR-safe: returns the source itself on the server. Under reduced
|
|
19
|
+
* motion it also returns the source directly (no trailing motion).
|
|
20
|
+
*
|
|
21
|
+
* ```tsx
|
|
22
|
+
* const [tab, setTab] = createSignal(0)
|
|
23
|
+
* // The indicator glides behind the selection instead of jumping.
|
|
24
|
+
* const ghost = createTrail(tab, { delay: 150 })
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function createTrail(source: Accessor<number>, options?: TrailOptions): Accessor<number>;
|
package/dist/trail.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { createEffect, createSignal, onCleanup, untrack, } from "solid-js";
|
|
2
|
+
import { now, schedule } from "./engine.js";
|
|
3
|
+
import { prefersReducedMotion } from "./reduced-motion.js";
|
|
4
|
+
/**
|
|
5
|
+
* A signal that replays another signal's past: it returns the value the
|
|
6
|
+
* source had `delay` milliseconds ago, interpolated between samples.
|
|
7
|
+
*
|
|
8
|
+
* Chain trails off one source for follower effects (a cursor with a
|
|
9
|
+
* comet tail, cascading highlights), or trail a scroll progress for a
|
|
10
|
+
* delayed echo of the page. The trail catches up and parks exactly on
|
|
11
|
+
* the latest value when the source rests.
|
|
12
|
+
*
|
|
13
|
+
* The follow loop runs on the shared clock only while the trail is
|
|
14
|
+
* behind: it starts when the source changes and stops once caught up.
|
|
15
|
+
*
|
|
16
|
+
* SSR-safe: returns the source itself on the server. Under reduced
|
|
17
|
+
* motion it also returns the source directly (no trailing motion).
|
|
18
|
+
*
|
|
19
|
+
* ```tsx
|
|
20
|
+
* const [tab, setTab] = createSignal(0)
|
|
21
|
+
* // The indicator glides behind the selection instead of jumping.
|
|
22
|
+
* const ghost = createTrail(tab, { delay: 150 })
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export function createTrail(source, options = {}) {
|
|
26
|
+
const { delay = 120 } = options;
|
|
27
|
+
if (typeof window === "undefined" || prefersReducedMotion() || delay <= 0) {
|
|
28
|
+
return source;
|
|
29
|
+
}
|
|
30
|
+
const [value, setValue] = createSignal(untrack(source));
|
|
31
|
+
const samples = [
|
|
32
|
+
[now(), untrack(source)],
|
|
33
|
+
];
|
|
34
|
+
let cancel = null;
|
|
35
|
+
const tick = (t) => {
|
|
36
|
+
const target = t - delay;
|
|
37
|
+
// Drop samples the trail has already passed (keep one for context).
|
|
38
|
+
while (samples.length > 2 && samples[1][0] <= target)
|
|
39
|
+
samples.shift();
|
|
40
|
+
const [firstT, firstV] = samples[0];
|
|
41
|
+
const [lastT, lastV] = samples[samples.length - 1];
|
|
42
|
+
let current;
|
|
43
|
+
if (samples.length === 1 || target <= firstT) {
|
|
44
|
+
current = firstV;
|
|
45
|
+
}
|
|
46
|
+
else if (target >= lastT) {
|
|
47
|
+
current = lastV;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
const [ta, va] = samples[0];
|
|
51
|
+
const [tb, vb] = samples[1];
|
|
52
|
+
const p = (target - ta) / Math.max(tb - ta, 0.0001);
|
|
53
|
+
current = va + (vb - va) * p;
|
|
54
|
+
}
|
|
55
|
+
setValue(current);
|
|
56
|
+
if (target >= lastT) {
|
|
57
|
+
cancel = null; // caught up: park exactly on the latest value
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
return true;
|
|
61
|
+
};
|
|
62
|
+
const kick = () => {
|
|
63
|
+
if (!cancel)
|
|
64
|
+
cancel = schedule(tick);
|
|
65
|
+
};
|
|
66
|
+
createEffect(() => {
|
|
67
|
+
const v = source();
|
|
68
|
+
samples.push([now(), v]);
|
|
69
|
+
if (samples.length > 600)
|
|
70
|
+
samples.splice(0, samples.length - 600);
|
|
71
|
+
kick();
|
|
72
|
+
});
|
|
73
|
+
onCleanup(() => cancel?.());
|
|
74
|
+
return value;
|
|
75
|
+
}
|
package/dist/tween.d.ts
CHANGED
|
@@ -13,11 +13,11 @@ export interface TweenOptions {
|
|
|
13
13
|
/**
|
|
14
14
|
* A signal that tweens toward a source signal's value over a fixed duration.
|
|
15
15
|
*
|
|
16
|
-
* Interrupting mid-tween retargets from the current value
|
|
16
|
+
* Interrupting mid-tween retargets from the current value, with no snapping.
|
|
17
17
|
*
|
|
18
18
|
* ```tsx
|
|
19
|
-
* const [open, setOpen] = createSignal(false)
|
|
20
|
-
* const opacity = createTween(() => (open() ? 1 : 0), { duration: 250 })
|
|
19
|
+
* const [open, setOpen] = createSignal(false)
|
|
20
|
+
* const opacity = createTween(() => (open() ? 1 : 0), { duration: 250 })
|
|
21
21
|
* <div style={{ opacity: opacity() }} />
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
package/dist/tween.js
CHANGED
|
@@ -5,11 +5,11 @@ import { prefersReducedMotion } from "./reduced-motion.js";
|
|
|
5
5
|
/**
|
|
6
6
|
* A signal that tweens toward a source signal's value over a fixed duration.
|
|
7
7
|
*
|
|
8
|
-
* Interrupting mid-tween retargets from the current value
|
|
8
|
+
* Interrupting mid-tween retargets from the current value, with no snapping.
|
|
9
9
|
*
|
|
10
10
|
* ```tsx
|
|
11
|
-
* const [open, setOpen] = createSignal(false)
|
|
12
|
-
* const opacity = createTween(() => (open() ? 1 : 0), { duration: 250 })
|
|
11
|
+
* const [open, setOpen] = createSignal(false)
|
|
12
|
+
* const opacity = createTween(() => (open() ? 1 : 0), { duration: 250 })
|
|
13
13
|
* <div style={{ opacity: opacity() }} />
|
|
14
14
|
* ```
|
|
15
15
|
*/
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { type Accessor } from "solid-js";
|
|
2
|
+
import { type Easing, type EasingName } from "./easing.js";
|
|
3
|
+
type MaybeElement = () => Element | null | undefined;
|
|
4
|
+
export interface FontSwapOptions {
|
|
5
|
+
/** Font family to swap to on hover. */
|
|
6
|
+
to: string;
|
|
7
|
+
/** Font weight to swap to. Defaults to keeping the current weight. */
|
|
8
|
+
toWeight?: string | number;
|
|
9
|
+
/** Duration in ms for each half of the letter roll. Default 160. */
|
|
10
|
+
duration?: number;
|
|
11
|
+
/** Stagger in ms between letters. Default 24. */
|
|
12
|
+
stagger?: number;
|
|
13
|
+
/** Easing for the roll. Default "easeInOutCubic". */
|
|
14
|
+
easing?: Easing | EasingName;
|
|
15
|
+
/** On touch devices (no hover) a tap toggles the swap. Default true. */
|
|
16
|
+
tapToToggle?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface FontSwapResult {
|
|
19
|
+
/** True while the swapped font is showing. */
|
|
20
|
+
swapped: Accessor<boolean>;
|
|
21
|
+
/** Swap to the alternate font (true) or back (false). */
|
|
22
|
+
swap: (to: boolean) => void;
|
|
23
|
+
/** Toggle between the two fonts. */
|
|
24
|
+
toggle: () => void;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Swap a heading's font family (and optionally weight) on hover with a
|
|
28
|
+
* per-letter roll: each letter flips away in the old font and lands in the
|
|
29
|
+
* new one. Because the letters roll individually, the metric change never
|
|
30
|
+
* reads as a layout jump.
|
|
31
|
+
*
|
|
32
|
+
* On touch devices a tap toggles the swap instead of hover. Under reduced
|
|
33
|
+
* motion the font swaps instantly with no roll.
|
|
34
|
+
*/
|
|
35
|
+
export declare function createFontSwap(ref: MaybeElement, options: FontSwapOptions): FontSwapResult;
|
|
36
|
+
export interface TypingOptions {
|
|
37
|
+
/** Text to type. Defaults to the element's current text. */
|
|
38
|
+
text?: string;
|
|
39
|
+
/** Base milliseconds per character. Default 45. */
|
|
40
|
+
speed?: number;
|
|
41
|
+
/** Randomness 0..1 added to each character's timing. Default 0.4. */
|
|
42
|
+
variance?: number;
|
|
43
|
+
/** Extra pause in ms after specific characters. */
|
|
44
|
+
pauses?: Record<string, number>;
|
|
45
|
+
/** Cursor glyph. Set to "" for no cursor. Default "|". */
|
|
46
|
+
cursor?: string;
|
|
47
|
+
/** Cursor blink period in ms. Default 530. */
|
|
48
|
+
blinkRate?: number;
|
|
49
|
+
/** Start typing as soon as the element is available. Default true. */
|
|
50
|
+
autostart?: boolean;
|
|
51
|
+
/** Called when typing completes. */
|
|
52
|
+
onComplete?: () => void;
|
|
53
|
+
}
|
|
54
|
+
export interface TypingResult {
|
|
55
|
+
/** Start typing from the beginning. */
|
|
56
|
+
start: () => void;
|
|
57
|
+
/** Type again from an empty element. */
|
|
58
|
+
replay: () => void;
|
|
59
|
+
/** Stop typing where it is. */
|
|
60
|
+
stop: () => void;
|
|
61
|
+
/** True while characters are being typed. */
|
|
62
|
+
typing: Accessor<boolean>;
|
|
63
|
+
/** True once the full text is showing. */
|
|
64
|
+
completed: Accessor<boolean>;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Type out text character by character with human-like variable speed:
|
|
68
|
+
* each character's delay jitters around the base speed, and punctuation
|
|
69
|
+
* from `pauses` gets a beat of its own. A blinking block cursor rides
|
|
70
|
+
* along and parks itself when the text is done.
|
|
71
|
+
*
|
|
72
|
+
* Under reduced motion (or on the server) the full text appears instantly.
|
|
73
|
+
*/
|
|
74
|
+
export declare function createTyping(ref: MaybeElement, options?: TypingOptions): TypingResult;
|
|
75
|
+
export interface TextPhysicsOptions {
|
|
76
|
+
/** How far above their slots (px) letters start falling. Default 320. */
|
|
77
|
+
dropHeight?: number;
|
|
78
|
+
/** Gravity in px/s^2. Default 2600. */
|
|
79
|
+
gravity?: number;
|
|
80
|
+
/** Bounciness 0..1 on each bounce. Default 0.45. */
|
|
81
|
+
bounciness?: number;
|
|
82
|
+
/** Max initial tumble in degrees. Default 200. */
|
|
83
|
+
tumble?: number;
|
|
84
|
+
/** Stagger in ms between letters. Default 45. */
|
|
85
|
+
stagger?: number;
|
|
86
|
+
/** Bounce speed below which a letter settles. Default 60. */
|
|
87
|
+
restThreshold?: number;
|
|
88
|
+
/** Called when every letter has settled. */
|
|
89
|
+
onSettle?: () => void;
|
|
90
|
+
}
|
|
91
|
+
export interface TextPhysicsResult {
|
|
92
|
+
/** Rain the letters in: they fall, tumble, bounce, and settle into place. */
|
|
93
|
+
drop: () => void;
|
|
94
|
+
/** Fling the letters apart so they can rain again. */
|
|
95
|
+
scatter: () => void;
|
|
96
|
+
/** True once every letter has settled. */
|
|
97
|
+
settled: Accessor<boolean>;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Per-letter cartoon physics: `drop()` rains each letter from above with
|
|
101
|
+
* gravity, tumbling rotation, and squashy bounces until every letter lands
|
|
102
|
+
* in its slot. `scatter()` flings the letters apart so they can rain again.
|
|
103
|
+
*
|
|
104
|
+
* Pair it with `createInView` to rain a headline in as it scrolls into view.
|
|
105
|
+
* Under reduced motion (or on the server) letters simply sit in place.
|
|
106
|
+
*/
|
|
107
|
+
export declare function createTextPhysics(ref: MaybeElement, options?: TextPhysicsOptions): TextPhysicsResult;
|
|
108
|
+
export interface TextTunnelOptions {
|
|
109
|
+
/** What drives the zoom: "time", "scroll", or your own 0..1 signal. Default "time". */
|
|
110
|
+
drive?: "time" | "scroll" | Accessor<number>;
|
|
111
|
+
/** Seconds per zoom cycle (time drive). Default 3. */
|
|
112
|
+
period?: number;
|
|
113
|
+
/** Number of depth layers. Default 6. */
|
|
114
|
+
layers?: number;
|
|
115
|
+
/** Scale of the front layer. Default 3. */
|
|
116
|
+
zoom?: number;
|
|
117
|
+
}
|
|
118
|
+
export interface TextTunnelResult {
|
|
119
|
+
/** The current 0..1 zoom phase. */
|
|
120
|
+
progress: Accessor<number>;
|
|
121
|
+
/** Stop a time-driven tunnel. */
|
|
122
|
+
stop: () => void;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* An infinite 3D text tunnel: copies of the text at staggered depths zoom
|
|
126
|
+
* toward the viewer forever, each fading in from the distance and out past
|
|
127
|
+
* the camera. Drive it with time, with scroll progress, or with your own
|
|
128
|
+
* 0..1 signal.
|
|
129
|
+
*
|
|
130
|
+
* Under reduced motion (or on the server) the text renders as a single
|
|
131
|
+
* static line.
|
|
132
|
+
*/
|
|
133
|
+
export declare function createTextTunnel(ref: MaybeElement, options?: TextTunnelOptions): TextTunnelResult;
|
|
134
|
+
export interface TextCutoutOptions {
|
|
135
|
+
/**
|
|
136
|
+
* "gradient": an animated inner world clipped inside the letterforms.
|
|
137
|
+
* "window": transparent fill with a stroked outline, made to overlay a
|
|
138
|
+
* live scene (canvas, video, 3D) so it shows through the letters.
|
|
139
|
+
* Default "gradient".
|
|
140
|
+
*/
|
|
141
|
+
mode?: "gradient" | "window";
|
|
142
|
+
/** 0..1 signal driving the inner world. Defaults to a slow time drift. */
|
|
143
|
+
progress?: Accessor<number>;
|
|
144
|
+
/** The three colors of the inner world. */
|
|
145
|
+
palette?: [string, string, string];
|
|
146
|
+
/** Stroke color for "window" mode. Default "currentColor". */
|
|
147
|
+
stroke?: string;
|
|
148
|
+
/** Stroke width in px for "window" mode. Default 1.5. */
|
|
149
|
+
strokeWidth?: number;
|
|
150
|
+
/** Seconds per drift cycle (time drive). Default 9. */
|
|
151
|
+
period?: number;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Turn text into letter-shaped windows onto another world. In "gradient"
|
|
155
|
+
* mode an animated nebula drifts behind the letterforms via
|
|
156
|
+
* background-clip. In "window" mode the fill goes transparent with a
|
|
157
|
+
* stroked outline: overlay it on a canvas, video, or 3D scene and the live
|
|
158
|
+
* scene shows through the letters themselves.
|
|
159
|
+
*/
|
|
160
|
+
export declare function createTextCutout(ref: MaybeElement, options?: TextCutoutOptions): {
|
|
161
|
+
stop: () => void;
|
|
162
|
+
};
|
|
163
|
+
export interface TextGradientOptions {
|
|
164
|
+
/** 0..1 signal driving the hue cycle. Defaults to a slow time loop. */
|
|
165
|
+
progress?: Accessor<number>;
|
|
166
|
+
/** Hue degrees spread across the string. Default 140. */
|
|
167
|
+
spread?: number;
|
|
168
|
+
/** Base hue. Default 210. */
|
|
169
|
+
hue?: number;
|
|
170
|
+
/** Saturation percent. Default 85. */
|
|
171
|
+
saturation?: number;
|
|
172
|
+
/** Lightness percent. Default 62. */
|
|
173
|
+
lightness?: number;
|
|
174
|
+
/** Seconds per full hue cycle (time drive). Default 7. */
|
|
175
|
+
period?: number;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Paint each character its own hue and cycle the rainbow across the text:
|
|
179
|
+
* the hue shifts along the string by `spread` degrees and the whole cycle
|
|
180
|
+
* rotates over time (or with your own progress signal, e.g. scroll).
|
|
181
|
+
* Under reduced motion the gradient parks on its first frame.
|
|
182
|
+
*/
|
|
183
|
+
export declare function createTextGradient(ref: MaybeElement, options?: TextGradientOptions): {
|
|
184
|
+
stop: () => void;
|
|
185
|
+
};
|
|
186
|
+
export interface TextScrambleOptions {
|
|
187
|
+
/** Text to reveal. Defaults to the element's current text. */
|
|
188
|
+
text?: string;
|
|
189
|
+
/** Glyph pool the letters scramble through. */
|
|
190
|
+
charset?: string;
|
|
191
|
+
/** Stagger in ms between characters starting. Default 28. */
|
|
192
|
+
stagger?: number;
|
|
193
|
+
/** How long in ms each character scrambles before locking in. Default 500. */
|
|
194
|
+
duration?: number;
|
|
195
|
+
/** Milliseconds between glyph swaps. Default 50. */
|
|
196
|
+
frameRate?: number;
|
|
197
|
+
/** Start as soon as the element is available. Default true. */
|
|
198
|
+
autostart?: boolean;
|
|
199
|
+
/** Called when every character has locked in. */
|
|
200
|
+
onComplete?: () => void;
|
|
201
|
+
}
|
|
202
|
+
export interface TextScrambleResult {
|
|
203
|
+
/** Start the decode from the beginning. */
|
|
204
|
+
start: () => void;
|
|
205
|
+
/** Run the decode again. */
|
|
206
|
+
replay: () => void;
|
|
207
|
+
/** Stop mid-decode. */
|
|
208
|
+
stop: () => void;
|
|
209
|
+
/** True while glyphs are still resolving. */
|
|
210
|
+
scrambling: Accessor<boolean>;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* A decoder-ring text reveal: every character cycles through random glyphs
|
|
214
|
+
* and locks into its final letter left to right, like a combination lock
|
|
215
|
+
* finding its code. Spaces resolve instantly.
|
|
216
|
+
*
|
|
217
|
+
* Under reduced motion (or on the server) the full text appears instantly.
|
|
218
|
+
*/
|
|
219
|
+
export declare function createTextScramble(ref: MaybeElement, options?: TextScrambleOptions): TextScrambleResult;
|
|
220
|
+
export interface TextWaveOptions {
|
|
221
|
+
/** Wave height in px. Default 9. */
|
|
222
|
+
amplitude?: number;
|
|
223
|
+
/** Characters per full wave. Default 7. */
|
|
224
|
+
wavelength?: number;
|
|
225
|
+
/** Seconds per wave cycle. Default 1.8. */
|
|
226
|
+
period?: number;
|
|
227
|
+
/** Tilt each character with the wave slope. Default true. */
|
|
228
|
+
tilt?: boolean;
|
|
229
|
+
/** 0..1 signal driving the phase (e.g. scroll). Defaults to time. */
|
|
230
|
+
progress?: Accessor<number>;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* A traveling sine wave across the text: each character bobs up and down
|
|
234
|
+
* (and tilts with the slope) as the wave passes through. Drive it with
|
|
235
|
+
* time for an ambient shimmer or with scroll progress for a wave that
|
|
236
|
+
* moves as you scroll. Under reduced motion the text sits still.
|
|
237
|
+
*/
|
|
238
|
+
export declare function createTextWave(ref: MaybeElement, options?: TextWaveOptions): {
|
|
239
|
+
stop: () => void;
|
|
240
|
+
};
|
|
241
|
+
export {};
|