@sarmal/core 0.6.0 → 0.7.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.js CHANGED
@@ -49,7 +49,7 @@ function resolveCurve(curveDef) {
49
49
  period: curveDef.period ?? TWO_PI,
50
50
  speed: curveDef.speed ?? 1,
51
51
  skeleton: curveDef.skeleton,
52
- skeletonFn: curveDef.skeletonFn,
52
+ skeletonFn: curveDef.skeletonFn
53
53
  };
54
54
  }
55
55
  function createEngine(curveDef, trailLength = 120) {
@@ -75,7 +75,7 @@ function createEngine(curveDef, trailLength = 120) {
75
75
  actualTime += deltaTime;
76
76
  if (morphCurveB !== null && _morphAlpha !== null) {
77
77
  const a = curve.fn(t, actualTime, {});
78
- const tB = _morphStrategy === "normalized" ? (t / curve.period) * morphCurveB.period : t;
78
+ const tB = _morphStrategy === "normalized" ? t / curve.period * morphCurveB.period : t;
79
79
  const b = morphCurveB.fn(tB, actualTime, {});
80
80
  trail.push(a.x + (b.x - a.x) * _morphAlpha, a.y + (b.y - a.y) * _morphAlpha);
81
81
  } else {
@@ -99,14 +99,14 @@ function createEngine(curveDef, trailLength = 120) {
99
99
  trail.clear();
100
100
  },
101
101
  seek(newT, { clearTrail = false } = {}) {
102
- t = ((newT % curve.period) + curve.period) % curve.period;
102
+ t = (newT % curve.period + curve.period) % curve.period;
103
103
  if (clearTrail) {
104
104
  trail.clear();
105
105
  }
106
106
  },
107
107
  seekWithTrail(targetT, { wrap = false, step = curve.period / trailLength } = {}) {
108
108
  const advance = curve.speed * step;
109
- const target = ((targetT % curve.period) + curve.period) % curve.period;
109
+ const target = (targetT % curve.period + curve.period) % curve.period;
110
110
  const targetTime = target / curve.speed;
111
111
  t = target;
112
112
  actualTime = targetTime;
@@ -132,16 +132,13 @@ function createEngine(curveDef, trailLength = 120) {
132
132
  ...frozenB,
133
133
  fn: (sampleT, time, params) => {
134
134
  const a = frozenA.fn(sampleT, time, params);
135
- const tB =
136
- frozenStrategy === "normalized"
137
- ? (sampleT / frozenA.period) * frozenB.period
138
- : sampleT;
135
+ const tB = frozenStrategy === "normalized" ? sampleT / frozenA.period * frozenB.period : sampleT;
139
136
  const b = frozenB.fn(tB, time, params);
140
137
  return {
141
138
  x: a.x + (b.x - a.x) * frozenAlpha,
142
- y: a.y + (b.y - a.y) * frozenAlpha,
139
+ y: a.y + (b.y - a.y) * frozenAlpha
143
140
  };
144
- },
141
+ }
145
142
  };
146
143
  }
147
144
  _morphStrategy = strategy;
@@ -153,6 +150,9 @@ function createEngine(curveDef, trailLength = 120) {
153
150
  },
154
151
  completeMorph() {
155
152
  if (morphCurveB !== null) {
153
+ if (_morphStrategy === "normalized" && curve.period !== morphCurveB.period) {
154
+ t = t / curve.period * morphCurveB.period;
155
+ }
156
156
  curve = morphCurveB;
157
157
  }
158
158
  morphCurveB = null;
@@ -163,26 +163,23 @@ function createEngine(curveDef, trailLength = 120) {
163
163
  const points = new Array(steps);
164
164
  if (morphCurveB !== null && _morphAlpha !== null) {
165
165
  for (let i = 0; i < steps; i++) {
166
- const sampleT = (i / (steps - 1)) * curve.period;
166
+ const sampleT = i / (steps - 1) * curve.period;
167
167
  const a = sampleSkeleton(curve, sampleT);
168
- const tB =
169
- _morphStrategy === "normalized"
170
- ? (sampleT / curve.period) * morphCurveB.period
171
- : sampleT;
168
+ const tB = _morphStrategy === "normalized" ? sampleT / curve.period * morphCurveB.period : sampleT;
172
169
  const b = sampleSkeleton(morphCurveB, tB);
173
170
  points[i] = {
174
171
  x: a.x + (b.x - a.x) * _morphAlpha,
175
- y: a.y + (b.y - a.y) * _morphAlpha,
172
+ y: a.y + (b.y - a.y) * _morphAlpha
176
173
  };
177
174
  }
178
175
  return points;
179
176
  }
180
177
  for (let i = 0; i < steps; i++) {
181
- const sampleT = (i / (steps - 1)) * curve.period;
178
+ const sampleT = i / (steps - 1) * curve.period;
182
179
  points[i] = sampleSkeleton(curve, sampleT);
183
180
  }
184
181
  return points;
185
- },
182
+ }
186
183
  };
187
184
  }
