@sarmal/core 0.7.0 → 0.8.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/dist/index.d.cts DELETED
@@ -1,262 +0,0 @@
1
- interface Point {
2
- x: number;
3
- y: number;
4
- }
5
- interface CurveDef {
6
- name: string;
7
- fn: (t: number, time: number, params: Record<string, number>) => Point;
8
- /**
9
- * @default (Math.PI * 2)
10
- */
11
- period?: number;
12
- /**
13
- * @default 1
14
- */
15
- speed?: number;
16
- /**
17
- * To indicate a compatible library version when providing the curve definitions
18
- * Intended for potential backwards compatibility scenarios and futureproofing
19
- */
20
- version?: number;
21
- /**
22
- * Skeleton rendering mode:
23
- * - 'static': Skeleton is computed once at init from `fn(t, 0)` and cached
24
- * - 'live': Skeleton is recomputed each frame using `fn(t, actualTime)` specifically for curves whose shape drifts *over time*
25
- * @default "static"
26
- */
27
- skeleton?: "static" | "live";
28
- /**
29
- * An **override** function for computing a skeleton independent of `fn`
30
- * If provided, this function is used instead of `fn` to sample the skeleton,
31
- * and the result is cached just like like 'static' mode
32
- * @param t The parametric time value from `0` to `period`
33
- * @returns The point on the skeleton at time `t`
34
- */
35
- skeletonFn?: (t: number) => Point;
36
- }
37
- type SeekOptions = {
38
- /**
39
- * Decides whether the sarmal trail should be cleared when `seek` is called
40
- */
41
- clearTrail?: boolean;
42
- };
43
- type SeekWithTrailOptions = {
44
- /**
45
- * When true, the trail wraps around the period boundary,
46
- * which results in a full trail even near `t=0`
47
- * By default, the trail stops at `t=0`, which results in a partial trail near the start
48
- * @default false
49
- */
50
- wrap?: boolean;
51
- /**
52
- * Time gap between each trail point (in same units as `t`)
53
- * Smaller value means a trail that is more dense
54
- * @default period / trailLength
55
- */
56
- step?: number;
57
- };
58
- type MorpStrategy = "raw" | "normalized";
59
- type MorphOptions = {
60
- /**
61
- * Duration of the morph transition in milliseconds
62
- * @default 300
63
- */
64
- duration?: number;
65
- /**
66
- * Strategy for lerping between curves with different periods:
67
- * - 'normalized': maps `t` proportionally into each curve's period (smooth for all period ratios)
68
- * - 'raw': uses the same `t` for both curves (can produce incoherent results for mismatched periods)
69
- * @default 'normalized'
70
- */
71
- morphStrategy?: MorpStrategy;
72
- };
73
- interface Engine {
74
- /**
75
- * Advances the Sarmal simulation by the given delta time (dt) in seconds.
76
- * Internally, this increases the simulation time `t` by `speed * dt`,
77
- * wraps `t` at `period`, evaluates the curve's parametric function `fn(t)`,
78
- * and appends the new point to the trail.
79
- * Returns the pre-allocated trail buffer, which has the *same* reference every call
80
- * ! Do not use `Array.length` to determine size
81
- * @param deltaTime Delta time in seconds (typically frame time from **requestAnimationFrame** or similar)
82
- */
83
- tick(deltaTime: number): Array<Point>;
84
- /**
85
- * Number of valid points in the trail buffer returned by the last `tick()` call
86
- * ! Use this instead of `trail.length`
87
- */
88
- readonly trailCount: number;
89
- /**
90
- * Resets the simulation state, by clearing the trail and reverting internal time `t` to 0.
91
- * The next call to `tick` will start fresh from the beginning of the curve.
92
- */
93
- reset(): void;
94
- /**
95
- * Returns the *skeleton* of the curve.
96
- * In technicality, it just represents the complete traversal of the curve over one full period,
97
- * which is sampled at points from `t=0` to `t=period`
98
- *
99
- * For "static" skeletons, this returns the same array on every call
100
- * For "live" skeletons, this returns a different array each frame
101
- * For `skeletonFn` overrides, this returns the skeleton from that function, which is *always* static
102
- *
103
- * The number of sample points is automatically derived from the curve's period.
104
- */
105
- getSarmalSkeleton(): Array<Point>;
106
- readonly isLiveSkeleton: boolean;
107
- /**
108
- * Sets the simulation time `t` directly to the specified value.
109
- * By default, the trail is preserved
110
- * @param t The time value to seek to (will be wrapped into [0, period))
111
- */
112
- seek(t: number, options?: SeekOptions): void;
113
- /**
114
- * Seeks to `t` and rebuilds the trail as if the animation naturally arrived there from `t=0`
115
- * @param t The time value to seek to (will be wrapped into [0, period))
116
- */
117
- seekWithTrail(t: number, options?: SeekWithTrailOptions): void;
118
- /**
119
- * Begins a smooth transition from the current curve to `target`
120
- * Saves the current curve as `curveA`, registers `target` as `curveB`, and resets `morphAlpha` to `0`
121
- *
122
- * If called while a morph is already in progress,
123
- * the interpolated state is frozen and becomes the new `curveA`
124
- * @param target The curve to transition to
125
- * @param strategy 'normalized' maps t proportionally into each curve's period (default), 'raw' uses the same t
126
- */
127
- startMorph(target: CurveDef, strategy?: MorpStrategy): void;
128
- /**
129
- * Sets the interpolation amount between `curveA` and `curveB`.
130
- * 0 = full curveA
131
- * 1 = full curveB
132
- * Called by the renderer each frame as `actualTime` advances
133
- * @param alpha A value in [0, 1]
134
- */
135
- setMorphAlpha(alpha: number): void;
136
- /**
137
- * Finalises the morph: `curveB` becomes the new active curve and `morphAlpha` is reset to `null`
138
- * ! Called by the renderer when alpha reaches `1`
139
- */
140
- completeMorph(): void;
141
- /**
142
- * Current interpolation progress between `curveA` and `curveB`
143
- * `null` when no morph is in progress
144
- */
145
- readonly morphAlpha: number | null;
146
- }
147
- interface SarmalInstance {
148
- start(): void;
149
- stop(): void;
150
- /** Resets the engine and clears the trail */
151
- reset(): void;
152
- /** Stops the animation and cleans up resources */
153
- destroy(): void;
154
- /**
155
- * Sets the simulation time `t` directly to the specified value.
156
- * By default, the trail is preserved
157
- * @param t The time value to seek to (will be wrapped into [0, period))
158
- */
159
- seek(t: number, options?: SeekOptions): void;
160
- /**
161
- * Seeks to `t` and rebuilds the trail as if the animation naturally arrived there from `t=0`
162
- * @param t The time value to seek to (will be wrapped into [0, period))
163
- */
164
- seekWithTrail(t: number, options?: SeekWithTrailOptions): void;
165
- /**
166
- * Smoothly transitions from the current curve to `target`.
167
- * The trail naturally reflects the new curve as new points are added.
168
- * @param target The curve to transition to
169
- * @param options.duration How long the morph takes in milliseconds (default: 300)
170
- * @param options.morphStrategy 'normalized' uses proportional t mapping (default), 'raw' uses same t
171
- * @returns Promise that resolves when the morph is complete
172
- */
173
- morphTo(target: CurveDef, options?: MorphOptions): Promise<void>;
174
- }
175
- interface RendererOptions {
176
- /** Target canvas element that will contain the Sarmal */
177
- canvas: HTMLCanvasElement;
178
- engine: Engine;
179
- /**
180
- * @default '#ffffff'
181
- */
182
- skeletonColor?: string;
183
- /**
184
- * @default '#ffffff'
185
- */
186
- trailColor?: string;
187
- /**
188
- * @default '#ffffff'
189
- */
190
- headColor?: string;
191
- /** @default 4 */
192
- headRadius?: number;
193
- /** @default 20 */
194
- glowSize?: number;
195
- }
196
- interface SarmalOptions extends Omit<RendererOptions, "canvas" | "engine"> {
197
- /** @default 120 */
198
- trailLength?: number;
199
- }
200
-
201
- interface SVGRendererOptions {
202
- /** Container element that will contain the SVG */
203
- container: Element;
204
- engine: Engine;
205
- /** @default '#ffffff' */
206
- skeletonColor?: string;
207
- /** @default '#ffffff' */
208
- trailColor?: string;
209
- /** @default '#ffffff' */
210
- headColor?: string;
211
- /** @default 4 */
212
- headRadius?: number;
213
- /** @default 20 */
214
- glowSize?: number;
215
- /** @default 'Loading' */
216
- ariaLabel?: string;
217
- }
218
- interface SVGSarmalOptions extends Omit<SVGRendererOptions, "container" | "engine"> {
219
- /** @default 120 */
220
- trailLength?: number;
221
- }
222
- /**
223
- * Creates a live SVG renderer for sarmal animations
224
- * The SVG is appended into `container` and updated each frame via **requestAnimationFrame**
225
- */
226
- declare function createSVGRenderer(options: SVGRendererOptions): SarmalInstance;
227
- /**
228
- * Creates a sarmal animation inside a container element using an SVG renderer
229
- * The SVG is appended to the container and animated via requestAnimationFrame
230
- *
231
- * @example
232
- * ```ts
233
- * import { createSarmalSVG, curves } from '@sarmal/core'
234
- * const sarmal = createSarmalSVG(document.getElementById('spinner'), curves.epitrochoid7)
235
- * sarmal.start()
236
- * ```
237
- */
238
- declare function createSarmalSVG(container: Element, curveDef: CurveDef, options?: SVGSarmalOptions): SarmalInstance;
239
-
240
- declare function createEngine(curveDef: CurveDef, trailLength?: number): Engine;
241
-
242
- /**
243
- * Creates a Canvas 2D renderer for sarmal animations
244
- * Renders the skeleton, the trail, and the glowing dot
245
- */
246
- declare function createRenderer(options: RendererOptions): SarmalInstance;
247
-
248
- declare const curves: Record<string, CurveDef>;
249
-
250
- /**
251
- * Creates a sarmal animation on a canvas element
252
- *
253
- * @example
254
- * ```ts
255
- * import { createSarmal, curves } from '@sarmal/core'
256
- * const sarmal = createSarmal(canvas, curves.artemis2)
257
- * sarmal.start()
258
- * ```
259
- */
260
- declare function createSarmal(canvas: HTMLCanvasElement, curveDef: CurveDef, options?: SarmalOptions): SarmalInstance;
261
-
262
- export { type CurveDef, type Engine, type Point, type RendererOptions, type SVGRendererOptions, type SVGSarmalOptions, type SarmalInstance, type SarmalOptions, type SeekOptions, type SeekWithTrailOptions, createEngine, createRenderer, createSVGRenderer, createSarmal, createSarmalSVG, curves };
package/dist/index.d.ts DELETED
@@ -1,262 +0,0 @@
1
- interface Point {
2
- x: number;
3
- y: number;
4
- }
5
- interface CurveDef {
6
- name: string;
7
- fn: (t: number, time: number, params: Record<string, number>) => Point;
8
- /**
9
- * @default (Math.PI * 2)
10
- */
11
- period?: number;
12
- /**
13
- * @default 1
14
- */
15
- speed?: number;
16
- /**
17
- * To indicate a compatible library version when providing the curve definitions
18
- * Intended for potential backwards compatibility scenarios and futureproofing
19
- */
20
- version?: number;
21
- /**
22
- * Skeleton rendering mode:
23
- * - 'static': Skeleton is computed once at init from `fn(t, 0)` and cached
24
- * - 'live': Skeleton is recomputed each frame using `fn(t, actualTime)` specifically for curves whose shape drifts *over time*
25
- * @default "static"
26
- */
27
- skeleton?: "static" | "live";
28
- /**
29
- * An **override** function for computing a skeleton independent of `fn`
30
- * If provided, this function is used instead of `fn` to sample the skeleton,
31
- * and the result is cached just like like 'static' mode
32
- * @param t The parametric time value from `0` to `period`
33
- * @returns The point on the skeleton at time `t`
34
- */
35
- skeletonFn?: (t: number) => Point;
36
- }
37
- type SeekOptions = {
38
- /**
39
- * Decides whether the sarmal trail should be cleared when `seek` is called
40
- */
41
- clearTrail?: boolean;
42
- };
43
- type SeekWithTrailOptions = {
44
- /**
45
- * When true, the trail wraps around the period boundary,
46
- * which results in a full trail even near `t=0`
47
- * By default, the trail stops at `t=0`, which results in a partial trail near the start
48
- * @default false
49
- */
50
- wrap?: boolean;
51
- /**
52
- * Time gap between each trail point (in same units as `t`)
53
- * Smaller value means a trail that is more dense
54
- * @default period / trailLength
55
- */
56
- step?: number;
57
- };
58
- type MorpStrategy = "raw" | "normalized";
59
- type MorphOptions = {
60
- /**
61
- * Duration of the morph transition in milliseconds
62
- * @default 300
63
- */
64
- duration?: number;
65
- /**
66
- * Strategy for lerping between curves with different periods:
67
- * - 'normalized': maps `t` proportionally into each curve's period (smooth for all period ratios)
68
- * - 'raw': uses the same `t` for both curves (can produce incoherent results for mismatched periods)
69
- * @default 'normalized'
70
- */
71
- morphStrategy?: MorpStrategy;
72
- };
73
- interface Engine {
74
- /**
75
- * Advances the Sarmal simulation by the given delta time (dt) in seconds.
76
- * Internally, this increases the simulation time `t` by `speed * dt`,
77
- * wraps `t` at `period`, evaluates the curve's parametric function `fn(t)`,
78
- * and appends the new point to the trail.
79
- * Returns the pre-allocated trail buffer, which has the *same* reference every call
80
- * ! Do not use `Array.length` to determine size
81
- * @param deltaTime Delta time in seconds (typically frame time from **requestAnimationFrame** or similar)
82
- */
83
- tick(deltaTime: number): Array<Point>;
84
- /**
85
- * Number of valid points in the trail buffer returned by the last `tick()` call
86
- * ! Use this instead of `trail.length`
87
- */
88
- readonly trailCount: number;
89
- /**
90
- * Resets the simulation state, by clearing the trail and reverting internal time `t` to 0.
91
- * The next call to `tick` will start fresh from the beginning of the curve.
92
- */
93
- reset(): void;
94
- /**
95
- * Returns the *skeleton* of the curve.
96
- * In technicality, it just represents the complete traversal of the curve over one full period,
97
- * which is sampled at points from `t=0` to `t=period`
98
- *
99
- * For "static" skeletons, this returns the same array on every call
100
- * For "live" skeletons, this returns a different array each frame
101
- * For `skeletonFn` overrides, this returns the skeleton from that function, which is *always* static
102
- *
103
- * The number of sample points is automatically derived from the curve's period.
104
- */
105
- getSarmalSkeleton(): Array<Point>;
106
- readonly isLiveSkeleton: boolean;
107
- /**
108
- * Sets the simulation time `t` directly to the specified value.
109
- * By default, the trail is preserved
110
- * @param t The time value to seek to (will be wrapped into [0, period))
111
- */
112
- seek(t: number, options?: SeekOptions): void;
113
- /**
114
- * Seeks to `t` and rebuilds the trail as if the animation naturally arrived there from `t=0`
115
- * @param t The time value to seek to (will be wrapped into [0, period))
116
- */
117
- seekWithTrail(t: number, options?: SeekWithTrailOptions): void;
118
- /**
119
- * Begins a smooth transition from the current curve to `target`
120
- * Saves the current curve as `curveA`, registers `target` as `curveB`, and resets `morphAlpha` to `0`
121
- *
122
- * If called while a morph is already in progress,
123
- * the interpolated state is frozen and becomes the new `curveA`
124
- * @param target The curve to transition to
125
- * @param strategy 'normalized' maps t proportionally into each curve's period (default), 'raw' uses the same t
126
- */
127
- startMorph(target: CurveDef, strategy?: MorpStrategy): void;
128
- /**
129
- * Sets the interpolation amount between `curveA` and `curveB`.
130
- * 0 = full curveA
131
- * 1 = full curveB
132
- * Called by the renderer each frame as `actualTime` advances
133
- * @param alpha A value in [0, 1]
134
- */
135
- setMorphAlpha(alpha: number): void;
136
- /**
137
- * Finalises the morph: `curveB` becomes the new active curve and `morphAlpha` is reset to `null`
138
- * ! Called by the renderer when alpha reaches `1`
139
- */
140
- completeMorph(): void;
141
- /**
142
- * Current interpolation progress between `curveA` and `curveB`
143
- * `null` when no morph is in progress
144
- */
145
- readonly morphAlpha: number | null;
146
- }
147
- interface SarmalInstance {
148
- start(): void;
149
- stop(): void;
150
- /** Resets the engine and clears the trail */
151
- reset(): void;
152
- /** Stops the animation and cleans up resources */
153
- destroy(): void;
154
- /**
155
- * Sets the simulation time `t` directly to the specified value.
156
- * By default, the trail is preserved
157
- * @param t The time value to seek to (will be wrapped into [0, period))
158
- */
159
- seek(t: number, options?: SeekOptions): void;
160
- /**
161
- * Seeks to `t` and rebuilds the trail as if the animation naturally arrived there from `t=0`
162
- * @param t The time value to seek to (will be wrapped into [0, period))
163
- */
164
- seekWithTrail(t: number, options?: SeekWithTrailOptions): void;
165
- /**
166
- * Smoothly transitions from the current curve to `target`.
167
- * The trail naturally reflects the new curve as new points are added.
168
- * @param target The curve to transition to
169
- * @param options.duration How long the morph takes in milliseconds (default: 300)
170
- * @param options.morphStrategy 'normalized' uses proportional t mapping (default), 'raw' uses same t
171
- * @returns Promise that resolves when the morph is complete
172
- */
173
- morphTo(target: CurveDef, options?: MorphOptions): Promise<void>;
174
- }
175
- interface RendererOptions {
176
- /** Target canvas element that will contain the Sarmal */
177
- canvas: HTMLCanvasElement;
178
- engine: Engine;
179
- /**
180
- * @default '#ffffff'
181
- */
182
- skeletonColor?: string;
183
- /**
184
- * @default '#ffffff'
185
- */
186
- trailColor?: string;
187
- /**
188
- * @default '#ffffff'
189
- */
190
- headColor?: string;
191
- /** @default 4 */
192
- headRadius?: number;
193
- /** @default 20 */
194
- glowSize?: number;
195
- }
196
- interface SarmalOptions extends Omit<RendererOptions, "canvas" | "engine"> {
197
- /** @default 120 */
198
- trailLength?: number;
199
- }
200
-
201
- interface SVGRendererOptions {
202
- /** Container element that will contain the SVG */
203
- container: Element;
204
- engine: Engine;
205
- /** @default '#ffffff' */
206
- skeletonColor?: string;
207
- /** @default '#ffffff' */
208
- trailColor?: string;
209
- /** @default '#ffffff' */
210
- headColor?: string;
211
- /** @default 4 */
212
- headRadius?: number;
213
- /** @default 20 */
214
- glowSize?: number;
215
- /** @default 'Loading' */
216
- ariaLabel?: string;
217
- }
218
- interface SVGSarmalOptions extends Omit<SVGRendererOptions, "container" | "engine"> {
219
- /** @default 120 */
220
- trailLength?: number;
221
- }
222
- /**
223
- * Creates a live SVG renderer for sarmal animations
224
- * The SVG is appended into `container` and updated each frame via **requestAnimationFrame**
225
- */
226
- declare function createSVGRenderer(options: SVGRendererOptions): SarmalInstance;
227
- /**
228
- * Creates a sarmal animation inside a container element using an SVG renderer
229
- * The SVG is appended to the container and animated via requestAnimationFrame
230
- *
231
- * @example
232
- * ```ts
233
- * import { createSarmalSVG, curves } from '@sarmal/core'
234
- * const sarmal = createSarmalSVG(document.getElementById('spinner'), curves.epitrochoid7)
235
- * sarmal.start()
236
- * ```
237
- */
238
- declare function createSarmalSVG(container: Element, curveDef: CurveDef, options?: SVGSarmalOptions): SarmalInstance;
239
-
240
- declare function createEngine(curveDef: CurveDef, trailLength?: number): Engine;
241
-
242
- /**
243
- * Creates a Canvas 2D renderer for sarmal animations
244
- * Renders the skeleton, the trail, and the glowing dot
245
- */
246
- declare function createRenderer(options: RendererOptions): SarmalInstance;
247
-
248
- declare const curves: Record<string, CurveDef>;
249
-
250
- /**
251
- * Creates a sarmal animation on a canvas element
252
- *
253
- * @example
254
- * ```ts
255
- * import { createSarmal, curves } from '@sarmal/core'
256
- * const sarmal = createSarmal(canvas, curves.artemis2)
257
- * sarmal.start()
258
- * ```
259
- */
260
- declare function createSarmal(canvas: HTMLCanvasElement, curveDef: CurveDef, options?: SarmalOptions): SarmalInstance;
261
-
262
- export { type CurveDef, type Engine, type Point, type RendererOptions, type SVGRendererOptions, type SVGSarmalOptions, type SarmalInstance, type SarmalOptions, type SeekOptions, type SeekWithTrailOptions, createEngine, createRenderer, createSVGRenderer, createSarmal, createSarmalSVG, curves };