@sarmal/core 0.35.1 → 0.36.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 (53) hide show
  1. package/dist/auto-init.cjs +3 -1
  2. package/dist/auto-init.cjs.map +1 -1
  3. package/dist/auto-init.js +3 -1
  4. package/dist/auto-init.js.map +1 -1
  5. package/dist/cli.js +9 -3
  6. package/dist/cli.js.map +1 -1
  7. package/dist/curves/artemis2.d.cts +1 -1
  8. package/dist/curves/artemis2.d.ts +1 -1
  9. package/dist/curves/astroid.d.cts +1 -1
  10. package/dist/curves/astroid.d.ts +1 -1
  11. package/dist/curves/deltoid.d.cts +1 -1
  12. package/dist/curves/deltoid.d.ts +1 -1
  13. package/dist/curves/epicycloid3.d.cts +1 -1
  14. package/dist/curves/epicycloid3.d.ts +1 -1
  15. package/dist/curves/epitrochoid7.d.cts +1 -1
  16. package/dist/curves/epitrochoid7.d.ts +1 -1
  17. package/dist/curves/index.d.cts +1 -1
  18. package/dist/curves/index.d.ts +1 -1
  19. package/dist/curves/lame.d.cts +1 -1
  20. package/dist/curves/lame.d.ts +1 -1
  21. package/dist/curves/lissajous32.d.cts +1 -1
  22. package/dist/curves/lissajous32.d.ts +1 -1
  23. package/dist/curves/lissajous43.d.cts +1 -1
  24. package/dist/curves/lissajous43.d.ts +1 -1
  25. package/dist/curves/rose3.d.cts +1 -1
  26. package/dist/curves/rose3.d.ts +1 -1
  27. package/dist/curves/rose5.d.cts +1 -1
  28. package/dist/curves/rose5.d.ts +1 -1
  29. package/dist/curves/rose52.d.cts +1 -1
  30. package/dist/curves/rose52.d.ts +1 -1
  31. package/dist/curves/star.d.cts +1 -1
  32. package/dist/curves/star.d.ts +1 -1
  33. package/dist/curves/star4.d.cts +1 -1
  34. package/dist/curves/star4.d.ts +1 -1
  35. package/dist/curves/star7.d.cts +1 -1
  36. package/dist/curves/star7.d.ts +1 -1
  37. package/dist/index.cjs +78 -7
  38. package/dist/index.cjs.map +1 -1
  39. package/dist/index.d.cts +4 -4
  40. package/dist/index.d.ts +4 -4
  41. package/dist/index.js +78 -7
  42. package/dist/index.js.map +1 -1
  43. package/dist/{renderer-shared-DyOI68gd.d.ts → renderer-shared-BZV9ELOa.d.ts} +1 -1
  44. package/dist/{renderer-shared-C3KCEABq.d.cts → renderer-shared-CFimm7VD.d.cts} +1 -1
  45. package/dist/terminal.cjs +9 -3
  46. package/dist/terminal.cjs.map +1 -1
  47. package/dist/terminal.d.cts +2 -2
  48. package/dist/terminal.d.ts +2 -2
  49. package/dist/terminal.js +9 -3
  50. package/dist/terminal.js.map +1 -1
  51. package/dist/{types-_f27GDkU.d.cts → types-CCgSK31t.d.cts} +8 -4
  52. package/dist/{types-_f27GDkU.d.ts → types-CCgSK31t.d.ts} +8 -4
  53. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
- import { C as CurveDef } from '../types-_f27GDkU.js';
1
+ import { C as CurveDef } from '../types-CCgSK31t.js';
2
2
  export { artemis2 } from './artemis2.js';
3
3
  export { astroid } from './astroid.js';
4
4
  export { deltoid } from './deltoid.js';
@@ -1,4 +1,4 @@
1
- import { C as CurveDef } from '../types-_f27GDkU.cjs';
1
+ import { C as CurveDef } from '../types-CCgSK31t.cjs';
2
2
 
