@sarmal/core 0.23.0 → 0.25.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.
Files changed (79) hide show
  1. package/dist/auto-init.cjs +255 -175
  2. package/dist/auto-init.cjs.map +1 -1
  3. package/dist/auto-init.js +254 -174
  4. package/dist/auto-init.js.map +1 -1
  5. package/dist/curves/artemis2.cjs +82 -17
  6. package/dist/curves/artemis2.cjs.map +1 -1
  7. package/dist/curves/artemis2.d.cts +1 -5
  8. package/dist/curves/artemis2.d.ts +1 -5
  9. package/dist/curves/artemis2.js +81 -16
  10. package/dist/curves/artemis2.js.map +1 -1
  11. package/dist/curves/astroid.cjs +4 -4
  12. package/dist/curves/astroid.d.cts +1 -1
  13. package/dist/curves/astroid.d.ts +1 -1
  14. package/dist/curves/astroid.js +3 -3
  15. package/dist/curves/deltoid.cjs +4 -4
  16. package/dist/curves/deltoid.d.cts +1 -1
  17. package/dist/curves/deltoid.d.ts +1 -1
  18. package/dist/curves/deltoid.js +3 -3
  19. package/dist/curves/epicycloid3.cjs +4 -4
  20. package/dist/curves/epicycloid3.d.cts +1 -1
  21. package/dist/curves/epicycloid3.d.ts +1 -1
  22. package/dist/curves/epicycloid3.js +3 -3
  23. package/dist/curves/epitrochoid7.cjs +5 -5
  24. package/dist/curves/epitrochoid7.d.cts +1 -1
  25. package/dist/curves/epitrochoid7.d.ts +1 -1
  26. package/dist/curves/epitrochoid7.js +4 -4
  27. package/dist/curves/index.cjs +139 -84
  28. package/dist/curves/index.cjs.map +1 -1
  29. package/dist/curves/index.d.cts +29 -29
  30. package/dist/curves/index.d.ts +29 -29
  31. package/dist/curves/index.js +139 -100
  32. package/dist/curves/index.js.map +1 -1
  33. package/dist/curves/lame.cjs +5 -6
  34. package/dist/curves/lame.d.cts +1 -1
  35. package/dist/curves/lame.d.ts +1 -1
  36. package/dist/curves/lame.js +4 -5
  37. package/dist/curves/lissajous32.cjs +4 -4
  38. package/dist/curves/lissajous32.d.cts +1 -1
  39. package/dist/curves/lissajous32.d.ts +1 -1
  40. package/dist/curves/lissajous32.js +3 -3
  41. package/dist/curves/lissajous43.cjs +4 -4
  42. package/dist/curves/lissajous43.d.cts +1 -1
  43. package/dist/curves/lissajous43.d.ts +1 -1
  44. package/dist/curves/lissajous43.js +3 -3
  45. package/dist/curves/rose3.cjs +4 -4
  46. package/dist/curves/rose3.d.cts +1 -1
  47. package/dist/curves/rose3.d.ts +1 -1
  48. package/dist/curves/rose3.js +3 -3
  49. package/dist/curves/rose5.cjs +4 -4
  50. package/dist/curves/rose5.d.cts +1 -1
  51. package/dist/curves/rose5.d.ts +1 -1
  52. package/dist/curves/rose5.js +3 -3
  53. package/dist/curves/rose52.cjs +5 -5
  54. package/dist/curves/rose52.d.cts +1 -1
  55. package/dist/curves/rose52.d.ts +1 -1
  56. package/dist/curves/rose52.js +4 -4
  57. package/dist/curves/star.cjs +5 -8
  58. package/dist/curves/star.d.cts +1 -1
  59. package/dist/curves/star.d.ts +1 -1
  60. package/dist/curves/star.js +4 -7
  61. package/dist/curves/star4.cjs +5 -8
  62. package/dist/curves/star4.d.cts +1 -1
  63. package/dist/curves/star4.d.ts +1 -1
  64. package/dist/curves/star4.js +4 -7
  65. package/dist/curves/star7.cjs +5 -8
  66. package/dist/curves/star7.d.cts +1 -1
  67. package/dist/curves/star7.d.ts +1 -1
  68. package/dist/curves/star7.js +4 -7
  69. package/dist/index.cjs +244 -210
  70. package/dist/index.cjs.map +1 -1
  71. package/dist/index.d.cts +55 -78
  72. package/dist/index.d.ts +55 -78
  73. package/dist/index.js +243 -230
  74. package/dist/index.js.map +1 -1
  75. package/dist/types-BZpzgNau.d.cts +332 -0
  76. package/dist/types-BZpzgNau.d.ts +332 -0
  77. package/package.json +1 -1
  78. package/dist/types-C0b4MPtI.d.cts +0 -321
  79. package/dist/types-C0b4MPtI.d.ts +0 -321
package/dist/auto-init.js CHANGED
@@ -61,13 +61,13 @@ function resolveCurve(curveDef) {
61
61
  period,
62
62
  speed,
63
63
  skeleton: curveDef.skeleton,
64
- skeletonFn: curveDef.skeletonFn,
64
+ skeletonFn: curveDef.skeletonFn
65
65
  };
66
66
  }
