@prtcl/plonk 1.0.5 → 1.0.7

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 CHANGED
@@ -12,7 +12,7 @@ npm i @prtcl/plonk
12
12
 
13
13
  - **Timers** — `Metro`, `Frames` — high-resolution recursive loops with runtime metrics
14
14
  - **Generators** — `Drunk`, `Rand`, `Env`, `Sine`, `Scale` — random walks, envelopes, oscillators, and range mapping
15
- - **Utilities** — `now`, `ms`, `clamp`, `expo`, `flip` — timing and math helpers
15
+ - **Utilities** — `now`, `ms`, `clamp`, `expo` — timing and math helpers
16
16
 
17
17
  Generators follow an iterator-inspired `value()` / `next()` pattern — they're stateful objects you pull from on your own schedule (a timer callback, a Web Audio worklet, a game loop, etc).
18
18
 
@@ -24,10 +24,13 @@ import { Metro, Drunk, Rand } from '@prtcl/plonk';
24
24
  const d = new Drunk({ min: -1, max: 1 });
25
25
  const r = new Rand({ min: 50, max: 150 });
26
26
 
27
- const metro = new Metro(() => {
28
- console.log(d.next());
29
- metro.setTime(r.next());
30
- }, { time: 100 });
27
+ const metro = new Metro(
28
+ () => {
29
+ console.log(d.next());
30
+ metro.setTime(r.next());
31
+ },
32
+ { time: 100 }
33
+ );
31
34
 
32
35
  metro.run();
