@sarmal/core 0.27.0 → 0.28.1

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 (80) hide show
  1. package/dist/auto-init.cjs +106 -145
  2. package/dist/auto-init.js +105 -144
  3. package/dist/cli.js +103 -145
  4. package/dist/cli.js.map +1 -1
  5. package/dist/curves/artemis2.cjs +10 -16
  6. package/dist/curves/artemis2.d.cts +1 -1
  7. package/dist/curves/artemis2.d.ts +1 -1
  8. package/dist/curves/artemis2.js +9 -15
  9. package/dist/curves/astroid.cjs +4 -4
  10. package/dist/curves/astroid.d.cts +1 -1
  11. package/dist/curves/astroid.d.ts +1 -1
  12. package/dist/curves/astroid.js +3 -3
  13. package/dist/curves/deltoid.cjs +4 -4
  14. package/dist/curves/deltoid.d.cts +1 -1
  15. package/dist/curves/deltoid.d.ts +1 -1
  16. package/dist/curves/deltoid.js +3 -3
  17. package/dist/curves/epicycloid3.cjs +4 -4
  18. package/dist/curves/epicycloid3.d.cts +1 -1
  19. package/dist/curves/epicycloid3.d.ts +1 -1
  20. package/dist/curves/epicycloid3.js +3 -3
  21. package/dist/curves/epitrochoid7.cjs +5 -5
  22. package/dist/curves/epitrochoid7.d.cts +1 -1
  23. package/dist/curves/epitrochoid7.d.ts +1 -1
  24. package/dist/curves/epitrochoid7.js +4 -4
  25. package/dist/curves/index.cjs +43 -59
  26. package/dist/curves/index.d.cts +29 -29
  27. package/dist/curves/index.d.ts +29 -29
  28. package/dist/curves/index.js +43 -75
  29. package/dist/curves/lame.cjs +5 -6
  30. package/dist/curves/lame.d.cts +1 -1
  31. package/dist/curves/lame.d.ts +1 -1
  32. package/dist/curves/lame.js +4 -5
  33. package/dist/curves/lissajous32.cjs +4 -4
  34. package/dist/curves/lissajous32.d.cts +1 -1
  35. package/dist/curves/lissajous32.d.ts +1 -1
  36. package/dist/curves/lissajous32.js +3 -3
  37. package/dist/curves/lissajous43.cjs +4 -4
  38. package/dist/curves/lissajous43.d.cts +1 -1
  39. package/dist/curves/lissajous43.d.ts +1 -1
  40. package/dist/curves/lissajous43.js +3 -3
  41. package/dist/curves/rose3.cjs +4 -4
  42. package/dist/curves/rose3.d.cts +1 -1
  43. package/dist/curves/rose3.d.ts +1 -1
  44. package/dist/curves/rose3.js +3 -3
  45. package/dist/curves/rose5.cjs +4 -4
  46. package/dist/curves/rose5.d.cts +1 -1
  47. package/dist/curves/rose5.d.ts +1 -1
  48. package/dist/curves/rose5.js +3 -3
  49. package/dist/curves/rose52.cjs +5 -5
  50. package/dist/curves/rose52.d.cts +1 -1
  51. package/dist/curves/rose52.d.ts +1 -1
  52. package/dist/curves/rose52.js +4 -4
  53. package/dist/curves/star.cjs +5 -8
  54. package/dist/curves/star.d.cts +1 -1
  55. package/dist/curves/star.d.ts +1 -1
  56. package/dist/curves/star.js +4 -7
  57. package/dist/curves/star4.cjs +5 -8
  58. package/dist/curves/star4.d.cts +1 -1
  59. package/dist/curves/star4.d.ts +1 -1
  60. package/dist/curves/star4.js +4 -7
  61. package/dist/curves/star7.cjs +5 -8
  62. package/dist/curves/star7.d.cts +1 -1
  63. package/dist/curves/star7.d.ts +1 -1
  64. package/dist/curves/star7.js +4 -7
  65. package/dist/index.cjs +94 -131
  66. package/dist/index.d.cts +30 -78
  67. package/dist/index.d.ts +30 -78
  68. package/dist/index.js +94 -152
  69. package/dist/renderer-shared-OR--cv-t.d.ts +15 -26
  70. package/dist/renderer-shared-jqw_Q1WO.d.cts +15 -26
  71. package/dist/terminal.cjs +52 -75
  72. package/dist/terminal.cjs.map +1 -1
  73. package/dist/terminal.d.cts +14 -31
  74. package/dist/terminal.d.ts +14 -31
  75. package/dist/terminal.js +51 -74
  76. package/dist/terminal.js.map +1 -1
  77. package/dist/types-zbxUgcmZ.d.cts +266 -280
  78. package/dist/types-zbxUgcmZ.d.ts +266 -280
  79. package/package.json +9 -3
  80. package/skills/core/SKILL.md +151 -0
