@sarmal/core 0.9.1 → 0.9.10

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 (61) hide show
  1. package/dist/auto-init.cjs +196 -157
  2. package/dist/auto-init.cjs.map +1 -1
  3. package/dist/auto-init.d.cts +2 -1
  4. package/dist/auto-init.d.ts +2 -1
  5. package/dist/auto-init.js +195 -156
  6. package/dist/auto-init.js.map +1 -1
  7. package/dist/curves/artemis2.cjs +7 -10
  8. package/dist/curves/artemis2.d.cts +1 -1
  9. package/dist/curves/artemis2.d.ts +1 -1
  10. package/dist/curves/artemis2.js +6 -9
  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 +28 -32
  28. package/dist/curves/index.d.cts +11 -11
  29. package/dist/curves/index.d.ts +11 -11
  30. package/dist/curves/index.js +28 -44
  31. package/dist/curves/lame.cjs +5 -6
  32. package/dist/curves/lame.d.cts +1 -1
  33. package/dist/curves/lame.d.ts +1 -1
  34. package/dist/curves/lame.js +4 -5
  35. package/dist/curves/lissajous32.cjs +4 -4
  36. package/dist/curves/lissajous32.d.cts +1 -1
  37. package/dist/curves/lissajous32.d.ts +1 -1
  38. package/dist/curves/lissajous32.js +3 -3
  39. package/dist/curves/lissajous43.cjs +4 -4
  40. package/dist/curves/lissajous43.d.cts +1 -1
  41. package/dist/curves/lissajous43.d.ts +1 -1
  42. package/dist/curves/lissajous43.js +3 -3
  43. package/dist/curves/rose3.cjs +4 -4
  44. package/dist/curves/rose3.d.cts +1 -1
  45. package/dist/curves/rose3.d.ts +1 -1
  46. package/dist/curves/rose3.js +3 -3
  47. package/dist/curves/rose5.cjs +4 -4
  48. package/dist/curves/rose5.d.cts +1 -1
  49. package/dist/curves/rose5.d.ts +1 -1
  50. package/dist/curves/rose5.js +3 -3
  51. package/dist/index.cjs +233 -265
  52. package/dist/index.cjs.map +1 -1
  53. package/dist/index.d.cts +31 -64
  54. package/dist/index.d.ts +31 -64
  55. package/dist/index.js +233 -282
  56. package/dist/index.js.map +1 -1
  57. package/dist/types-cR2xOewv.d.cts +223 -0
  58. package/dist/types-cR2xOewv.d.ts +223 -0
  59. package/package.json +5 -3
  60. package/dist/types-DX8VfIVK.d.cts +0 -226
  61. package/dist/types-DX8VfIVK.d.ts +0 -226
@@ -1,8 +1,12 @@
1
- "use strict";
1
+ 'use strict';
2
2
 
3
3
  // src/engine.ts
4
4
  var TWO_PI = Math.PI * 2;
5
5
  var POINTS_PER_PERIOD_UNIT = 50;
