@zakkster/lite-ambient-fx 1.0.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/AmbientFX.d.ts ADDED
@@ -0,0 +1,179 @@
1
+ /**
2
+ * @zakkster/lite-ambient-fx -- TypeScript declarations.
3
+ * (c) 2026 Zahary Shinikchiev. MIT.
4
+ */
5
+
6
+ export type BuiltInBehavior = 'EMBER' | 'MIST' | 'FLOAT' | 'CHAOS';
7
+
8
+ /**
9
+ * Any registered behavior name -- widen to `string` because users can
10
+ * install their own via `registerBehavior`.
11
+ */
12
+ export type BehaviorName = BuiltInBehavior | (string & {});
13
+
14
+ export type ThemeName = 'Fire' | 'Night' | 'Ice' | 'Frost' | 'Toxic' | 'Void';
15
+
16
+ export interface WindVector {
17
+ x: number;
18
+ y: number;
19
+ }
20
+
21
+ export interface AmbientConfig {
22
+ behavior: BehaviorName;
23
+ /** Base palette. Particles pick uniformly at random from these. */
24
+ colors: string[];
25
+ /** Rarer highlight color (~10% chance per spawn). */
26
+ spark: string;
27
+ /** Live particle count. */
28
+ count: number;
29
+ /** Constant advection vector applied per frame. */
30
+ wind: WindVector;
31
+ /** Per-frame life increment. Smaller = longer-lived. */
32
+ decay: number;
33
+ /** Base velocity magnitude. */
34
+ speed: number;
35
+ /**
36
+ * Sprite draw size in CSS pixels. Interpretation is behavior-specific:
37
+ * EMBER/FLOAT/CHAOS are small (2..30), MIST is large (50..500).
38
+ */
39
+ size: number;
40
+ /** Alpha cap; multiplied by z for depth. Clamped to [0, 1]. */
41
+ alpha: number;
42
+ /** Amplitude of the sin-LUT lateral turbulence. */
43
+ turbulence: number;
44
+ }
45
+
46
+ export interface AmbientOptions {
47
+ /** Preset name from THEMES. Defaults to 'Fire'. */
48
+ theme?: ThemeName;
49
+ /** Partial config to merge over the theme. `wind` merges shallowly. */
50
+ overrides?: Partial<AmbientConfig>;
51
+ /** Start the RAF loop immediately. Defaults to true. */
52
+ autoStart?: boolean;
53
+ }
54
+
55
+ export interface AmbientInstance {
56
+ setTheme(name: ThemeName): void;
57
+ updateConfig(overrides: Partial<AmbientConfig>): void;
58
+ readonly config: AmbientConfig;
59
+ readonly theme: ThemeName;
60
+ readonly count: number;
61
+ readonly running: boolean;
62
+ pause(): void;
63
+ resume(): void;
64
+ destroy(): void;
65
+ }
66
+
67
+ export interface ThemeMeta {
68
+ id: ThemeName;
69
+ name: string;
70
+ icon: string;
71
+ behavior: BuiltInBehavior;
72
+ }
73
+
74
+ /**
75
+ * Pooled per-frame context passed to every behavior's spawn/tick call.
76
+ * Do NOT retain references to this object or any of its slots past the
77
+ * current call -- the instance mutates it in place.
78
+ */
79
+ export interface FrameContext {
80
+ /** Current merged config (read-only from behavior perspective). */
81
+ cfg: AmbientConfig;
82
+ /** Viewport width in CSS pixels. */
83
+ W: number;
84
+ /** Viewport height in CSS pixels. */
85
+ H: number;
86
+ /** Milliseconds since last frame, clamped to <=50. */
87
+ dt: number;
88
+ /** dt / 16 -- delta-scale to the 60fps velocity reference. */
89
+ ds: number;
90
+ /** RAF-callback timestamp for this frame. */
91
+ timestamp: number;
92
+ /** True during initial population, false during in-flight respawns. */
93
+ isInit: boolean;
94
+ /** Get or build a DPR-aware sprite for the given color + logical size. */
95
+ getSprite(color: string, logicalSize: number): HTMLCanvasElement;
96
+ /** Recycle a particle in place. Called from tick when a particle dies. */
97
+ respawn(particle: Particle, isInit: boolean): void;
98
+ }
99
+
100
+ /**
101
+ * Monomorphic particle shape. Every field is present on every particle
102
+ * regardless of active behavior; MIST-specific slots stay zeroed for other
103
+ * behaviors so V8's hidden class never transitions.
104
+ */
105
+ export interface Particle {
106
+ id: number;
107
+ color: string;
108
+ spriteCanvas: HTMLCanvasElement | null;
109
+ z: number;
110
+ life: number;
111
+ x: number;
112
+ y: number;
113
+ size: number;
114
+ vx: number;
115
+ vy: number;
116
+ decay: number;
117
+ maxAlpha: number;
118
+ anchorX: number;
119
+ anchorY: number;
120
+ pulseOffset: number;
121
+ }
122
+
123
+ export interface BehaviorDefinition {
124
+ /** CSS-pixel size at which sprites for this behavior are rasterized. */
125
+ spriteLogical: number;
126
+ /** Populate/reset a particle. MUST NOT add new fields to `p`. */
127
+ spawn(p: Particle, frame: FrameContext): void;
128
+ /** Advance and render every particle for one frame. */
129
+ tick(particles: Particle[], ctx: CanvasRenderingContext2D, frame: FrameContext): void;
130
+ }
131
+
132
+ /** Package version string. */
133
+ export const VERSION: string;
134
+
135
+ /** Six shipped presets, keyed by theme name. */
136
+ export const THEMES: Record<ThemeName, AmbientConfig>;
137
+
138
+ /** Human-readable metadata for UI builders. */
139
+ export const THEME_META: ThemeMeta[];
140
+
141
+ /**
142
+ * The behavior registry. Four built-in entries at module load; users can
143
+ * install their own via `registerBehavior`. Uses a null prototype so
144
+ * property lookups don't fall through to `Object.prototype`.
145
+ */
146
+ export const BEHAVIORS: Record<string, BehaviorDefinition>;
147
+
148
+ /** Register a custom behavior (or replace a built-in). Throws on invalid def. */
149
+ export function registerBehavior(name: string, def: BehaviorDefinition): void;
150
+
151
+ /** Drop cached sprites by color, or the entire cache when `colors` is omitted. */
152
+ export function clearAmbientSpriteCache(colors?: string[]): void;
153
+
154
+ /** Merge a theme with overrides. `wind` merges shallowly. */
155
+ export function mergeThemeConfig(base: AmbientConfig, overrides: Partial<AmbientConfig> | null | undefined): AmbientConfig;
156
+
157
+ /** Validate a config object. Throws on violation. Returns the input for chaining. */
158
+ export function validateConfig(cfg: AmbientConfig): AmbientConfig;
159
+
160
+ /** Delta-time scale factor: dtMs / 16. */
161
+ export function deltaScale(dtMs: number): number;
162
+
163
+ /** Signed-modulo sine LUT access. */
164
+ export function sinLut(index: number): number;
165
+
166
+ /**
167
+ * Alpha envelope for `life` in [0, 1] under the given built-in mode.
168
+ * Kept as a shared helper for tests and downstream reuse; the built-in
169
+ * behaviors inline these curves inside their tick loops.
170
+ */
171
+ export function envelopeAlpha(mode: BuiltInBehavior, life: number, maxAlpha: number): number;
172
+
173
+ /**
174
+ * Create a fullscreen ambient particle atmosphere on the given canvas.
175
+ * The canvas should be positioned as a fullscreen overlay via CSS.
176
+ */
177
+ export function createAmbientFX(canvas: HTMLCanvasElement, options?: AmbientOptions): AmbientInstance;
178
+
179
+ export default createAmbientFX;