3
3
  /**
4
4
  * Lamé curve (superellipse) with time-varying exponent
@@ -1,4 +1,4 @@
1
- import { C as CurveDef } from '../types-_f27GDkU.js';
1
+ import { C as CurveDef } from '../types-CCgSK31t.js';
2
2
 
3
3
  /**
4
4
  * Lamé curve (superellipse) with time-varying exponent
@@ -1,4 +1,4 @@
1
- import { C as CurveDef } from '../types-_f27GDkU.cjs';
1
+ import { C as CurveDef } from '../types-CCgSK31t.cjs';
2
2
 
3
3
  /**
4
4
  * Lissajous curve with frequency ratio 3:2
@@ -1,4 +1,4 @@
1
- import { C as CurveDef } from '../types-_f27GDkU.js';
1
+ import { C as CurveDef } from '../types-CCgSK31t.js';
2
2
 
3
3
  /**
4
4
  * Lissajous curve with frequency ratio 3:2
@@ -1,4 +1,4 @@
1
- import { C as CurveDef } from '../types-_f27GDkU.cjs';
1
+ import { C as CurveDef } from '../types-CCgSK31t.cjs';
2
2
 
3
3
  /**
4
4
  * Lissajous curve with frequency ratio 4:3
@@ -1,4 +1,4 @@
1
- import { C as CurveDef } from '../types-_f27GDkU.js';
1
+ import { C as CurveDef } from '../types-CCgSK31t.js';
2
2
 
3
3
  /**
4
4
  * Lissajous curve with frequency ratio 4:3
@@ -1,4 +1,4 @@
1
- import { C as CurveDef } from '../types-_f27GDkU.cjs';
1
+ import { C as CurveDef } from '../types-CCgSK31t.cjs';
2
2
 
3
3
  /**
4
4
  * Rose curve with 3 petals
@@ -1,4 +1,4 @@
1
- import { C as CurveDef } from '../types-_f27GDkU.js';
1
+ import { C as CurveDef } from '../types-CCgSK31t.js';
2
2
 
3
3
  /**
4
4
  * Rose curve with 3 petals
@@ -1,4 +1,4 @@
1
- import { C as CurveDef } from '../types-_f27GDkU.cjs';
1
+ import { C as CurveDef } from '../types-CCgSK31t.cjs';
2
2
 
3
3
  /**
4
4
  * Rose curve with 5 petals
@@ -1,4 +1,4 @@
1
- import { C as CurveDef } from '../types-_f27GDkU.js';
1
+ import { C as CurveDef } from '../types-CCgSK31t.js';
2
2
 
3
3
  /**
4
4
  * Rose curve with 5 petals
@@ -1,4 +1,4 @@
1
- import { C as CurveDef } from '../types-_f27GDkU.cjs';
1
+ import { C as CurveDef } from '../types-CCgSK31t.cjs';
2
2
 
3
3
  /**
4
4
  * Rose curve with n=5/2 that traces 5 petals over two full revolutions
@@ -1,4 +1,4 @@
1
- import { C as CurveDef } from '../types-_f27GDkU.js';
1
+ import { C as CurveDef } from '../types-CCgSK31t.js';
2
2
 
3
3
  /**
4
4
  * Rose curve with n=5/2 that traces 5 petals over two full revolutions
@@ -1,4 +1,4 @@
1
- import { C as CurveDef } from '../types-_f27GDkU.cjs';
1
+ import { C as CurveDef } from '../types-CCgSK31t.cjs';
2
2
 
3
3
  /**
4
4
  * 5-pointed star based on Fourier harmonics.
@@ -1,4 +1,4 @@
1
- import { C as CurveDef } from '../types-_f27GDkU.js';
1
+ import { C as CurveDef } from '../types-CCgSK31t.js';
2
2
 
3
3
  /**
4
4
  * 5-pointed star based on Fourier harmonics.
@@ -1,4 +1,4 @@
1
- import { C as CurveDef } from '../types-_f27GDkU.cjs';
1
+ import { C as CurveDef } from '../types-CCgSK31t.cjs';
2
2
 
3
3
  /**
4
4
  * 4-pointed star based on Fourier harmonics.
@@ -1,4 +1,4 @@
1
- import { C as CurveDef } from '../types-_f27GDkU.js';
1
+ import { C as CurveDef } from '../types-CCgSK31t.js';
2
2
 
3
3
  /**
4
4
  * 4-pointed star based on Fourier harmonics.
@@ -1,4 +1,4 @@
1
- import { C as CurveDef } from '../types-_f27GDkU.cjs';
1
+ import { C as CurveDef } from '../types-CCgSK31t.cjs';
2
2
 
3
3
  /**
4
4
  * 7-pointed star based on Fourier harmonics.
@@ -1,4 +1,4 @@
1
- import { C as CurveDef } from '../types-_f27GDkU.js';
1
+ import { C as CurveDef } from '../types-CCgSK31t.js';
2
2
 
3
3
  /**
4
4
  * 7-pointed star based on Fourier harmonics.
package/dist/index.cjs CHANGED
@@ -322,7 +322,9 @@ function computeTrailQuad(trail, i, trailCount, toX, toY, minWidth = TRAIL_MIN_W
322
322
  };
323
323
  }
324
324
  function computeBoundaries(pts, logicalWidth, logicalHeight, minPaddingPx = FIT_PADDING_MIN) {
325
- if (pts.length === 0) return null;
325
+ if (pts.length === 0) {
326
+ return null;
327
+ }
326
328
  const first = pts[0];
327
329
  let minX = first.x, maxX = first.x, minY = first.y, maxY = first.y;
328
330
  for (const p of pts) {
@@ -520,7 +522,11 @@ function getPaletteColor(palette, position, timeOffset = 0) {
520
522
  return lerpOklab(c1, c2, t);
521
523
  }
522
524
  var TRAIL_STYLES = ["default", "gradient-static", "gradient-animated"];
523
- var BASE_RENDER_OPTION_KEYS = /* @__PURE__ */ new Set(["trailColor", "trailStyle"]);
525
+ var BASE_RENDER_OPTION_KEYS = /* @__PURE__ */ new Set([
526
+ "trailColor",
527
+ "trailStyle",
528
+ "skeletonColor"
529
+ ]);
524
530
  var RENDER_OPTION_KEYS = /* @__PURE__ */ new Set([
525
531
  "trailColor",
526
532
  "headColor",
@@ -541,6 +547,9 @@ function validateBaseRenderOptions(partial) {
541
547
  if (partial.trailStyle !== void 0) {
542
548
  assertTrailStyle(partial.trailStyle);
543
549
  }
550
+ if (partial.skeletonColor !== void 0) {
551
+ assertSkeletonColor(partial.skeletonColor);
552
+ }
544
553
  }
545
554
  function validateRenderOptions(partial) {
546
555
  for (const key of Object.keys(partial)) {
@@ -1426,6 +1435,7 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
1426
1435
  trailLength: trailLengthOpt,
1427
1436
  trailColor: initialColor = "#ffffff",
1428
1437
  trailStyle: initialTrailStyle = "default",
1438
+ skeletonColor: skeletonColorOpt = "#ffffff",
1429
1439
  autoStart = true,
1430
1440
  pauseOnHidden: pauseOnHiddenOpt = true,
1431
1441
  initialPhase
@@ -1456,6 +1466,8 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
1456
1466
  let pixelMaskCoverages = new Float32Array(0);
1457
1467
  let bgImageData = null;
1458
1468
  let frameImageData = null;
1469
+ let skeletonColorOklab = null;
1470
+ const skeletonDotGrid = new Uint8Array(cols * rows);
1459
1471
  let animationId = null;
1460
1472
  let lastTime = 0;
1461
1473
  let pausedByVisibility = false;
@@ -1540,6 +1552,53 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
1540
1552
  colorRgb = colorToRgb(color);
1541
1553
  }
1542
1554
  }
1555
+ function applySkeletonColor(color) {
1556
+ skeletonColorOklab = color === "transparent" ? null : parseColorToOklab(color);
1557
+ }
1558
+ function computeSkeletonGrid(skel) {
1559
+ skeletonDotGrid.fill(0);
1560
+ const count = skel.length;
1561
+ for (let i = 0; i < count; i++) {
1562
+ const pt = skel[i];
1563
+ const [c, r] = mapPt(pt.x, pt.y);
1564
+ skeletonDotGrid[r * cols + c] = 1;
1565
+ if (i < count - 1) {
1566
+ const next = skel[i + 1];
1567
+ const [nc, nr] = mapPt(next.x, next.y);
1568
+ const steps = Math.ceil(Math.max(Math.abs(nc - c), Math.abs(nr - r))) * 2;
1569
+ for (let s = 1; s < steps; s++) {
1570
+ const t = s / steps;
1571
+ const ix = pt.x + (next.x - pt.x) * t;
1572
+ const iy = pt.y + (next.y - pt.y) * t;
1573
+ const [ic, ir] = mapPt(ix, iy);
1574
+ skeletonDotGrid[ir * cols + ic] = 1;
1575
+ }
1576
+ }
1577
+ }
1578
+ }
1579
+ function writeSkeletonPixels(data) {
1580
+ if (skeletonColorOklab === null) {
1581
+ return;
1582
+ }
1583
+ const { r, g, b } = oklabToRgb(skeletonColorOklab);
1584
+ const skelBaseAlpha = DEFAULT_SKELETON_OPACITY * 255;
1585
+ const n = cols * rows;
1586
+ for (let dotIdx = 0; dotIdx < n; dotIdx++) {
1587
+ if (!skeletonDotGrid[dotIdx]) {
1588
+ continue;
1589
+ }
1590
+ const start = pixelMaskStarts[dotIdx];
1591
+ const len = pixelMaskLengths[dotIdx];
1592
+ for (let k = 0; k < len; k++) {
1593
+ const px = pixelMaskIndices[start + k];
1594
+ const coverage = pixelMaskCoverages[start + k];
1595
+ data[px] = r;
1596
+ data[px + 1] = g;
1597
+ data[px + 2] = b;
1598
+ data[px + 3] = Math.round(skelBaseAlpha * coverage);
1599
+ }
1600
+ }
1601
+ }
1543
1602
  function calculateBoundaries(skel) {
1544
1603
  const b = computeBoundaries(skel, W, H);
1545
1604
  if (b) {
@@ -1592,6 +1651,7 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
1592
1651
  }
1593
1652
  frameImageData.data.set(bgImageData.data);
1594
1653
  const { data } = frameImageData;
1654
+ writeSkeletonPixels(data);
1595
1655
  const timeOffset = currentTrailStyle === "gradient-animated" ? animTime / ANIM_PERIOD : 0;
1596
1656
  const n = cols * rows;
1597
1657
  for (let dotIdx = 0; dotIdx < n; dotIdx++) {
@@ -1635,8 +1695,10 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
1635
1695
  completeMorphNow();
1636
1696
  calculateBoundaries(engine.getSarmalSkeleton());
1637
1697
  }
1698
+ computeSkeletonGrid(engine.getSarmalSkeleton());
1638
1699
  } else if (engine.isLiveSkeleton) {
1639
1700
  calculateBoundaries(engine.getSarmalSkeleton());
1701
+ computeSkeletonGrid(engine.getSarmalSkeleton());
1640
1702
  }
1641
1703
  if (currentTrailStyle === "gradient-animated") {
1642
1704
  animTime += deltaTime;
@@ -1650,10 +1712,12 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
1650
1712
  renderFrame(deltaTime);
1651
1713
  animationId = requestAnimationFrame(loop);
1652
1714
  }
1653
- validateBaseRenderOptions({ trailColor: initialColor });
1715
+ validateBaseRenderOptions({ trailColor: initialColor, skeletonColor: skeletonColorOpt });
1654
1716
  applyColor(initialColor);
1717
+ applySkeletonColor(skeletonColorOpt);
1655
1718
  calculateBoundaries(engine.getSarmalSkeleton());
1656
1719
  computePixelMask();
1720
+ computeSkeletonGrid(engine.getSarmalSkeleton());
1657
1721
  frameImageData = new ImageData(W, H);
1658
1722
  buildBgImageData();
1659
1723
  if (initialPhase !== void 0) {
@@ -1663,13 +1727,17 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
1663
1727
  const instance = {
1664
1728
  /** Starts the animation loop. Does nothing if already running. */
1665
1729
  play() {
1666
- if (animationId !== null) return;
1730
+ if (animationId !== null) {
1731
+ return;
1732
+ }
1667
1733
  lastTime = performance.now();
1668
1734
  loop();
1669
1735
  },
1670
1736
  /** Pauses the animation loop. Preserves current trail state. */
1671
1737
  pause() {
1672
- if (animationId === null) return;
1738
+ if (animationId === null) {
1739
+ return;
1740
+ }
1673
1741
  cancelAnimationFrame(animationId);
1674
1742
  animationId = null;
1675
1743
  engine.cancelSpeedTransition();
@@ -1713,8 +1781,8 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
1713
1781
  /**
1714
1782
  * Updates render options on a live instance without stopping the animation.
1715
1783
  *
1716
- * Supported: `trailColor` and `trailStyle`.
1717
- * ! Unsupported fields (`headColor`, `skeletonColor`, `headRadius`, `trailWidth`) throw.
1784
+ * Supported: `trailColor`, `trailStyle`, and `skeletonColor`.
1785
+ * ! Unsupported fields (`headColor`, `headRadius`, `trailWidth`) throw.
1718
1786
  * ! Validation fails the entire call if any field is invalid, leaving options unchanged.
1719
1787
  */
1720
1788
  setRenderOptions(partial) {
@@ -1724,6 +1792,9 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
1724
1792
  applyColor(partial.trailColor);
1725
1793
  needsRebuildBg = true;
1726
1794
  }
1795
+ if (partial.skeletonColor !== void 0) {
1796
+ applySkeletonColor(partial.skeletonColor);
1797
+ }
1727
1798
  if (partial.trailStyle !== void 0) {
1728
1799
  currentTrailStyle = partial.trailStyle;
1729
1800
  if (currentTrailStyle === "default") {