33
36
  ```
package/dist/index.cjs CHANGED
@@ -37,13 +37,12 @@ __export(index_exports, {
37
37
  TimeFormat: () => TimeFormat,
38
38
  clamp: () => clamp,
39
39
  expo: () => expo,
40
- flip: () => flip,
41
40
  ms: () => ms,
42
41
  now: () => now
43
42
  });
44
43
  module.exports = __toCommonJS(index_exports);
45
44
 
46
- // src/utils/clamp.ts
45
+ // src/clamp.ts
47
46
  function clamp(n, min, max) {
48
47
  let a = 0;
49
48
  let b = 1;
@@ -59,7 +58,7 @@ function clamp(n, min, max) {
59
58
  return Math.min(Math.max(n, a), b);
60
59
  }
61
60
 
62
- // src/math/Rand.ts
61
+ // src/Rand.ts
63
62
  var parseOptions = (opts) => {
64
63
  return {
65
64
  min: 0,
@@ -101,7 +100,7 @@ var Rand = class _Rand {
101
100
  }
102
101
  };
103
102
 
104
- // src/math/Drunk.ts
103
+ // src/Drunk.ts
105
104
  var DEFAULT_DRUNK_STEP = 0.1;
106
105
  var parseStepSize = (step) => typeof step !== "undefined" ? clamp(step, 0, 1) : DEFAULT_DRUNK_STEP;
107
106
  var parseOptions2 = (opts) => {
@@ -181,35 +180,10 @@ var Drunk = class {
181
180
  }
182
181
  };
183
182
 
184
- // src/utils/now.ts
185
- var internal;
186
- if (typeof performance !== "undefined" && "now" in performance) {
187
- internal = () => {
188
- return performance.now();
189
- };
190
- } else if (typeof process === "object" && process.toString() === "[object process]") {
191
- const timestamp = () => {
192
- const hr = process.hrtime();
193
- return hr[0] * 1e9 + hr[1];
194
- };
195
- const initial = timestamp();
196
- internal = () => {
197
- return (timestamp() - initial) / 1e6;
198
- };
199
- } else {
200
- const initial = Date.now();
201
- internal = () => {
202
- return Date.now() - initial;
203
- };
204
- }
205
- function now() {
206
- return internal();
207
- }
208
-
209
- // src/math/Scale.ts
210
- var parseOptions3 = (opts) => {
211
- const { from, to } = {
212
- ...opts,
183
+ // src/Scale.ts
184
+ var computeRatio = (from, to) => (to.max - to.min) / (from.max - from.min);
185
+ var parseInitialState = (opts) => {
186
+ const initialRange = {
213
187
  from: {
214
188
  min: 0,
215
189
  max: 1,
@@ -222,22 +196,25 @@ var parseOptions3 = (opts) => {
222
196
  }
223
197
  };
224
198
  return {
225
- from,
226
- to
199
+ ...initialRange,
200
+ ratio: computeRatio(initialRange.from, initialRange.to),
201
+ value: initialRange.to.min
227
202
  };
228
203
  };
229
204
  var updateStateFromOptions = (opts, prevState) => {
230
205
  const { from, to } = opts;
206
+ const updatedFrom = {
207
+ ...prevState.from,
208
+ ...from
209
+ };
231
210
  const updatedTo = {
232
211
  ...prevState.to,
233
212
  ...to
234
213
  };
235
214
  return {
236
215
  ...prevState,
237
- from: {
238
- ...prevState.from,
239
- ...from
240
- },
216
+ from: updatedFrom,
217
+ ratio: computeRatio(updatedFrom, updatedTo),
241
218
  to: updatedTo,
242
219
  value: clamp(prevState.value, updatedTo.min, updatedTo.max)
243
220
  };
@@ -245,8 +222,7 @@ var updateStateFromOptions = (opts, prevState) => {
245
222
  var Scale = class _Scale {
246
223
  constructor(opts) {
247
224
  __publicField(this, "state");
248
- const { from, to } = parseOptions3(opts);
249
- this.state = { from, to, value: to.min };
225
+ this.state = parseInitialState(opts);
250
226
  }
251
227
  static scale(n, opts) {
252
228
  return new _Scale(opts).scale(n);
@@ -255,22 +231,41 @@ var Scale = class _Scale {
255
231
  this.state = updateStateFromOptions(opts, this.state);
256
232
  }
257
233
  reset(opts) {
258
- const { from, to } = parseOptions3(opts);
259
- this.state = { from, to, value: to.min };
234
+ this.state = parseInitialState(opts);
260
235
  }
261
236
  value() {
262
237
  return this.state.value;
263
238
  }
264
239
  scale(n) {
265
- const { from, to } = this.state;
266
- const updates = to.min + (clamp(n, from.min, from.max) - from.min) * (to.max - to.min) / (from.max - from.min);
240
+ const { from, to, ratio } = this.state;
241
+ const updates = to.min + (clamp(n, from.min, from.max) - from.min) * ratio;
267
242
  this.state.value = updates;
268
243
  return updates;
269
244
  }
270
245
  };
271
246
 
272
- // src/math/Env.ts
273
- var parseOptions4 = (opts) => {
247
+ // src/now.ts
248
+ var innerNow = (() => {
249
+ if (typeof performance !== "undefined" && "now" in performance) {
250
+ return () => performance.now();
251
+ }
252
+ if (typeof process === "object" && process.toString() === "[object process]") {
253
+ const ts = () => {
254
+ const hr = process.hrtime();
255
+ return hr[0] * 1e9 + hr[1];
256
+ };
257
+ const initialNow2 = ts();
258
+ return () => (ts() - initialNow2) / 1e6;
259
+ }
260
+ const initialNow = Date.now();
261
+ return () => Date.now() - initialNow;
262
+ })();
263
+ function now() {
264
+ return innerNow();
265
+ }
266
+
267
+ // src/Env.ts
268
+ var parseOptions3 = (opts) => {
274
269
  return {
275
270
  duration: 0,
276
271
  from: 0,
@@ -278,11 +273,7 @@ var parseOptions4 = (opts) => {
278
273
  ...opts
279
274
  };
280
275
  };
281
- var getInitialState = ({
282
- from,
283
- to,
284
- duration
285
- }) => {
276
+ var getInitialState = ({ from, to, duration }) => {
286
277
  return {
287
278
  duration,
288
279
  from,
@@ -309,7 +300,7 @@ var Env = class {
309
300
  constructor(opts) {
310
301
  __publicField(this, "state");
311
302
  __publicField(this, "_interpolator");
312
- const { from, to, duration } = parseOptions4(opts);
303
+ const { from, to, duration } = parseOptions3(opts);
313
304
  this.state = getInitialState({ from, to, duration });
314
305
  this._interpolator = new Scale({
315
306
  from: {
@@ -376,7 +367,7 @@ var Env = class {
376
367
  }
377
368
  };
378
369
 
379
- // src/math/Sine.ts
370
+ // src/Sine.ts
380
371
  var SINE_PERIOD = Math.PI * 2 - 1e-4;
381
372
  var getInitialState2 = (duration) => ({
382
373
  cycle: 0,
@@ -419,20 +410,11 @@ var Sine = class {
419
410
  return this.state.value;
420
411
  }
421
412
  next() {
422
- const {
423
- cycle,
424
- duration,
425
- prev,
426
- totalElapsed: prevTotalElapsed
427
- } = this.state;
413
+ const { cycle, duration, prev, totalElapsed: prevTotalElapsed } = this.state;
428
414
  const curr = now();
429
415
  const tickInterval = curr - prev;
430
416
  const totalElapsed = prevTotalElapsed + tickInterval;
431
- const updates = clamp(
432
- Math.sin(this._interpolator.scale(totalElapsed)),
433
- -1,
434
- 1
435
- );
417
+ const updates = clamp(Math.sin(this._interpolator.scale(totalElapsed)), -1, 1);
436
418
  if (cycle >= duration) {
437
419
  this.state.cycle = 0;
438
420
  } else {
@@ -451,74 +433,7 @@ var MS_IN_SECOND = 1e3;
451
433
  var MS_IN_MINUTE = 60 * MS_IN_SECOND;
452
434
  var MS_IN_HOUR = MS_IN_MINUTE * 60;
453
435
 
454
- // src/utils/ms.ts
455
- var TimeFormat = /* @__PURE__ */ ((TimeFormat2) => {
456
- TimeFormat2["FPS"] = "fps";
457
- TimeFormat2["HOURS"] = "h";
458
- TimeFormat2["HZ"] = "hz";
459
- TimeFormat2["MILLISECONDS"] = "ms";
460
- TimeFormat2["MINUTES"] = "m";
461
- TimeFormat2["SECONDS"] = "s";
462
- return TimeFormat2;
463
- })(TimeFormat || {});
464
- var FORMAT_IDENTIFIERS = [
465
- "fps" /* FPS */,
466
- "h" /* HOURS */,
467
- "hz" /* HZ */,
468
- "ms" /* MILLISECONDS */,
469
- "m" /* MINUTES */,
470
- "s" /* SECONDS */
471
- ].sort((a, b) => b.length - a.length);
472
- var FORMATTERS = /* @__PURE__ */ new Map([
473
- ["fps" /* FPS */, (val) => MS_IN_SECOND / val],
474
- ["h" /* HOURS */, (val) => val * MS_IN_HOUR],
475
- ["hz" /* HZ */, (val) => 1 / val * MS_IN_SECOND],
476
- ["ms" /* MILLISECONDS */, (val) => val],
477
- ["m" /* MINUTES */, (val) => val * MS_IN_MINUTE],
478
- ["s" /* SECONDS */, (val) => val * MS_IN_SECOND]
479
- ]);
480
- var sanitizeStringVal = (val) => val.toLocaleLowerCase().trim();
481
- var parseStringValAndFormat = (val) => {
482
- for (let i = 0; i < FORMAT_IDENTIFIERS.length; i += 1) {
483
- const format = FORMAT_IDENTIFIERS[i];
484
- if (val.includes(format)) {
485
- const value = Number(val.replace(" ", "").replace(format, ""));
486
- return {
487
- format,
488
- value
489
- };
490
- }
491
- }
492
- return {
493
- format: void 0,
494
- value: void 0
495
- };
496
- };
497
- function ms(val, format) {
498
- let parsedValue = null;
499
- let parsedFormat = format || "ms" /* MILLISECONDS */;
500
- if (typeof val === "string") {
501
- const parsed = parseStringValAndFormat(sanitizeStringVal(val));
502
- if (typeof parsed.value !== "undefined") {
503
- parsedValue = parsed.value;
504
- }
505
- if (parsed.format) {
506
- parsedFormat = parsed.format;
507
- }
508
- } else {
509
- parsedValue = val;
510
- }
511
- if (typeof parsedValue === "undefined" || parsedValue === null || Number.isNaN(parsedValue)) {
512
- return void 0;
513
- }
514
- const formatter = FORMATTERS.get(parsedFormat);
515
- if (!formatter) {
516
- return void 0;
517
- }
518
- return formatter(parsedValue);
519
- }
520
-
521
- // src/timers/Metro.ts
436
+ // src/Metro.ts
522
437
  var getInitialState3 = (initialTime) => {
523
438
  return {
524
439
  initialTime,
@@ -552,7 +467,7 @@ var processTimerState = (state) => {
552
467
  totalElapsed: totalElapsed + tickInterval
553
468
  };
554
469
  };
555
- var parseOptions5 = (opts) => {
470
+ var parseOptions4 = (opts) => {
556
471
  return {
557
472
  time: SIXTY_FPS,
558
473
  ...opts
@@ -603,7 +518,7 @@ var Metro = class {
603
518
  };
604
519
  tick();
605
520
  });
606
- const { time } = parseOptions5(opts);
521
+ const { time } = parseOptions4(opts);
607
522
  this.state = getInitialState3(time);
608
523
  this._listeners = [callback];
609
524
  }
@@ -615,9 +530,76 @@ var Metro = class {
615
530
  }
616
531
  };
617
532
 
618
- // src/timers/Frames.ts
533
+ // src/ms.ts
534
+ var TimeFormat = /* @__PURE__ */ ((TimeFormat2) => {
535
+ TimeFormat2["FPS"] = "fps";
536
+ TimeFormat2["HOURS"] = "h";
537
+ TimeFormat2["HZ"] = "hz";
538
+ TimeFormat2["MILLISECONDS"] = "ms";
539
+ TimeFormat2["MINUTES"] = "m";
540
+ TimeFormat2["SECONDS"] = "s";
541
+ return TimeFormat2;
542
+ })(TimeFormat || {});
543
+ var FORMAT_IDENTIFIERS = [
544
+ "fps" /* FPS */,
545
+ "h" /* HOURS */,
546
+ "hz" /* HZ */,
547
+ "ms" /* MILLISECONDS */,
548
+ "m" /* MINUTES */,
549
+ "s" /* SECONDS */
550
+ ].sort((a, b) => b.length - a.length);
551
+ var FORMATTERS = /* @__PURE__ */ new Map([
552
+ ["fps" /* FPS */, (val) => MS_IN_SECOND / val],
553
+ ["h" /* HOURS */, (val) => val * MS_IN_HOUR],
554
+ ["hz" /* HZ */, (val) => 1 / val * MS_IN_SECOND],
555
+ ["ms" /* MILLISECONDS */, (val) => val],
556
+ ["m" /* MINUTES */, (val) => val * MS_IN_MINUTE],
557
+ ["s" /* SECONDS */, (val) => val * MS_IN_SECOND]
558
+ ]);
559
+ var sanitizeStringVal = (val) => val.toLocaleLowerCase().trim();
560
+ var parseStringValAndFormat = (val) => {
561
+ for (let i = 0; i < FORMAT_IDENTIFIERS.length; i += 1) {
562
+ const format = FORMAT_IDENTIFIERS[i];
563
+ if (val.includes(format)) {
564
+ const value = Number(val.replace(" ", "").replace(format, ""));
565
+ return {
566
+ format,
567
+ value
568
+ };
569
+ }
570
+ }
571
+ return {
572
+ format: void 0,
573
+ value: void 0
574
+ };
575
+ };
576
+ function ms(val, format) {
577
+ let parsedValue = null;
578
+ let parsedFormat = format || "ms" /* MILLISECONDS */;
579
+ if (typeof val === "string") {
580
+ const parsed = parseStringValAndFormat(sanitizeStringVal(val));
581
+ if (typeof parsed.value !== "undefined") {
582
+ parsedValue = parsed.value;
583
+ }
584
+ if (parsed.format) {
585
+ parsedFormat = parsed.format;
586
+ }
587
+ } else {
588
+ parsedValue = val;
589
+ }
590
+ if (typeof parsedValue === "undefined" || parsedValue === null || Number.isNaN(parsedValue)) {
591
+ return void 0;
592
+ }
593
+ const formatter = FORMATTERS.get(parsedFormat);
594
+ if (!formatter) {
595
+ return void 0;
596
+ }
597
+ return formatter(parsedValue);
598
+ }
599
+
600
+ // src/Frames.ts
619
601
  var DEFAULT_FPS = 60;
620
- var parseOptions6 = (opts) => {
602
+ var parseOptions5 = (opts) => {
621
603
  const { fps } = {
622
604
  fps: DEFAULT_FPS,
623
605
  ...opts
@@ -628,7 +610,7 @@ var parseOptions6 = (opts) => {
628
610
  };
629
611
  var Frames = class extends Metro {
630
612
  constructor(callback, opts) {
631
- super(() => callback(this), parseOptions6(opts));
613
+ super(() => callback(this), parseOptions5(opts));
632
614
  __publicField(this, "setFPS", (fps = DEFAULT_FPS) => {
633
615
  this.setTime(ms(fps, "fps" /* FPS */));
634
616
  });
@@ -649,15 +631,10 @@ var Frames = class extends Metro {
649
631
  }
650
632
  };
651
633
 
652
- // src/utils/expo.ts
634
+ // src/expo.ts
653
635
  function expo(n) {
654
636
  return Math.pow(clamp(n, 0, 1), Math.E);
655
637
  }
656
-
657
- // src/utils/flip.ts
658
- function flip(n) {
659
- return n * -1;
660
- }
661
638
  // Annotate the CommonJS export names for ESM import in node:
662
639
  0 && (module.exports = {
663
640
  Drunk,
@@ -675,7 +652,6 @@ function flip(n) {
675
652
  TimeFormat,
676
653
  clamp,
677
654
  expo,
678
- flip,
679
655
  ms,
680
656
  now
681
657
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/utils/clamp.ts","../src/math/Rand.ts","../src/math/Drunk.ts","../src/utils/now.ts","../src/math/Scale.ts","../src/math/Env.ts","../src/math/Sine.ts","../src/constants.ts","../src/utils/ms.ts","../src/timers/Metro.ts","../src/timers/Frames.ts","../src/utils/expo.ts","../src/utils/flip.ts"],"sourcesContent":["export { Drunk, type DrunkOptions, type DrunkState } from './math/Drunk';\nexport { Env, type EnvOptions, type EnvState } from './math/Env';\nexport { Rand, type RandOptions, type RandState } from './math/Rand';\nexport {\n Scale,\n type ScaleOptions,\n type ScaleRange,\n type ScaleState,\n} from './math/Scale';\nexport {\n Sine,\n type SineOptions,\n type SineState,\n SINE_PERIOD,\n} from './math/Sine';\nexport { Frames, type FramesOptions } from './timers/Frames';\nexport { Metro, type MetroOptions, type TimerCallback } from './timers/Metro';\nexport { clamp } from './utils/clamp';\nexport { expo } from './utils/expo';\nexport { flip } from './utils/flip';\nexport { ms, type FPS, TimeFormat } from './utils/ms';\nexport { now } from './utils/now';\nexport * from './constants';\n","export function clamp(n: number): number;\nexport function clamp(n: number, max: number): number;\nexport function clamp(n: number, min: number, max: number): number;\n\n/**\n * Constrains an input value to a min...max range.\n * @param n - The value to constrain.\n * @param min - Lower bound (defaults to 0).\n * @param max - Upper bound (defaults to 1).\n * @returns The clamped value.\n */\nexport function clamp(n: number, min?: number, max?: number) {\n let a = 0;\n let b = 1;\n\n if (typeof min === 'number') {\n if (typeof max === 'number') {\n a = min;\n b = max;\n } else {\n a = 0;\n b = min;\n }\n }\n\n return Math.min(Math.max(n, a), b);\n}\n","import { clamp } from '../utils/clamp';\n\n/** Options for configuring a Rand generator. */\nexport type RandOptions = {\n /** Lower bound of the range. Defaults to 0. */\n min?: number;\n /** Upper bound of the range. Defaults to 1. */\n max?: number;\n};\n\n/** Snapshot of a Rand generator's internal state. */\nexport type RandState = {\n min: number;\n max: number;\n value: number;\n};\n\nexport const parseOptions = (opts?: RandOptions): Required<RandOptions> => {\n return {\n min: 0,\n max: 1,\n ...opts,\n };\n};\n\n/**\n * Random number generator that produces values within a bounded range.\n * @param opts - {@link RandOptions} for configuring the range.\n */\nexport class Rand {\n state: RandState;\n\n static rand(opts?: RandOptions) {\n return new Rand(opts).value();\n }\n\n constructor(opts?: RandOptions) {\n const { min, max } = parseOptions(opts);\n\n this.state = { max, min, value: 0 };\n this.next();\n }\n\n setRange(partialOpts: RandOptions) {\n const { value = 0 } = this.state;\n const { min, max } = {\n ...this.state,\n ...partialOpts,\n };\n\n this.state = {\n ...this.state,\n max,\n min,\n value: clamp(value, min, max),\n };\n }\n\n value() {\n return this.state.value;\n }\n\n next() {\n const { min, max } = this.state;\n const updates = Math.random() * (max - min) + min;\n\n this.state.value = updates;\n\n return updates;\n }\n}\n","import { clamp } from '../utils/clamp';\nimport { Rand } from './Rand';\n\nexport const DEFAULT_DRUNK_STEP = 0.1;\n\n/** Options for configuring a Drunk random walk. */\nexport type DrunkOptions = {\n /** Upper bound of the range. Defaults to 1. */\n max?: number;\n /** Lower bound of the range. Defaults to 0. */\n min?: number;\n /** Initial value. If omitted, a random value within the range is used. */\n startsAt?: number;\n /** Maximum step size as a fraction of the range (0-1). Defaults to 0.1. */\n step?: number;\n};\n\n/** Snapshot of a Drunk walk's internal state. */\nexport type DrunkState = {\n initialValue: number;\n max: number;\n min: number;\n step: number;\n value: number;\n};\n\nexport const parseStepSize = (step?: number): number =>\n typeof step !== 'undefined' ? clamp(step, 0, 1) : DEFAULT_DRUNK_STEP;\n\nexport const parseOptions = (opts?: DrunkOptions): Required<DrunkOptions> => {\n const { step, ...restOpts } = opts || {};\n const parsedStepSize = parseStepSize(step);\n\n return {\n max: 1,\n min: 0,\n startsAt: 0,\n step: parsedStepSize,\n ...restOpts,\n };\n};\n\n/**\n * Stochastic random walk generator that produces values within a bounded range.\n * @param opts - {@link DrunkOptions} for configuring the walk.\n */\nexport class Drunk {\n state: DrunkState;\n protected _initialValue: Rand;\n protected _step: Rand;\n\n constructor(opts?: DrunkOptions) {\n const { min, max, step, startsAt } = parseOptions(opts);\n\n this._initialValue = new Rand({ min, max });\n this._step = new Rand({ min: -1, max: 1 });\n\n const initialValue =\n typeof opts?.startsAt !== 'undefined'\n ? startsAt\n : this._initialValue.value();\n\n this.state = {\n initialValue,\n max,\n min,\n step,\n value: initialValue,\n };\n }\n\n setRange(partialOpts?: Pick<DrunkOptions, 'min' | 'max'>) {\n const { max, min } = {\n min: this.state.min,\n max: this.state.max,\n ...partialOpts,\n };\n\n this._initialValue.setRange({ min, max });\n this.state = {\n ...this.state,\n ...(min !== this.state.min || max !== this.state.max\n ? {\n initialValue: clamp(this._initialValue.value(), min, max),\n max,\n min,\n value: clamp(this.state.value, min, max),\n }\n : {\n max,\n min,\n }),\n };\n }\n\n setStepSize(partialOpts?: Pick<DrunkOptions, 'step'>) {\n const step = parseStepSize(partialOpts?.step);\n\n this.state = {\n ...this.state,\n step,\n };\n }\n\n reset(opts?: DrunkOptions) {\n const { min, max, startsAt, step } = parseOptions(opts);\n\n this.setRange({ min, max });\n this.setStepSize({ step });\n\n const initialValue =\n typeof opts?.startsAt !== 'undefined'\n ? startsAt\n : this._initialValue.next();\n\n this.state = {\n ...this.state,\n initialValue,\n value: initialValue,\n };\n }\n\n value() {\n return this.state.value;\n }\n\n next() {\n const { min, max, step, value } = this.state;\n const updates = clamp(value + max * this._step.next() * step, min, max);\n\n this.state.value = updates;\n\n return updates;\n }\n}\n","let internal: () => number;\n\nif (typeof performance !== 'undefined' && 'now' in performance) {\n internal = () => {\n return performance.now();\n };\n} else if (\n typeof process === 'object' &&\n process.toString() === '[object process]'\n) {\n const timestamp = () => {\n const hr = process.hrtime();\n return hr[0] * 1e9 + hr[1];\n };\n const initial = timestamp();\n\n internal = () => {\n return (timestamp() - initial) / 1e6;\n };\n} else {\n const initial = Date.now();\n\n internal = () => {\n return Date.now() - initial;\n };\n}\n\n/**\n * Cross-environment high-resolution timestamp (performance.now polyfill).\n * @returns Elapsed milliseconds since initialization.\n */\nexport function now() {\n return internal();\n}\n","import { clamp } from '../utils/clamp';\n\n/** A numeric range with min and max bounds. */\nexport type ScaleRange = {\n min?: number;\n max: number;\n};\n\n/** Options for configuring a Scale mapper. */\nexport type ScaleOptions = {\n /** Input range. Defaults to { min: 0, max: 1 }. */\n from?: ScaleRange;\n /** Output range. Defaults to { min: 0, max: 1 }. */\n to?: ScaleRange;\n};\n\n/** Snapshot of a Scale mapper's internal state. */\nexport type ScaleState = {\n from: Required<ScaleRange>;\n to: Required<ScaleRange>;\n value: number;\n};\n\nexport const parseOptions = (\n opts?: ScaleOptions,\n): { from: Required<ScaleRange>; to: Required<ScaleRange> } => {\n const { from, to } = {\n ...opts,\n from: {\n min: 0,\n max: 1,\n ...opts?.from,\n },\n to: {\n min: 0,\n max: 1,\n ...opts?.to,\n },\n };\n\n return {\n from,\n to,\n };\n};\n\nexport const updateStateFromOptions = (\n opts: ScaleOptions,\n prevState: ScaleState,\n): ScaleState => {\n const { from, to } = opts;\n\n const updatedTo = {\n ...prevState.to,\n ...to,\n };\n\n return {\n ...prevState,\n from: {\n ...prevState.from,\n ...from,\n },\n to: updatedTo,\n value: clamp(prevState.value, updatedTo.min, updatedTo.max),\n };\n};\n\n/**\n * Linear map of values from one range to another, supports negative values and inversion.\n * @param opts - {@link ScaleOptions} for configuring input and output ranges.\n */\nexport class Scale {\n state: ScaleState;\n\n static scale(n: number, opts?: ScaleOptions) {\n return new Scale(opts).scale(n);\n }\n\n constructor(opts?: ScaleOptions) {\n const { from, to } = parseOptions(opts);\n this.state = { from, to, value: to.min };\n }\n\n setRanges(opts: ScaleOptions) {\n this.state = updateStateFromOptions(opts, this.state);\n }\n\n reset(opts: ScaleOptions) {\n const { from, to } = parseOptions(opts);\n this.state = { from, to, value: to.min };\n }\n\n value() {\n return this.state.value;\n }\n\n scale(n: number) {\n const { from, to } = this.state;\n const updates =\n to.min +\n ((clamp(n, from.min, from.max) - from.min) * (to.max - to.min)) /\n (from.max - from.min);\n\n this.state.value = updates;\n\n return updates;\n }\n}\n","import { now } from '../utils/now';\nimport { Scale } from './Scale';\n\n/** Snapshot of an Env's internal state. */\nexport type EnvState = {\n duration: number;\n from: number;\n prev: number;\n to: number;\n totalElapsed: number;\n value: number;\n};\n\n/** Options for configuring an Env envelope. */\nexport type EnvOptions = {\n /** Duration of the envelope in milliseconds. */\n duration: number;\n /** Starting value. Defaults to 0. */\n from?: number;\n /** Ending value. Defaults to 1. */\n to?: number;\n};\n\nexport const parseOptions = (opts?: EnvOptions): Required<EnvOptions> => {\n return {\n duration: 0,\n from: 0,\n to: 1,\n ...opts,\n };\n};\n\nconst getInitialState = ({\n from,\n to,\n duration,\n}: Required<EnvOptions>): EnvState => {\n return {\n duration,\n from,\n prev: now(),\n to,\n totalElapsed: 0,\n value: from,\n };\n};\n\nexport const updateStateFromOptions = (\n opts: EnvOptions | undefined,\n prevState: EnvState,\n): EnvState => {\n const { from, to, duration } = {\n ...prevState,\n ...opts,\n };\n\n return {\n ...prevState,\n duration,\n from,\n to,\n totalElapsed: 0,\n };\n};\n\n/**\n * Linear envelope which interpolates between two values over a duration. Useful for audio envelopes, transitions, and animations.\n * @param opts - {@link EnvOptions} for configuring the envelope.\n */\nexport class Env {\n state: EnvState;\n protected _interpolator: Scale;\n\n constructor(opts: EnvOptions) {\n const { from, to, duration } = parseOptions(opts);\n\n this.state = getInitialState({ from, to, duration });\n this._interpolator = new Scale({\n from: {\n min: 0,\n max: duration,\n },\n to: {\n min: from,\n max: to,\n },\n });\n }\n\n setDuration(duration: number) {\n const { to, totalElapsed } = this.state;\n\n this.state = {\n ...this.state,\n ...(duration <= totalElapsed\n ? {\n duration,\n value: to,\n }\n : { duration }),\n };\n }\n\n reset(opts?: EnvOptions) {\n const updates = updateStateFromOptions(opts, this.state);\n\n this.state = {\n ...updates,\n prev: now(),\n value: updates.from,\n };\n this._interpolator.setRanges({\n from: {\n min: 0,\n max: updates.duration,\n },\n to: {\n min: updates.from,\n max: updates.to,\n },\n });\n }\n\n done() {\n return this.state.duration <= this.state.totalElapsed;\n }\n\n value() {\n const { to, value } = this.state;\n\n if (this.done()) {\n return to;\n }\n\n return value;\n }\n\n next() {\n if (this.done()) {\n return this.value();\n }\n\n const { prev, totalElapsed: prevTotalElapsed } = this.state;\n\n const curr = now();\n const tickInterval = curr - prev;\n const totalElapsed = prevTotalElapsed + tickInterval;\n const updates = this._interpolator.scale(totalElapsed);\n\n this.state.prev = curr;\n this.state.totalElapsed = totalElapsed;\n this.state.value = updates;\n\n return updates;\n }\n}\n","import { clamp } from '../utils/clamp';\nimport { now } from '../utils/now';\nimport { Scale } from './Scale';\n\nexport const SINE_PERIOD = Math.PI * 2 - 0.0001;\n\n/** Options for configuring a Sine oscillator. */\nexport type SineOptions = {\n /** Duration of one full cycle in milliseconds. */\n duration: number;\n};\n\n/** Snapshot of a Sine oscillator's internal state. */\nexport type SineState = {\n cycle: number;\n duration: number;\n prev: number;\n totalElapsed: number;\n value: number;\n};\n\nconst getInitialState = (duration: number): SineState => ({\n cycle: 0,\n duration,\n prev: now(),\n totalElapsed: 0,\n value: 0,\n});\n\n/**\n * Time-based sine wave oscillator that outputs values between -1 and 1.\n * @param opts - {@link SineOptions} for configuring the oscillator.\n */\nexport class Sine {\n state: SineState;\n protected _interpolator: Scale;\n\n constructor(opts: SineOptions) {\n const { duration } = opts;\n\n this._interpolator = new Scale({\n from: {\n min: 0,\n max: duration,\n },\n to: {\n min: 0,\n max: SINE_PERIOD,\n },\n });\n this.state = getInitialState(duration);\n }\n\n setDuration(duration: number) {\n this.state = {\n ...this.state,\n duration,\n };\n }\n\n reset(opts?: SineOptions) {\n const { duration } = {\n ...this.state,\n ...opts,\n };\n\n this.state = getInitialState(duration);\n }\n\n value() {\n return this.state.value;\n }\n\n next() {\n const {\n cycle,\n duration,\n prev,\n totalElapsed: prevTotalElapsed,\n } = this.state;\n const curr = now();\n const tickInterval = curr - prev;\n const totalElapsed = prevTotalElapsed + tickInterval;\n\n const updates = clamp(\n Math.sin(this._interpolator.scale(totalElapsed)),\n -1,\n 1,\n );\n\n if (cycle >= duration) {\n this.state.cycle = 0;\n } else {\n this.state.cycle = cycle + tickInterval;\n }\n\n this.state.prev = curr;\n this.state.totalElapsed = totalElapsed;\n this.state.value = updates;\n\n return updates;\n }\n}\n","export const SIXTY_FPS = 1000 / 60;\nexport const MS_IN_SECOND = 1000;\nexport const MS_IN_MINUTE = 60 * MS_IN_SECOND;\nexport const MS_IN_HOUR = MS_IN_MINUTE * 60;\n","import { MS_IN_SECOND, MS_IN_MINUTE, MS_IN_HOUR } from '../constants';\n\nexport type FPS = 15 | 30 | 60;\n\nexport enum TimeFormat {\n FPS = 'fps',\n HOURS = 'h',\n HZ = 'hz',\n MILLISECONDS = 'ms',\n MINUTES = 'm',\n SECONDS = 's',\n}\n\nexport type AvailableTimeFormats = `${TimeFormat}`;\n\nexport const FORMAT_IDENTIFIERS: AvailableTimeFormats[] = [\n TimeFormat.FPS,\n TimeFormat.HOURS,\n TimeFormat.HZ,\n TimeFormat.MILLISECONDS,\n TimeFormat.MINUTES,\n TimeFormat.SECONDS,\n]\n // Desc length sort so that `ms` matches prior to `m`\n .sort((a, b) => b.length - a.length);\n\ntype FormatGetter = (val: number) => number;\n\nconst FORMATTERS = new Map<AvailableTimeFormats, FormatGetter>([\n [TimeFormat.FPS, (val: number) => MS_IN_SECOND / val],\n [TimeFormat.HOURS, (val: number) => val * MS_IN_HOUR],\n [TimeFormat.HZ, (val: number) => (1 / val) * MS_IN_SECOND],\n [TimeFormat.MILLISECONDS, (val: number) => val],\n [TimeFormat.MINUTES, (val: number) => val * MS_IN_MINUTE],\n [TimeFormat.SECONDS, (val: number) => val * MS_IN_SECOND],\n]);\n\nconst sanitizeStringVal = (val: string) => val.toLocaleLowerCase().trim();\n\nconst parseStringValAndFormat = (val: string) => {\n for (let i = 0; i < FORMAT_IDENTIFIERS.length; i += 1) {\n const format = FORMAT_IDENTIFIERS[i];\n\n if (val.includes(format)) {\n const value = Number(val.replace(' ', '').replace(format, ''));\n\n return {\n format,\n value,\n };\n }\n }\n\n return {\n format: undefined,\n value: undefined,\n };\n};\n\nexport function ms(val: string | null | undefined): number | undefined;\nexport function ms(\n val: string | number | null | undefined,\n format?: AvailableTimeFormats | TimeFormat,\n): number | undefined;\n\n/**\n * Converts time format strings or numeric values to their corresponding value in milliseconds.\n * @param val - A string like `'60fps'`, `'2s'`, or a numeric value.\n * @param format - Explicit time format when `val` is a number.\n * @returns Milliseconds, or undefined if the input is invalid.\n */\nexport function ms(\n val: string | number | null | undefined,\n format?: AvailableTimeFormats | TimeFormat,\n): number | undefined {\n let parsedValue: number | null | undefined = null;\n let parsedFormat: AvailableTimeFormats = format || TimeFormat.MILLISECONDS;\n\n if (typeof val === 'string') {\n const parsed = parseStringValAndFormat(sanitizeStringVal(val));\n\n if (typeof parsed.value !== 'undefined') {\n parsedValue = parsed.value;\n }\n\n if (parsed.format) {\n parsedFormat = parsed.format;\n }\n } else {\n parsedValue = val;\n }\n\n if (\n typeof parsedValue === 'undefined' ||\n parsedValue === null ||\n Number.isNaN(parsedValue)\n ) {\n return undefined;\n }\n\n const formatter = FORMATTERS.get(parsedFormat);\n\n if (!formatter) {\n return undefined;\n }\n\n return formatter(parsedValue);\n}\n","import { SIXTY_FPS } from '../constants';\nimport { now } from '../utils/now';\n\n/** Snapshot of a running timer's internal state. */\nexport type TimerState = {\n initialTime: number;\n isRunning: boolean;\n iterations: number;\n prev: number;\n tickInterval: number;\n time: number;\n totalElapsed: number;\n};\n\nexport const getInitialState = (initialTime: number): TimerState => {\n return {\n initialTime,\n isRunning: false,\n iterations: -1,\n prev: 0,\n tickInterval: 0,\n time: initialTime,\n totalElapsed: 0,\n };\n};\n\nexport const processTimerState = (state: TimerState): TimerState | null => {\n const { time, prev, totalElapsed, iterations } = state;\n const curr = now();\n\n if (iterations === -1) {\n return {\n ...state,\n prev: curr,\n iterations: 0,\n };\n }\n\n const tickInterval = curr - prev;\n\n if (tickInterval <= time) {\n return null;\n }\n\n return {\n ...state,\n iterations: iterations + 1,\n prev: curr,\n tickInterval,\n totalElapsed: totalElapsed + tickInterval,\n };\n};\n\n/** Options for configuring a Metro timer. */\nexport type MetroOptions = {\n /** Interval between ticks in milliseconds. Defaults to ~16.67ms (60fps). */\n time?: number;\n};\n\nexport const parseOptions = (opts?: MetroOptions): Required<MetroOptions> => {\n return {\n time: SIXTY_FPS,\n ...opts,\n };\n};\n\n/** Callback invoked on each timer tick with the timer instance. */\nexport type TimerCallback<T extends Metro> = (timer: T) => void;\n\n/**\n * High-resolution recursive timer with variable interval, provides runtime metrics via callback for time-based calculations.\n * @param callback - {@link TimerCallback} called on each tick with the timer instance.\n * @param opts - {@link MetroOptions} for configuring the timer interval.\n */\nexport class Metro {\n state: TimerState;\n protected _listeners: TimerCallback<Metro>[];\n protected declare _timerId: ReturnType<typeof setTimeout> | number;\n\n constructor(callback: TimerCallback<Metro>, opts?: MetroOptions) {\n const { time } = parseOptions(opts);\n this.state = getInitialState(time);\n this._listeners = [callback];\n }\n\n protected asyncHandler(callback: () => void) {\n this._timerId = setTimeout(callback, SIXTY_FPS);\n }\n\n protected clearAsyncHandler() {\n clearTimeout(this._timerId);\n }\n\n stop = () => {\n const { totalElapsed } = this.state;\n this.reset();\n this.clearAsyncHandler();\n\n return totalElapsed;\n };\n\n reset = () => {\n const { initialTime } = this.state;\n this.state = getInitialState(initialTime);\n };\n\n setTime = (updatedTime = this.state.time) => {\n const time = Math.max(updatedTime, 0);\n\n this.state = {\n ...this.state,\n time,\n initialTime: time,\n };\n };\n\n run = () => {\n if (this.state.isRunning) {\n this.stop();\n }\n\n this.state = {\n ...this.state,\n isRunning: true,\n prev: now(),\n };\n\n const tick = () => {\n const updates = processTimerState(this.state);\n\n if (updates) {\n this.state = updates;\n this._listeners.forEach((listener) => {\n listener(this);\n });\n }\n\n if (this.state.isRunning) {\n this.asyncHandler(tick);\n }\n };\n\n tick();\n };\n}\n","import { ms, TimeFormat, type FPS } from '../utils/ms';\nimport { Metro, type TimerCallback, type MetroOptions } from './Metro';\n\n/** Options for configuring a Frames timer. */\nexport type FramesOptions = {\n /** Target frames per second (15, 30, or 60). Defaults to 60. */\n fps: FPS;\n};\n\nexport const DEFAULT_FPS: FPS = 60;\n\nexport const parseOptions = (opts?: FramesOptions): MetroOptions => {\n const { fps } = {\n fps: DEFAULT_FPS,\n ...opts,\n };\n\n return {\n time: ms(fps, TimeFormat.FPS),\n };\n};\n\n/**\n * Animation-loop timer that uses requestAnimationFrame when available.\n * @param callback - {@link TimerCallback} called on each frame tick.\n * @param opts - {@link FramesOptions} for configuring the target frame rate.\n */\nexport class Frames extends Metro {\n protected declare _timerId: ReturnType<typeof requestAnimationFrame>;\n\n constructor(callback: TimerCallback<Frames>, opts?: FramesOptions) {\n super(() => callback(this), parseOptions(opts));\n }\n\n protected asyncHandler(callback: () => void) {\n if (typeof window === 'undefined' || !('requestAnimationFrame' in window)) {\n super.asyncHandler(callback);\n } else {\n this._timerId = requestAnimationFrame(callback);\n }\n }\n\n protected clearAsyncHandler() {\n if (typeof window === 'undefined' || !('cancelAnimationFrame' in window)) {\n super.clearAsyncHandler();\n } else {\n cancelAnimationFrame(this._timerId);\n }\n }\n\n setFPS = (fps = DEFAULT_FPS) => {\n this.setTime(ms(fps, TimeFormat.FPS));\n };\n}\n","import { clamp } from './clamp';\n\n/**\n * Scales 0...1 by Euler's number to produce a natural feeling curve.\n * @param n - Input value (clamped to 0-1).\n * @returns The exponentially scaled value.\n */\nexport function expo(n: number): number {\n return Math.pow(clamp(n, 0, 1), Math.E);\n}\n","/**\n * Flips the sign of a number.\n * @param n - The input value.\n * @returns The negated value.\n */\nexport function flip(n: number): number {\n return n * -1;\n}\n"],"mappings":"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","names":["parseOptions","parseOptions","parseOptions","updateStateFromOptions","getInitialState","TimeFormat","getInitialState","parseOptions","parseOptions"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/clamp.ts","../src/Rand.ts","../src/Drunk.ts","../src/Scale.ts","../src/now.ts","../src/Env.ts","../src/Sine.ts","../src/constants.ts","../src/Metro.ts","../src/ms.ts","../src/Frames.ts","../src/expo.ts"],"sourcesContent":["export { Drunk, type DrunkOptions, type DrunkState } from './Drunk';\nexport { Env, type EnvOptions, type EnvState } from './Env';\nexport { Rand, type RandOptions, type RandState } from './Rand';\nexport { Scale, type ScaleOptions, type ScaleRange, type ScaleState } from './Scale';\nexport { Sine, type SineOptions, type SineState, SINE_PERIOD } from './Sine';\nexport { Frames, type FramesOptions } from './Frames';\nexport { Metro, type MetroOptions, type TimerCallback } from './Metro';\nexport { clamp } from './clamp';\nexport { expo } from './expo';\nexport { ms, type FPS, TimeFormat } from './ms';\nexport { now } from './now';\nexport * from './constants';\n","export function clamp(n: number): number;\nexport function clamp(n: number, max: number): number;\nexport function clamp(n: number, min: number, max: number): number;\n\n/**\n * Constrains an input value to a min...max range.\n * @param n - The value to constrain.\n * @param min - Lower bound (defaults to 0).\n * @param max - Upper bound (defaults to 1).\n * @returns The clamped value.\n */\nexport function clamp(n: number, min?: number, max?: number) {\n let a = 0;\n let b = 1;\n\n if (typeof min === 'number') {\n if (typeof max === 'number') {\n a = min;\n b = max;\n } else {\n a = 0;\n b = min;\n }\n }\n\n return Math.min(Math.max(n, a), b);\n}\n","import { clamp } from './clamp';\n\n/** Options for configuring a Rand generator. */\nexport type RandOptions = {\n /** Lower bound of the range. Defaults to 0. */\n min?: number;\n /** Upper bound of the range. Defaults to 1. */\n max?: number;\n};\n\n/** Snapshot of a Rand generator's internal state. */\nexport type RandState = {\n min: number;\n max: number;\n value: number;\n};\n\nexport const parseOptions = (opts?: RandOptions): Required<RandOptions> => {\n return {\n min: 0,\n max: 1,\n ...opts,\n };\n};\n\n/**\n * Random number generator that produces values within a bounded range.\n * @param opts - {@link RandOptions} for configuring the range.\n */\nexport class Rand {\n state: RandState;\n\n static rand(opts?: RandOptions) {\n return new Rand(opts).value();\n }\n\n constructor(opts?: RandOptions) {\n const { min, max } = parseOptions(opts);\n\n this.state = { max, min, value: 0 };\n this.next();\n }\n\n setRange(partialOpts: RandOptions) {\n const { value = 0 } = this.state;\n const { min, max } = {\n ...this.state,\n ...partialOpts,\n };\n\n this.state = {\n ...this.state,\n max,\n min,\n value: clamp(value, min, max),\n };\n }\n\n value() {\n return this.state.value;\n }\n\n next() {\n const { min, max } = this.state;\n const updates = Math.random() * (max - min) + min;\n\n this.state.value = updates;\n\n return updates;\n }\n}\n","import { Rand } from './Rand';\nimport { clamp } from './clamp';\n\nexport const DEFAULT_DRUNK_STEP = 0.1;\n\n/** Options for configuring a Drunk random walk. */\nexport type DrunkOptions = {\n /** Upper bound of the range. Defaults to 1. */\n max?: number;\n /** Lower bound of the range. Defaults to 0. */\n min?: number;\n /** Initial value. If omitted, a random value within the range is used. */\n startsAt?: number;\n /** Maximum step size as a fraction of the range (0-1). Defaults to 0.1. */\n step?: number;\n};\n\n/** Snapshot of a Drunk walk's internal state. */\nexport type DrunkState = {\n initialValue: number;\n max: number;\n min: number;\n step: number;\n value: number;\n};\n\nexport const parseStepSize = (step?: number): number =>\n typeof step !== 'undefined' ? clamp(step, 0, 1) : DEFAULT_DRUNK_STEP;\n\nexport const parseOptions = (opts?: DrunkOptions): Required<DrunkOptions> => {\n const { step, ...restOpts } = opts || {};\n const parsedStepSize = parseStepSize(step);\n\n return {\n max: 1,\n min: 0,\n startsAt: 0,\n step: parsedStepSize,\n ...restOpts,\n };\n};\n\n/**\n * Stochastic random walk generator that produces values within a bounded range.\n * @param opts - {@link DrunkOptions} for configuring the walk.\n */\nexport class Drunk {\n state: DrunkState;\n protected _initialValue: Rand;\n protected _step: Rand;\n\n constructor(opts?: DrunkOptions) {\n const { min, max, step, startsAt } = parseOptions(opts);\n\n this._initialValue = new Rand({ min, max });\n this._step = new Rand({ min: -1, max: 1 });\n\n const initialValue =\n typeof opts?.startsAt !== 'undefined' ? startsAt : this._initialValue.value();\n\n this.state = {\n initialValue,\n max,\n min,\n step,\n value: initialValue,\n };\n }\n\n setRange(partialOpts?: Pick<DrunkOptions, 'min' | 'max'>) {\n const { max, min } = {\n min: this.state.min,\n max: this.state.max,\n ...partialOpts,\n };\n\n this._initialValue.setRange({ min, max });\n this.state = {\n ...this.state,\n ...(min !== this.state.min || max !== this.state.max\n ? {\n initialValue: clamp(this._initialValue.value(), min, max),\n max,\n min,\n value: clamp(this.state.value, min, max),\n }\n : {\n max,\n min,\n }),\n };\n }\n\n setStepSize(partialOpts?: Pick<DrunkOptions, 'step'>) {\n const step = parseStepSize(partialOpts?.step);\n\n this.state = {\n ...this.state,\n step,\n };\n }\n\n reset(opts?: DrunkOptions) {\n const { min, max, startsAt, step } = parseOptions(opts);\n\n this.setRange({ min, max });\n this.setStepSize({ step });\n\n const initialValue =\n typeof opts?.startsAt !== 'undefined' ? startsAt : this._initialValue.next();\n\n this.state = {\n ...this.state,\n initialValue,\n value: initialValue,\n };\n }\n\n value() {\n return this.state.value;\n }\n\n next() {\n const { min, max, step, value } = this.state;\n const updates = clamp(value + max * this._step.next() * step, min, max);\n\n this.state.value = updates;\n\n return updates;\n }\n}\n","import { clamp } from './clamp';\n\n/** A numeric range with min and max bounds. */\nexport type ScaleRange = {\n min?: number;\n max: number;\n};\n\n/** Options for configuring a Scale mapper. */\nexport type ScaleOptions = {\n /** Input range. Defaults to { min: 0, max: 1 }. */\n from?: ScaleRange;\n /** Output range. Defaults to { min: 0, max: 1 }. */\n to?: ScaleRange;\n};\n\n/** Snapshot of a Scale mapper's internal state. */\nexport type ScaleState = {\n /** Input range. */\n from: Required<ScaleRange>;\n /** Precomputed (to.max - to.min) / (from.max - from.min), updated when ranges change. */\n ratio: number;\n /** Output range. */\n to: Required<ScaleRange>;\n /** Last scaled value. */\n value: number;\n};\n\n/** Precompute the scale factor so the hot path avoids a division per call. */\nconst computeRatio = (from: Required<ScaleRange>, to: Required<ScaleRange>) =>\n (to.max - to.min) / (from.max - from.min);\n\n/** Build initial state from options, applying defaults and computing the ratio. */\nexport const parseInitialState = (opts?: ScaleOptions): ScaleState => {\n const initialRange: Pick<ScaleState, 'from' | 'to'> = {\n from: {\n min: 0,\n max: 1,\n ...opts?.from,\n },\n to: {\n min: 0,\n max: 1,\n ...opts?.to,\n },\n };\n\n return {\n ...initialRange,\n ratio: computeRatio(initialRange.from, initialRange.to),\n value: initialRange.to.min,\n };\n};\n\n/** Merge partial range updates into existing state, recomputing the ratio. */\nexport const updateStateFromOptions = (opts: ScaleOptions, prevState: ScaleState): ScaleState => {\n const { from, to } = opts;\n const updatedFrom: Required<ScaleRange> = {\n ...prevState.from,\n ...from,\n };\n const updatedTo: Required<ScaleRange> = {\n ...prevState.to,\n ...to,\n };\n\n return {\n ...prevState,\n from: updatedFrom,\n ratio: computeRatio(updatedFrom, updatedTo),\n to: updatedTo,\n value: clamp(prevState.value, updatedTo.min, updatedTo.max),\n };\n};\n\n/**\n * Linear map of values from one range to another, supports negative values and inversion.\n * @param opts - {@link ScaleOptions} for configuring input and output ranges.\n */\nexport class Scale {\n state: ScaleState;\n\n static scale(n: number, opts?: ScaleOptions) {\n return new Scale(opts).scale(n);\n }\n\n constructor(opts?: ScaleOptions) {\n this.state = parseInitialState(opts);\n }\n\n setRanges(opts: ScaleOptions) {\n this.state = updateStateFromOptions(opts, this.state);\n }\n\n reset(opts: ScaleOptions) {\n this.state = parseInitialState(opts);\n }\n\n value() {\n return this.state.value;\n }\n\n scale(n: number) {\n const { from, to, ratio } = this.state;\n const updates = to.min + (clamp(n, from.min, from.max) - from.min) * ratio;\n\n this.state.value = updates;\n\n return updates;\n }\n}\n","type InnerNow = () => number;\n\n/** Resolve the best available clock once at module load. */\nconst innerNow = ((): InnerNow => {\n // Browser or modern Node (>= 16)\n if (typeof performance !== 'undefined' && 'now' in performance) {\n return () => performance.now();\n }\n\n // Older Node — use process.hrtime, offset from first call\n if (typeof process === 'object' && process.toString() === '[object process]') {\n const ts = () => {\n const hr = process.hrtime();\n return hr[0] * 1e9 + hr[1];\n };\n const initialNow = ts();\n return () => (ts() - initialNow) / 1e6;\n }\n\n // Fallback — Date.now with manual offset\n const initialNow = Date.now();\n return () => Date.now() - initialNow;\n})();\n\n/**\n * Cross-environment high-resolution timestamp (performance.now polyfill).\n * @returns Elapsed milliseconds since initialization.\n */\nexport function now(): number {\n return innerNow();\n}\n","import { Scale } from './Scale';\nimport { now } from './now';\n\n/** Snapshot of an Env's internal state. */\nexport type EnvState = {\n duration: number;\n from: number;\n prev: number;\n to: number;\n totalElapsed: number;\n value: number;\n};\n\n/** Options for configuring an Env envelope. */\nexport type EnvOptions = {\n /** Duration of the envelope in milliseconds. */\n duration: number;\n /** Starting value. Defaults to 0. */\n from?: number;\n /** Ending value. Defaults to 1. */\n to?: number;\n};\n\nexport const parseOptions = (opts?: EnvOptions): Required<EnvOptions> => {\n return {\n duration: 0,\n from: 0,\n to: 1,\n ...opts,\n };\n};\n\nconst getInitialState = ({ from, to, duration }: Required<EnvOptions>): EnvState => {\n return {\n duration,\n from,\n prev: now(),\n to,\n totalElapsed: 0,\n value: from,\n };\n};\n\nexport const updateStateFromOptions = (\n opts: EnvOptions | undefined,\n prevState: EnvState\n): EnvState => {\n const { from, to, duration } = {\n ...prevState,\n ...opts,\n };\n\n return {\n ...prevState,\n duration,\n from,\n to,\n totalElapsed: 0,\n };\n};\n\n/**\n * Linear envelope which interpolates between two values over a duration. Useful for audio envelopes, transitions, and animations.\n * @param opts - {@link EnvOptions} for configuring the envelope.\n */\nexport class Env {\n state: EnvState;\n protected _interpolator: Scale;\n\n constructor(opts: EnvOptions) {\n const { from, to, duration } = parseOptions(opts);\n\n this.state = getInitialState({ from, to, duration });\n this._interpolator = new Scale({\n from: {\n min: 0,\n max: duration,\n },\n to: {\n min: from,\n max: to,\n },\n });\n }\n\n setDuration(duration: number) {\n const { to, totalElapsed } = this.state;\n\n this.state = {\n ...this.state,\n ...(duration <= totalElapsed\n ? {\n duration,\n value: to,\n }\n : { duration }),\n };\n }\n\n reset(opts?: EnvOptions) {\n const updates = updateStateFromOptions(opts, this.state);\n\n this.state = {\n ...updates,\n prev: now(),\n value: updates.from,\n };\n this._interpolator.setRanges({\n from: {\n min: 0,\n max: updates.duration,\n },\n to: {\n min: updates.from,\n max: updates.to,\n },\n });\n }\n\n done() {\n return this.state.duration <= this.state.totalElapsed;\n }\n\n value() {\n const { to, value } = this.state;\n\n if (this.done()) {\n return to;\n }\n\n return value;\n }\n\n next() {\n if (this.done()) {\n return this.value();\n }\n\n const { prev, totalElapsed: prevTotalElapsed } = this.state;\n\n const curr = now();\n const tickInterval = curr - prev;\n const totalElapsed = prevTotalElapsed + tickInterval;\n const updates = this._interpolator.scale(totalElapsed);\n\n this.state.prev = curr;\n this.state.totalElapsed = totalElapsed;\n this.state.value = updates;\n\n return updates;\n }\n}\n","import { Scale } from './Scale';\nimport { clamp } from './clamp';\nimport { now } from './now';\n\nexport const SINE_PERIOD = Math.PI * 2 - 0.0001;\n\n/** Options for configuring a Sine oscillator. */\nexport type SineOptions = {\n /** Duration of one full cycle in milliseconds. */\n duration: number;\n};\n\n/** Snapshot of a Sine oscillator's internal state. */\nexport type SineState = {\n cycle: number;\n duration: number;\n prev: number;\n totalElapsed: number;\n value: number;\n};\n\nconst getInitialState = (duration: number): SineState => ({\n cycle: 0,\n duration,\n prev: now(),\n totalElapsed: 0,\n value: 0,\n});\n\n/**\n * Time-based sine wave oscillator that outputs values between -1 and 1.\n * @param opts - {@link SineOptions} for configuring the oscillator.\n */\nexport class Sine {\n state: SineState;\n protected _interpolator: Scale;\n\n constructor(opts: SineOptions) {\n const { duration } = opts;\n\n this._interpolator = new Scale({\n from: {\n min: 0,\n max: duration,\n },\n to: {\n min: 0,\n max: SINE_PERIOD,\n },\n });\n this.state = getInitialState(duration);\n }\n\n setDuration(duration: number) {\n this.state = {\n ...this.state,\n duration,\n };\n }\n\n reset(opts?: SineOptions) {\n const { duration } = {\n ...this.state,\n ...opts,\n };\n\n this.state = getInitialState(duration);\n }\n\n value() {\n return this.state.value;\n }\n\n next() {\n const { cycle, duration, prev, totalElapsed: prevTotalElapsed } = this.state;\n const curr = now();\n const tickInterval = curr - prev;\n const totalElapsed = prevTotalElapsed + tickInterval;\n\n const updates = clamp(Math.sin(this._interpolator.scale(totalElapsed)), -1, 1);\n\n if (cycle >= duration) {\n this.state.cycle = 0;\n } else {\n this.state.cycle = cycle + tickInterval;\n }\n\n this.state.prev = curr;\n this.state.totalElapsed = totalElapsed;\n this.state.value = updates;\n\n return updates;\n }\n}\n","export const SIXTY_FPS = 1000 / 60;\nexport const MS_IN_SECOND = 1000;\nexport const MS_IN_MINUTE = 60 * MS_IN_SECOND;\nexport const MS_IN_HOUR = MS_IN_MINUTE * 60;\n","import { SIXTY_FPS } from './constants';\nimport { now } from './now';\n\n/** Snapshot of a running timer's internal state. */\nexport type TimerState = {\n initialTime: number;\n isRunning: boolean;\n iterations: number;\n prev: number;\n tickInterval: number;\n time: number;\n totalElapsed: number;\n};\n\nexport const getInitialState = (initialTime: number): TimerState => {\n return {\n initialTime,\n isRunning: false,\n iterations: -1,\n prev: 0,\n tickInterval: 0,\n time: initialTime,\n totalElapsed: 0,\n };\n};\n\nexport const processTimerState = (state: TimerState): TimerState | null => {\n const { time, prev, totalElapsed, iterations } = state;\n const curr = now();\n\n if (iterations === -1) {\n return {\n ...state,\n prev: curr,\n iterations: 0,\n };\n }\n\n const tickInterval = curr - prev;\n\n if (tickInterval <= time) {\n return null;\n }\n\n return {\n ...state,\n iterations: iterations + 1,\n prev: curr,\n tickInterval,\n totalElapsed: totalElapsed + tickInterval,\n };\n};\n\n/** Options for configuring a Metro timer. */\nexport type MetroOptions = {\n /** Interval between ticks in milliseconds. Defaults to ~16.67ms (60fps). */\n time?: number;\n};\n\nexport const parseOptions = (opts?: MetroOptions): Required<MetroOptions> => {\n return {\n time: SIXTY_FPS,\n ...opts,\n };\n};\n\n/** Callback invoked on each timer tick with the timer instance. */\nexport type TimerCallback<T extends Metro> = (timer: T) => void;\n\n/**\n * High-resolution recursive timer with variable interval, provides runtime metrics via callback for time-based calculations.\n * @param callback - {@link TimerCallback} called on each tick with the timer instance.\n * @param opts - {@link MetroOptions} for configuring the timer interval.\n */\nexport class Metro {\n state: TimerState;\n protected _listeners: TimerCallback<Metro>[];\n declare protected _timerId: ReturnType<typeof setTimeout> | number;\n\n constructor(callback: TimerCallback<Metro>, opts?: MetroOptions) {\n const { time } = parseOptions(opts);\n this.state = getInitialState(time);\n this._listeners = [callback];\n }\n\n protected asyncHandler(callback: () => void) {\n this._timerId = setTimeout(callback, SIXTY_FPS);\n }\n\n protected clearAsyncHandler() {\n clearTimeout(this._timerId);\n }\n\n stop = () => {\n const { totalElapsed } = this.state;\n this.reset();\n this.clearAsyncHandler();\n\n return totalElapsed;\n };\n\n reset = () => {\n const { initialTime } = this.state;\n this.state = getInitialState(initialTime);\n };\n\n setTime = (updatedTime = this.state.time) => {\n const time = Math.max(updatedTime, 0);\n\n this.state = {\n ...this.state,\n time,\n initialTime: time,\n };\n };\n\n run = () => {\n if (this.state.isRunning) {\n this.stop();\n }\n\n this.state = {\n ...this.state,\n isRunning: true,\n prev: now(),\n };\n\n const tick = () => {\n const updates = processTimerState(this.state);\n\n if (updates) {\n this.state = updates;\n this._listeners.forEach((listener) => {\n listener(this);\n });\n }\n\n if (this.state.isRunning) {\n this.asyncHandler(tick);\n }\n };\n\n tick();\n };\n}\n","import { MS_IN_SECOND, MS_IN_MINUTE, MS_IN_HOUR } from './constants';\n\nexport type FPS = 15 | 30 | 60;\n\nexport enum TimeFormat {\n FPS = 'fps',\n HOURS = 'h',\n HZ = 'hz',\n MILLISECONDS = 'ms',\n MINUTES = 'm',\n SECONDS = 's',\n}\n\nexport type AvailableTimeFormats = `${TimeFormat}`;\n\nexport const FORMAT_IDENTIFIERS: AvailableTimeFormats[] = [\n TimeFormat.FPS,\n TimeFormat.HOURS,\n TimeFormat.HZ,\n TimeFormat.MILLISECONDS,\n TimeFormat.MINUTES,\n TimeFormat.SECONDS,\n]\n // Desc length sort so that `ms` matches prior to `m`\n .sort((a, b) => b.length - a.length);\n\ntype FormatGetter = (val: number) => number;\n\nconst FORMATTERS = new Map<AvailableTimeFormats, FormatGetter>([\n [TimeFormat.FPS, (val: number) => MS_IN_SECOND / val],\n [TimeFormat.HOURS, (val: number) => val * MS_IN_HOUR],\n [TimeFormat.HZ, (val: number) => (1 / val) * MS_IN_SECOND],\n [TimeFormat.MILLISECONDS, (val: number) => val],\n [TimeFormat.MINUTES, (val: number) => val * MS_IN_MINUTE],\n [TimeFormat.SECONDS, (val: number) => val * MS_IN_SECOND],\n]);\n\nconst sanitizeStringVal = (val: string) => val.toLocaleLowerCase().trim();\n\nconst parseStringValAndFormat = (val: string) => {\n for (let i = 0; i < FORMAT_IDENTIFIERS.length; i += 1) {\n const format = FORMAT_IDENTIFIERS[i];\n\n if (val.includes(format)) {\n const value = Number(val.replace(' ', '').replace(format, ''));\n\n return {\n format,\n value,\n };\n }\n }\n\n return {\n format: undefined,\n value: undefined,\n };\n};\n\nexport function ms(val: string | null | undefined): number | undefined;\nexport function ms(\n val: string | number | null | undefined,\n format?: AvailableTimeFormats | TimeFormat\n): number | undefined;\n\n/**\n * Converts time format strings or numeric values to their corresponding value in milliseconds.\n * @param val - A string like `'60fps'`, `'2s'`, or a numeric value.\n * @param format - Explicit time format when `val` is a number.\n * @returns Milliseconds, or undefined if the input is invalid.\n */\nexport function ms(\n val: string | number | null | undefined,\n format?: AvailableTimeFormats | TimeFormat\n): number | undefined {\n let parsedValue: number | null | undefined = null;\n let parsedFormat: AvailableTimeFormats = format || TimeFormat.MILLISECONDS;\n\n if (typeof val === 'string') {\n const parsed = parseStringValAndFormat(sanitizeStringVal(val));\n\n if (typeof parsed.value !== 'undefined') {\n parsedValue = parsed.value;\n }\n\n if (parsed.format) {\n parsedFormat = parsed.format;\n }\n } else {\n parsedValue = val;\n }\n\n if (typeof parsedValue === 'undefined' || parsedValue === null || Number.isNaN(parsedValue)) {\n return undefined;\n }\n\n const formatter = FORMATTERS.get(parsedFormat);\n\n if (!formatter) {\n return undefined;\n }\n\n return formatter(parsedValue);\n}\n","import { Metro, type TimerCallback, type MetroOptions } from './Metro';\nimport { ms, TimeFormat, type FPS } from './ms';\n\n/** Options for configuring a Frames timer. */\nexport type FramesOptions = {\n /** Target frames per second (15, 30, or 60). Defaults to 60. */\n fps: FPS;\n};\n\nexport const DEFAULT_FPS: FPS = 60;\n\nexport const parseOptions = (opts?: FramesOptions): MetroOptions => {\n const { fps } = {\n fps: DEFAULT_FPS,\n ...opts,\n };\n\n return {\n time: ms(fps, TimeFormat.FPS),\n };\n};\n\n/**\n * Animation-loop timer that uses requestAnimationFrame when available.\n * @param callback - {@link TimerCallback} called on each frame tick.\n * @param opts - {@link FramesOptions} for configuring the target frame rate.\n */\nexport class Frames extends Metro {\n declare protected _timerId: ReturnType<typeof requestAnimationFrame>;\n\n constructor(callback: TimerCallback<Frames>, opts?: FramesOptions) {\n super(() => callback(this), parseOptions(opts));\n }\n\n protected asyncHandler(callback: () => void) {\n if (typeof window === 'undefined' || !('requestAnimationFrame' in window)) {\n super.asyncHandler(callback);\n } else {\n this._timerId = requestAnimationFrame(callback);\n }\n }\n\n protected clearAsyncHandler() {\n if (typeof window === 'undefined' || !('cancelAnimationFrame' in window)) {\n super.clearAsyncHandler();\n } else {\n cancelAnimationFrame(this._timerId);\n }\n }\n\n setFPS = (fps = DEFAULT_FPS) => {\n this.setTime(ms(fps, TimeFormat.FPS));\n };\n}\n","import { clamp } from './clamp';\n\n/**\n * Scales 0...1 by Euler's number to produce a natural feeling curve.\n * @param n - Input value (clamped to 0-1).\n * @returns The exponentially scaled value.\n */\nexport function expo(n: number): number {\n return Math.pow(clamp(n, 0, 1), Math.E);\n}\n"],"mappings":"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","names":["parseOptions","initialNow","parseOptions","updateStateFromOptions","getInitialState","getInitialState","parseOptions","TimeFormat","parseOptions"]}