@@ -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,8 +110,7 @@ function createEngine(curveDef, trailLength = 120) {
110
110
  actualTime += deltaTime;
111
111
  if (morphCurveB !== null && _morphAlpha !== null) {
112
112
  const a = curve.fn(phase, actualTime, EMPTY_PARAMS);
113
- const phaseB =
114
- _morphStrategy === "normalized" ? (phase / curve.period) * morphCurveB.period : phase;
113
+ const phaseB = _morphStrategy === "normalized" ? phase / curve.period * morphCurveB.period : phase;
115
114
  const b = morphCurveB.fn(phaseB, actualTime, EMPTY_PARAMS);
116
115
  trail.push(a.x + (b.x - a.x) * _morphAlpha, a.y + (b.y - a.y) * _morphAlpha);
117
116
  } else {
@@ -138,14 +137,14 @@ function createEngine(curveDef, trailLength = 120) {
138
137
  trail.clear();
139
138
  },
140
139
  jump(newPhase, { clearTrail = false } = {}) {
141
- phase = ((newPhase % curve.period) + curve.period) % curve.period;
140
+ phase = (newPhase % curve.period + curve.period) % curve.period;
142
141
  if (clearTrail) {
143
142
  trail.clear();
144
143
  }
145
144
  },
146
145
  seek(targetPhase, { wrap = false, step = curve.period / trailLength } = {}) {
147
146
  const advance = curve.speed * step;
148
- const target = ((targetPhase % curve.period) + curve.period) % curve.period;
147
+ const target = (targetPhase % curve.period + curve.period) % curve.period;
149
148
  const targetTime = target / curve.speed;
150
149
  phase = target;
151
150
  actualTime = targetTime;
@@ -154,7 +153,7 @@ function createEngine(curveDef, trailLength = 120) {
154
153
  const count = wrap ? trailLength : Math.min(trailLength, pointsFromStart);
155
154
  for (let i = count - 1; i >= 0; i--) {
156
155
  const samplePhase = target - i * advance;
157
- const wrappedPhase = ((samplePhase % curve.period) + curve.period) % curve.period;
156
+ const wrappedPhase = (samplePhase % curve.period + curve.period) % curve.period;
158
157
  const elapsed = targetTime - i * step;
159
158
  const point = curve.fn(wrappedPhase, elapsed, EMPTY_PARAMS);
160
159
  trail.push(point.x, point.y);
@@ -171,16 +170,13 @@ function createEngine(curveDef, trailLength = 120) {
171
170
  ...frozenB,
172
171
  fn: (samplePhase, elapsed, params) => {
173
172
  const a = frozenA.fn(samplePhase, elapsed, params);
174
- const phaseB =
175
- frozenStrategy === "normalized"
176
- ? (samplePhase / frozenA.period) * frozenB.period
177
- : samplePhase;
173
+ const phaseB = frozenStrategy === "normalized" ? samplePhase / frozenA.period * frozenB.period : samplePhase;
178
174
  const b = frozenB.fn(phaseB, elapsed, params);
179
175
  return {
180
176
  x: a.x + (b.x - a.x) * frozenAlpha,
181
- y: a.y + (b.y - a.y) * frozenAlpha,
177
+ y: a.y + (b.y - a.y) * frozenAlpha
182
178
  };
183
- },
179
+ }
184
180
  };
185
181
  }
186
182
  _morphStrategy = strategy;
@@ -193,7 +189,7 @@ function createEngine(curveDef, trailLength = 120) {
193
189
  completeMorph() {
194
190
  if (morphCurveB !== null) {
195
191
  if (_morphStrategy === "normalized" && curve.period !== morphCurveB.period) {
196
- phase = (phase / curve.period) * morphCurveB.period;
192
+ phase = phase / curve.period * morphCurveB.period;
197
193
  }
198
194
  curve = morphCurveB;
199
195
  }
@@ -205,22 +201,19 @@ function createEngine(curveDef, trailLength = 120) {
205
201
  const points2 = new Array(steps);
206
202
  if (morphCurveB !== null && _morphAlpha !== null) {
207
203
  for (let i = 0; i < steps; i++) {
208
- const samplePhase = (i / (steps - 1)) * curve.period;
204
+ const samplePhase = i / (steps - 1) * curve.period;
209
205
  const a = sampleSkeleton(curve, samplePhase);
210
- const phaseB =
211
- _morphStrategy === "normalized"
212
- ? (samplePhase / curve.period) * morphCurveB.period
213
- : samplePhase;
206
+ const phaseB = _morphStrategy === "normalized" ? samplePhase / curve.period * morphCurveB.period : samplePhase;
214
207
  const b = sampleSkeleton(morphCurveB, phaseB);
215
208
  points2[i] = {
216
209
  x: a.x + (b.x - a.x) * _morphAlpha,
217
- y: a.y + (b.y - a.y) * _morphAlpha,
210
+ y: a.y + (b.y - a.y) * _morphAlpha
218
211
  };
219
212
  }
220
213
  return points2;
221
214
  }
222
215
  for (let i = 0; i < steps; i++) {
223
- const samplePhase = (i / (steps - 1)) * curve.period;
216
+ const samplePhase = i / (steps - 1) * curve.period;
224
217
  points2[i] = sampleSkeleton(curve, samplePhase);
225
218
  }
226
219
  return points2;
@@ -262,7 +255,7 @@ function createEngine(curveDef, trailLength = 120) {
262
255
  _speedTransition.reject(new Error("Speed transition cancelled"));
263
256
  _speedTransition = null;
264
257
  }
265
- },
258
+ }
266
259
  };
267
260
  }
268
261
 
@@ -301,15 +294,7 @@ function computeNormal(trail, i) {
301
294
  const tangent = computeTangent(trail, i);
302
295
  return { x: -tangent.y, y: tangent.x };
303
296
  }
304
- function computeTrailQuad(
305
- trail,
306
- i,
307
- trailCount,
308
- toX,
309
- toY,
310
- minWidth = TRAIL_MIN_WIDTH,
311
- maxWidth = TRAIL_MAX_WIDTH,
312
- ) {
297
+ function computeTrailQuad(trail, i, trailCount, toX, toY, minWidth = TRAIL_MIN_WIDTH, maxWidth = TRAIL_MAX_WIDTH) {
313
298
  const progress = i / (trailCount - 1);
314
299
  const nextProgress = (i + 1) / (trailCount - 1);
315
300
  const opacity = Math.pow(progress, TRAIL_FADE_CURVE) * TRAIL_MAX_OPACITY;
@@ -333,16 +318,13 @@ function computeTrailQuad(
333
318
  r1x: nx - n1.x * w1,
334
319
  r1y: ny - n1.y * w1,
335
320
  opacity,
336
- progress,
321
+ progress
337
322
  };
338
323
  }
339
324
  function computeBoundaries(pts, logicalWidth, logicalHeight, minPaddingPx = FIT_PADDING_MIN) {
340
325
  if (pts.length === 0) return null;
341
326
  const first = pts[0];
342
- let minX = first.x,
343
- maxX = first.x,
344
- minY = first.y,
345
- maxY = first.y;
327
+ let minX = first.x, maxX = first.x, minY = first.y, maxY = first.y;
346
328
  for (const p of pts) {
347
329
  if (p.x < minX) {
348
330
  minX = p.x;
@@ -361,7 +343,7 @@ function computeBoundaries(pts, logicalWidth, logicalHeight, minPaddingPx = FIT_
361
343
  const h = maxY - minY;
362
344
  if (w === 0 && h === 0) {
363
345
  throw new Error(
364
- "[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."
365
347
  );
366
348
  }
367
349
  const scaleXProportional = logicalWidth / (w * (1 + FIT_PADDING * 2));
@@ -372,12 +354,12 @@ function computeBoundaries(pts, logicalWidth, logicalHeight, minPaddingPx = FIT_
372
354
  scaleXProportional,
373
355
  scaleYProportional,
374
356
  scaleXMinPadding,
375
- scaleYMinPadding,
357
+ scaleYMinPadding
376
358
  );
377
359
  return {
378
360
  scale,
379
361
  offsetX: (logicalWidth - w * scale) / 2 - minX * scale,
380
- offsetY: (logicalHeight - h * scale) / 2 - minY * scale,
362
+ offsetY: (logicalHeight - h * scale) / 2 - minY * scale
381
363
  };
382
364
  }
383
365
  function enginePassthroughs(engine) {
@@ -388,17 +370,17 @@ function enginePassthroughs(engine) {
388
370
  getSpeed: engine.getSpeed,
389
371
  resetSpeed: engine.resetSpeed,
390
372
  setSpeedOver: engine.setSpeedOver,
391
- getSarmalSkeleton: engine.getSarmalSkeleton,
373
+ getSarmalSkeleton: engine.getSarmalSkeleton
392
374
  };
393
375
  }
394
376
  function hexToRgb(hex) {
395
377
  const n = parseInt(hex.slice(1), 16);
396
- return { r: n >> 16, g: (n >> 8) & 255, b: n & 255 };
378
+ return { r: n >> 16, g: n >> 8 & 255, b: n & 255 };
397
379
  }
398
380
  var lerpRgb = (a, b, t) => ({
399
381
  r: Math.round(a.r + (b.r - a.r) * t),
400
382
  g: Math.round(a.g + (b.g - a.g) * t),
401
- b: Math.round(a.b + (b.b - a.b) * t),
383
+ b: Math.round(a.b + (b.b - a.b) * t)
402
384
  });
403
385
  function getPaletteColor(palette, position, timeOffset = 0) {
404
386
  if (palette.length === 0) {
@@ -407,7 +389,7 @@ function getPaletteColor(palette, position, timeOffset = 0) {
407
389
  if (palette.length === 1) {
408
390
  return hexToRgb(palette[0]);
409
391
  }
410
- const cyclePos = (((position + timeOffset) % 1) + 1) % 1;
392
+ const cyclePos = ((position + timeOffset) % 1 + 1) % 1;
411
393
  const scaled = cyclePos * palette.length;
412
394
  const idx = Math.floor(scaled);
413
395
  const t = scaled - idx;
@@ -422,7 +404,7 @@ var RENDER_OPTION_KEYS = /* @__PURE__ */ new Set([
422
404
  "headColor",
423
405
  "skeletonColor",
424
406
  "trailStyle",
425
- "headRadius",
407
+ "headRadius"
426
408
  ]);
427
409
  function validateRenderOptions(partial) {
428
410
  for (const key of Object.keys(partial)) {
@@ -450,7 +432,7 @@ function assertTrailColor(value) {
450
432
  if (typeof value === "string") {
451
433
  if (!HEX_COLOR_RE.test(value)) {
452
434
  throw new TypeError(
453
- `[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}"`
454
436
  );
455
437
  }
456
438
  return;
@@ -458,21 +440,21 @@ function assertTrailColor(value) {
458
440
  if (Array.isArray(value)) {
459
441
  if (value.length < 2) {
460
442
  throw new RangeError(
461
- `[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}`
462
444
  );
463
445
  }
464
446
  for (let i = 0; i < value.length; i++) {
465
447
  const entry = value[i];
466
448
  if (typeof entry !== "string" || !HEX_COLOR_RE.test(entry)) {
467
449
  throw new TypeError(
468
- `[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)}`
469
451
  );
470
452
  }
471
453
  }
472
454
  return;
473
455
  }
474
456
  throw new TypeError(
475
- `[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)}`
476
458
  );
477
459
  }
478
460
  function assertHeadColor(value) {
@@ -481,7 +463,7 @@ function assertHeadColor(value) {
481
463
  }
482
464
  if (typeof value !== "string" || !HEX_COLOR_RE.test(value)) {
483
465
  throw new TypeError(
484
- `[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)}`
485
467
  );
486
468
  }
487
469
  }
@@ -491,26 +473,26 @@ function assertSkeletonColor(value) {
491
473
  }
492
474
  if (typeof value !== "string" || !HEX_COLOR_RE.test(value)) {
493
475
  throw new TypeError(
494
- `[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)}`
495
477
  );
496
478
  }
497
479
  }
498
480
  function assertTrailStyle(value) {
499
481
  if (!TRAIL_STYLES.includes(value)) {
500
482
  throw new RangeError(
501
- `[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)}`
502
484
  );
503
485
  }
504
486
  }
505
487
  function assertHeadRadius(value) {
506
488
  if (typeof value !== "number") {
507
489
  throw new TypeError(
508
- `[sarmal] setRenderOptions: headRadius must be a number, got ${JSON.stringify(value)}`,
490
+ `[sarmal] setRenderOptions: headRadius must be a number, got ${JSON.stringify(value)}`
509
491
  );
510
492
  }
511
493
  if (!Number.isFinite(value) || value <= 0) {
512
494
  throw new TypeError(
513
- `[sarmal] setRenderOptions: headRadius must be a finite positive number, got ${value}`,
495
+ `[sarmal] setRenderOptions: headRadius must be a finite positive number, got ${value}`
514
496
  );
515
497
  }
516
498
  }
@@ -532,13 +514,13 @@ function resolveHeadColor(trailColor, trailStyle) {
532
514
  function warnIfTrailColorMismatch(trailColor, trailStyle) {
533
515
  if (trailStyle === "default" && Array.isArray(trailColor)) {
534
516
  console.warn(
535
- '[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.'
536
518
  );
537
519
  return;
538
520
  }
539
521
  if (trailStyle !== "default" && typeof trailColor === "string") {
540
522
  console.warn(
541
- `[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.`
542
524
  );
543
525
  }
544
526
  }
@@ -548,7 +530,7 @@ var getHeadDotRadius = (w, h) => Math.max(1, 3 * Math.sqrt(Math.min(w, h) / 160)
548
530
  var WHITE_HEX = "#ffffff";
549
531
  function hexToRgbComponents(hex) {
550
532
  const n = parseInt(hex.slice(1), 16);
551
- return `${n >> 16},${(n >> 8) & 255},${n & 255}`;
533
+ return `${n >> 16},${n >> 8 & 255},${n & 255}`;
552
534
  }
553
535
  function applyDprSizing(target, logicalWidth, logicalHeight, dpr) {
554
536
  target.style.width = `${logicalWidth}px`;
@@ -675,7 +657,7 @@ function createRenderer(options) {
675
657
  i,
676
658
  trailCount,
677
659
  toX,
678
- toY,
660
+ toY
679
661
  );
680
662
  if (trailStyle === "default") {
681
663
  ctx.fillStyle = `rgba(${trailSolidRgb},${opacity})`;
@@ -840,7 +822,7 @@ function createRenderer(options) {
840
822
  if (partial.trailColor !== void 0 || partial.trailStyle !== void 0) {
841
823
  warnIfTrailColorMismatch(trailColor, trailStyle);
842
824
  }
843
- },
825
+ }
844
826
  };
845
827
  const pauseOnHidden = options.pauseOnHidden !== false;
846
828
  function handleVisibilityChange() {
@@ -890,10 +872,8 @@ function sampleCurveSkeleton(curveDef) {
890
872
  const samples = Math.ceil(period * 50);
891
873
  const pts = Array.from({ length: samples });
892
874
  for (let i = 0; i < samples; i++) {
893
- const phase = (i / (samples - 1)) * period;
894
- pts[i] = curveDef.skeletonFn
895
- ? curveDef.skeletonFn(phase)
896
- : curveDef.fn(phase, 0, EMPTY_PARAMS2);
875
+ const phase = i / (samples - 1) * period;
876
+ pts[i] = curveDef.skeletonFn ? curveDef.skeletonFn(phase) : curveDef.fn(phase, 0, EMPTY_PARAMS2);
897
877
  }
898
878
  return pts;
899
879
  }
@@ -905,7 +885,7 @@ function createSVGRenderer(options) {
905
885
  const poolSize = engine.trailLength;
906
886
  if (poolSize > HIGH_TRAIL_LENGTH_THRESHOLD) {
907
887
  console.warn(
908
- `[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.`
909
889
  );
910
890
  }
911
891
  let trailStyle = options.trailStyle ?? "default";
@@ -924,9 +904,9 @@ function createSVGRenderer(options) {
924
904
  return rect.width && rect.height ? Math.min(rect.width, rect.height) : 200;
925
905
  }
926
906
  const containerPx = getContainerPixelSize();
927
- const svgTrailMinWidth = (TRAIL_MIN_WIDTH * viewSize) / containerPx;
928
- const svgTrailMaxWidth = (TRAIL_MAX_WIDTH * viewSize) / containerPx;
929
- 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);
930
910
  headRadius = options.headRadius ?? SVG_DEFAULT_HEAD_RADIUS;
931
911
  container.setAttribute("viewBox", `0 0 ${viewSize} ${viewSize}`);
932
912
  container.setAttribute("role", "img");
@@ -1014,7 +994,7 @@ function createSVGRenderer(options) {
1014
994
  px,
1015
995
  py,
1016
996
  svgTrailMinWidth,
1017
- svgTrailMaxWidth,
997
+ svgTrailMaxWidth
1018
998
  );
1019
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`;
1020
1000
  trailPaths[i].setAttribute("d", d);
@@ -1042,8 +1022,7 @@ function createSVGRenderer(options) {
1042
1022
  let animationId = null;
1043
1023
  let lastTime = 0;
1044
1024
  let pausedByVisibility = false;
1045
- const prefersReducedMotion =
1046
- typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
1025
+ const prefersReducedMotion = typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
1047
1026
  let morphResolve = null;
1048
1027
  let morphReject = null;
1049
1028
  let morphDurationMs = DEFAULT_MORPH_DURATION_MS;
@@ -1061,7 +1040,7 @@ function createSVGRenderer(options) {
1061
1040
  skeletonPathA.setAttribute("visibility", "visible");
1062
1041
  skeletonPathA.setAttribute(
1063
1042
  "stroke-opacity",
1064
- String((1 - morphAlpha) * DEFAULT_SKELETON_OPACITY),
1043
+ String((1 - morphAlpha) * DEFAULT_SKELETON_OPACITY)
1065
1044
  );
1066
1045
  }
1067
1046
  if (morphPathBBuilt) {
@@ -1215,7 +1194,7 @@ function createSVGRenderer(options) {
1215
1194
  if (partial.trailColor !== void 0 || partial.trailStyle !== void 0) {
1216
1195
  warnIfTrailColorMismatch(trailColor, trailStyle);
1217
1196
  }
1218
- },
1197
+ }
1219
1198
  };
1220
1199
  const pauseOnHidden = options.pauseOnHidden !== false;
1221
1200
  function handleVisibilityChange() {
@@ -1253,13 +1232,7 @@ var PERIOD = 2 * Math.PI;
1253
1232
  function catmullRom1D(p0, p1, p2, p3, u) {
1254
1233
  const u2 = u * u;
1255
1234
  const u3 = u2 * u;
1256
- return (
1257
- 0.5 *
1258
- (2 * p1 +
1259
- (-p0 + p2) * u +
1260
- (2 * p0 - 5 * p1 + 4 * p2 - p3) * u2 +
1261
- (-p0 + 3 * p1 - 3 * p2 + p3) * u3)
1262
- );
1235
+ return 0.5 * (2 * p1 + (-p0 + p2) * u + (2 * p0 - 5 * p1 + 4 * p2 - p3) * u2 + (-p0 + 3 * p1 - 3 * p2 + p3) * u3);
1263
1236
  }
1264
1237
  function evaluateCatmullRom(points2, phase) {
1265
1238
  const N = points2.length;
@@ -1269,7 +1242,7 @@ function evaluateCatmullRom(points2, phase) {
1269
1242
  if (N === 1) {
1270
1243
  return { x: points2[0][0], y: points2[0][1] };
1271
1244
  }
1272
- phase = ((phase % PERIOD) + PERIOD) % PERIOD;
1245
+ phase = (phase % PERIOD + PERIOD) % PERIOD;
1273
1246
  const segmentSize = PERIOD / N;
1274
1247
  let i = Math.floor(phase / segmentSize);
1275
1248
  if (i >= N) {
@@ -1283,7 +1256,7 @@ function evaluateCatmullRom(points2, phase) {
1283
1256
  const p3 = points2[(i + 2) % N];
1284
1257
  return {
1285
1258
  x: catmullRom1D(p0[0], p1[0], p2[0], p3[0], u),
1286
- y: catmullRom1D(p0[1], p1[1], p2[1], p3[1], u),
1259
+ y: catmullRom1D(p0[1], p1[1], p2[1], p3[1], u)
1287
1260
  };
1288
1261
  }
1289
1262
  function drawCurve(points2, opts) {
@@ -1293,20 +1266,20 @@ function drawCurve(points2, opts) {
1293
1266
  const first = points2[0];
1294
1267
  if (points2.every((p) => p[0] === first[0] && p[1] === first[1])) {
1295
1268
  console.warn(
1296
- "[sarmal].drawCurve: all control points are identical. The curve will be a single point.",
1269
+ "[sarmal].drawCurve: all control points are identical. The curve will be a single point."
1297
1270
  );
1298
1271
  }
1299
1272
  const maxAbs = points2.reduce((m, p) => Math.max(m, Math.abs(p[0]), Math.abs(p[1])), 0);
1300
1273
  if (maxAbs > 2) {
1301
1274
  console.warn(
1302
- `[sarmal].drawCurve: control points extend to \xB1${maxAbs.toFixed(1)}, which may render off-screen. Coordinates should be in [-1, 1].`,
1275
+ `[sarmal].drawCurve: control points extend to \xB1${maxAbs.toFixed(1)}, which may render off-screen. Coordinates should be in [-1, 1].`
1303
1276
  );
1304
1277
  }
1305
1278
  const pts = points2.map(([x, y]) => [x, y]);
1306
1279
  return {
1307
1280
  name: opts?.name ?? "drawn",
1308
1281
  fn: (phase) => evaluateCatmullRom(pts, phase),
1309
- period: PERIOD,
1282
+ period: PERIOD
1310
1283
  };
1311
1284
  }
1312
1285
 
@@ -1332,11 +1305,11 @@ var points = [
1332
1305
  [-0.69, -0.84],
1333
1306
  [-0.87, -0.66],
1334
1307
  [-0.9, -0.47],
1335
- [-0.76, -0.35],
1308
+ [-0.76, -0.35]
1336
1309
  ];
1337
1310
  var artemis2 = {
1338
1311
  ...drawCurve(points, { name: "Artemis II" }),
1339
- speed: 0.7,
1312
+ speed: 0.7
1340
1313
  };
1341
1314
 
1342
1315
  // src/curves/astroid.ts
@@ -1346,14 +1319,14 @@ function astroidFn(phase, _elapsed, _params) {
1346
1319
  const s = Math.sin(phase);
1347
1320
  return {
1348
1321
  x: c * c * c,
1349
- y: s * s * s,
1322
+ y: s * s * s
1350
1323
  };
1351
1324
  }
1352
1325
  var astroid = {
1353
1326
  name: "Astroid",
1354
1327
  fn: astroidFn,
1355
1328
  period: TWO_PI2,
1356
- speed: 1.1,
1329
+ speed: 1.1
1357
1330
  };
1358
1331
 
1359
1332
  // src/curves/deltoid.ts
@@ -1361,14 +1334,14 @@ var TWO_PI3 = Math.PI * 2;
1361
1334
  function deltoidFn(phase, _elapsed, _params) {
1362
1335
  return {
1363
1336
  x: 2 * Math.cos(phase) + Math.cos(2 * phase),
1364
- y: 2 * Math.sin(phase) - Math.sin(2 * phase),
1337
+ y: 2 * Math.sin(phase) - Math.sin(2 * phase)
1365
1338
  };
1366
1339
  }
1367
1340
  var deltoid = {
1368
1341
  name: "Deltoid",
1369
1342
  fn: deltoidFn,
1370
1343
  period: TWO_PI3,
1371
- speed: 0.9,
1344
+ speed: 0.9
1372
1345
  };
1373
1346
 
1374
1347
  // src/curves/epicycloid3.ts
@@ -1376,14 +1349,14 @@ var TWO_PI4 = Math.PI * 2;
1376
1349
  function epicycloid3Fn(phase, _elapsed, _params) {
1377
1350
  return {
1378
1351
  x: 4 * Math.cos(phase) - Math.cos(4 * phase),
1379
- y: 4 * Math.sin(phase) - Math.sin(4 * phase),
1352
+ y: 4 * Math.sin(phase) - Math.sin(4 * phase)
1380
1353
  };
1381
1354
  }
1382
1355
  var epicycloid3 = {
1383
1356
  name: "Epicycloid (n=3)",
1384
1357
  fn: epicycloid3Fn,
1385
1358
  period: TWO_PI4,
1386
- speed: 0.75,
1359
+ speed: 0.75
1387
1360
  };
1388
1361
 
1389
1362
  // src/curves/epitrochoid7.ts
@@ -1392,14 +1365,14 @@ function epitrochoid7Fn(phase, _elapsed, _params) {
1392
1365
  const d = 1 + 0.55 * Math.sin(phase * 0.5);
1393
1366
  return {
1394
1367
  x: 7 * Math.cos(phase) - d * Math.cos(7 * phase),
1395
- y: 7 * Math.sin(phase) - d * Math.sin(7 * phase),
1368
+ y: 7 * Math.sin(phase) - d * Math.sin(7 * phase)
1396
1369
  };
1397
1370
  }
1398
1371
  function epitrochoid7SkeletonFn(phase) {
1399
1372
  const d = 1.275;
1400
1373
  return {
1401
1374
  x: 7 * Math.cos(phase) - d * Math.cos(7 * phase),
1402
- y: 7 * Math.sin(phase) - d * Math.sin(7 * phase),
1375
+ y: 7 * Math.sin(phase) - d * Math.sin(7 * phase)
1403
1376
  };
1404
1377
  }
1405
1378
  var epitrochoid7 = {
@@ -1407,7 +1380,7 @@ var epitrochoid7 = {
1407
1380
  fn: epitrochoid7Fn,
1408
1381
  period: TWO_PI5,
1409
1382
  speed: 1.4,
1410
- skeletonFn: epitrochoid7SkeletonFn,
1383
+ skeletonFn: epitrochoid7SkeletonFn
1411
1384
  };
1412
1385
 
1413
1386
  // src/curves/lissajous32.ts
@@ -1416,7 +1389,7 @@ function lissajous32Fn(phase, elapsed, _params) {
1416
1389
  const phi = elapsed * 0.45;
1417
1390
  return {
1418
1391
  x: Math.sin(3 * phase + phi),
1419
- y: Math.sin(2 * phase),
1392
+ y: Math.sin(2 * phase)
1420
1393
  };
1421
1394
  }
1422
1395
  var lissajous32 = {
@@ -1424,7 +1397,7 @@ var lissajous32 = {
1424
1397
  fn: lissajous32Fn,
1425
1398
  period: TWO_PI6,
1426
1399
  speed: 2,
1427
- skeleton: "live",
1400
+ skeleton: "live"
1428
1401
  };
1429
1402
 
1430
1403
  // src/curves/lissajous43.ts
@@ -1433,7 +1406,7 @@ function lissajous43Fn(phase, elapsed, _params) {
1433
1406
  const phi = elapsed * 0.38;
1434
1407
  return {
1435
1408
  x: Math.sin(4 * phase + phi),
1436
- y: Math.sin(3 * phase),
1409
+ y: Math.sin(3 * phase)
1437
1410
  };
1438
1411
  }
1439
1412
  var lissajous43 = {
@@ -1441,18 +1414,17 @@ var lissajous43 = {
1441
1414
  fn: lissajous43Fn,
1442
1415
  period: TWO_PI7,
1443
1416
  speed: 1.8,
1444
- skeleton: "live",
1417
+ skeleton: "live"
1445
1418
  };
1446
1419
 
1447
1420
  // src/curves/lame.ts
1448
1421
  var TWO_PI8 = Math.PI * 2;
1449
1422
  function lameFn(phase, elapsed, _params) {
1450
1423
  const p = 1.75 + 1.25 * Math.sin(elapsed * 0.48);
1451
- const c = Math.cos(phase),
1452
- s = Math.sin(phase);
1424
+ const c = Math.cos(phase), s = Math.sin(phase);
1453
1425
  return {
1454
1426
  x: Math.sign(c) * Math.pow(Math.abs(c), p),
1455
- y: Math.sign(s) * Math.pow(Math.abs(s), p),
1427
+ y: Math.sign(s) * Math.pow(Math.abs(s), p)
1456
1428
  };
1457
1429
  }
1458
1430
  var lame = {
@@ -1460,7 +1432,7 @@ var lame = {
1460
1432
  fn: lameFn,
1461
1433
  period: TWO_PI8,
1462
1434
  speed: 1,
1463
- skeleton: "live",
1435
+ skeleton: "live"
1464
1436
  };
1465
1437
 
1466
1438
  // src/curves/rose3.ts
@@ -1469,14 +1441,14 @@ function rose3Fn(phase, _elapsed, _params) {
1469
1441
  const r = Math.cos(3 * phase);
1470
1442
  return {
1471
1443
  x: r * Math.cos(phase),
1472
- y: r * Math.sin(phase),
1444
+ y: r * Math.sin(phase)
1473
1445
  };
1474
1446
  }
1475
1447
  var rose3 = {
1476
1448
  name: "Rose (n=3)",
1477
1449
  fn: rose3Fn,
1478
1450
  period: TWO_PI9,
1479
- speed: 1.15,
1451
+ speed: 1.15
1480
1452
  };
1481
1453
 
1482
1454
  // src/curves/rose5.ts
@@ -1485,87 +1457,78 @@ function rose5Fn(phase, _elapsed, _params) {
1485
1457
  const r = Math.cos(5 * phase);
1486
1458
  return {
1487
1459
  x: r * Math.cos(phase),
1488
- y: r * Math.sin(phase),
1460
+ y: r * Math.sin(phase)
1489
1461
  };
1490
1462
  }
1491
1463
  var rose5 = {
1492
1464
  name: "Rose (n=5)",
1493
1465
  fn: rose5Fn,
1494
1466
  period: TWO_PI10,
1495
- speed: 1,
1467
+ speed: 1
1496
1468
  };
1497
1469
 
1498
1470
  // src/curves/rose52.ts
1499
1471
  var FOUR_PI = Math.PI * 4;
1500
1472
  function rose52Fn(phase, _elapsed, _params) {
1501
- const r = Math.cos((5 / 2) * phase);
1473
+ const r = Math.cos(5 / 2 * phase);
1502
1474
  return {
1503
1475
  x: r * Math.cos(phase),
1504
- y: r * Math.sin(phase),
1476
+ y: r * Math.sin(phase)
1505
1477
  };
1506
1478
  }
1507
1479
  var rose52 = {
1508
1480
  name: "Rose (n=5/2)",
1509
1481
  fn: rose52Fn,
1510
1482
  period: FOUR_PI,
1511
- speed: 0.8,
1483
+ speed: 0.8
1512
1484
  };
1513
1485
 
1514
1486
  // src/curves/star.ts
1515
1487
  var TWO_PI11 = Math.PI * 2;
1516
1488
  function starFn(phase, _elapsed, _params) {
1517
- const r =
1518
- Math.abs(Math.cos((5 / 2) * phase)) +
1519
- 0.35 * Math.abs(Math.cos((15 / 2) * phase)) +
1520
- 0.15 * Math.abs(Math.cos((25 / 2) * phase));
1489
+ const r = Math.abs(Math.cos(5 / 2 * phase)) + 0.35 * Math.abs(Math.cos(15 / 2 * phase)) + 0.15 * Math.abs(Math.cos(25 / 2 * phase));
1521
1490
  return {
1522
1491
  x: r * Math.cos(phase),
1523
- y: r * Math.sin(phase),
1492
+ y: r * Math.sin(phase)
1524
1493
  };
1525
1494
  }
1526
1495
  var star = {
1527
1496
  name: "Star",
1528
1497
  fn: starFn,
1529
1498
  period: TWO_PI11,
1530
- speed: 1,
1499
+ speed: 1
1531
1500
  };
1532
1501
 
1533
1502
  // src/curves/star4.ts
1534
1503
  var TWO_PI12 = Math.PI * 2;
1535
1504
  function star4Fn(phase, _elapsed, _params) {
1536
- const r =
1537
- Math.abs(Math.cos(2 * phase)) +
1538
- 0.35 * Math.abs(Math.cos(6 * phase)) +
1539
- 0.15 * Math.abs(Math.cos(10 * phase));
1505
+ const r = Math.abs(Math.cos(2 * phase)) + 0.35 * Math.abs(Math.cos(6 * phase)) + 0.15 * Math.abs(Math.cos(10 * phase));
1540
1506
  return {
1541
1507
  x: r * Math.cos(phase),
1542
- y: r * Math.sin(phase),
1508
+ y: r * Math.sin(phase)
1543
1509
  };
1544
1510
  }
1545
1511
  var star4 = {
1546
1512
  name: "Star (4-arm)",
1547
1513
  fn: star4Fn,
1548
1514
  period: TWO_PI12,
1549
- speed: 1,
1515
+ speed: 1
1550
1516
  };
1551
1517
 
1552
1518
  // src/curves/star7.ts
1553
1519
  var TWO_PI13 = Math.PI * 2;
1554
1520
  function star7Fn(phase, _elapsed, _params) {
1555
- const r =
1556
- Math.abs(Math.cos((7 / 2) * phase)) +
1557
- 0.35 * Math.abs(Math.cos((21 / 2) * phase)) +
1558
- 0.15 * Math.abs(Math.cos((35 / 2) * phase));
1521
+ const r = Math.abs(Math.cos(7 / 2 * phase)) + 0.35 * Math.abs(Math.cos(21 / 2 * phase)) + 0.15 * Math.abs(Math.cos(35 / 2 * phase));
1559
1522
  return {
1560
1523
  x: r * Math.cos(phase),
1561
- y: r * Math.sin(phase),
1524
+ y: r * Math.sin(phase)
1562
1525
  };
1563
1526
  }
1564
1527
  var star7 = {
1565
1528
  name: "Star (7-arm)",
1566
1529
  fn: star7Fn,
1567
1530
  period: TWO_PI13,
1568
- speed: 1,
1531
+ speed: 1
1569
1532
  };
1570
1533
 
1571
1534
  // src/curves/index.ts
@@ -1583,7 +1546,7 @@ var curves = {
1583
1546
  lissajous32,
1584
1547
  lissajous43,
1585
1548
  epicycloid3,
1586
- lame,
1549
+ lame
1587
1550
  };
1588
1551
 
1589
1552
  // src/index.ts
@@ -1600,21 +1563,22 @@ function parseTrailColor(value) {
1600
1563
  if (Array.isArray(parsed)) {
1601
1564
  return parsed;
1602
1565
  }
1603
- } catch {}
1566
+ } catch {
1567
+ }
1604
1568
  return value;
1605
1569
  }
1606
1570
  function buildOptions(el2) {
1607
1571
  return {
1608
- ...(el2.dataset.trailColor && {
1609
- trailColor: parseTrailColor(el2.dataset.trailColor),
1610
- }),
1611
- ...(el2.dataset.skeletonColor && { skeletonColor: el2.dataset.skeletonColor }),
1612
- ...(el2.dataset.headColor && { headColor: el2.dataset.headColor }),
1613
- ...(el2.dataset.headRadius && { headRadius: parseFloat(el2.dataset.headRadius) }),
1614
- ...(el2.dataset.trailLength && { trailLength: parseInt(el2.dataset.trailLength, 10) }),
1615
- ...(el2.dataset.trailStyle && {
1616
- trailStyle: el2.dataset.trailStyle,
1617
- }),
1572
+ ...el2.dataset.trailColor && {
1573
+ trailColor: parseTrailColor(el2.dataset.trailColor)
1574
+ },
1575
+ ...el2.dataset.skeletonColor && { skeletonColor: el2.dataset.skeletonColor },
1576
+ ...el2.dataset.headColor && { headColor: el2.dataset.headColor },
1577
+ ...el2.dataset.headRadius && { headRadius: parseFloat(el2.dataset.headRadius) },
1578
+ ...el2.dataset.trailLength && { trailLength: parseInt(el2.dataset.trailLength, 10) },
1579
+ ...el2.dataset.trailStyle && {
1580
+ trailStyle: el2.dataset.trailStyle
1581
+ }
1618
1582
  };
1619
1583
  }
1620
1584
  function init() {
@@ -1629,10 +1593,7 @@ function init() {
1629
1593
  return console.error(`[sarmal] "${curveName}" is not a valid curve name`);
1630
1594
  }
1631
1595
  const options = buildOptions(el2);
1632
- const instance =
1633
- el2 instanceof HTMLCanvasElement
1634
- ? createSarmal(el2, curveDef, options)
1635
- : createSarmalSVG(el2, curveDef, options);
1596
+ const instance = el2 instanceof HTMLCanvasElement ? createSarmal(el2, curveDef, options) : createSarmalSVG(el2, curveDef, options);
1636
1597
  if (el2.dataset.speed) {
1637
1598
  instance.setSpeed(parseFloat(el2.dataset.speed));
1638
1599
  }
@@ -1648,4 +1609,4 @@ if (document.readyState === "loading") {
1648
1609
 
1649
1610
  exports.init = init;
1650
1611
  //# sourceMappingURL=auto-init.cjs.map
1651
- //# sourceMappingURL=auto-init.cjs.map
1612
+ //# sourceMappingURL=auto-init.cjs.map