188
185
 
@@ -202,7 +199,7 @@ var GLOW_INNER_EDGE = 0.4;
202
199
  var GLOW_FALLOFF_OPACITY = 0.53;
203
200
  function hexToRgbComponents(hex) {
204
201
  const n = parseInt(hex.slice(1), 16);
205
- return `${n >> 16},${(n >> 8) & 255},${n & 255}`;
202
+ return `${n >> 16},${n >> 8 & 255},${n & 255}`;
206
203
  }
207
204
  function createRenderer(options) {
208
205
  const canvas = options.canvas;
@@ -216,7 +213,7 @@ function createRenderer(options) {
216
213
  trailColor: options.trailColor ?? "#ffffff",
217
214
  headColor: options.headColor ?? "#ffffff",
218
215
  headRadius: options.headRadius ?? DEFAULT_HEAD_RADIUS,
219
- glowSize: options.glowSize ?? DEFAULT_GLOW_SIZE,
216
+ glowSize: options.glowSize ?? DEFAULT_GLOW_SIZE
220
217
  };
221
218
  const trailRgb = hexToRgbComponents(opts.trailColor);
222
219
  const headRgbFalloff = `rgba(${hexToRgbComponents(opts.headColor)},${GLOW_FALLOFF_OPACITY})`;
@@ -232,32 +229,18 @@ function createRenderer(options) {
232
229
  let lastTime = 0;
233
230
  let morphResolve = null;
234
231
  let morphDurationMs = DEFAULT_MORPH_DURATION_MS;
235
- let morphTarget = null;
236
232
  let morphAlpha = 0;
237
- let skeletonCanvasA = null;
238
- let skeletonCanvasB = null;
239
- function calculateBoundaries() {
240
- if (skeleton.length === 0) {
241
- return;
242
- }
243
- const first = skeleton[0];
244
- let minX = first.x,
245
- maxX = first.x,
246
- minY = first.y,
247
- maxY = first.y;
248
- for (const p of skeleton) {
249
- if (p.x < minX) {
250
- minX = p.x;
251
- }
252
- if (p.x > maxX) {
253
- maxX = p.x;
254
- }
255
- if (p.y < minY) {
256
- minY = p.y;
257
- }
258
- if (p.y > maxY) {
259
- maxY = p.y;
260
- }
233
+ let morphBoundsA = null;
234
+ let morphBoundsB = null;
235
+ function computeBoundaries(pts) {
236
+ if (pts.length === 0) return null;
237
+ const first = pts[0];
238
+ let minX = first.x, maxX = first.x, minY = first.y, maxY = first.y;
239
+ for (const p of pts) {
240
+ if (p.x < minX) minX = p.x;
241
+ if (p.x > maxX) maxX = p.x;
242
+ if (p.y < minY) minY = p.y;
243
+ if (p.y > maxY) maxY = p.y;
261
244
  }
262
245
  const width = maxX - minX;
263
246
  const height = maxY - minY;
@@ -265,11 +248,22 @@ function createRenderer(options) {
265
248
  const canvasHeight = canvas.height;
266
249
  const scaleX = canvasWidth / (width * (1 + FIT_PADDING * 2));
267
250
  const scaleY = canvasHeight / (height * (1 + FIT_PADDING * 2));
268
- scale = Math.min(scaleX, scaleY);
269
- const boundsWidth = width * scale;
270
- const boundsHeight = height * scale;
271
- offsetX = (canvasWidth - boundsWidth) / 2 - minX * scale;
272
- offsetY = (canvasHeight - boundsHeight) / 2 - minY * scale;
251
+ const s = Math.min(scaleX, scaleY);
252
+ const boundsWidth = width * s;
253
+ const boundsHeight = height * s;
254
+ return {
255
+ scale: s,
256
+ offsetX: (canvasWidth - boundsWidth) / 2 - minX * s,
257
+ offsetY: (canvasHeight - boundsHeight) / 2 - minY * s
258
+ };
259
+ }
260
+ function calculateBoundaries() {
261
+ const b = computeBoundaries(skeleton);
262
+ if (b) {
263
+ scale = b.scale;
264
+ offsetX = b.offsetX;
265
+ offsetY = b.offsetY;
266
+ }
273
267
  }
274
268
  function buildSkeletonCanvas() {
275
269
  if (skeleton.length < 2) return;
@@ -286,20 +280,23 @@ function createRenderer(options) {
286
280
  }
287
281
  skeletonCtx.stroke();
288
282
  }
283
+ function drawSkeletonPath(pts, opacity) {
284
+ if (pts.length < 2) return;
285
+ ctx.strokeStyle = `rgba(${hexToRgbComponents(opts.skeletonColor)},${opacity})`;
286
+ ctx.lineWidth = 1.5;
287
+ ctx.beginPath();
288
+ ctx.moveTo(pts[0].x * scale + offsetX, pts[0].y * scale + offsetY);
289
+ for (let i = 1; i < pts.length; i++) {
290
+ ctx.lineTo(pts[i].x * scale + offsetX, pts[i].y * scale + offsetY);
291
+ }
292
+ ctx.stroke();
293
+ }
289
294
  function drawSkeleton() {
290
295
  if (opts.skeletonColor === "transparent") {
291
296
  return;
292
297
  }
293
298
  if (engine.morphAlpha !== null) {
294
- if (skeletonCanvasA) {
295
- ctx.globalAlpha = (1 - morphAlpha) * DEFAULT_SKELETON_OPACITY;
296
- ctx.drawImage(skeletonCanvasA, 0, 0);
297
- }
298
- if (skeletonCanvasB) {
299
- ctx.globalAlpha = morphAlpha * DEFAULT_SKELETON_OPACITY;
300
- ctx.drawImage(skeletonCanvasB, 0, 0);
301
- }
302
- ctx.globalAlpha = 1;
299
+ drawSkeletonPath(engine.getSarmalSkeleton(), DEFAULT_SKELETON_OPACITY);
303
300
  return;
304
301
  }
305
302
  if (engine.isLiveSkeleton) {
@@ -371,23 +368,31 @@ function createRenderer(options) {
371
368
  if (engine.morphAlpha !== null) {
372
369
  morphAlpha = Math.min(1, morphAlpha + deltaTime / (morphDurationMs / 1e3));
373
370
  engine.setMorphAlpha(morphAlpha);
374
- skeleton = engine.getSarmalSkeleton();
375
- calculateBoundaries();
371
+ if (morphBoundsA && morphBoundsB) {
372
+ const a = morphBoundsA;
373
+ const b = morphBoundsB;
374
+ scale = a.scale + (b.scale - a.scale) * morphAlpha;
375
+ offsetX = a.offsetX + (b.offsetX - a.offsetX) * morphAlpha;
376
+ offsetY = a.offsetY + (b.offsetY - a.offsetY) * morphAlpha;
377
+ }
376
378
  if (morphAlpha >= 1) {
377
379
  engine.completeMorph();
378
380
  morphResolve?.();
379
381
  morphResolve = null;
380
- morphTarget = null;
381
382
  morphAlpha = 0;
382
- skeletonCanvasA = null;
383
- skeletonCanvasB = null;
383
+ morphBoundsA = null;
384
+ morphBoundsB = null;
385
+ skeleton = engine.getSarmalSkeleton();
386
+ if (!engine.isLiveSkeleton) {
387
+ buildSkeletonCanvas();
388
+ }
384
389
  }
385
390
  }
386
391
  trail = engine.tick(deltaTime);
387
392
  trailCount = engine.trailCount;
388
393
  head = trailCount > 0 ? trail[trailCount - 1] : null;
389
394
  ctx.clearRect(0, 0, canvas.width, canvas.height);
390
- if (engine.isLiveSkeleton || engine.morphAlpha !== null) {
395
+ if (engine.isLiveSkeleton && engine.morphAlpha === null) {
391
396
  skeleton = engine.getSarmalSkeleton();
392
397
  calculateBoundaries();
393
398
  }
@@ -434,54 +439,31 @@ function createRenderer(options) {
434
439
  engine.seekWithTrail(t);
435
440
  },
436
441
  morphTo(target, options2) {
442
+ const interruptBounds = morphResolve !== null ? { scale, offsetX, offsetY } : null;
437
443
  if (morphResolve !== null) {
438
444
  engine.completeMorph();
439
445
  morphResolve();
440
446
  morphResolve = null;
441
447
  morphAlpha = 0;
442
- skeletonCanvasA = null;
443
- skeletonCanvasB = null;
448
+ morphBoundsA = null;
449
+ morphBoundsB = null;
444
450
  }
445
451
  morphDurationMs = options2?.duration ?? DEFAULT_MORPH_DURATION_MS;
446
- morphTarget = target;
447
452
  morphAlpha = 0;
448
- const currentSkeleton = engine.getSarmalSkeleton();
449
- if (currentSkeleton.length >= 2) {
450
- skeletonCanvasA = new OffscreenCanvas(canvas.width, canvas.height);
451
- const ctxA = skeletonCanvasA.getContext("2d");
452
- ctxA.strokeStyle = `rgba(${hexToRgbComponents(opts.skeletonColor)},${DEFAULT_SKELETON_OPACITY})`;
453
- ctxA.lineWidth = 1.5;
454
- ctxA.beginPath();
455
- const first = currentSkeleton[0];
456
- ctxA.moveTo(first.x * scale + offsetX, first.y * scale + offsetY);
457
- for (let i = 1; i < currentSkeleton.length; i++) {
458
- const p = currentSkeleton[i];
459
- ctxA.lineTo(p.x * scale + offsetX, p.y * scale + offsetY);
460
- }
461
- ctxA.stroke();
462
- }
453
+ morphBoundsA = interruptBounds ?? computeBoundaries(engine.getSarmalSkeleton()) ?? { scale, offsetX, offsetY };
463
454
  engine.startMorph(target, options2?.morphStrategy);
464
- if (morphTarget && !engine.isLiveSkeleton) {
465
- skeletonCanvasB = new OffscreenCanvas(canvas.width, canvas.height);
466
- const skeletonCtx = skeletonCanvasB.getContext("2d");
467
- skeletonCtx.strokeStyle = `rgba(${hexToRgbComponents(opts.skeletonColor)},${DEFAULT_SKELETON_OPACITY})`;
468
- skeletonCtx.lineWidth = 1.5;
469
- skeletonCtx.beginPath();
470
- const period = morphTarget.period ?? Math.PI * 2;
471
- const samples = Math.max(50, Math.round(period * 20));
472
- const firstB = morphTarget.fn(0, 0, {});
473
- skeletonCtx.moveTo(firstB.x * scale + offsetX, firstB.y * scale + offsetY);
474
- for (let i = 1; i <= samples; i++) {
475
- const t = (i / samples) * period;
476
- const p = morphTarget.fn(t, 0, {});
477
- skeletonCtx.lineTo(p.x * scale + offsetX, p.y * scale + offsetY);
478
- }
479
- skeletonCtx.stroke();
480
- }
455
+ const period = target.period ?? Math.PI * 2;
456
+ const samples = Math.max(50, Math.round(period * 20));
457
+ const skeletonFn = target.skeletonFn ?? ((t) => target.fn(t, 0, {}));
458
+ const skeletonB = Array.from(
459
+ { length: samples + 1 },
460
+ (_, i) => skeletonFn(i / samples * period)
461
+ );
462
+ morphBoundsB = computeBoundaries(skeletonB) ?? { scale, offsetX, offsetY };
481
463
  return new Promise((resolve) => {
482
464
  morphResolve = resolve;
483
465
  });
484
- },
466
+ }
485
467
  };
486
468
  }
487
469
 
@@ -508,7 +490,7 @@ function createSVGRenderer(options) {
508
490
  headColor: options.headColor ?? "#ffffff",
509
491
  headRadius: options.headRadius ?? 4,
510
492
  glowSize: options.glowSize ?? 20,
511
- ariaLabel: options.ariaLabel ?? "Loading",
493
+ ariaLabel: options.ariaLabel ?? "Loading"
512
494
  };
513
495
  const uid = ++instanceCount;
514
496
  const gradientId = `sarmal-glow-${uid}`;
@@ -592,10 +574,7 @@ function createSVGRenderer(options) {
592
574
  return;
593
575
  }
594
576
  const first = skeleton2[0];
595
- let minX = first.x,
596
- maxX = first.x,
597
- minY = first.y,
598
- maxY = first.y;
577
+ let minX = first.x, maxX = first.x, minY = first.y, maxY = first.y;
599
578
  for (const p of skeleton2) {
600
579
  if (p.x < minX) {
601
580
  minX = p.x;
@@ -682,8 +661,7 @@ function createSVGRenderer(options) {
682
661
  }
683
662
  let animationId = null;
684
663
  let lastTime = 0;
685
- const prefersReducedMotion =
686
- typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
664
+ const prefersReducedMotion = typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
687
665
  let morphResolve = null;
688
666
  let morphDurationMs = DEFAULT_MORPH_DURATION_MS2;
689
667
  let morphTarget = null;
@@ -693,7 +671,7 @@ function createSVGRenderer(options) {
693
671
  const samples = Math.max(50, Math.round(period * 20));
694
672
  const points = [];
695
673
  for (let i = 0; i <= samples; i++) {
696
- const t = (i / samples) * period;
674
+ const t = i / samples * period;
697
675
  const p = target.fn(t, 0, {});
698
676
  points.push(p);
699
677
  }
@@ -716,26 +694,18 @@ function createSVGRenderer(options) {
716
694
  if (engine.morphAlpha !== null) {
717
695
  morphAlpha = Math.min(1, morphAlpha + dt / (morphDurationMs / 1e3));
718
696
  engine.setMorphAlpha(morphAlpha);
719
- const morphSkeleton = engine.getSarmalSkeleton();
720
- calculateBoundaries(morphSkeleton);
721
- if (!engine.isLiveSkeleton) {
722
- updateSkeleton(morphSkeleton);
723
- }
724
697
  if (morphPathABuilt) {
725
698
  skeletonPathA.setAttribute("d", morphPathABuilt);
726
699
  skeletonPathA.setAttribute("visibility", "visible");
727
700
  skeletonPathA.setAttribute(
728
701
  "stroke-opacity",
729
- String((1 - morphAlpha) * DEFAULT_SKELETON_OPACITY2),
702
+ String((1 - morphAlpha) * DEFAULT_SKELETON_OPACITY2)
730
703
  );
731
704
  }
732
705
  if (morphPathBBuilt) {
733
706
  skeletonPathB.setAttribute("d", morphPathBBuilt);
734
707
  skeletonPathB.setAttribute("visibility", "visible");
735
- skeletonPathB.setAttribute(
736
- "stroke-opacity",
737
- String(morphAlpha * DEFAULT_SKELETON_OPACITY2),
738
- );
708
+ skeletonPathB.setAttribute("stroke-opacity", String(morphAlpha * DEFAULT_SKELETON_OPACITY2));
739
709
  }
740
710
  if (morphAlpha >= 1) {
741
711
  engine.completeMorph();
@@ -747,11 +717,14 @@ function createSVGRenderer(options) {
747
717
  morphPathBBuilt = "";
748
718
  skeletonPathA.setAttribute("visibility", "hidden");
749
719
  skeletonPathB.setAttribute("visibility", "hidden");
720
+ const newSkeleton = engine.getSarmalSkeleton();
721
+ calculateBoundaries(newSkeleton);
722
+ updateSkeleton(newSkeleton);
750
723
  }
751
724
  }
752
725
  const trail = engine.tick(dt);
753
726
  const trailCount = engine.trailCount;
754
- if (engine.isLiveSkeleton) {
727
+ if (engine.isLiveSkeleton && engine.morphAlpha === null) {
755
728
  const liveSkeleton = engine.getSarmalSkeleton();
756
729
  calculateBoundaries(liveSkeleton);
757
730
  updateSkeleton(liveSkeleton);
@@ -824,7 +797,7 @@ function createSVGRenderer(options) {
824
797
  return new Promise((resolve) => {
825
798
  morphResolve = resolve;
826
799
  });
827
- },
800
+ }
828
801
  };
829
802
  }
830
803
  function createSarmalSVG(container, curveDef, options) {
@@ -836,29 +809,26 @@ function createSarmalSVG(container, curveDef, options) {
836
809
  // src/curves.ts
837
810
  var TWO_PI2 = Math.PI * 2;
838
811
  function artemis2(t, _time, _params) {
839
- const a = 0.35,
840
- b = 0.15,
841
- ox = 0.175;
842
- const s = Math.sin(t),
843
- c = Math.cos(t);
812
+ const a = 0.35, b = 0.15, ox = 0.175;
813
+ const s = Math.sin(t), c = Math.cos(t);
844
814
  const denom = 1 + s * s;
845
815
  return {
846
- x: (c * (1 + a * c)) / denom - ox,
847
- y: (s * c * (1 + b * c)) / denom,
816
+ x: c * (1 + a * c) / denom - ox,
817
+ y: s * c * (1 + b * c) / denom
848
818
  };
849
819
  }
850
820
  function epitrochoid7(t, _time, _params) {
851
821
  const d = 1 + 0.55 * Math.sin(t * 0.5);
852
822
  return {
853
823
  x: 7 * Math.cos(t) - d * Math.cos(7 * t),
854
- y: 7 * Math.sin(t) - d * Math.sin(7 * t),
824
+ y: 7 * Math.sin(t) - d * Math.sin(7 * t)
855
825
  };
856
826
  }
857
827
  function epitrochoid7Skeleton(t) {
858
828
  const d = 1.275;
859
829
  return {
860
830
  x: 7 * Math.cos(t) - d * Math.cos(7 * t),
861
- y: 7 * Math.sin(t) - d * Math.sin(7 * t),
831
+ y: 7 * Math.sin(t) - d * Math.sin(7 * t)
862
832
  };
863
833
  }
864
834
  function astroid(t, _time, _params) {
@@ -866,56 +836,55 @@ function astroid(t, _time, _params) {
866
836
  const s = Math.sin(t);
867
837
  return {
868
838
  x: c * c * c,
869
- y: s * s * s,
839
+ y: s * s * s
870
840
  };
871
841
  }
872
842
  function deltoid(t, _time, _params) {
873
843
  return {
874
844
  x: 2 * Math.cos(t) + Math.cos(2 * t),
875
- y: 2 * Math.sin(t) - Math.sin(2 * t),
845
+ y: 2 * Math.sin(t) - Math.sin(2 * t)
876
846
  };
877
847
  }
878
848
  function rose5(t, _time, _params) {
879
849
  const r = Math.cos(5 * t);
880
850
  return {
881
851
  x: r * Math.cos(t),
882
- y: r * Math.sin(t),
852
+ y: r * Math.sin(t)
883
853
  };
884
854
  }
885
855
  function rose3(t, _time, _params) {
886
856
  const r = Math.cos(3 * t);
887
857
  return {
888
858
  x: r * Math.cos(t),
889
- y: r * Math.sin(t),
859
+ y: r * Math.sin(t)
890
860
  };
891
861
  }
892
862
  function lissajous32(t, time, _params) {
893
863
  const phi = time * 0.45;
894
864
  return {
895
865
  x: Math.sin(3 * t + phi),
896
- y: Math.sin(2 * t),
866
+ y: Math.sin(2 * t)
897
867
  };
898
868
  }
899
869
  function lissajous43(t, time, _params) {
900
870
  const phi = time * 0.38;
901
871
  return {
902
872
  x: Math.sin(4 * t + phi),
903
- y: Math.sin(3 * t),
873
+ y: Math.sin(3 * t)
904
874
  };
905
875
  }
906
876
  function epicycloid3(t, _time, _params) {
907
877
  return {
908
878
  x: 4 * Math.cos(t) - Math.cos(4 * t),
909
- y: 4 * Math.sin(t) - Math.sin(4 * t),
879
+ y: 4 * Math.sin(t) - Math.sin(4 * t)
910
880
  };
911
881
  }
912
882
  function lame(t, time, _params) {
913
883
  const p = 1.75 + 1.25 * Math.sin(time * 0.48);
914
- const c = Math.cos(t),
915
- s = Math.sin(t);
884
+ const c = Math.cos(t), s = Math.sin(t);
916
885
  return {
917
886
  x: Math.sign(c) * Math.pow(Math.abs(c), p),
918
- y: Math.sign(s) * Math.pow(Math.abs(s), p),
887
+ y: Math.sign(s) * Math.pow(Math.abs(s), p)
919
888
  };
920
889
  }
921
890
  var curves = {
@@ -923,66 +892,66 @@ var curves = {
923
892
  name: "Artemis II",
924
893
  fn: artemis2,
925
894
  period: TWO_PI2,
926
- speed: 0.7,
895
+ speed: 0.7
927
896
  },
928
897
  epitrochoid7: {
929
898
  name: "Epitrochoid",
930
899
  fn: epitrochoid7,
931
900
  period: TWO_PI2,
932
901
  speed: 1.4,
933
- skeletonFn: epitrochoid7Skeleton,
902
+ skeletonFn: epitrochoid7Skeleton
934
903
  },
935
904
  astroid: {
936
905
  name: "Astroid",
937
906
  fn: astroid,
938
907
  period: TWO_PI2,
939
- speed: 1.1,
908
+ speed: 1.1
940
909
  },
941
910
  deltoid: {
942
911
  name: "Deltoid",
943
912
  fn: deltoid,
944
913
  period: TWO_PI2,
945
- speed: 0.9,
914
+ speed: 0.9
946
915
  },
947
916
  rose5: {
948
917
  name: "Rose (n=5)",
949
918
  fn: rose5,
950
919
  period: TWO_PI2,
951
- speed: 1,
920
+ speed: 1
952
921
  },
953
922
  rose3: {
954
923
  name: "Rose (n=3)",
955
924
  fn: rose3,
956
925
  period: TWO_PI2,
957
- speed: 1.15,
926
+ speed: 1.15
958
927
  },
959
928
  lissajous32: {
960
929
  name: "Lissajous 3:2",
961
930
  fn: lissajous32,
962
931
  period: TWO_PI2,
963
932
  speed: 2,
964
- skeleton: "live",
933
+ skeleton: "live"
965
934
  },
966
935
  lissajous43: {
967
936
  name: "Lissajous 4:3",
968
937
  fn: lissajous43,
969
938
  period: TWO_PI2,
970
939
  speed: 1.8,
971
- skeleton: "live",
940
+ skeleton: "live"
972
941
  },
973
942
  epicycloid3: {
974
943
  name: "Epicycloid (n=3)",
975
944
  fn: epicycloid3,
976
945
  period: TWO_PI2,
977
- speed: 0.75,
946
+ speed: 0.75
978
947
  },
979
948
  lame: {
980
949
  name: "Lam\xE9 Curve",
981
950
  fn: lame,
982
951
  period: TWO_PI2,
983
952
  speed: 1,
984
- skeleton: "live",
985
- },
953
+ skeleton: "live"
954
+ }
986
955
  };
987
956
 
988
957
  // src/index.ts
@@ -994,4 +963,4 @@ function createSarmal(canvas, curveDef, options) {
994
963
 
995
964
  export { createEngine, createRenderer, createSVGRenderer, createSarmal, createSarmalSVG, curves };
996
965
  //# sourceMappingURL=index.js.map
997
- //# sourceMappingURL=index.js.map
966
+ //# sourceMappingURL=index.js.map