6
+ function lerp(start, end, t) {
7
+ return start + (end - start) * t;
8
+ }
9
+ var EMPTY_PARAMS = {};
6
10
  var CircularBuffer = class {
7
11
  constructor(capacity) {
8
12
  this.head = 0;
@@ -45,16 +49,29 @@ var CircularBuffer = class {
45
49
  }
46
50
  };
47
51
  function resolveCurve(curveDef) {
52
+ const period = curveDef.period ?? TWO_PI;
53
+ if (!Number.isFinite(period) || period <= 0) {
54
+ throw new RangeError(`[sarmal] period must be a positive finite number, got ${period}`);
55
+ }
56
+ const speed = curveDef.speed ?? 1;
57
+ if (!Number.isFinite(speed)) {
58
+ throw new RangeError(`[sarmal] speed must be a finite number, got ${speed}`);
59
+ }
48
60
  return {
49
61
  name: curveDef.name,
50
62
  fn: curveDef.fn,
51
- period: curveDef.period ?? TWO_PI,
52
- speed: curveDef.speed ?? 1,
63
+ period,
64
+ speed,
53
65
  skeleton: curveDef.skeleton,
54
- skeletonFn: curveDef.skeletonFn,
66
+ skeletonFn: curveDef.skeletonFn
55
67
  };
56
68
  }
57
69
  function createEngine(curveDef, trailLength = 120) {
70
+ if (!Number.isFinite(trailLength) || trailLength <= 0) {
71
+ throw new RangeError(
72
+ `[sarmal] trailLength must be a positive finite number, got ${trailLength}`
73
+ );
74
+ }
58
75
  let curve = resolveCurve(curveDef);
59
76
  const trail = new CircularBuffer(trailLength);
60
77
  let t = 0;
@@ -67,21 +84,25 @@ function createEngine(curveDef, trailLength = 120) {
67
84
  return c.skeletonFn(sampleT);
68
85
  }
69
86
  if (c.skeleton === "live") {
70
- return c.fn(sampleT, actualTime, {});
87
+ return c.fn(sampleT, actualTime, EMPTY_PARAMS);
71
88
  }
72
- return c.fn(sampleT, 0, {});
89
+ return c.fn(sampleT, 0, EMPTY_PARAMS);
73
90
  }
74
91
  return {
75
92
  tick(deltaTime) {
76
- t = (t + curve.speed * deltaTime) % curve.period;
93
+ let effectiveSpeed = curve.speed;
94
+ if (morphCurveB !== null && _morphAlpha !== null) {
95
+ effectiveSpeed = lerp(curve.speed, morphCurveB.speed, _morphAlpha);
96
+ }
97
+ t = (t + effectiveSpeed * deltaTime) % curve.period;
77
98
  actualTime += deltaTime;
78
99
  if (morphCurveB !== null && _morphAlpha !== null) {
79
- const a = curve.fn(t, actualTime, {});
80
- const tB = _morphStrategy === "normalized" ? (t / curve.period) * morphCurveB.period : t;
81
- const b = morphCurveB.fn(tB, actualTime, {});
100
+ const a = curve.fn(t, actualTime, EMPTY_PARAMS);
101
+ const tB = _morphStrategy === "normalized" ? t / curve.period * morphCurveB.period : t;
102
+ const b = morphCurveB.fn(tB, actualTime, EMPTY_PARAMS);
82
103
  trail.push(a.x + (b.x - a.x) * _morphAlpha, a.y + (b.y - a.y) * _morphAlpha);
83
104
  } else {
84
- const point = curve.fn(t, actualTime, {});
105
+ const point = curve.fn(t, actualTime, EMPTY_PARAMS);
85
106
  trail.push(point.x, point.y);
86
107
  }
87
108
  return trail.toArray();
@@ -101,14 +122,14 @@ function createEngine(curveDef, trailLength = 120) {
101
122
  trail.clear();
102
123
  },
103
124
  seek(newT, { clearTrail = false } = {}) {
104
- t = ((newT % curve.period) + curve.period) % curve.period;
125
+ t = (newT % curve.period + curve.period) % curve.period;
105
126
  if (clearTrail) {
106
127
  trail.clear();
107
128
  }
108
129
  },
109
130
  seekWithTrail(targetT, { wrap = false, step = curve.period / trailLength } = {}) {
110
131
  const advance = curve.speed * step;
111
- const target = ((targetT % curve.period) + curve.period) % curve.period;
132
+ const target = (targetT % curve.period + curve.period) % curve.period;
112
133
  const targetTime = target / curve.speed;
113
134
  t = target;
114
135
  actualTime = targetTime;
@@ -117,9 +138,9 @@ function createEngine(curveDef, trailLength = 120) {
117
138
  const count = wrap ? trailLength : Math.min(trailLength, pointsFromStart);
118
139
  for (let i = count - 1; i >= 0; i--) {
119
140
  const sampleT = target - i * advance;
120
- const wrappedT = sampleT < 0 ? sampleT + curve.period : sampleT;
141
+ const wrappedT = (sampleT % curve.period + curve.period) % curve.period;
121
142
  const time = targetTime - i * step;
122
- const point = curve.fn(wrappedT, time, {});
143
+ const point = curve.fn(wrappedT, time, EMPTY_PARAMS);
123
144
  trail.push(point.x, point.y);
124
145
  }
125
146
  },
@@ -134,16 +155,13 @@ function createEngine(curveDef, trailLength = 120) {
134
155
  ...frozenB,
135
156
  fn: (sampleT, time, params) => {
136
157
  const a = frozenA.fn(sampleT, time, params);
137
- const tB =
138
- frozenStrategy === "normalized"
139
- ? (sampleT / frozenA.period) * frozenB.period
140
- : sampleT;
158
+ const tB = frozenStrategy === "normalized" ? sampleT / frozenA.period * frozenB.period : sampleT;
141
159
  const b = frozenB.fn(tB, time, params);
142
160
  return {
143
161
  x: a.x + (b.x - a.x) * frozenAlpha,
144
- y: a.y + (b.y - a.y) * frozenAlpha,
162
+ y: a.y + (b.y - a.y) * frozenAlpha
145
163
  };
146
- },
164
+ }
147
165
  };
148
166
  }
149
167
  _morphStrategy = strategy;
@@ -156,7 +174,7 @@ function createEngine(curveDef, trailLength = 120) {
156
174
  completeMorph() {
157
175
  if (morphCurveB !== null) {
158
176
  if (_morphStrategy === "normalized" && curve.period !== morphCurveB.period) {
159
- t = (t / curve.period) * morphCurveB.period;
177
+ t = t / curve.period * morphCurveB.period;
160
178
  }
161
179
  curve = morphCurveB;
162
180
  }
@@ -168,46 +186,132 @@ function createEngine(curveDef, trailLength = 120) {
168
186
  const points = new Array(steps);
169
187
  if (morphCurveB !== null && _morphAlpha !== null) {
170
188
  for (let i = 0; i < steps; i++) {
171
- const sampleT = (i / (steps - 1)) * curve.period;
189
+ const sampleT = i / (steps - 1) * curve.period;
172
190
  const a = sampleSkeleton(curve, sampleT);
173
- const tB =
174
- _morphStrategy === "normalized"
175
- ? (sampleT / curve.period) * morphCurveB.period
176
- : sampleT;
191
+ const tB = _morphStrategy === "normalized" ? sampleT / curve.period * morphCurveB.period : sampleT;
177
192
  const b = sampleSkeleton(morphCurveB, tB);
178
193
  points[i] = {
179
194
  x: a.x + (b.x - a.x) * _morphAlpha,
180
- y: a.y + (b.y - a.y) * _morphAlpha,
195
+ y: a.y + (b.y - a.y) * _morphAlpha
181
196
  };
182
197
  }
183
198
  return points;
184
199
  }
185
200
  for (let i = 0; i < steps; i++) {
186
- const sampleT = (i / (steps - 1)) * curve.period;
201
+ const sampleT = i / (steps - 1) * curve.period;
187
202
  points[i] = sampleSkeleton(curve, sampleT);
188
203
  }
189
204
  return points;
190
- },
205
+ }
191
206
  };
192
207
  }
193
208
 
194
- // src/renderer.ts
209
+ // src/renderer-shared.ts
195
210
  var DEFAULT_MORPH_DURATION_MS = 300;
196
- var DEFAULT_HEAD_RADIUS = 4;
197
- var DEFAULT_SKELETON_COLOR = "#ffffff";
198
211
  var DEFAULT_SKELETON_OPACITY = 0.15;
199
212
  var FIT_PADDING = 0.1;
200
213
  var TRAIL_FADE_CURVE = 1.5;
201
214
  var TRAIL_MAX_OPACITY = 0.88;
202
215
  var TRAIL_MIN_WIDTH = 0.5;
203
216
  var TRAIL_MAX_WIDTH = 2.5;
217
+ function computeTangent(trail, i) {
218
+ const count = trail.length;
219
+ if (count < 2) {
220
+ return { x: 1, y: 0 };
221
+ }
222
+ if (i === 0) {
223
+ const dx2 = trail[1].x - trail[0].x;
224
+ const dy2 = trail[1].y - trail[0].y;
225
+ const len2 = Math.sqrt(dx2 * dx2 + dy2 * dy2) || 1;
226
+ return { x: dx2 / len2, y: dy2 / len2 };
227
+ }
228
+ if (i === count - 1) {
229
+ const dx2 = trail[count - 1].x - trail[count - 2].x;
230
+ const dy2 = trail[count - 1].y - trail[count - 2].y;
231
+ const len2 = Math.sqrt(dx2 * dx2 + dy2 * dy2) || 1;
232
+ return { x: dx2 / len2, y: dy2 / len2 };
233
+ }
234
+ const dx = trail[i + 1].x - trail[i - 1].x;
235
+ const dy = trail[i + 1].y - trail[i - 1].y;
236
+ const len = Math.sqrt(dx * dx + dy * dy) || 1;
237
+ return { x: dx / len, y: dy / len };
238
+ }
239
+ function computeNormal(trail, i) {
240
+ const tangent = computeTangent(trail, i);
241
+ return { x: -tangent.y, y: tangent.x };
242
+ }
243
+ function computeTrailQuad(trail, i, trailCount, toX, toY) {
244
+ const progress = i / (trailCount - 1);
245
+ const nextProgress = (i + 1) / (trailCount - 1);
246
+ const opacity = Math.pow(progress, TRAIL_FADE_CURVE) * TRAIL_MAX_OPACITY;
247
+ const w0 = (TRAIL_MIN_WIDTH + progress * (TRAIL_MAX_WIDTH - TRAIL_MIN_WIDTH)) / 2;
248
+ const w1 = (TRAIL_MIN_WIDTH + nextProgress * (TRAIL_MAX_WIDTH - TRAIL_MIN_WIDTH)) / 2;
249
+ const curr = trail[i];
250
+ const next = trail[i + 1];
251
+ const n0 = computeNormal(trail, i);
252
+ const n1 = computeNormal(trail, i + 1);
253
+ const cx = toX(curr);
254
+ const cy = toY(curr);
255
+ const nx = toX(next);
256
+ const ny = toY(next);
257
+ return {
258
+ l0x: cx + n0.x * w0,
259
+ l0y: cy + n0.y * w0,
260
+ r0x: cx - n0.x * w0,
261
+ r0y: cy - n0.y * w0,
262
+ l1x: nx + n1.x * w1,
263
+ l1y: ny + n1.y * w1,
264
+ r1x: nx - n1.x * w1,
265
+ r1y: ny - n1.y * w1,
266
+ opacity,
267
+ progress
268
+ };
269
+ }
270
+ function computeBoundaries(pts, logicalWidth, logicalHeight) {
271
+ if (pts.length === 0) return null;
272
+ const first = pts[0];
273
+ let minX = first.x, maxX = first.x, minY = first.y, maxY = first.y;
274
+ for (const p of pts) {
275
+ if (p.x < minX) {
276
+ minX = p.x;
277
+ }
278
+ if (p.x > maxX) {
279
+ maxX = p.x;
280
+ }
281
+ if (p.y < minY) {
282
+ minY = p.y;
283
+ }
284
+ if (p.y > maxY) {
285
+ maxY = p.y;
286
+ }
287
+ }
288
+ const w = maxX - minX;
289
+ const h = maxY - minY;
290
+ if (w === 0 && h === 0) {
291
+ throw new Error(
292
+ "[sarmal] Degenerate curve: all skeleton points are identical. Check that your curve fn returns distinct points for different values of t."
293
+ );
294
+ }
295
+ const scaleX = logicalWidth / (w * (1 + FIT_PADDING * 2));
296
+ const scaleY = logicalHeight / (h * (1 + FIT_PADDING * 2));
297
+ const scale = Math.min(scaleX, scaleY);
298
+ return {
299
+ scale,
300
+ offsetX: (logicalWidth - w * scale) / 2 - minX * scale,
301
+ offsetY: (logicalHeight - h * scale) / 2 - minY * scale
302
+ };
303
+ }
304
+
305
+ // src/renderer.ts
306
+ var DEFAULT_HEAD_RADIUS = 4;
307
+ var DEFAULT_SKELETON_COLOR = "#ffffff";
204
308
  var GRADIENT = {
205
309
  bard: ["#a855f7", "#3b82f6", "#14b8a6", "#ec4899"],
206
310
  sunset: ["#f97316", "#dc2626", "#9333ea", "#f472b6"],
207
311
  ocean: ["#1e3a8a", "#06b6d4", "#22d3ee", "#e0f2fe"],
208
312
  ice: ["#1e3a8a", "#67e8f9"],
209
313
  fire: ["#7f1d1d", "#fbbf24"],
210
- forest: ["#14532d", "#86efac"],
314
+ forest: ["#14532d", "#86efac"]
211
315
  };
212
316
  var PRESETS = {
213
317
  bard: GRADIENT.bard,
@@ -215,16 +319,16 @@ var PRESETS = {
215
319
  ocean: GRADIENT.ocean,
216
320
  ice: GRADIENT.ice,
217
321
  fire: GRADIENT.fire,
218
- forest: GRADIENT.forest,
322
+ forest: GRADIENT.forest
219
323
  };
220
324
  function hexToRgb(hex) {
221
325
  const n = parseInt(hex.slice(1), 16);
222
- return { r: n >> 16, g: (n >> 8) & 255, b: n & 255 };
326
+ return { r: n >> 16, g: n >> 8 & 255, b: n & 255 };
223
327
  }
224
328
  var lerpRgb = (a, b, t) => ({
225
329
  r: Math.round(a.r + (b.r - a.r) * t),
226
330
  g: Math.round(a.g + (b.g - a.g) * t),
227
- b: Math.round(a.b + (b.b - a.b) * t),
331
+ b: Math.round(a.b + (b.b - a.b) * t)
228
332
  });
229
333
  function getPaletteColor(palette, position, timeOffset = 0) {
230
334
  if (palette.length === 0) return { r: 255, g: 255, b: 255 };
@@ -244,33 +348,7 @@ function resolvePalette(palette, trailStyle) {
244
348
  }
245
349
  function hexToRgbComponents(hex) {
246
350
  const n = parseInt(hex.slice(1), 16);
247
- return `${n >> 16},${(n >> 8) & 255},${n & 255}`;
248
- }
249
- function computeTangent(trail, i) {
250
- const count = trail.length;
251
- if (count < 2) {
252
- return { x: 1, y: 0 };
253
- }
254
- if (i === 0) {
255
- const dx2 = trail[1].x - trail[0].x;
256
- const dy2 = trail[1].y - trail[0].y;
257
- const len2 = Math.sqrt(dx2 * dx2 + dy2 * dy2) || 1;
258
- return { x: dx2 / len2, y: dy2 / len2 };
259
- }
260
- if (i === count - 1) {
261
- const dx2 = trail[count - 1].x - trail[count - 2].x;
262
- const dy2 = trail[count - 1].y - trail[count - 2].y;
263
- const len2 = Math.sqrt(dx2 * dx2 + dy2 * dy2) || 1;
264
- return { x: dx2 / len2, y: dy2 / len2 };
265
- }
266
- const dx = trail[i + 1].x - trail[i - 1].x;
267
- const dy = trail[i + 1].y - trail[i - 1].y;
268
- const len = Math.sqrt(dx * dx + dy * dy) || 1;
269
- return { x: dx / len, y: dy / len };
270
- }
271
- function computeNormal(trail, i) {
272
- const tangent = computeTangent(trail, i);
273
- return { x: -tangent.y, y: tangent.x };
351
+ return `${n >> 16},${n >> 8 & 255},${n & 255}`;
274
352
  }
275
353
  function applyDprSizing(target, logicalWidth, logicalHeight, dpr) {
276
354
  target.style.width = `${logicalWidth}px`;
@@ -289,7 +367,7 @@ function createRenderer(options) {
289
367
  skeletonColor: options.skeletonColor ?? DEFAULT_SKELETON_COLOR,
290
368
  trailColor: options.trailColor ?? "#ffffff",
291
369
  headColor: options.headColor ?? "#ffffff",
292
- headRadius: options.headRadius ?? DEFAULT_HEAD_RADIUS,
370
+ headRadius: options.headRadius ?? DEFAULT_HEAD_RADIUS
293
371
  };
294
372
  const trailStyle = options.trailStyle ?? "default";
295
373
  const palette = resolvePalette(options.palette, trailStyle);
@@ -319,34 +397,8 @@ function createRenderer(options) {
319
397
  let morphDurationMs = DEFAULT_MORPH_DURATION_MS;
320
398
  let morphAlpha = 0;
321
399
  let gradientAnimTime = 0;
322
- function computeBoundaries(pts) {
323
- if (pts.length === 0) return null;
324
- const first = pts[0];
325
- let minX = first.x,
326
- maxX = first.x,
327
- minY = first.y,
328
- maxY = first.y;
329
- for (const p of pts) {
330
- if (p.x < minX) minX = p.x;
331
- if (p.x > maxX) maxX = p.x;
332
- if (p.y < minY) minY = p.y;
333
- if (p.y > maxY) maxY = p.y;
334
- }
335
- const width = maxX - minX;
336
- const height = maxY - minY;
337
- const scaleX = logicalWidth / (width * (1 + FIT_PADDING * 2));
338
- const scaleY = logicalHeight / (height * (1 + FIT_PADDING * 2));
339
- const s = Math.min(scaleX, scaleY);
340
- const boundsWidth = width * s;
341
- const boundsHeight = height * s;
342
- return {
343
- scale: s,
344
- offsetX: (logicalWidth - boundsWidth) / 2 - minX * s,
345
- offsetY: (logicalHeight - boundsHeight) / 2 - minY * s,
346
- };
347
- }
348
400
  function calculateBoundaries() {
349
- const b = computeBoundaries(skeleton);
401
+ const b = computeBoundaries(skeleton, logicalWidth, logicalHeight);
350
402
  if (b) {
351
403
  scale = b.scale;
352
404
  offsetX = b.offsetX;
@@ -410,32 +462,22 @@ function createRenderer(options) {
410
462
  if (trailCount < 2) {
411
463
  return;
412
464
  }
465
+ const toX = (p) => p.x * scale + offsetX;
466
+ const toY = (p) => p.y * scale + offsetY;
413
467
  for (let i = 0; i < trailCount - 1; i++) {
414
- const progress = i / (trailCount - 1);
415
- const nextProgress = (i + 1) / (trailCount - 1);
416
- const alpha = Math.pow(progress, TRAIL_FADE_CURVE) * TRAIL_MAX_OPACITY;
417
- const width = TRAIL_MIN_WIDTH + progress * (TRAIL_MAX_WIDTH - TRAIL_MIN_WIDTH);
418
- const nextWidth = TRAIL_MIN_WIDTH + nextProgress * (TRAIL_MAX_WIDTH - TRAIL_MIN_WIDTH);
419
- const curr = trail[i];
420
- const next = trail[i + 1];
421
- const n0 = computeNormal(trail, i);
422
- const n1 = computeNormal(trail, i + 1);
423
- const halfW0 = width / 2;
424
- const halfW1 = nextWidth / 2;
425
- const l0x = curr.x * scale + offsetX + n0.x * halfW0;
426
- const l0y = curr.y * scale + offsetY + n0.y * halfW0;
427
- const r0x = curr.x * scale + offsetX - n0.x * halfW0;
428
- const r0y = curr.y * scale + offsetY - n0.y * halfW0;
429
- const l1x = next.x * scale + offsetX + n1.x * halfW1;
430
- const l1y = next.y * scale + offsetY + n1.y * halfW1;
431
- const r1x = next.x * scale + offsetX - n1.x * halfW1;
432
- const r1y = next.y * scale + offsetY - n1.y * halfW1;
468
+ const { l0x, l0y, r0x, r0y, l1x, l1y, r1x, r1y, opacity, progress } = computeTrailQuad(
469
+ trail,
470
+ i,
471
+ trailCount,
472
+ toX,
473
+ toY
474
+ );
433
475
  if (trailStyle === "default") {
434
- ctx.fillStyle = `rgba(${trailRgb},${alpha})`;
476
+ ctx.fillStyle = `rgba(${trailRgb},${opacity})`;
435
477
  } else {
436
478
  const timeOffset = trailStyle === "gradient-animated" ? gradientAnimTime * 5e-4 : 0;
437
479
  const color = getPaletteColor(palette, progress, timeOffset);
438
- ctx.fillStyle = `rgba(${color.r},${color.g},${color.b},${alpha})`;
480
+ ctx.fillStyle = `rgba(${color.r},${color.g},${color.b},${opacity})`;
439
481
  }
440
482
  ctx.beginPath();
441
483
  ctx.moveTo(l0x, l0y);
@@ -468,7 +510,7 @@ function createRenderer(options) {
468
510
  morphAlpha = Math.min(1, morphAlpha + deltaTime / (morphDurationMs / 1e3));
469
511
  engine.setMorphAlpha(morphAlpha);
470
512
  const interpolatedSkeleton = engine.getSarmalSkeleton();
471
- const bounds = computeBoundaries(interpolatedSkeleton);
513
+ const bounds = computeBoundaries(interpolatedSkeleton, logicalWidth, logicalHeight);
472
514
  if (bounds) {
473
515
  scale = bounds.scale;
474
516
  offsetX = bounds.offsetX;
@@ -548,29 +590,26 @@ function createRenderer(options) {
548
590
  return new Promise((resolve) => {
549
591
  morphResolve = resolve;
550
592
  });
551
- },
593
+ }
552
594
  };
553
595
  }
554
596
 
555
597
  // src/curves/artemis2.ts
556
598
  var TWO_PI2 = Math.PI * 2;
557
599
  function artemis2Fn(t, _time, _params) {
558
- const a = 0.35,
559
- b = 0.15,
560
- ox = 0.175;
561
- const s = Math.sin(t),
562
- c = Math.cos(t);
600
+ const a = 0.35, b = 0.15, ox = 0.175;
601
+ const s = Math.sin(t), c = Math.cos(t);
563
602
  const denom = 1 + s * s;
564
603
  return {
565
- x: (c * (1 + a * c)) / denom - ox,
566
- y: (s * c * (1 + b * c)) / denom,
604
+ x: c * (1 + a * c) / denom - ox,
605
+ y: s * c * (1 + b * c) / denom
567
606
  };
568
607
  }
569
608
  var artemis2 = {
570
609
  name: "Artemis II",
571
610
  fn: artemis2Fn,
572
611
  period: TWO_PI2,
573
- speed: 0.7,
612
+ speed: 0.7
574
613
  };
575
614
 
576
615
  // src/curves/astroid.ts
@@ -580,14 +619,14 @@ function astroidFn(t, _time, _params) {
580
619
  const s = Math.sin(t);
581
620
  return {
582
621
  x: c * c * c,
583
- y: s * s * s,
622
+ y: s * s * s
584
623
  };
585
624
  }
586
625
  var astroid = {
587
626
  name: "Astroid",
588
627
  fn: astroidFn,
589
628
  period: TWO_PI3,
590
- speed: 1.1,
629
+ speed: 1.1
591
630
  };
592
631
 
593
632
  // src/curves/deltoid.ts
@@ -595,14 +634,14 @@ var TWO_PI4 = Math.PI * 2;
595
634
  function deltoidFn(t, _time, _params) {
596
635
  return {
597
636
  x: 2 * Math.cos(t) + Math.cos(2 * t),
598
- y: 2 * Math.sin(t) - Math.sin(2 * t),
637
+ y: 2 * Math.sin(t) - Math.sin(2 * t)
599
638
  };
600
639
  }
601
640
  var deltoid = {
602
641
  name: "Deltoid",
603
642
  fn: deltoidFn,
604
643
  period: TWO_PI4,
605
- speed: 0.9,
644
+ speed: 0.9
606
645
  };
607
646
 
608
647
  // src/curves/epicycloid3.ts
@@ -610,14 +649,14 @@ var TWO_PI5 = Math.PI * 2;
610
649
  function epicycloid3Fn(t, _time, _params) {
611
650
  return {
612
651
  x: 4 * Math.cos(t) - Math.cos(4 * t),
613
- y: 4 * Math.sin(t) - Math.sin(4 * t),
652
+ y: 4 * Math.sin(t) - Math.sin(4 * t)
614
653
  };
615
654
  }
616
655
  var epicycloid3 = {
617
656
  name: "Epicycloid (n=3)",
618
657
  fn: epicycloid3Fn,
619
658
  period: TWO_PI5,
620
- speed: 0.75,
659
+ speed: 0.75
621
660
  };
622
661
 
623
662
  // src/curves/epitrochoid7.ts
@@ -626,14 +665,14 @@ function epitrochoid7Fn(t, _time, _params) {
626
665
  const d = 1 + 0.55 * Math.sin(t * 0.5);
627
666
  return {
628
667
  x: 7 * Math.cos(t) - d * Math.cos(7 * t),
629
- y: 7 * Math.sin(t) - d * Math.sin(7 * t),
668
+ y: 7 * Math.sin(t) - d * Math.sin(7 * t)
630
669
  };
631
670
  }
632
671
  function epitrochoid7SkeletonFn(t) {
633
672
  const d = 1.275;
634
673
  return {
635
674
  x: 7 * Math.cos(t) - d * Math.cos(7 * t),
636
- y: 7 * Math.sin(t) - d * Math.sin(7 * t),
675
+ y: 7 * Math.sin(t) - d * Math.sin(7 * t)
637
676
  };
638
677
  }
639
678
  var epitrochoid7 = {
@@ -641,7 +680,7 @@ var epitrochoid7 = {
641
680
  fn: epitrochoid7Fn,
642
681
  period: TWO_PI6,
643
682
  speed: 1.4,
644
- skeletonFn: epitrochoid7SkeletonFn,
683
+ skeletonFn: epitrochoid7SkeletonFn
645
684
  };
646
685
 
647
686
  // src/curves/lissajous32.ts
@@ -650,7 +689,7 @@ function lissajous32Fn(t, time, _params) {
650
689
  const phi = time * 0.45;
651
690
  return {
652
691
  x: Math.sin(3 * t + phi),
653
- y: Math.sin(2 * t),
692
+ y: Math.sin(2 * t)
654
693
  };
655
694
  }
656
695
  var lissajous32 = {
@@ -658,7 +697,7 @@ var lissajous32 = {
658
697
  fn: lissajous32Fn,
659
698
  period: TWO_PI7,
660
699
  speed: 2,
661
- skeleton: "live",
700
+ skeleton: "live"
662
701
  };
663
702
 
664
703
  // src/curves/lissajous43.ts
@@ -667,7 +706,7 @@ function lissajous43Fn(t, time, _params) {
667
706
  const phi = time * 0.38;
668
707
  return {
669
708
  x: Math.sin(4 * t + phi),
670
- y: Math.sin(3 * t),
709
+ y: Math.sin(3 * t)
671
710
  };
672
711
  }
673
712
  var lissajous43 = {
@@ -675,18 +714,17 @@ var lissajous43 = {
675
714
  fn: lissajous43Fn,
676
715
  period: TWO_PI8,
677
716
  speed: 1.8,
678
- skeleton: "live",
717
+ skeleton: "live"
679
718
  };
680
719
 
681
720
  // src/curves/lame.ts
682
721
  var TWO_PI9 = Math.PI * 2;
683
722
  function lameFn(t, time, _params) {
684
723
  const p = 1.75 + 1.25 * Math.sin(time * 0.48);
685
- const c = Math.cos(t),
686
- s = Math.sin(t);
724
+ const c = Math.cos(t), s = Math.sin(t);
687
725
  return {
688
726
  x: Math.sign(c) * Math.pow(Math.abs(c), p),
689
- y: Math.sign(s) * Math.pow(Math.abs(s), p),
727
+ y: Math.sign(s) * Math.pow(Math.abs(s), p)
690
728
  };
691
729
  }
692
730
  var lame = {
@@ -694,7 +732,7 @@ var lame = {
694
732
  fn: lameFn,
695
733
  period: TWO_PI9,
696
734
  speed: 1,
697
- skeleton: "live",
735
+ skeleton: "live"
698
736
  };
699
737
 
700
738
  // src/curves/rose3.ts
@@ -703,14 +741,14 @@ function rose3Fn(t, _time, _params) {
703
741
  const r = Math.cos(3 * t);
704
742
  return {
705
743
  x: r * Math.cos(t),
706
- y: r * Math.sin(t),
744
+ y: r * Math.sin(t)
707
745
  };
708
746
  }
709
747
  var rose3 = {
710
748
  name: "Rose (n=3)",
711
749
  fn: rose3Fn,
712
750
  period: TWO_PI10,
713
- speed: 1.15,
751
+ speed: 1.15
714
752
  };
715
753
 
716
754
  // src/curves/rose5.ts
@@ -719,14 +757,14 @@ function rose5Fn(t, _time, _params) {
719
757
  const r = Math.cos(5 * t);
720
758
  return {
721
759
  x: r * Math.cos(t),
722
- y: r * Math.sin(t),
760
+ y: r * Math.sin(t)
723
761
  };
724
762
  }
725
763
  var rose5 = {
726
764
  name: "Rose (n=5)",
727
765
  fn: rose5Fn,
728
766
  period: TWO_PI11,
729
- speed: 1,
767
+ speed: 1
730
768
  };
731
769
 
732
770
  // src/curves/index.ts
@@ -740,7 +778,7 @@ var curves = {
740
778
  lissajous32,
741
779
  lissajous43,
742
780
  epicycloid3,
743
- lame,
781
+ lame
744
782
  };
745
783
 
746
784
  // src/index.ts
@@ -757,7 +795,8 @@ function parsePalette(value) {
757
795
  if (Array.isArray(parsed)) {
758
796
  return parsed;
759
797
  }
760
- } catch {}
798
+ } catch {
799
+ }
761
800
  return value;
762
801
  }
763
802
  function init() {
@@ -765,22 +804,22 @@ function init() {
765
804
  canvases.forEach((canvas) => {
766
805
  const curveName = canvas.getAttribute("data-sarmal");
767
806
  if (curveName == null) {
768
- return console.warn("[sarmal] curveName isrequried");
807
+ return console.warn("[sarmal] curveName is required");
769
808
  }
770
809
  const curveDef = curves[curveName];
771
810
  if (!curveDef) {
772
811
  return console.error(`[sarmal] "${curveName}" is not a valid curve name`);
773
812
  }
774
813
  const sarmal = createSarmal(canvas, curveDef, {
775
- ...(canvas.dataset.trailColor && { trailColor: canvas.dataset.trailColor }),
776
- ...(canvas.dataset.skeletonColor && { skeletonColor: canvas.dataset.skeletonColor }),
777
- ...(canvas.dataset.headColor && { headColor: canvas.dataset.headColor }),
778
- ...(canvas.dataset.headRadius && { headRadius: parseFloat(canvas.dataset.headRadius) }),
779
- ...(canvas.dataset.trailLength && { trailLength: parseInt(canvas.dataset.trailLength, 10) }),
780
- ...(canvas.dataset.trailStyle && {
781
- trailStyle: canvas.dataset.trailStyle,
782
- }),
783
- ...(canvas.dataset.palette && { palette: parsePalette(canvas.dataset.palette) }),
814
+ ...canvas.dataset.trailColor && { trailColor: canvas.dataset.trailColor },
815
+ ...canvas.dataset.skeletonColor && { skeletonColor: canvas.dataset.skeletonColor },
816
+ ...canvas.dataset.headColor && { headColor: canvas.dataset.headColor },
817
+ ...canvas.dataset.headRadius && { headRadius: parseFloat(canvas.dataset.headRadius) },
818
+ ...canvas.dataset.trailLength && { trailLength: parseInt(canvas.dataset.trailLength, 10) },
819
+ ...canvas.dataset.trailStyle && {
820
+ trailStyle: canvas.dataset.trailStyle
821
+ },
822
+ ...canvas.dataset.palette && { palette: parsePalette(canvas.dataset.palette) }
784
823
  });
785
824
  sarmal.start();
786
825
  });
@@ -793,4 +832,4 @@ if (document.readyState === "loading") {
793
832
  requestAnimationFrame(init);
794
833
  }
795
834
  //# sourceMappingURL=auto-init.cjs.map
796
- //# sourceMappingURL=auto-init.cjs.map
835
+ //# sourceMappingURL=auto-init.cjs.map