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