@ansh-ui/core 0.2.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/LICENSE +21 -0
- package/dist/behaviours.cjs +64 -0
- package/dist/behaviours.cjs.map +1 -0
- package/dist/behaviours.d.cts +3 -0
- package/dist/behaviours.d.ts +3 -0
- package/dist/behaviours.js +7 -0
- package/dist/behaviours.js.map +1 -0
- package/dist/chunk-23GSSIMK.cjs +439 -0
- package/dist/chunk-23GSSIMK.cjs.map +1 -0
- package/dist/chunk-56NNBIAO.js +2446 -0
- package/dist/chunk-56NNBIAO.js.map +1 -0
- package/dist/chunk-6PFYGJWD.cjs +136 -0
- package/dist/chunk-6PFYGJWD.cjs.map +1 -0
- package/dist/chunk-7MEIXWPH.js +313 -0
- package/dist/chunk-7MEIXWPH.js.map +1 -0
- package/dist/chunk-7MYTSAPR.js +83 -0
- package/dist/chunk-7MYTSAPR.js.map +1 -0
- package/dist/chunk-BOQQHICI.js +1036 -0
- package/dist/chunk-BOQQHICI.js.map +1 -0
- package/dist/chunk-C6XPQO2O.js +1170 -0
- package/dist/chunk-C6XPQO2O.js.map +1 -0
- package/dist/chunk-DXJ63QAR.cjs +723 -0
- package/dist/chunk-DXJ63QAR.cjs.map +1 -0
- package/dist/chunk-FAVIEION.js +705 -0
- package/dist/chunk-FAVIEION.js.map +1 -0
- package/dist/chunk-FNR35HTL.cjs +107 -0
- package/dist/chunk-FNR35HTL.cjs.map +1 -0
- package/dist/chunk-GHBRGMSO.cjs +91 -0
- package/dist/chunk-GHBRGMSO.cjs.map +1 -0
- package/dist/chunk-GJRIHN76.cjs +359 -0
- package/dist/chunk-GJRIHN76.cjs.map +1 -0
- package/dist/chunk-ILKUL7GD.cjs +115 -0
- package/dist/chunk-ILKUL7GD.cjs.map +1 -0
- package/dist/chunk-KTUBCQC3.js +409 -0
- package/dist/chunk-KTUBCQC3.js.map +1 -0
- package/dist/chunk-KU2C6GEA.js +90 -0
- package/dist/chunk-KU2C6GEA.js.map +1 -0
- package/dist/chunk-LGA3N3YJ.cjs +413 -0
- package/dist/chunk-LGA3N3YJ.cjs.map +1 -0
- package/dist/chunk-MMO7KO53.cjs +1060 -0
- package/dist/chunk-MMO7KO53.cjs.map +1 -0
- package/dist/chunk-NSXKCJJ7.js +109 -0
- package/dist/chunk-NSXKCJJ7.js.map +1 -0
- package/dist/chunk-QALZKHWH.js +387 -0
- package/dist/chunk-QALZKHWH.js.map +1 -0
- package/dist/chunk-R7UJ7MWP.cjs +2479 -0
- package/dist/chunk-R7UJ7MWP.cjs.map +1 -0
- package/dist/chunk-UJBXY6QC.cjs +1186 -0
- package/dist/chunk-UJBXY6QC.cjs.map +1 -0
- package/dist/chunk-YFQXRC5R.js +99 -0
- package/dist/chunk-YFQXRC5R.js.map +1 -0
- package/dist/color.cjs +257 -0
- package/dist/color.cjs.map +1 -0
- package/dist/color.d.cts +303 -0
- package/dist/color.d.ts +303 -0
- package/dist/color.js +8 -0
- package/dist/color.js.map +1 -0
- package/dist/easing.cjs +189 -0
- package/dist/easing.cjs.map +1 -0
- package/dist/easing.d.cts +134 -0
- package/dist/easing.d.ts +134 -0
- package/dist/easing.js +4 -0
- package/dist/easing.js.map +1 -0
- package/dist/effects.cjs +99 -0
- package/dist/effects.cjs.map +1 -0
- package/dist/effects.d.cts +5 -0
- package/dist/effects.d.ts +5 -0
- package/dist/effects.js +10 -0
- package/dist/effects.js.map +1 -0
- package/dist/index-CCdpefMp.d.ts +967 -0
- package/dist/index-CQEEPu-D.d.ts +435 -0
- package/dist/index-DHOfsEIn.d.cts +967 -0
- package/dist/index-Dl8GCsya.d.cts +435 -0
- package/dist/index.cjs +2206 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1122 -0
- package/dist/index.d.ts +1122 -0
- package/dist/index.js +1182 -0
- package/dist/index.js.map +1 -0
- package/dist/math.cjs +238 -0
- package/dist/math.cjs.map +1 -0
- package/dist/math.d.cts +120 -0
- package/dist/math.d.ts +120 -0
- package/dist/math.js +5 -0
- package/dist/math.js.map +1 -0
- package/dist/noise.cjs +78 -0
- package/dist/noise.cjs.map +1 -0
- package/dist/noise.d.cts +190 -0
- package/dist/noise.d.ts +190 -0
- package/dist/noise.js +5 -0
- package/dist/noise.js.map +1 -0
- package/dist/palette-6HkVltYU.d.cts +219 -0
- package/dist/palette-6HkVltYU.d.ts +219 -0
- package/dist/random--4mSc5Lp.d.cts +75 -0
- package/dist/random--4mSc5Lp.d.ts +75 -0
- package/dist/reduced-motion-D0LUgZle.d.cts +120 -0
- package/dist/reduced-motion-D0LUgZle.d.ts +120 -0
- package/dist/types-B1FLLf3-.d.cts +21 -0
- package/dist/types-B1FLLf3-.d.ts +21 -0
- package/package.json +78 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seeded pseudo-random number generation.
|
|
3
|
+
*
|
|
4
|
+
* Determinism is a hard requirement in Ansh, not a nicety:
|
|
5
|
+
*
|
|
6
|
+
* - **SSR safety.** The server and the client must produce the same first frame, or React
|
|
7
|
+
* and Vue will both scream about hydration mismatches.
|
|
8
|
+
* - **Visual regression testing.** A screenshot diff is meaningless if the particle field
|
|
9
|
+
* is different on every run.
|
|
10
|
+
* - **Authoring.** A designer who likes seed `4821` can pin it and get that composition back.
|
|
11
|
+
*
|
|
12
|
+
* So no effect ever calls `Math.random()`. They all take a `seed` and derive a {@link Rng}.
|
|
13
|
+
*/
|
|
14
|
+
interface Rng {
|
|
15
|
+
/** Uniform in `[0, 1)`. */
|
|
16
|
+
next(): number;
|
|
17
|
+
/** Uniform in `[min, max)`. */
|
|
18
|
+
range(min: number, max: number): number;
|
|
19
|
+
/** Integer in `[min, max]`, inclusive on both ends. */
|
|
20
|
+
int(min: number, max: number): number;
|
|
21
|
+
/** `true` with probability `p`. */
|
|
22
|
+
bool(p?: number): boolean;
|
|
23
|
+
/** Uniform angle in `[0, 2π)`. */
|
|
24
|
+
angle(): number;
|
|
25
|
+
/** Approximately standard-normal, mean 0 and standard deviation 1. */
|
|
26
|
+
gaussian(): number;
|
|
27
|
+
/** A uniformly distributed point inside the unit circle. */
|
|
28
|
+
insideCircle(): {
|
|
29
|
+
x: number;
|
|
30
|
+
y: number;
|
|
31
|
+
};
|
|
32
|
+
/** Uniformly pick an element. Throws on an empty array. */
|
|
33
|
+
pick<T>(items: readonly T[]): T;
|
|
34
|
+
/** A new shuffled copy (Fisher–Yates). The input is not mutated. */
|
|
35
|
+
shuffle<T>(items: readonly T[]): T[];
|
|
36
|
+
/** A fresh independent stream, deterministically derived from this one's current state. */
|
|
37
|
+
fork(): Rng;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Mulberry32: 32-bit state, period 2³², passes gjrand's basic suites and is roughly as fast
|
|
41
|
+
* as `Math.random()`. Chosen over xorshift because its avalanche is better for small seeds
|
|
42
|
+
* (`seed = 1` and `seed = 2` produce visibly unrelated streams, which matters when authors
|
|
43
|
+
* type small numbers).
|
|
44
|
+
*/
|
|
45
|
+
declare function createRng(seed?: number | string): Rng;
|
|
46
|
+
/** FNV-1a. Lets authors seed with a memorable string (`seed="hero-aurora"`). */
|
|
47
|
+
declare function hashString(input: string): number;
|
|
48
|
+
/**
|
|
49
|
+
* Deterministically derive a child seed from a parent seed and an index.
|
|
50
|
+
*
|
|
51
|
+
* Used so that particle *n* of an effect gets a stable stream regardless of how many
|
|
52
|
+
* particles were created before it — which keeps a field visually stable when the count
|
|
53
|
+
* changes at runtime under adaptive quality.
|
|
54
|
+
*/
|
|
55
|
+
declare function deriveSeed(seed: number, index: number): number;
|
|
56
|
+
/**
|
|
57
|
+
* Low-discrepancy 1D sequence. Fills `[0,1)` far more evenly than uniform random, which is
|
|
58
|
+
* what you want for scattering stars or fireflies — pure random leaves visible clumps and
|
|
59
|
+
* voids that read as a mistake.
|
|
60
|
+
*/
|
|
61
|
+
declare function goldenRatioSequence(index: number, offset?: number): number;
|
|
62
|
+
/** 2D low-discrepancy sequence (R₂ / plastic constant). The 2D analogue of the above. */
|
|
63
|
+
declare function r2Sequence(index: number): {
|
|
64
|
+
x: number;
|
|
65
|
+
y: number;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Weighted pick. `weights` need not be normalised; non-finite or negative entries are
|
|
69
|
+
* treated as zero. Falls back to the last item if floating point leaves a remainder.
|
|
70
|
+
*/
|
|
71
|
+
declare function weightedPick<T>(rng: Rng, items: readonly T[], weights: readonly number[]): T;
|
|
72
|
+
/** Jitter a value by ±`amount` (absolute), clamped to an optional range. */
|
|
73
|
+
declare function jitter(rng: Rng, value: number, amount: number, min?: number, max?: number): number;
|
|
74
|
+
|
|
75
|
+
export { type Rng as R, createRng as c, deriveSeed as d, goldenRatioSequence as g, hashString as h, jitter as j, r2Sequence as r, weightedPick as w };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seeded pseudo-random number generation.
|
|
3
|
+
*
|
|
4
|
+
* Determinism is a hard requirement in Ansh, not a nicety:
|
|
5
|
+
*
|
|
6
|
+
* - **SSR safety.** The server and the client must produce the same first frame, or React
|
|
7
|
+
* and Vue will both scream about hydration mismatches.
|
|
8
|
+
* - **Visual regression testing.** A screenshot diff is meaningless if the particle field
|
|
9
|
+
* is different on every run.
|
|
10
|
+
* - **Authoring.** A designer who likes seed `4821` can pin it and get that composition back.
|
|
11
|
+
*
|
|
12
|
+
* So no effect ever calls `Math.random()`. They all take a `seed` and derive a {@link Rng}.
|
|
13
|
+
*/
|
|
14
|
+
interface Rng {
|
|
15
|
+
/** Uniform in `[0, 1)`. */
|
|
16
|
+
next(): number;
|
|
17
|
+
/** Uniform in `[min, max)`. */
|
|
18
|
+
range(min: number, max: number): number;
|
|
19
|
+
/** Integer in `[min, max]`, inclusive on both ends. */
|
|
20
|
+
int(min: number, max: number): number;
|
|
21
|
+
/** `true` with probability `p`. */
|
|
22
|
+
bool(p?: number): boolean;
|
|
23
|
+
/** Uniform angle in `[0, 2π)`. */
|
|
24
|
+
angle(): number;
|
|
25
|
+
/** Approximately standard-normal, mean 0 and standard deviation 1. */
|
|
26
|
+
gaussian(): number;
|
|
27
|
+
/** A uniformly distributed point inside the unit circle. */
|
|
28
|
+
insideCircle(): {
|
|
29
|
+
x: number;
|
|
30
|
+
y: number;
|
|
31
|
+
};
|
|
32
|
+
/** Uniformly pick an element. Throws on an empty array. */
|
|
33
|
+
pick<T>(items: readonly T[]): T;
|
|
34
|
+
/** A new shuffled copy (Fisher–Yates). The input is not mutated. */
|
|
35
|
+
shuffle<T>(items: readonly T[]): T[];
|
|
36
|
+
/** A fresh independent stream, deterministically derived from this one's current state. */
|
|
37
|
+
fork(): Rng;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Mulberry32: 32-bit state, period 2³², passes gjrand's basic suites and is roughly as fast
|
|
41
|
+
* as `Math.random()`. Chosen over xorshift because its avalanche is better for small seeds
|
|
42
|
+
* (`seed = 1` and `seed = 2` produce visibly unrelated streams, which matters when authors
|
|
43
|
+
* type small numbers).
|
|
44
|
+
*/
|
|
45
|
+
declare function createRng(seed?: number | string): Rng;
|
|
46
|
+
/** FNV-1a. Lets authors seed with a memorable string (`seed="hero-aurora"`). */
|
|
47
|
+
declare function hashString(input: string): number;
|
|
48
|
+
/**
|
|
49
|
+
* Deterministically derive a child seed from a parent seed and an index.
|
|
50
|
+
*
|
|
51
|
+
* Used so that particle *n* of an effect gets a stable stream regardless of how many
|
|
52
|
+
* particles were created before it — which keeps a field visually stable when the count
|
|
53
|
+
* changes at runtime under adaptive quality.
|
|
54
|
+
*/
|
|
55
|
+
declare function deriveSeed(seed: number, index: number): number;
|
|
56
|
+
/**
|
|
57
|
+
* Low-discrepancy 1D sequence. Fills `[0,1)` far more evenly than uniform random, which is
|
|
58
|
+
* what you want for scattering stars or fireflies — pure random leaves visible clumps and
|
|
59
|
+
* voids that read as a mistake.
|
|
60
|
+
*/
|
|
61
|
+
declare function goldenRatioSequence(index: number, offset?: number): number;
|
|
62
|
+
/** 2D low-discrepancy sequence (R₂ / plastic constant). The 2D analogue of the above. */
|
|
63
|
+
declare function r2Sequence(index: number): {
|
|
64
|
+
x: number;
|
|
65
|
+
y: number;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Weighted pick. `weights` need not be normalised; non-finite or negative entries are
|
|
69
|
+
* treated as zero. Falls back to the last item if floating point leaves a remainder.
|
|
70
|
+
*/
|
|
71
|
+
declare function weightedPick<T>(rng: Rng, items: readonly T[], weights: readonly number[]): T;
|
|
72
|
+
/** Jitter a value by ±`amount` (absolute), clamped to an optional range. */
|
|
73
|
+
declare function jitter(rng: Rng, value: number, amount: number, min?: number, max?: number): number;
|
|
74
|
+
|
|
75
|
+
export { type Rng as R, createRng as c, deriveSeed as d, goldenRatioSequence as g, hashString as h, jitter as j, r2Sequence as r, weightedPick as w };
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Everything a frame callback receives.
|
|
3
|
+
*
|
|
4
|
+
* Passed as a single frozen-by-convention object rather than positional arguments so that new
|
|
5
|
+
* fields can be added without breaking every subscriber in the ecosystem.
|
|
6
|
+
*/
|
|
7
|
+
interface FrameState {
|
|
8
|
+
/** Scaled seconds since the ticker started, excluding paused time. */
|
|
9
|
+
time: number;
|
|
10
|
+
/** Scaled, clamped seconds since the previous frame. Use this for all motion. */
|
|
11
|
+
delta: number;
|
|
12
|
+
/** Unscaled, unclamped seconds since the previous frame. For profiling only. */
|
|
13
|
+
rawDelta: number;
|
|
14
|
+
/** Monotonically increasing frame index. */
|
|
15
|
+
frame: number;
|
|
16
|
+
/** Smoothed frames per second. */
|
|
17
|
+
fps: number;
|
|
18
|
+
/**
|
|
19
|
+
* Adaptive quality in `[0, 1]`. Multiply expensive work by this — particle counts, render
|
|
20
|
+
* resolution, octave counts — so the effect degrades gracefully instead of dropping frames.
|
|
21
|
+
*/
|
|
22
|
+
quality: number;
|
|
23
|
+
/** Raw `performance.now()` timestamp for this frame. */
|
|
24
|
+
timestamp: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Scheduling phases, executed in this order every frame.
|
|
28
|
+
*
|
|
29
|
+
* The separation exists to make layout thrashing structurally impossible. If one component
|
|
30
|
+
* reads `getBoundingClientRect()` while another has already written a style, the browser must
|
|
31
|
+
* synchronously recompute layout — and with N components interleaving, that happens N times
|
|
32
|
+
* per frame. By collecting all reads before any write, it happens at most once.
|
|
33
|
+
*
|
|
34
|
+
* - `read` — measure the DOM. Never mutate here.
|
|
35
|
+
* - `compute` — pure calculation: physics, interpolation, layout maths. Touch no DOM.
|
|
36
|
+
* - `write` — mutate styles, draw to canvas. Never measure here.
|
|
37
|
+
* - `post` — bookkeeping after the visual work: analytics, `onComplete` callbacks.
|
|
38
|
+
*/
|
|
39
|
+
type FramePhase = 'read' | 'compute' | 'write' | 'post';
|
|
40
|
+
declare const FRAME_PHASES: readonly FramePhase[];
|
|
41
|
+
type FrameCallback = (state: FrameState) => void;
|
|
42
|
+
interface SubscribeOptions {
|
|
43
|
+
/** Which phase to run in. Default `'write'` — the common case for drawing effects. */
|
|
44
|
+
phase?: FramePhase;
|
|
45
|
+
/**
|
|
46
|
+
* Ordering within the phase. Lower runs first. Default `0`.
|
|
47
|
+
*
|
|
48
|
+
* Use this for genuine dependencies (a parallax container must position before its children
|
|
49
|
+
* measure), not as a general-purpose knob — over-ordered systems are hard to reason about.
|
|
50
|
+
*/
|
|
51
|
+
priority?: number;
|
|
52
|
+
/** Label used in error messages and the dev inspector. */
|
|
53
|
+
name?: string;
|
|
54
|
+
}
|
|
55
|
+
/** Returned by `ticker.add()`. Idempotent — calling it twice is safe. */
|
|
56
|
+
type Unsubscribe = () => void;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Reduced-motion support.
|
|
60
|
+
*
|
|
61
|
+
* `prefers-reduced-motion` is not a niche preference. It is set by users with vestibular
|
|
62
|
+
* disorders, for whom large-scale parallax and continuous background motion cause genuine
|
|
63
|
+
* physical nausea. Honouring it is not a nice-to-have, and it must not be each component's
|
|
64
|
+
* job to remember — so the kernel owns it and every effect declares a strategy.
|
|
65
|
+
*
|
|
66
|
+
* The strategies exist because "disable all animation" is the wrong answer for most effects.
|
|
67
|
+
* A gradient that slowly shifts hue is not what makes people ill; a full-viewport parallax
|
|
68
|
+
* scroll is. So each effect states what it should do, and authors can override per instance.
|
|
69
|
+
*/
|
|
70
|
+
/**
|
|
71
|
+
* How an effect should behave when the user prefers reduced motion.
|
|
72
|
+
*
|
|
73
|
+
* - `static` — render one frame and stop. The design still reads correctly, nothing moves.
|
|
74
|
+
* The right default for backgrounds.
|
|
75
|
+
* - `slow` — keep animating at a fraction of the speed. Suitable for gentle, small-amplitude
|
|
76
|
+
* motion where stillness would lose meaning (a loading indicator).
|
|
77
|
+
* - `pause` — don't render at all. For effects whose whole purpose is movement.
|
|
78
|
+
* - `none` — ignore the preference. Only correct for motion that conveys required
|
|
79
|
+
* information, e.g. a progress indicator with no other affordance.
|
|
80
|
+
*/
|
|
81
|
+
type ReducedMotionStrategy = 'static' | 'slow' | 'pause' | 'none';
|
|
82
|
+
/** Application-level override, usually surfaced through a `<MotionConfig>` provider. */
|
|
83
|
+
type ReducedMotionMode = 'auto' | 'always' | 'never';
|
|
84
|
+
/**
|
|
85
|
+
* Does the user want reduced motion?
|
|
86
|
+
*
|
|
87
|
+
* Returns `false` during SSR. That is the correct default: rendering the static fallback on the
|
|
88
|
+
* server and the animated version on the client would be a hydration mismatch, whereas
|
|
89
|
+
* rendering the animated markup and then immediately stopping it on the client is seamless.
|
|
90
|
+
*/
|
|
91
|
+
declare function prefersReducedMotion(): boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Override the system preference application-wide.
|
|
94
|
+
*
|
|
95
|
+
* `'always'` is genuinely useful in production (an in-app "reduce motion" setting), and
|
|
96
|
+
* essential in tests and screenshot harnesses where you need the static frame deterministically.
|
|
97
|
+
*/
|
|
98
|
+
declare function setReducedMotionMode(mode: ReducedMotionMode): void;
|
|
99
|
+
declare function getReducedMotionMode(): ReducedMotionMode;
|
|
100
|
+
/** Subscribe to preference changes. Fires immediately with the current value. */
|
|
101
|
+
declare function onReducedMotionChange(listener: (reduced: boolean) => void): Unsubscribe;
|
|
102
|
+
interface MotionResolution {
|
|
103
|
+
/** Should the effect run its frame loop at all? */
|
|
104
|
+
animate: boolean;
|
|
105
|
+
/** Should it render a single frame before stopping? */
|
|
106
|
+
renderOnce: boolean;
|
|
107
|
+
/** Multiplier to apply to the effect's speed. */
|
|
108
|
+
timeScale: number;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Turn a strategy plus the current preference into concrete instructions.
|
|
112
|
+
*
|
|
113
|
+
* Centralising this means every effect behaves consistently, and that adding a new strategy
|
|
114
|
+
* later is a change in one file rather than eighty.
|
|
115
|
+
*/
|
|
116
|
+
declare function resolveMotion(strategy?: ReducedMotionStrategy, slowFactor?: number): MotionResolution;
|
|
117
|
+
/** Reset module state. Test-only. */
|
|
118
|
+
declare function resetReducedMotion(): void;
|
|
119
|
+
|
|
120
|
+
export { type FrameCallback as F, type MotionResolution as M, type ReducedMotionStrategy as R, type SubscribeOptions as S, type Unsubscribe as U, type FrameState as a, type FramePhase as b, FRAME_PHASES as c, type ReducedMotionMode as d, resolveMotion as e, getReducedMotionMode as g, onReducedMotionChange as o, prefersReducedMotion as p, resetReducedMotion as r, setReducedMotionMode as s };
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Everything a frame callback receives.
|
|
3
|
+
*
|
|
4
|
+
* Passed as a single frozen-by-convention object rather than positional arguments so that new
|
|
5
|
+
* fields can be added without breaking every subscriber in the ecosystem.
|
|
6
|
+
*/
|
|
7
|
+
interface FrameState {
|
|
8
|
+
/** Scaled seconds since the ticker started, excluding paused time. */
|
|
9
|
+
time: number;
|
|
10
|
+
/** Scaled, clamped seconds since the previous frame. Use this for all motion. */
|
|
11
|
+
delta: number;
|
|
12
|
+
/** Unscaled, unclamped seconds since the previous frame. For profiling only. */
|
|
13
|
+
rawDelta: number;
|
|
14
|
+
/** Monotonically increasing frame index. */
|
|
15
|
+
frame: number;
|
|
16
|
+
/** Smoothed frames per second. */
|
|
17
|
+
fps: number;
|
|
18
|
+
/**
|
|
19
|
+
* Adaptive quality in `[0, 1]`. Multiply expensive work by this — particle counts, render
|
|
20
|
+
* resolution, octave counts — so the effect degrades gracefully instead of dropping frames.
|
|
21
|
+
*/
|
|
22
|
+
quality: number;
|
|
23
|
+
/** Raw `performance.now()` timestamp for this frame. */
|
|
24
|
+
timestamp: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Scheduling phases, executed in this order every frame.
|
|
28
|
+
*
|
|
29
|
+
* The separation exists to make layout thrashing structurally impossible. If one component
|
|
30
|
+
* reads `getBoundingClientRect()` while another has already written a style, the browser must
|
|
31
|
+
* synchronously recompute layout — and with N components interleaving, that happens N times
|
|
32
|
+
* per frame. By collecting all reads before any write, it happens at most once.
|
|
33
|
+
*
|
|
34
|
+
* - `read` — measure the DOM. Never mutate here.
|
|
35
|
+
* - `compute` — pure calculation: physics, interpolation, layout maths. Touch no DOM.
|
|
36
|
+
* - `write` — mutate styles, draw to canvas. Never measure here.
|
|
37
|
+
* - `post` — bookkeeping after the visual work: analytics, `onComplete` callbacks.
|
|
38
|
+
*/
|
|
39
|
+
type FramePhase = 'read' | 'compute' | 'write' | 'post';
|
|
40
|
+
declare const FRAME_PHASES: readonly FramePhase[];
|
|
41
|
+
type FrameCallback = (state: FrameState) => void;
|
|
42
|
+
interface SubscribeOptions {
|
|
43
|
+
/** Which phase to run in. Default `'write'` — the common case for drawing effects. */
|
|
44
|
+
phase?: FramePhase;
|
|
45
|
+
/**
|
|
46
|
+
* Ordering within the phase. Lower runs first. Default `0`.
|
|
47
|
+
*
|
|
48
|
+
* Use this for genuine dependencies (a parallax container must position before its children
|
|
49
|
+
* measure), not as a general-purpose knob — over-ordered systems are hard to reason about.
|
|
50
|
+
*/
|
|
51
|
+
priority?: number;
|
|
52
|
+
/** Label used in error messages and the dev inspector. */
|
|
53
|
+
name?: string;
|
|
54
|
+
}
|
|
55
|
+
/** Returned by `ticker.add()`. Idempotent — calling it twice is safe. */
|
|
56
|
+
type Unsubscribe = () => void;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Reduced-motion support.
|
|
60
|
+
*
|
|
61
|
+
* `prefers-reduced-motion` is not a niche preference. It is set by users with vestibular
|
|
62
|
+
* disorders, for whom large-scale parallax and continuous background motion cause genuine
|
|
63
|
+
* physical nausea. Honouring it is not a nice-to-have, and it must not be each component's
|
|
64
|
+
* job to remember — so the kernel owns it and every effect declares a strategy.
|
|
65
|
+
*
|
|
66
|
+
* The strategies exist because "disable all animation" is the wrong answer for most effects.
|
|
67
|
+
* A gradient that slowly shifts hue is not what makes people ill; a full-viewport parallax
|
|
68
|
+
* scroll is. So each effect states what it should do, and authors can override per instance.
|
|
69
|
+
*/
|
|
70
|
+
/**
|
|
71
|
+
* How an effect should behave when the user prefers reduced motion.
|
|
72
|
+
*
|
|
73
|
+
* - `static` — render one frame and stop. The design still reads correctly, nothing moves.
|
|
74
|
+
* The right default for backgrounds.
|
|
75
|
+
* - `slow` — keep animating at a fraction of the speed. Suitable for gentle, small-amplitude
|
|
76
|
+
* motion where stillness would lose meaning (a loading indicator).
|
|
77
|
+
* - `pause` — don't render at all. For effects whose whole purpose is movement.
|
|
78
|
+
* - `none` — ignore the preference. Only correct for motion that conveys required
|
|
79
|
+
* information, e.g. a progress indicator with no other affordance.
|
|
80
|
+
*/
|
|
81
|
+
type ReducedMotionStrategy = 'static' | 'slow' | 'pause' | 'none';
|
|
82
|
+
/** Application-level override, usually surfaced through a `<MotionConfig>` provider. */
|
|
83
|
+
type ReducedMotionMode = 'auto' | 'always' | 'never';
|
|
84
|
+
/**
|
|
85
|
+
* Does the user want reduced motion?
|
|
86
|
+
*
|
|
87
|
+
* Returns `false` during SSR. That is the correct default: rendering the static fallback on the
|
|
88
|
+
* server and the animated version on the client would be a hydration mismatch, whereas
|
|
89
|
+
* rendering the animated markup and then immediately stopping it on the client is seamless.
|
|
90
|
+
*/
|
|
91
|
+
declare function prefersReducedMotion(): boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Override the system preference application-wide.
|
|
94
|
+
*
|
|
95
|
+
* `'always'` is genuinely useful in production (an in-app "reduce motion" setting), and
|
|
96
|
+
* essential in tests and screenshot harnesses where you need the static frame deterministically.
|
|
97
|
+
*/
|
|
98
|
+
declare function setReducedMotionMode(mode: ReducedMotionMode): void;
|
|
99
|
+
declare function getReducedMotionMode(): ReducedMotionMode;
|
|
100
|
+
/** Subscribe to preference changes. Fires immediately with the current value. */
|
|
101
|
+
declare function onReducedMotionChange(listener: (reduced: boolean) => void): Unsubscribe;
|
|
102
|
+
interface MotionResolution {
|
|
103
|
+
/** Should the effect run its frame loop at all? */
|
|
104
|
+
animate: boolean;
|
|
105
|
+
/** Should it render a single frame before stopping? */
|
|
106
|
+
renderOnce: boolean;
|
|
107
|
+
/** Multiplier to apply to the effect's speed. */
|
|
108
|
+
timeScale: number;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Turn a strategy plus the current preference into concrete instructions.
|
|
112
|
+
*
|
|
113
|
+
* Centralising this means every effect behaves consistently, and that adding a new strategy
|
|
114
|
+
* later is a change in one file rather than eighty.
|
|
115
|
+
*/
|
|
116
|
+
declare function resolveMotion(strategy?: ReducedMotionStrategy, slowFactor?: number): MotionResolution;
|
|
117
|
+
/** Reset module state. Test-only. */
|
|
118
|
+
declare function resetReducedMotion(): void;
|
|
119
|
+
|
|
120
|
+
export { type FrameCallback as F, type MotionResolution as M, type ReducedMotionStrategy as R, type SubscribeOptions as S, type Unsubscribe as U, type FrameState as a, type FramePhase as b, FRAME_PHASES as c, type ReducedMotionMode as d, resolveMotion as e, getReducedMotionMode as g, onReducedMotionChange as o, prefersReducedMotion as p, resetReducedMotion as r, setReducedMotionMode as s };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An easing function maps normalised progress to eased progress.
|
|
3
|
+
*
|
|
4
|
+
* Input is always in `[0, 1]`. Output is usually in `[0, 1]` but may overshoot — `back` and
|
|
5
|
+
* `elastic` curves deliberately exceed the range, which is what gives them their character.
|
|
6
|
+
* Implementations must be pure and must return exactly `0` at `t = 0` and `1` at `t = 1`.
|
|
7
|
+
*/
|
|
8
|
+
type EasingFn = (t: number) => number;
|
|
9
|
+
/** Names of every easing shipped in the built-in library. */
|
|
10
|
+
type EasingName = 'linear' | 'easeInSine' | 'easeOutSine' | 'easeInOutSine' | 'easeInQuad' | 'easeOutQuad' | 'easeInOutQuad' | 'easeInCubic' | 'easeOutCubic' | 'easeInOutCubic' | 'easeInQuart' | 'easeOutQuart' | 'easeInOutQuart' | 'easeInQuint' | 'easeOutQuint' | 'easeInOutQuint' | 'easeInExpo' | 'easeOutExpo' | 'easeInOutExpo' | 'easeInCirc' | 'easeOutCirc' | 'easeInOutCirc' | 'easeInBack' | 'easeOutBack' | 'easeInOutBack' | 'easeInElastic' | 'easeOutElastic' | 'easeInOutElastic' | 'easeInBounce' | 'easeOutBounce' | 'easeInOutBounce' | 'smoothstep' | 'smootherstep' | 'anticipate';
|
|
11
|
+
/**
|
|
12
|
+
* Anywhere Ansh accepts an easing you may pass:
|
|
13
|
+
*
|
|
14
|
+
* - a built-in name — `'easeOutCubic'`
|
|
15
|
+
* - a name registered via `registerEasing()` — `'myBrandCurve'`
|
|
16
|
+
* - a raw function — `(t) => t * t`
|
|
17
|
+
* - CSS-style bézier coordinates — `[0.22, 1, 0.36, 1]`
|
|
18
|
+
*/
|
|
19
|
+
type EasingInput = EasingName | (string & {}) | EasingFn | readonly [number, number, number, number];
|
|
20
|
+
|
|
21
|
+
export type { EasingInput as E, EasingFn as a, EasingName as b };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An easing function maps normalised progress to eased progress.
|
|
3
|
+
*
|
|
4
|
+
* Input is always in `[0, 1]`. Output is usually in `[0, 1]` but may overshoot — `back` and
|
|
5
|
+
* `elastic` curves deliberately exceed the range, which is what gives them their character.
|
|
6
|
+
* Implementations must be pure and must return exactly `0` at `t = 0` and `1` at `t = 1`.
|
|
7
|
+
*/
|
|
8
|
+
type EasingFn = (t: number) => number;
|
|
9
|
+
/** Names of every easing shipped in the built-in library. */
|
|
10
|
+
type EasingName = 'linear' | 'easeInSine' | 'easeOutSine' | 'easeInOutSine' | 'easeInQuad' | 'easeOutQuad' | 'easeInOutQuad' | 'easeInCubic' | 'easeOutCubic' | 'easeInOutCubic' | 'easeInQuart' | 'easeOutQuart' | 'easeInOutQuart' | 'easeInQuint' | 'easeOutQuint' | 'easeInOutQuint' | 'easeInExpo' | 'easeOutExpo' | 'easeInOutExpo' | 'easeInCirc' | 'easeOutCirc' | 'easeInOutCirc' | 'easeInBack' | 'easeOutBack' | 'easeInOutBack' | 'easeInElastic' | 'easeOutElastic' | 'easeInOutElastic' | 'easeInBounce' | 'easeOutBounce' | 'easeInOutBounce' | 'smoothstep' | 'smootherstep' | 'anticipate';
|
|
11
|
+
/**
|
|
12
|
+
* Anywhere Ansh accepts an easing you may pass:
|
|
13
|
+
*
|
|
14
|
+
* - a built-in name — `'easeOutCubic'`
|
|
15
|
+
* - a name registered via `registerEasing()` — `'myBrandCurve'`
|
|
16
|
+
* - a raw function — `(t) => t * t`
|
|
17
|
+
* - CSS-style bézier coordinates — `[0.22, 1, 0.36, 1]`
|
|
18
|
+
*/
|
|
19
|
+
type EasingInput = EasingName | (string & {}) | EasingFn | readonly [number, number, number, number];
|
|
20
|
+
|
|
21
|
+
export type { EasingInput as E, EasingFn as a, EasingName as b };
|
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ansh-ui/core",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "The Ansh animation engine — a zero-dependency, framework-agnostic kernel for high-performance motion.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"keywords": [
|
|
9
|
+
"animation",
|
|
10
|
+
"motion",
|
|
11
|
+
"spring",
|
|
12
|
+
"easing",
|
|
13
|
+
"noise",
|
|
14
|
+
"simplex",
|
|
15
|
+
"oklch",
|
|
16
|
+
"canvas",
|
|
17
|
+
"particles",
|
|
18
|
+
"timeline"
|
|
19
|
+
],
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/jithin003/ui-library.git",
|
|
23
|
+
"directory": "packages/core"
|
|
24
|
+
},
|
|
25
|
+
"homepage": "https://github.com/jithin003/ui-library",
|
|
26
|
+
"files": [
|
|
27
|
+
"dist"
|
|
28
|
+
],
|
|
29
|
+
"main": "./dist/index.cjs",
|
|
30
|
+
"module": "./dist/index.js",
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"import": "./dist/index.js",
|
|
36
|
+
"require": "./dist/index.cjs"
|
|
37
|
+
},
|
|
38
|
+
"./math": {
|
|
39
|
+
"types": "./dist/math.d.ts",
|
|
40
|
+
"import": "./dist/math.js",
|
|
41
|
+
"require": "./dist/math.cjs"
|
|
42
|
+
},
|
|
43
|
+
"./easing": {
|
|
44
|
+
"types": "./dist/easing.d.ts",
|
|
45
|
+
"import": "./dist/easing.js",
|
|
46
|
+
"require": "./dist/easing.cjs"
|
|
47
|
+
},
|
|
48
|
+
"./color": {
|
|
49
|
+
"types": "./dist/color.d.ts",
|
|
50
|
+
"import": "./dist/color.js",
|
|
51
|
+
"require": "./dist/color.cjs"
|
|
52
|
+
},
|
|
53
|
+
"./noise": {
|
|
54
|
+
"types": "./dist/noise.d.ts",
|
|
55
|
+
"import": "./dist/noise.js",
|
|
56
|
+
"require": "./dist/noise.cjs"
|
|
57
|
+
},
|
|
58
|
+
"./effects": {
|
|
59
|
+
"types": "./dist/effects.d.ts",
|
|
60
|
+
"import": "./dist/effects.js",
|
|
61
|
+
"require": "./dist/effects.cjs"
|
|
62
|
+
},
|
|
63
|
+
"./behaviours": {
|
|
64
|
+
"types": "./dist/behaviours.d.ts",
|
|
65
|
+
"import": "./dist/behaviours.js",
|
|
66
|
+
"require": "./dist/behaviours.cjs"
|
|
67
|
+
},
|
|
68
|
+
"./package.json": "./package.json"
|
|
69
|
+
},
|
|
70
|
+
"publishConfig": {
|
|
71
|
+
"access": "public"
|
|
72
|
+
},
|
|
73
|
+
"scripts": {
|
|
74
|
+
"build": "tsup",
|
|
75
|
+
"dev": "tsup --watch",
|
|
76
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
77
|
+
}
|
|
78
|
+
}
|