67
67
  function createEngine(curveDef, trailLength = 120) {
68
68
  if (!Number.isFinite(trailLength) || trailLength <= 0) {
69
69
  throw new RangeError(
70
- `[sarmal] trailLength must be a positive finite number, got ${trailLength}`,
70
+ `[sarmal] trailLength must be a positive finite number, got ${trailLength}`
71
71
  );
72
72
  }
73
73
  let curve = resolveCurve(curveDef);
@@ -108,7 +108,7 @@ function createEngine(curveDef, trailLength = 120) {
108
108
  actualTime += deltaTime;
109
109
  if (morphCurveB !== null && _morphAlpha !== null) {
110
110
  const a = curve.fn(t, actualTime, EMPTY_PARAMS);
111
- const tB = _morphStrategy === "normalized" ? (t / curve.period) * morphCurveB.period : t;
111
+ const tB = _morphStrategy === "normalized" ? t / curve.period * morphCurveB.period : t;
112
112
  const b = morphCurveB.fn(tB, actualTime, EMPTY_PARAMS);
113
113
  trail.push(a.x + (b.x - a.x) * _morphAlpha, a.y + (b.y - a.y) * _morphAlpha);
114
114
  } else {
@@ -135,14 +135,14 @@ function createEngine(curveDef, trailLength = 120) {
135
135
  trail.clear();
136
136
  },
137
137
  jump(newT, { clearTrail = false } = {}) {
138
- t = ((newT % curve.period) + curve.period) % curve.period;
138
+ t = (newT % curve.period + curve.period) % curve.period;
139
139
  if (clearTrail) {
140
140
  trail.clear();
141
141
  }
142
142
  },
143
143
  seek(targetT, { wrap = false, step = curve.period / trailLength } = {}) {
144
144
  const advance = curve.speed * step;
145
- const target = ((targetT % curve.period) + curve.period) % curve.period;
145
+ const target = (targetT % curve.period + curve.period) % curve.period;
146
146
  const targetTime = target / curve.speed;
147
147
  t = target;
148
148
  actualTime = targetTime;
@@ -151,7 +151,7 @@ function createEngine(curveDef, trailLength = 120) {
151
151
  const count = wrap ? trailLength : Math.min(trailLength, pointsFromStart);
152
152
  for (let i = count - 1; i >= 0; i--) {
153
153
  const sampleT = target - i * advance;
154
- const wrappedT = ((sampleT % curve.period) + curve.period) % curve.period;
154
+ const wrappedT = (sampleT % curve.period + curve.period) % curve.period;
155
155
  const time = targetTime - i * step;
156
156
  const point = curve.fn(wrappedT, time, EMPTY_PARAMS);
157
157
  trail.push(point.x, point.y);
@@ -168,16 +168,13 @@ function createEngine(curveDef, trailLength = 120) {
168
168
  ...frozenB,
169
169
  fn: (sampleT, time, params) => {
170
170
  const a = frozenA.fn(sampleT, time, params);
171
- const tB =
172
- frozenStrategy === "normalized"
173
- ? (sampleT / frozenA.period) * frozenB.period
174
- : sampleT;
171
+ const tB = frozenStrategy === "normalized" ? sampleT / frozenA.period * frozenB.period : sampleT;
175
172
  const b = frozenB.fn(tB, time, params);
176
173
  return {
177
174
  x: a.x + (b.x - a.x) * frozenAlpha,
178
- y: a.y + (b.y - a.y) * frozenAlpha,
175
+ y: a.y + (b.y - a.y) * frozenAlpha
179
176
  };
180
- },
177
+ }
181
178
  };
182
179
  }
183
180
  _morphStrategy = strategy;
@@ -190,7 +187,7 @@ function createEngine(curveDef, trailLength = 120) {
190
187
  completeMorph() {
191
188
  if (morphCurveB !== null) {
192
189
  if (_morphStrategy === "normalized" && curve.period !== morphCurveB.period) {
193
- t = (t / curve.period) * morphCurveB.period;
190
+ t = t / curve.period * morphCurveB.period;
194
191
  }
195
192
  curve = morphCurveB;
196
193
  }
@@ -199,28 +196,25 @@ function createEngine(curveDef, trailLength = 120) {
199
196
  },
200
197
  getSarmalSkeleton() {
201
198
  const steps = Math.ceil(curve.period * POINTS_PER_PERIOD_UNIT);
202
- const points = new Array(steps);
199
+ const points2 = new Array(steps);
203
200
  if (morphCurveB !== null && _morphAlpha !== null) {
204
201
  for (let i = 0; i < steps; i++) {
205
- const sampleT = (i / (steps - 1)) * curve.period;
202
+ const sampleT = i / (steps - 1) * curve.period;
206
203
  const a = sampleSkeleton(curve, sampleT);
207
- const tB =
208
- _morphStrategy === "normalized"
209
- ? (sampleT / curve.period) * morphCurveB.period
210
- : sampleT;
204
+ const tB = _morphStrategy === "normalized" ? sampleT / curve.period * morphCurveB.period : sampleT;
211
205
  const b = sampleSkeleton(morphCurveB, tB);
212
- points[i] = {
206
+ points2[i] = {
213
207
  x: a.x + (b.x - a.x) * _morphAlpha,
214
- y: a.y + (b.y - a.y) * _morphAlpha,
208
+ y: a.y + (b.y - a.y) * _morphAlpha
215
209
  };
216
210
  }
217
- return points;
211
+ return points2;
218
212
  }
219
213
  for (let i = 0; i < steps; i++) {
220
- const sampleT = (i / (steps - 1)) * curve.period;
221
- points[i] = sampleSkeleton(curve, sampleT);
214
+ const sampleT = i / (steps - 1) * curve.period;
215
+ points2[i] = sampleSkeleton(curve, sampleT);
222
216
  }
223
- return points;
217
+ return points2;
224
218
  },
225
219
  setSpeed(speed) {
226
220
  if (!Number.isFinite(speed)) {
@@ -259,7 +253,7 @@ function createEngine(curveDef, trailLength = 120) {
259
253
  _speedTransition.reject(new Error("Speed transition cancelled"));
260
254
  _speedTransition = null;
261
255
  }
262
- },
256
+ }
263
257
  };
264
258
  }
265
259
 
@@ -298,15 +292,7 @@ function computeNormal(trail, i) {
298
292
  const tangent = computeTangent(trail, i);
299
293
  return { x: -tangent.y, y: tangent.x };
300
294
  }
301
- function computeTrailQuad(
302
- trail,
303
- i,
304
- trailCount,
305
- toX,
306
- toY,
307
- minWidth = TRAIL_MIN_WIDTH,
308
- maxWidth = TRAIL_MAX_WIDTH,
309
- ) {
295
+ function computeTrailQuad(trail, i, trailCount, toX, toY, minWidth = TRAIL_MIN_WIDTH, maxWidth = TRAIL_MAX_WIDTH) {
310
296
  const progress = i / (trailCount - 1);
311
297
  const nextProgress = (i + 1) / (trailCount - 1);
312
298
  const opacity = Math.pow(progress, TRAIL_FADE_CURVE) * TRAIL_MAX_OPACITY;
@@ -330,16 +316,13 @@ function computeTrailQuad(
330
316
  r1x: nx - n1.x * w1,
331
317
  r1y: ny - n1.y * w1,
332
318
  opacity,
333
- progress,
319
+ progress
334
320
  };
335
321
  }
336
- function computeBoundaries(pts, logicalWidth, logicalHeight) {
322
+ function computeBoundaries(pts, logicalWidth, logicalHeight, minPaddingPx = FIT_PADDING_MIN) {
337
323
  if (pts.length === 0) return null;
338
324
  const first = pts[0];
339
- let minX = first.x,
340
- maxX = first.x,
341
- minY = first.y,
342
- maxY = first.y;
325
+ let minX = first.x, maxX = first.x, minY = first.y, maxY = first.y;
343
326
  for (const p of pts) {
344
327
  if (p.x < minX) {
345
328
  minX = p.x;
@@ -358,23 +341,23 @@ function computeBoundaries(pts, logicalWidth, logicalHeight) {
358
341
  const h = maxY - minY;
359
342
  if (w === 0 && h === 0) {
360
343
  throw new Error(
361
- "[sarmal] Degenerate curve: all skeleton points are identical. Check that your curve fn returns distinct points for different values of t.",
344
+ "[sarmal] Degenerate curve: all skeleton points are identical. Check that your curve fn returns distinct points for different values of t."
362
345
  );
363
346
  }
364
347
  const scaleXProportional = logicalWidth / (w * (1 + FIT_PADDING * 2));
365
348
  const scaleYProportional = logicalHeight / (h * (1 + FIT_PADDING * 2));
366
- const scaleXMinPadding = (logicalWidth - FIT_PADDING_MIN * 2) / w;
367
- const scaleYMinPadding = (logicalHeight - FIT_PADDING_MIN * 2) / h;
349
+ const scaleXMinPadding = (logicalWidth - minPaddingPx * 2) / w;
350
+ const scaleYMinPadding = (logicalHeight - minPaddingPx * 2) / h;
368
351
  const scale = Math.min(
369
352
  scaleXProportional,
370
353
  scaleYProportional,
371
354
  scaleXMinPadding,
372
- scaleYMinPadding,
355
+ scaleYMinPadding
373
356
  );
374
357
  return {
375
358
  scale,
376
359
  offsetX: (logicalWidth - w * scale) / 2 - minX * scale,
377
- offsetY: (logicalHeight - h * scale) / 2 - minY * scale,
360
+ offsetY: (logicalHeight - h * scale) / 2 - minY * scale
378
361
  };
379
362
  }
380
363
  function enginePassthroughs(engine) {
@@ -385,16 +368,17 @@ function enginePassthroughs(engine) {
385
368
  getSpeed: engine.getSpeed,
386
369
  resetSpeed: engine.resetSpeed,
387
370
  setSpeedOver: engine.setSpeedOver,
371
+ getSarmalSkeleton: engine.getSarmalSkeleton
388
372
  };
389
373
  }
390
374
  function hexToRgb(hex) {
391
375
  const n = parseInt(hex.slice(1), 16);
392
- return { r: n >> 16, g: (n >> 8) & 255, b: n & 255 };
376
+ return { r: n >> 16, g: n >> 8 & 255, b: n & 255 };
393
377
  }
394
378
  var lerpRgb = (a, b, t) => ({
395
379
  r: Math.round(a.r + (b.r - a.r) * t),
396
380
  g: Math.round(a.g + (b.g - a.g) * t),
397
- b: Math.round(a.b + (b.b - a.b) * t),
381
+ b: Math.round(a.b + (b.b - a.b) * t)
398
382
  });
399
383
  function getPaletteColor(palette, position, timeOffset = 0) {
400
384
  if (palette.length === 0) {
@@ -403,7 +387,7 @@ function getPaletteColor(palette, position, timeOffset = 0) {
403
387
  if (palette.length === 1) {
404
388
  return hexToRgb(palette[0]);
405
389
  }
406
- const cyclePos = (((position + timeOffset) % 1) + 1) % 1;
390
+ const cyclePos = ((position + timeOffset) % 1 + 1) % 1;
407
391
  const scaled = cyclePos * palette.length;
408
392
  const idx = Math.floor(scaled);
409
393
  const t = scaled - idx;
@@ -418,7 +402,7 @@ var RENDER_OPTION_KEYS = /* @__PURE__ */ new Set([
418
402
  "headColor",
419
403
  "skeletonColor",
420
404
  "trailStyle",
421
- "headRadius",
405
+ "headRadius"
422
406
  ]);
423
407
  function validateRenderOptions(partial) {
424
408
  for (const key of Object.keys(partial)) {
@@ -446,7 +430,7 @@ function assertTrailColor(value) {
446
430
  if (typeof value === "string") {
447
431
  if (!HEX_COLOR_RE.test(value)) {
448
432
  throw new TypeError(
449
- `[sarmal] setRenderOptions: trailColor must be a 6-digit hex string, got "${value}"`,
433
+ `[sarmal] setRenderOptions: trailColor must be a 6-digit hex string, got "${value}"`
450
434
  );
451
435
  }
452
436
  return;
@@ -454,21 +438,21 @@ function assertTrailColor(value) {
454
438
  if (Array.isArray(value)) {
455
439
  if (value.length < 2) {
456
440
  throw new RangeError(
457
- `[sarmal] setRenderOptions: trailColor array must have at least 2 entries, got ${value.length}`,
441
+ `[sarmal] setRenderOptions: trailColor array must have at least 2 entries, got ${value.length}`
458
442
  );
459
443
  }
460
444
  for (let i = 0; i < value.length; i++) {
461
445
  const entry = value[i];
462
446
  if (typeof entry !== "string" || !HEX_COLOR_RE.test(entry)) {
463
447
  throw new TypeError(
464
- `[sarmal] setRenderOptions: trailColor[${i}] must be a 6-digit hex string, got ${JSON.stringify(entry)}`,
448
+ `[sarmal] setRenderOptions: trailColor[${i}] must be a 6-digit hex string, got ${JSON.stringify(entry)}`
465
449
  );
466
450
  }
467
451
  }
468
452
  return;
469
453
  }
470
454
  throw new TypeError(
471
- `[sarmal] setRenderOptions: trailColor must be a 6-digit hex string or an array of hex strings, got ${JSON.stringify(value)}`,
455
+ `[sarmal] setRenderOptions: trailColor must be a 6-digit hex string or an array of hex strings, got ${JSON.stringify(value)}`
472
456
  );
473
457
  }
474
458
  function assertHeadColor(value) {
@@ -477,7 +461,7 @@ function assertHeadColor(value) {
477
461
  }
478
462
  if (typeof value !== "string" || !HEX_COLOR_RE.test(value)) {
479
463
  throw new TypeError(
480
- `[sarmal] setRenderOptions: headColor must be a 6-digit hex string or null, got ${JSON.stringify(value)}`,
464
+ `[sarmal] setRenderOptions: headColor must be a 6-digit hex string or null, got ${JSON.stringify(value)}`
481
465
  );
482
466
  }
483
467
  }
@@ -487,26 +471,26 @@ function assertSkeletonColor(value) {
487
471
  }
488
472
  if (typeof value !== "string" || !HEX_COLOR_RE.test(value)) {
489
473
  throw new TypeError(
490
- `[sarmal] setRenderOptions: skeletonColor must be a 6-digit hex string or "transparent", got ${JSON.stringify(value)}`,
474
+ `[sarmal] setRenderOptions: skeletonColor must be a 6-digit hex string or "transparent", got ${JSON.stringify(value)}`
491
475
  );
492
476
  }
493
477
  }
494
478
  function assertTrailStyle(value) {
495
479
  if (!TRAIL_STYLES.includes(value)) {
496
480
  throw new RangeError(
497
- `[sarmal] setRenderOptions: trailStyle must be one of "default", "gradient-static", "gradient-animated", got ${JSON.stringify(value)}`,
481
+ `[sarmal] setRenderOptions: trailStyle must be one of "default", "gradient-static", "gradient-animated", got ${JSON.stringify(value)}`
498
482
  );
499
483
  }
500
484
  }
501
485
  function assertHeadRadius(value) {
502
486
  if (typeof value !== "number") {
503
487
  throw new TypeError(
504
- `[sarmal] setRenderOptions: headRadius must be a number, got ${JSON.stringify(value)}`,
488
+ `[sarmal] setRenderOptions: headRadius must be a number, got ${JSON.stringify(value)}`
505
489
  );
506
490
  }
507
491
  if (!Number.isFinite(value) || value <= 0) {
508
492
  throw new TypeError(
509
- `[sarmal] setRenderOptions: headRadius must be a finite positive number, got ${value}`,
493
+ `[sarmal] setRenderOptions: headRadius must be a finite positive number, got ${value}`
510
494
  );
511
495
  }
512
496
  }
@@ -528,13 +512,13 @@ function resolveHeadColor(trailColor, trailStyle) {
528
512
  function warnIfTrailColorMismatch(trailColor, trailStyle) {
529
513
  if (trailStyle === "default" && Array.isArray(trailColor)) {
530
514
  console.warn(
531
- '[sarmal] trailColor is an array but trailStyle is "default"; only the first color will be used. Pass a gradient trailStyle to use the whole palette.',
515
+ '[sarmal] trailColor is an array but trailStyle is "default"; only the first color will be used. Pass a gradient trailStyle to use the whole palette.'
532
516
  );
533
517
  return;
534
518
  }
535
519
  if (trailStyle !== "default" && typeof trailColor === "string") {
536
520
  console.warn(
537
- `[sarmal] trailColor is a single color but trailStyle is "${trailStyle}"; the trail will render as a solid color. Pass an array of hex colors to use a real gradient.`,
521
+ `[sarmal] trailColor is a single color but trailStyle is "${trailStyle}"; the trail will render as a solid color. Pass an array of hex colors to use a real gradient.`
538
522
  );
539
523
  }
540
524
  }
@@ -544,7 +528,7 @@ var getHeadDotRadius = (w, h) => Math.max(1, 3 * Math.sqrt(Math.min(w, h) / 160)
544
528
  var WHITE_HEX = "#ffffff";
545
529
  function hexToRgbComponents(hex) {
546
530
  const n = parseInt(hex.slice(1), 16);
547
- return `${n >> 16},${(n >> 8) & 255},${n & 255}`;
531
+ return `${n >> 16},${n >> 8 & 255},${n & 255}`;
548
532
  }
549
533
  function applyDprSizing(target, logicalWidth, logicalHeight, dpr) {
550
534
  target.style.width = `${logicalWidth}px`;
@@ -588,6 +572,7 @@ function createRenderer(options) {
588
572
  let offsetY = 0;
589
573
  let animationId = null;
590
574
  let lastTime = 0;
575
+ let pausedByVisibility = false;
591
576
  let morphResolve = null;
592
577
  let morphReject = null;
593
578
  let morphDurationMs = DEFAULT_MORPH_DURATION_MS;
@@ -670,7 +655,7 @@ function createRenderer(options) {
670
655
  i,
671
656
  trailCount,
672
657
  toX,
673
- toY,
658
+ toY
674
659
  );
675
660
  if (trailStyle === "default") {
676
661
  ctx.fillStyle = `rgba(${trailSolidRgb},${opacity})`;
@@ -781,6 +766,7 @@ function createRenderer(options) {
781
766
  cancelAnimationFrame(animationId);
782
767
  animationId = null;
783
768
  }
769
+ document.removeEventListener("visibilitychange", handleVisibilityChange);
784
770
  if (morphReject !== null) {
785
771
  morphReject(new Error("Instance destroyed during morph"));
786
772
  morphResolve = null;
@@ -834,10 +820,30 @@ function createRenderer(options) {
834
820
  if (partial.trailColor !== void 0 || partial.trailStyle !== void 0) {
835
821
  warnIfTrailColorMismatch(trailColor, trailStyle);
836
822
  }
837
- },
823
+ }
838
824
  };
839
- if (shouldAutoStart) {
825
+ const pauseOnHidden = options.pauseOnHidden !== false;
826
+ function handleVisibilityChange() {
827
+ if (document.hidden) {
828
+ if (animationId !== null) {
829
+ instance.pause();
830
+ pausedByVisibility = true;
831
+ }
832
+ } else {
833
+ if (pausedByVisibility) {
834
+ pausedByVisibility = false;
835
+ instance.play();
836
+ }
837
+ }
838
+ }
839
+ if (pauseOnHidden) {
840
+ document.addEventListener("visibilitychange", handleVisibilityChange);
841
+ }
842
+ const actuallyAutoStart = shouldAutoStart && !(pauseOnHidden && document.hidden);
843
+ if (actuallyAutoStart) {
840
844
  instance.play();
845
+ } else if (shouldAutoStart) {
846
+ pausedByVisibility = true;
841
847
  }
842
848
  return instance;
843
849
  }
@@ -864,7 +870,7 @@ function sampleCurveSkeleton(curveDef) {
864
870
  const samples = Math.ceil(period * 50);
865
871
  const pts = Array.from({ length: samples });
866
872
  for (let i = 0; i < samples; i++) {
867
- const t = (i / (samples - 1)) * period;
873
+ const t = i / (samples - 1) * period;
868
874
  pts[i] = curveDef.skeletonFn ? curveDef.skeletonFn(t) : curveDef.fn(t, 0, EMPTY_PARAMS2);
869
875
  }
870
876
  return pts;
@@ -877,7 +883,7 @@ function createSVGRenderer(options) {
877
883
  const poolSize = engine.trailLength;
878
884
  if (poolSize > HIGH_TRAIL_LENGTH_THRESHOLD) {
879
885
  console.warn(
880
- `[sarmal] High trailLength in SVG renderer (${poolSize}). Consider using the canvas renderer for long trails.`,
886
+ `[sarmal] High trailLength in SVG renderer (${poolSize}). Consider using the canvas renderer for long trails.`
881
887
  );
882
888
  }
883
889
  let trailStyle = options.trailStyle ?? "default";
@@ -896,9 +902,9 @@ function createSVGRenderer(options) {
896
902
  return rect.width && rect.height ? Math.min(rect.width, rect.height) : 200;
897
903
  }
898
904
  const containerPx = getContainerPixelSize();
899
- const svgTrailMinWidth = (TRAIL_MIN_WIDTH * viewSize) / containerPx;
900
- const svgTrailMaxWidth = (TRAIL_MAX_WIDTH * viewSize) / containerPx;
901
- const svgSkeletonStrokeWidth = String((SKELETON_STROKE_WIDTH_PX * viewSize) / containerPx);
905
+ const svgTrailMinWidth = TRAIL_MIN_WIDTH * viewSize / containerPx;
906
+ const svgTrailMaxWidth = TRAIL_MAX_WIDTH * viewSize / containerPx;
907
+ const svgSkeletonStrokeWidth = String(SKELETON_STROKE_WIDTH_PX * viewSize / containerPx);
902
908
  headRadius = options.headRadius ?? SVG_DEFAULT_HEAD_RADIUS;
903
909
  container.setAttribute("viewBox", `0 0 ${viewSize} ${viewSize}`);
904
910
  container.setAttribute("role", "img");
@@ -986,7 +992,7 @@ function createSVGRenderer(options) {
986
992
  px,
987
993
  py,
988
994
  svgTrailMinWidth,
989
- svgTrailMaxWidth,
995
+ svgTrailMaxWidth
990
996
  );
991
997
  const d = `M${l0x.toFixed(2)} ${l0y.toFixed(2)} L${l1x.toFixed(2)} ${l1y.toFixed(2)} L${r1x.toFixed(2)} ${r1y.toFixed(2)} L${r0x.toFixed(2)} ${r0y.toFixed(2)} Z`;
992
998
  trailPaths[i].setAttribute("d", d);
@@ -1013,8 +1019,8 @@ function createSVGRenderer(options) {
1013
1019
  }
1014
1020
  let animationId = null;
1015
1021
  let lastTime = 0;
1016
- const prefersReducedMotion =
1017
- typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
1022
+ let pausedByVisibility = false;
1023
+ const prefersReducedMotion = typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
1018
1024
  let morphResolve = null;
1019
1025
  let morphReject = null;
1020
1026
  let morphDurationMs = DEFAULT_MORPH_DURATION_MS;
@@ -1032,7 +1038,7 @@ function createSVGRenderer(options) {
1032
1038
  skeletonPathA.setAttribute("visibility", "visible");
1033
1039
  skeletonPathA.setAttribute(
1034
1040
  "stroke-opacity",
1035
- String((1 - morphAlpha) * DEFAULT_SKELETON_OPACITY),
1041
+ String((1 - morphAlpha) * DEFAULT_SKELETON_OPACITY)
1036
1042
  );
1037
1043
  }
1038
1044
  if (morphPathBBuilt) {
@@ -1104,6 +1110,7 @@ function createSVGRenderer(options) {
1104
1110
  cancelAnimationFrame(animationId);
1105
1111
  animationId = null;
1106
1112
  }
1113
+ document.removeEventListener("visibilitychange", handleVisibilityChange);
1107
1114
  if (morphReject !== null) {
1108
1115
  morphReject(new Error("Instance destroyed during morph"));
1109
1116
  morphResolve = null;
@@ -1185,10 +1192,30 @@ function createSVGRenderer(options) {
1185
1192
  if (partial.trailColor !== void 0 || partial.trailStyle !== void 0) {
1186
1193
  warnIfTrailColorMismatch(trailColor, trailStyle);
1187
1194
  }
1188
- },
1195
+ }
1189
1196
  };
1190
- if (shouldAutoStart) {
1197
+ const pauseOnHidden = options.pauseOnHidden !== false;
1198
+ function handleVisibilityChange() {
1199
+ if (document.hidden) {
1200
+ if (animationId !== null) {
1201
+ instance.pause();
1202
+ pausedByVisibility = true;
1203
+ }
1204
+ } else {
1205
+ if (pausedByVisibility) {
1206
+ pausedByVisibility = false;
1207
+ instance.play();
1208
+ }
1209
+ }
1210
+ }
1211
+ if (pauseOnHidden) {
1212
+ document.addEventListener("visibilitychange", handleVisibilityChange);
1213
+ }
1214
+ const actuallyAutoStart = shouldAutoStart && !(pauseOnHidden && document.hidden);
1215
+ if (actuallyAutoStart) {
1191
1216
  instance.play();
1217
+ } else if (shouldAutoStart) {
1218
+ pausedByVisibility = true;
1192
1219
  }
1193
1220
  return instance;
1194
1221
  }
@@ -1198,254 +1225,309 @@ function createSarmalSVG(container, curveDef, options) {
1198
1225
  return createSVGRenderer({ container, engine, ...rendererOpts });
1199
1226
  }
1200
1227
 
1201
- // src/curves/artemis2.ts
1202
- var TWO_PI2 = Math.PI * 2;
1203
- function artemis2Fn(t, _time, _params) {
1204
- const a = 0.35,
1205
- b = 0.15,
1206
- ox = 0.175;
1207
- const s = Math.sin(t),
1208
- c = Math.cos(t);
1209
- const denom = 1 + s * s;
1228
+ // src/catmull-rom.ts
1229
+ var PERIOD = 2 * Math.PI;
1230
+ function catmullRom1D(p0, p1, p2, p3, u) {
1231
+ const u2 = u * u;
1232
+ const u3 = u2 * u;
1233
+ return 0.5 * (2 * p1 + (-p0 + p2) * u + (2 * p0 - 5 * p1 + 4 * p2 - p3) * u2 + (-p0 + 3 * p1 - 3 * p2 + p3) * u3);
1234
+ }
1235
+ function evaluateCatmullRom(points2, t) {
1236
+ const N = points2.length;
1237
+ if (N === 0) {
1238
+ return { x: 0, y: 0 };
1239
+ }
1240
+ if (N === 1) {
1241
+ return { x: points2[0][0], y: points2[0][1] };
1242
+ }
1243
+ t = (t % PERIOD + PERIOD) % PERIOD;
1244
+ const segmentSize = PERIOD / N;
1245
+ let i = Math.floor(t / segmentSize);
1246
+ if (i >= N) {
1247
+ i = N - 1;
1248
+ }
1249
+ let u = (t - i * segmentSize) / segmentSize;
1250
+ u = Math.max(0, Math.min(1, u));
1251
+ const p0 = points2[(i - 1 + N) % N];
1252
+ const p1 = points2[i];
1253
+ const p2 = points2[(i + 1) % N];
1254
+ const p3 = points2[(i + 2) % N];
1210
1255
  return {
1211
- x: (c * (1 + a * c)) / denom - ox,
1212
- y: (s * c * (1 + b * c)) / denom,
1256
+ x: catmullRom1D(p0[0], p1[0], p2[0], p3[0], u),
1257
+ y: catmullRom1D(p0[1], p1[1], p2[1], p3[1], u)
1213
1258
  };
1214
1259
  }
1260
+ function drawCurve(points2, opts) {
1261
+ if (points2.length < 3) {
1262
+ throw new Error(`drawCurve requires at least 3 points, received ${points2.length}.`);
1263
+ }
1264
+ const first = points2[0];
1265
+ if (points2.every((p) => p[0] === first[0] && p[1] === first[1])) {
1266
+ console.warn(
1267
+ "[sarmal].drawCurve: all control points are identical. The curve will be a single point."
1268
+ );
1269
+ }
1270
+ const maxAbs = points2.reduce((m, p) => Math.max(m, Math.abs(p[0]), Math.abs(p[1])), 0);
1271
+ if (maxAbs > 2) {
1272
+ console.warn(
1273
+ `[sarmal].drawCurve: control points extend to \xB1${maxAbs.toFixed(1)}, which may render off-screen. Coordinates should be in [-1, 1].`
1274
+ );
1275
+ }
1276
+ const pts = points2.map(([x, y]) => [x, y]);
1277
+ return {
1278
+ name: opts?.name ?? "drawn",
1279
+ fn: (t) => evaluateCatmullRom(pts, t),
1280
+ period: PERIOD,
1281
+ kind: "drawn"
1282
+ };
1283
+ }
1284
+
1285
+ // src/curves/artemis2.ts
1286
+ var points = [
1287
+ [-0.44, -0.45],
1288
+ [-0.53, -0.77],
1289
+ [-0.82, -0.66],
1290
+ [-0.82, -0.18],
1291
+ [-0.25, -0.04],
1292
+ [0.16, -0.49],
1293
+ [-0.03, -0.87],
1294
+ [-0.68, -0.94],
1295
+ [-0.95, -0.61],
1296
+ [-0.87, -0],
1297
+ [-0.34, 0.21],
1298
+ [0.27, -0.04],
1299
+ [0.87, 0.06],
1300
+ [0.87, 0.57],
1301
+ [0.32, 0.66],
1302
+ [-0.21, -0.43],
1303
+ [-0.43, -0.81],
1304
+ [-0.69, -0.84],
1305
+ [-0.87, -0.66],
1306
+ [-0.9, -0.47],
1307
+ [-0.76, -0.35]
1308
+ ];
1215
1309
  var artemis2 = {
1216
- name: "Artemis II",
1217
- fn: artemis2Fn,
1218
- period: TWO_PI2,
1219
- speed: 0.7,
1310
+ ...drawCurve(points, { name: "Artemis II" }),
1311
+ speed: 0.7
1220
1312
  };
1221
1313
 
1222
1314
  // src/curves/astroid.ts
1223
- var TWO_PI3 = Math.PI * 2;
1315
+ var TWO_PI2 = Math.PI * 2;
1224
1316
  function astroidFn(t, _time, _params) {
1225
1317
  const c = Math.cos(t);
1226
1318
  const s = Math.sin(t);
1227
1319
  return {
1228
1320
  x: c * c * c,
1229
- y: s * s * s,
1321
+ y: s * s * s
1230
1322
  };
1231
1323
  }
1232
1324
  var astroid = {
1233
1325
  name: "Astroid",
1234
1326
  fn: astroidFn,
1235
- period: TWO_PI3,
1236
- speed: 1.1,
1327
+ period: TWO_PI2,
1328
+ speed: 1.1
1237
1329
  };
1238
1330
 
1239
1331
  // src/curves/deltoid.ts
1240
- var TWO_PI4 = Math.PI * 2;
1332
+ var TWO_PI3 = Math.PI * 2;
1241
1333
  function deltoidFn(t, _time, _params) {
1242
1334
  return {
1243
1335
  x: 2 * Math.cos(t) + Math.cos(2 * t),
1244
- y: 2 * Math.sin(t) - Math.sin(2 * t),
1336
+ y: 2 * Math.sin(t) - Math.sin(2 * t)
1245
1337
  };
1246
1338
  }
1247
1339
  var deltoid = {
1248
1340
  name: "Deltoid",
1249
1341
  fn: deltoidFn,
1250
- period: TWO_PI4,
1251
- speed: 0.9,
1342
+ period: TWO_PI3,
1343
+ speed: 0.9
1252
1344
  };
1253
1345
 
1254
1346
  // src/curves/epicycloid3.ts
1255
- var TWO_PI5 = Math.PI * 2;
1347
+ var TWO_PI4 = Math.PI * 2;
1256
1348
  function epicycloid3Fn(t, _time, _params) {
1257
1349
  return {
1258
1350
  x: 4 * Math.cos(t) - Math.cos(4 * t),
1259
- y: 4 * Math.sin(t) - Math.sin(4 * t),
1351
+ y: 4 * Math.sin(t) - Math.sin(4 * t)
1260
1352
  };
1261
1353
  }
1262
1354
  var epicycloid3 = {
1263
1355
  name: "Epicycloid (n=3)",
1264
1356
  fn: epicycloid3Fn,
1265
- period: TWO_PI5,
1266
- speed: 0.75,
1357
+ period: TWO_PI4,
1358
+ speed: 0.75
1267
1359
  };
1268
1360
 
1269
1361
  // src/curves/epitrochoid7.ts
1270
- var TWO_PI6 = Math.PI * 2;
1362
+ var TWO_PI5 = Math.PI * 2;
1271
1363
  function epitrochoid7Fn(t, _time, _params) {
1272
1364
  const d = 1 + 0.55 * Math.sin(t * 0.5);
1273
1365
  return {
1274
1366
  x: 7 * Math.cos(t) - d * Math.cos(7 * t),
1275
- y: 7 * Math.sin(t) - d * Math.sin(7 * t),
1367
+ y: 7 * Math.sin(t) - d * Math.sin(7 * t)
1276
1368
  };
1277
1369
  }
1278
1370
  function epitrochoid7SkeletonFn(t) {
1279
1371
  const d = 1.275;
1280
1372
  return {
1281
1373
  x: 7 * Math.cos(t) - d * Math.cos(7 * t),
1282
- y: 7 * Math.sin(t) - d * Math.sin(7 * t),
1374
+ y: 7 * Math.sin(t) - d * Math.sin(7 * t)
1283
1375
  };
1284
1376
  }
1285
1377
  var epitrochoid7 = {
1286
1378
  name: "Epitrochoid",
1287
1379
  fn: epitrochoid7Fn,
1288
- period: TWO_PI6,
1380
+ period: TWO_PI5,
1289
1381
  speed: 1.4,
1290
- skeletonFn: epitrochoid7SkeletonFn,
1382
+ skeletonFn: epitrochoid7SkeletonFn
1291
1383
  };
1292
1384
 
1293
1385
  // src/curves/lissajous32.ts
1294
- var TWO_PI7 = Math.PI * 2;
1386
+ var TWO_PI6 = Math.PI * 2;
1295
1387
  function lissajous32Fn(t, time, _params) {
1296
1388
  const phi = time * 0.45;
1297
1389
  return {
1298
1390
  x: Math.sin(3 * t + phi),
1299
- y: Math.sin(2 * t),
1391
+ y: Math.sin(2 * t)
1300
1392
  };
1301
1393
  }
1302
1394
  var lissajous32 = {
1303
1395
  name: "Lissajous 3:2",
1304
1396
  fn: lissajous32Fn,
1305
- period: TWO_PI7,
1397
+ period: TWO_PI6,
1306
1398
  speed: 2,
1307
- skeleton: "live",
1399
+ skeleton: "live"
1308
1400
  };
1309
1401
 
1310
1402
  // src/curves/lissajous43.ts
1311
- var TWO_PI8 = Math.PI * 2;
1403
+ var TWO_PI7 = Math.PI * 2;
1312
1404
  function lissajous43Fn(t, time, _params) {
1313
1405
  const phi = time * 0.38;
1314
1406
  return {
1315
1407
  x: Math.sin(4 * t + phi),
1316
- y: Math.sin(3 * t),
1408
+ y: Math.sin(3 * t)
1317
1409
  };
1318
1410
  }
1319
1411
  var lissajous43 = {
1320
1412
  name: "Lissajous 4:3",
1321
1413
  fn: lissajous43Fn,
1322
- period: TWO_PI8,
1414
+ period: TWO_PI7,
1323
1415
  speed: 1.8,
1324
- skeleton: "live",
1416
+ skeleton: "live"
1325
1417
  };
1326
1418
 
1327
1419
  // src/curves/lame.ts
1328
- var TWO_PI9 = Math.PI * 2;
1420
+ var TWO_PI8 = Math.PI * 2;
1329
1421
  function lameFn(t, time, _params) {
1330
1422
  const p = 1.75 + 1.25 * Math.sin(time * 0.48);
1331
- const c = Math.cos(t),
1332
- s = Math.sin(t);
1423
+ const c = Math.cos(t), s = Math.sin(t);
1333
1424
  return {
1334
1425
  x: Math.sign(c) * Math.pow(Math.abs(c), p),
1335
- y: Math.sign(s) * Math.pow(Math.abs(s), p),
1426
+ y: Math.sign(s) * Math.pow(Math.abs(s), p)
1336
1427
  };
1337
1428
  }
1338
1429
  var lame = {
1339
1430
  name: "Lam\xE9 Curve",
1340
1431
  fn: lameFn,
1341
- period: TWO_PI9,
1432
+ period: TWO_PI8,
1342
1433
  speed: 1,
1343
- skeleton: "live",
1434
+ skeleton: "live"
1344
1435
  };
1345
1436
 
1346
1437
  // src/curves/rose3.ts
1347
- var TWO_PI10 = Math.PI * 2;
1438
+ var TWO_PI9 = Math.PI * 2;
1348
1439
  function rose3Fn(t, _time, _params) {
1349
1440
  const r = Math.cos(3 * t);
1350
1441
  return {
1351
1442
  x: r * Math.cos(t),
1352
- y: r * Math.sin(t),
1443
+ y: r * Math.sin(t)
1353
1444
  };
1354
1445
  }
1355
1446
  var rose3 = {
1356
1447
  name: "Rose (n=3)",
1357
1448
  fn: rose3Fn,
1358
- period: TWO_PI10,
1359
- speed: 1.15,
1449
+ period: TWO_PI9,
1450
+ speed: 1.15
1360
1451
  };
1361
1452
 
1362
1453
  // src/curves/rose5.ts
1363
- var TWO_PI11 = Math.PI * 2;
1454
+ var TWO_PI10 = Math.PI * 2;
1364
1455
  function rose5Fn(t, _time, _params) {
1365
1456
  const r = Math.cos(5 * t);
1366
1457
  return {
1367
1458
  x: r * Math.cos(t),
1368
- y: r * Math.sin(t),
1459
+ y: r * Math.sin(t)
1369
1460
  };
1370
1461
  }
1371
1462
  var rose5 = {
1372
1463
  name: "Rose (n=5)",
1373
1464
  fn: rose5Fn,
1374
- period: TWO_PI11,
1375
- speed: 1,
1465
+ period: TWO_PI10,
1466
+ speed: 1
1376
1467
  };
1377
1468
 
1378
1469
  // src/curves/rose52.ts
1379
1470
  var FOUR_PI = Math.PI * 4;
1380
1471
  function rose52Fn(t, _time, _params) {
1381
- const r = Math.cos((5 / 2) * t);
1472
+ const r = Math.cos(5 / 2 * t);
1382
1473
  return {
1383
1474
  x: r * Math.cos(t),
1384
- y: r * Math.sin(t),
1475
+ y: r * Math.sin(t)
1385
1476
  };
1386
1477
  }
1387
1478
  var rose52 = {
1388
1479
  name: "Rose (n=5/2)",
1389
1480
  fn: rose52Fn,
1390
1481
  period: FOUR_PI,
1391
- speed: 0.8,
1482
+ speed: 0.8
1392
1483
  };
1393
1484
 
1394
1485
  // src/curves/star.ts
1395
- var TWO_PI12 = Math.PI * 2;
1486
+ var TWO_PI11 = Math.PI * 2;
1396
1487
  function starFn(t, _time, _params) {
1397
- const r =
1398
- Math.abs(Math.cos((5 / 2) * t)) +
1399
- 0.35 * Math.abs(Math.cos((15 / 2) * t)) +
1400
- 0.15 * Math.abs(Math.cos((25 / 2) * t));
1488
+ const r = Math.abs(Math.cos(5 / 2 * t)) + 0.35 * Math.abs(Math.cos(15 / 2 * t)) + 0.15 * Math.abs(Math.cos(25 / 2 * t));
1401
1489
  return {
1402
1490
  x: r * Math.cos(t),
1403
- y: r * Math.sin(t),
1491
+ y: r * Math.sin(t)
1404
1492
  };
1405
1493
  }
1406
1494
  var star = {
1407
1495
  name: "Star",
1408
1496
  fn: starFn,
1409
- period: TWO_PI12,
1410
- speed: 1,
1497
+ period: TWO_PI11,
1498
+ speed: 1
1411
1499
  };
1412
1500
 
1413
1501
  // src/curves/star4.ts
1414
- var TWO_PI13 = Math.PI * 2;
1502
+ var TWO_PI12 = Math.PI * 2;
1415
1503
  function star4Fn(t, _time, _params) {
1416
- const r =
1417
- Math.abs(Math.cos(2 * t)) +
1418
- 0.35 * Math.abs(Math.cos(6 * t)) +
1419
- 0.15 * Math.abs(Math.cos(10 * t));
1504
+ const r = Math.abs(Math.cos(2 * t)) + 0.35 * Math.abs(Math.cos(6 * t)) + 0.15 * Math.abs(Math.cos(10 * t));
1420
1505
  return {
1421
1506
  x: r * Math.cos(t),
1422
- y: r * Math.sin(t),
1507
+ y: r * Math.sin(t)
1423
1508
  };
1424
1509
  }
1425
1510
  var star4 = {
1426
1511
  name: "Star (4-arm)",
1427
1512
  fn: star4Fn,
1428
- period: TWO_PI13,
1429
- speed: 1,
1513
+ period: TWO_PI12,
1514
+ speed: 1
1430
1515
  };
1431
1516
 
1432
1517
  // src/curves/star7.ts
1433
- var TWO_PI14 = Math.PI * 2;
1518
+ var TWO_PI13 = Math.PI * 2;
1434
1519
  function star7Fn(t, _time, _params) {
1435
- const r =
1436
- Math.abs(Math.cos((7 / 2) * t)) +
1437
- 0.35 * Math.abs(Math.cos((21 / 2) * t)) +
1438
- 0.15 * Math.abs(Math.cos((35 / 2) * t));
1520
+ const r = Math.abs(Math.cos(7 / 2 * t)) + 0.35 * Math.abs(Math.cos(21 / 2 * t)) + 0.15 * Math.abs(Math.cos(35 / 2 * t));
1439
1521
  return {
1440
1522
  x: r * Math.cos(t),
1441
- y: r * Math.sin(t),
1523
+ y: r * Math.sin(t)
1442
1524
  };
1443
1525
  }
1444
1526
  var star7 = {
1445
1527
  name: "Star (7-arm)",
1446
1528
  fn: star7Fn,
1447
- period: TWO_PI14,
1448
- speed: 1,
1529
+ period: TWO_PI13,
1530
+ speed: 1
1449
1531
  };
1450
1532
 
1451
1533
  // src/curves/index.ts
@@ -1463,7 +1545,7 @@ var curves = {
1463
1545
  lissajous32,
1464
1546
  lissajous43,
1465
1547
  epicycloid3,
1466
- lame,
1548
+ lame
1467
1549
  };
1468
1550
 
1469
1551
  // src/index.ts
@@ -1480,21 +1562,22 @@ function parseTrailColor(value) {
1480
1562
  if (Array.isArray(parsed)) {
1481
1563
  return parsed;
1482
1564
  }
1483
- } catch {}
1565
+ } catch {
1566
+ }
1484
1567
  return value;
1485
1568
  }
1486
1569
  function buildOptions(el2) {
1487
1570
  return {
1488
- ...(el2.dataset.trailColor && {
1489
- trailColor: parseTrailColor(el2.dataset.trailColor),
1490
- }),
1491
- ...(el2.dataset.skeletonColor && { skeletonColor: el2.dataset.skeletonColor }),
1492
- ...(el2.dataset.headColor && { headColor: el2.dataset.headColor }),
1493
- ...(el2.dataset.headRadius && { headRadius: parseFloat(el2.dataset.headRadius) }),
1494
- ...(el2.dataset.trailLength && { trailLength: parseInt(el2.dataset.trailLength, 10) }),
1495
- ...(el2.dataset.trailStyle && {
1496
- trailStyle: el2.dataset.trailStyle,
1497
- }),
1571
+ ...el2.dataset.trailColor && {
1572
+ trailColor: parseTrailColor(el2.dataset.trailColor)
1573
+ },
1574
+ ...el2.dataset.skeletonColor && { skeletonColor: el2.dataset.skeletonColor },
1575
+ ...el2.dataset.headColor && { headColor: el2.dataset.headColor },
1576
+ ...el2.dataset.headRadius && { headRadius: parseFloat(el2.dataset.headRadius) },
1577
+ ...el2.dataset.trailLength && { trailLength: parseInt(el2.dataset.trailLength, 10) },
1578
+ ...el2.dataset.trailStyle && {
1579
+ trailStyle: el2.dataset.trailStyle
1580
+ }
1498
1581
  };
1499
1582
  }
1500
1583
  function init() {
@@ -1509,10 +1592,7 @@ function init() {
1509
1592
  return console.error(`[sarmal] "${curveName}" is not a valid curve name`);
1510
1593
  }
1511
1594
  const options = buildOptions(el2);
1512
- const instance =
1513
- el2 instanceof HTMLCanvasElement
1514
- ? createSarmal(el2, curveDef, options)
1515
- : createSarmalSVG(el2, curveDef, options);
1595
+ const instance = el2 instanceof HTMLCanvasElement ? createSarmal(el2, curveDef, options) : createSarmalSVG(el2, curveDef, options);
1516
1596
  if (el2.dataset.speed) {
1517
1597
  instance.setSpeed(parseFloat(el2.dataset.speed));
1518
1598
  }
@@ -1528,4 +1608,4 @@ if (document.readyState === "loading") {
1528
1608
 
1529
1609
  export { init };
1530
1610
  //# sourceMappingURL=auto-init.js.map
1531
- //# sourceMappingURL=auto-init.js.map
1611
+ //# sourceMappingURL=auto-init.js.map