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