@sarmal/core 0.14.0 → 0.15.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.
- package/dist/auto-init.cjs +173 -57
- package/dist/auto-init.cjs.map +1 -1
- package/dist/auto-init.d.cts +2 -1
- package/dist/auto-init.d.ts +2 -1
- package/dist/auto-init.js +173 -57
- package/dist/auto-init.js.map +1 -1
- package/dist/curves/artemis2.d.cts +1 -1
- package/dist/curves/artemis2.d.ts +1 -1
- package/dist/curves/astroid.d.cts +1 -1
- package/dist/curves/astroid.d.ts +1 -1
- package/dist/curves/deltoid.d.cts +1 -1
- package/dist/curves/deltoid.d.ts +1 -1
- package/dist/curves/epicycloid3.d.cts +1 -1
- package/dist/curves/epicycloid3.d.ts +1 -1
- package/dist/curves/epitrochoid7.d.cts +1 -1
- package/dist/curves/epitrochoid7.d.ts +1 -1
- package/dist/curves/index.d.cts +1 -1
- package/dist/curves/index.d.ts +1 -1
- package/dist/curves/lame.d.cts +1 -1
- package/dist/curves/lame.d.ts +1 -1
- package/dist/curves/lissajous32.d.cts +1 -1
- package/dist/curves/lissajous32.d.ts +1 -1
- package/dist/curves/lissajous43.d.cts +1 -1
- package/dist/curves/lissajous43.d.ts +1 -1
- package/dist/curves/rose3.d.cts +1 -1
- package/dist/curves/rose3.d.ts +1 -1
- package/dist/curves/rose5.d.cts +1 -1
- package/dist/curves/rose5.d.ts +1 -1
- package/dist/index.cjs +233 -69
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -3
- package/dist/index.d.ts +16 -3
- package/dist/index.js +233 -70
- package/dist/index.js.map +1 -1
- package/dist/{types-BQosOzlf.d.cts → types-BL9HhEmk.d.cts} +33 -10
- package/dist/{types-BQosOzlf.d.ts → types-BL9HhEmk.d.ts} +33 -10
- package/package.json +1 -1
package/dist/auto-init.js
CHANGED
|
@@ -367,22 +367,6 @@ function enginePassthroughs(engine) {
|
|
|
367
367
|
setSpeedOver: engine.setSpeedOver
|
|
368
368
|
};
|
|
369
369
|
}
|
|
370
|
-
var GRADIENT = {
|
|
371
|
-
bard: ["#a855f7", "#3b82f6", "#14b8a6", "#ec4899"],
|
|
372
|
-
sunset: ["#f97316", "#dc2626", "#9333ea", "#f472b6"],
|
|
373
|
-
ocean: ["#1e3a8a", "#06b6d4", "#22d3ee", "#e0f2fe"],
|
|
374
|
-
ice: ["#1e3a8a", "#67e8f9"],
|
|
375
|
-
fire: ["#7f1d1d", "#fbbf24"],
|
|
376
|
-
forest: ["#14532d", "#86efac"]
|
|
377
|
-
};
|
|
378
|
-
var PRESETS = {
|
|
379
|
-
bard: GRADIENT.bard,
|
|
380
|
-
sunset: GRADIENT.sunset,
|
|
381
|
-
ocean: GRADIENT.ocean,
|
|
382
|
-
ice: GRADIENT.ice,
|
|
383
|
-
fire: GRADIENT.fire,
|
|
384
|
-
forest: GRADIENT.forest
|
|
385
|
-
};
|
|
386
370
|
function hexToRgb(hex) {
|
|
387
371
|
const n = parseInt(hex.slice(1), 16);
|
|
388
372
|
return { r: n >> 16, g: n >> 8 & 255, b: n & 255 };
|
|
@@ -407,18 +391,121 @@ function getPaletteColor(palette, position, timeOffset = 0) {
|
|
|
407
391
|
const c2 = hexToRgb(palette[(idx + 1) % palette.length]);
|
|
408
392
|
return lerpRgb(c1, c2, t);
|
|
409
393
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
394
|
+
var HEX_COLOR_RE = /^#[0-9a-fA-F]{6}$/;
|
|
395
|
+
var TRAIL_STYLES = ["default", "gradient-static", "gradient-animated"];
|
|
396
|
+
var RENDER_OPTION_KEYS = /* @__PURE__ */ new Set([
|
|
397
|
+
"trailColor",
|
|
398
|
+
"headColor",
|
|
399
|
+
"skeletonColor",
|
|
400
|
+
"trailStyle"
|
|
401
|
+
]);
|
|
402
|
+
function validateRenderOptions(partial) {
|
|
403
|
+
for (const key of Object.keys(partial)) {
|
|
404
|
+
if (!RENDER_OPTION_KEYS.has(key)) {
|
|
405
|
+
throw new TypeError(`[sarmal] setRenderOptions: unknown key "${key}"`);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
if (partial.trailColor !== void 0) {
|
|
409
|
+
assertTrailColor(partial.trailColor);
|
|
413
410
|
}
|
|
414
|
-
if (
|
|
415
|
-
|
|
411
|
+
if (partial.headColor !== void 0) {
|
|
412
|
+
assertHeadColor(partial.headColor);
|
|
413
|
+
}
|
|
414
|
+
if (partial.skeletonColor !== void 0) {
|
|
415
|
+
assertSkeletonColor(partial.skeletonColor);
|
|
416
|
+
}
|
|
417
|
+
if (partial.trailStyle !== void 0) {
|
|
418
|
+
assertTrailStyle(partial.trailStyle);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
function assertTrailColor(value) {
|
|
422
|
+
if (typeof value === "string") {
|
|
423
|
+
if (!HEX_COLOR_RE.test(value)) {
|
|
424
|
+
throw new TypeError(
|
|
425
|
+
`[sarmal] setRenderOptions: trailColor must be a 6-digit hex string, got "${value}"`
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
if (Array.isArray(value)) {
|
|
431
|
+
if (value.length < 2) {
|
|
432
|
+
throw new RangeError(
|
|
433
|
+
`[sarmal] setRenderOptions: trailColor array must have at least 2 entries, got ${value.length}`
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
for (let i = 0; i < value.length; i++) {
|
|
437
|
+
const entry = value[i];
|
|
438
|
+
if (typeof entry !== "string" || !HEX_COLOR_RE.test(entry)) {
|
|
439
|
+
throw new TypeError(
|
|
440
|
+
`[sarmal] setRenderOptions: trailColor[${i}] must be a 6-digit hex string, got ${JSON.stringify(entry)}`
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
return;
|
|
416
445
|
}
|
|
417
|
-
|
|
446
|
+
throw new TypeError(
|
|
447
|
+
`[sarmal] setRenderOptions: trailColor must be a 6-digit hex string or an array of hex strings, got ${JSON.stringify(value)}`
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
function assertHeadColor(value) {
|
|
451
|
+
if (value === null) {
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
if (typeof value !== "string" || !HEX_COLOR_RE.test(value)) {
|
|
455
|
+
throw new TypeError(
|
|
456
|
+
`[sarmal] setRenderOptions: headColor must be a 6-digit hex string or null, got ${JSON.stringify(value)}`
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
function assertSkeletonColor(value) {
|
|
461
|
+
if (value === "transparent") {
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
if (typeof value !== "string" || !HEX_COLOR_RE.test(value)) {
|
|
465
|
+
throw new TypeError(
|
|
466
|
+
`[sarmal] setRenderOptions: skeletonColor must be a 6-digit hex string or "transparent", got ${JSON.stringify(value)}`
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
function assertTrailStyle(value) {
|
|
471
|
+
if (!TRAIL_STYLES.includes(value)) {
|
|
472
|
+
throw new RangeError(
|
|
473
|
+
`[sarmal] setRenderOptions: trailStyle must be one of "default", "gradient-static", "gradient-animated", got ${JSON.stringify(value)}`
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
function resolveTrailMainColor(trailColor) {
|
|
478
|
+
return typeof trailColor === "string" ? trailColor : trailColor[0];
|
|
418
479
|
}
|
|
480
|
+
function resolveTrailPalette(trailColor) {
|
|
481
|
+
return typeof trailColor === "string" ? [trailColor] : trailColor;
|
|
482
|
+
}
|
|
483
|
+
function resolveHeadColor(trailColor, trailStyle) {
|
|
484
|
+
if (trailStyle === "default") {
|
|
485
|
+
return resolveTrailMainColor(trailColor);
|
|
486
|
+
}
|
|
487
|
+
const palette = resolveTrailPalette(trailColor);
|
|
488
|
+
const last = palette[palette.length - 1];
|
|
489
|
+
const { r, g, b } = hexToRgb(last);
|
|
490
|
+
return `rgb(${r},${g},${b})`;
|
|
491
|
+
}
|
|
492
|
+
function warnIfTrailColorMismatch(trailColor, trailStyle) {
|
|
493
|
+
if (trailStyle === "default" && Array.isArray(trailColor)) {
|
|
494
|
+
console.warn(
|
|
495
|
+
'[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.'
|
|
496
|
+
);
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
if (trailStyle !== "default" && typeof trailColor === "string") {
|
|
500
|
+
console.warn(
|
|
501
|
+
`[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.`
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
var getHeadDotRadius = (w, h) => Math.max(1, 3 * Math.sqrt(Math.min(w, h) / 160));
|
|
419
506
|
|
|
420
507
|
// src/renderer.ts
|
|
421
|
-
var
|
|
508
|
+
var WHITE_HEX = "#ffffff";
|
|
422
509
|
function hexToRgbComponents(hex) {
|
|
423
510
|
const n = parseInt(hex.slice(1), 16);
|
|
424
511
|
return `${n >> 16},${n >> 8 & 255},${n & 255}`;
|
|
@@ -436,27 +523,18 @@ function createRenderer(options) {
|
|
|
436
523
|
}
|
|
437
524
|
const ctx = canvas.getContext("2d");
|
|
438
525
|
const engine = options.engine;
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
return trailColor;
|
|
448
|
-
}
|
|
449
|
-
const opts = {
|
|
450
|
-
skeletonColor: options.skeletonColor ?? DEFAULT_SKELETON_COLOR,
|
|
451
|
-
trailColor,
|
|
452
|
-
headColor: options.headColor ?? defaultHeadColor()
|
|
453
|
-
};
|
|
454
|
-
const trailRgb = hexToRgbComponents(opts.trailColor);
|
|
526
|
+
let trailStyle = options.trailStyle ?? "default";
|
|
527
|
+
let trailColor = options.trailColor ?? WHITE_HEX;
|
|
528
|
+
let skeletonColor = options.skeletonColor ?? WHITE_HEX;
|
|
529
|
+
let userHeadColor = options.headColor ?? null;
|
|
530
|
+
let headColor = userHeadColor ?? resolveHeadColor(trailColor, trailStyle);
|
|
531
|
+
let trailSolidRgb = hexToRgbComponents(resolveTrailMainColor(trailColor));
|
|
532
|
+
let trailPalette = resolveTrailPalette(trailColor);
|
|
533
|
+
warnIfTrailColorMismatch(trailColor, trailStyle);
|
|
455
534
|
const dpr = typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1;
|
|
456
535
|
function setupCanvas() {
|
|
457
|
-
const
|
|
458
|
-
const
|
|
459
|
-
const lh = rect.height || 200;
|
|
536
|
+
const lw = canvas.offsetWidth || 200;
|
|
537
|
+
const lh = canvas.offsetHeight || 200;
|
|
460
538
|
applyDprSizing(canvas, lw, lh, dpr);
|
|
461
539
|
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
462
540
|
}
|
|
@@ -486,11 +564,13 @@ function createRenderer(options) {
|
|
|
486
564
|
}
|
|
487
565
|
}
|
|
488
566
|
function buildSkeletonCanvas() {
|
|
489
|
-
if (skeleton.length < 2)
|
|
567
|
+
if (skeleton.length < 2) {
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
490
570
|
skeletonCanvas = new OffscreenCanvas(canvas.width, canvas.height);
|
|
491
571
|
const skeletonCtx = skeletonCanvas.getContext("2d");
|
|
492
572
|
skeletonCtx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
493
|
-
skeletonCtx.strokeStyle = `rgba(${hexToRgbComponents(
|
|
573
|
+
skeletonCtx.strokeStyle = `rgba(${hexToRgbComponents(skeletonColor)},${DEFAULT_SKELETON_OPACITY})`;
|
|
494
574
|
skeletonCtx.lineWidth = 1.5;
|
|
495
575
|
skeletonCtx.beginPath();
|
|
496
576
|
const first = skeleton[0];
|
|
@@ -502,8 +582,10 @@ function createRenderer(options) {
|
|
|
502
582
|
skeletonCtx.stroke();
|
|
503
583
|
}
|
|
504
584
|
function drawSkeletonPath(pts, opacity) {
|
|
505
|
-
if (pts.length < 2)
|
|
506
|
-
|
|
585
|
+
if (pts.length < 2) {
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
ctx.strokeStyle = `rgba(${hexToRgbComponents(skeletonColor)},${opacity})`;
|
|
507
589
|
ctx.lineWidth = 1.5;
|
|
508
590
|
ctx.beginPath();
|
|
509
591
|
ctx.moveTo(pts[0].x * scale + offsetX, pts[0].y * scale + offsetY);
|
|
@@ -513,7 +595,7 @@ function createRenderer(options) {
|
|
|
513
595
|
ctx.stroke();
|
|
514
596
|
}
|
|
515
597
|
function drawSkeleton() {
|
|
516
|
-
if (
|
|
598
|
+
if (skeletonColor === "transparent") {
|
|
517
599
|
return;
|
|
518
600
|
}
|
|
519
601
|
if (engine.morphAlpha !== null) {
|
|
@@ -524,7 +606,7 @@ function createRenderer(options) {
|
|
|
524
606
|
if (skeleton.length < 2) {
|
|
525
607
|
return;
|
|
526
608
|
}
|
|
527
|
-
ctx.strokeStyle = `rgba(${hexToRgbComponents(
|
|
609
|
+
ctx.strokeStyle = `rgba(${hexToRgbComponents(skeletonColor)},${DEFAULT_SKELETON_OPACITY})`;
|
|
528
610
|
ctx.lineWidth = 1.5;
|
|
529
611
|
ctx.beginPath();
|
|
530
612
|
const first = skeleton[0];
|
|
@@ -553,10 +635,10 @@ function createRenderer(options) {
|
|
|
553
635
|
toY
|
|
554
636
|
);
|
|
555
637
|
if (trailStyle === "default") {
|
|
556
|
-
ctx.fillStyle = `rgba(${
|
|
638
|
+
ctx.fillStyle = `rgba(${trailSolidRgb},${opacity})`;
|
|
557
639
|
} else {
|
|
558
640
|
const timeOffset = trailStyle === "gradient-animated" ? gradientAnimTime * 5e-4 : 0;
|
|
559
|
-
const color = getPaletteColor(
|
|
641
|
+
const color = getPaletteColor(trailPalette, progress, timeOffset);
|
|
560
642
|
ctx.fillStyle = `rgba(${color.r},${color.g},${color.b},${opacity})`;
|
|
561
643
|
}
|
|
562
644
|
ctx.beginPath();
|
|
@@ -574,8 +656,8 @@ function createRenderer(options) {
|
|
|
574
656
|
}
|
|
575
657
|
const x = head.x * scale + offsetX;
|
|
576
658
|
const y = head.y * scale + offsetY;
|
|
577
|
-
const r = options.headRadius ??
|
|
578
|
-
ctx.fillStyle =
|
|
659
|
+
const r = options.headRadius ?? getHeadDotRadius(logicalWidth, logicalHeight);
|
|
660
|
+
ctx.fillStyle = headColor;
|
|
579
661
|
ctx.beginPath();
|
|
580
662
|
ctx.arc(x, y, r, 0, Math.PI * 2);
|
|
581
663
|
ctx.fill();
|
|
@@ -675,6 +757,34 @@ function createRenderer(options) {
|
|
|
675
757
|
return new Promise((resolve) => {
|
|
676
758
|
morphResolve = resolve;
|
|
677
759
|
});
|
|
760
|
+
},
|
|
761
|
+
setRenderOptions(partial) {
|
|
762
|
+
validateRenderOptions(partial);
|
|
763
|
+
if (partial.trailColor !== void 0) {
|
|
764
|
+
trailColor = partial.trailColor;
|
|
765
|
+
trailSolidRgb = hexToRgbComponents(resolveTrailMainColor(trailColor));
|
|
766
|
+
trailPalette = resolveTrailPalette(trailColor);
|
|
767
|
+
}
|
|
768
|
+
if (partial.skeletonColor !== void 0) {
|
|
769
|
+
skeletonColor = partial.skeletonColor;
|
|
770
|
+
if (skeletonColor !== "transparent" && !engine.isLiveSkeleton) {
|
|
771
|
+
buildSkeletonCanvas();
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
if (partial.trailStyle !== void 0) {
|
|
775
|
+
trailStyle = partial.trailStyle;
|
|
776
|
+
}
|
|
777
|
+
if (partial.headColor !== void 0) {
|
|
778
|
+
userHeadColor = partial.headColor;
|
|
779
|
+
}
|
|
780
|
+
if (userHeadColor === null) {
|
|
781
|
+
headColor = resolveHeadColor(trailColor, trailStyle);
|
|
782
|
+
} else {
|
|
783
|
+
headColor = userHeadColor;
|
|
784
|
+
}
|
|
785
|
+
if (partial.trailColor !== void 0 || partial.trailStyle !== void 0) {
|
|
786
|
+
warnIfTrailColorMismatch(trailColor, trailStyle);
|
|
787
|
+
}
|
|
678
788
|
}
|
|
679
789
|
};
|
|
680
790
|
if (shouldAutoStart) {
|
|
@@ -878,7 +988,7 @@ function createSarmal(canvas, curveDef, options) {
|
|
|
878
988
|
}
|
|
879
989
|
|
|
880
990
|
// src/auto-init.ts
|
|
881
|
-
function
|
|
991
|
+
function parseTrailColor(value) {
|
|
882
992
|
try {
|
|
883
993
|
const parsed = JSON.parse(value);
|
|
884
994
|
if (Array.isArray(parsed)) {
|
|
@@ -899,17 +1009,21 @@ function init() {
|
|
|
899
1009
|
if (!curveDef) {
|
|
900
1010
|
return console.error(`[sarmal] "${curveName}" is not a valid curve name`);
|
|
901
1011
|
}
|
|
902
|
-
createSarmal(canvas, curveDef, {
|
|
903
|
-
...canvas.dataset.trailColor && {
|
|
1012
|
+
const instance = createSarmal(canvas, curveDef, {
|
|
1013
|
+
...canvas.dataset.trailColor && {
|
|
1014
|
+
trailColor: parseTrailColor(canvas.dataset.trailColor)
|
|
1015
|
+
},
|
|
904
1016
|
...canvas.dataset.skeletonColor && { skeletonColor: canvas.dataset.skeletonColor },
|
|
905
1017
|
...canvas.dataset.headColor && { headColor: canvas.dataset.headColor },
|
|
906
1018
|
...canvas.dataset.headRadius && { headRadius: parseFloat(canvas.dataset.headRadius) },
|
|
907
1019
|
...canvas.dataset.trailLength && { trailLength: parseInt(canvas.dataset.trailLength, 10) },
|
|
908
1020
|
...canvas.dataset.trailStyle && {
|
|
909
1021
|
trailStyle: canvas.dataset.trailStyle
|
|
910
|
-
}
|
|
911
|
-
...canvas.dataset.palette && { palette: parsePalette(canvas.dataset.palette) }
|
|
1022
|
+
}
|
|
912
1023
|
});
|
|
1024
|
+
if (canvas.dataset.speed) {
|
|
1025
|
+
instance.setSpeed(parseFloat(canvas.dataset.speed));
|
|
1026
|
+
}
|
|
913
1027
|
});
|
|
914
1028
|
}
|
|
915
1029
|
if (document.readyState === "loading") {
|
|
@@ -919,5 +1033,7 @@ if (document.readyState === "loading") {
|
|
|
919
1033
|
} else {
|
|
920
1034
|
requestAnimationFrame(init);
|
|
921
1035
|
}
|
|
1036
|
+
|
|
1037
|
+
export { init };
|
|
922
1038
|
//# sourceMappingURL=auto-init.js.map
|
|
923
1039
|
//# sourceMappingURL=auto-init.js.map
|