@sarmal/core 0.35.0 → 0.35.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/index.js CHANGED
@@ -1439,14 +1439,8 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
1439
1439
  const cellW = W / cols;
1440
1440
  const cellH = H / rows;
1441
1441
  const dotR = Math.min(cellW, cellH) * 0.36;
1442
- let gradientRgb;
1443
- if (Array.isArray(initialColor)) {
1444
- validateBaseRenderOptions({ trailColor: initialColor });
1445
- gradientRgb = initialColor.map(colorToRgb);
1446
- } else {
1447
- gradientRgb = null;
1448
- }
1449
- let colorRgb = gradientRgb ? gradientRgb[0] : colorToRgb(initialColor);
1442
+ let gradientOklab = null;
1443
+ let colorRgb = { r: 255, g: 255, b: 255 };
1450
1444
  let currentTrailStyle = initialTrailStyle;
1451
1445
  let animTime = 0;
1452
1446
  const ANIM_PERIOD = 6;
@@ -1518,7 +1512,7 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
1518
1512
  }
1519
1513
  function buildBgImageData() {
1520
1514
  bgImageData = new ImageData(W, H);
1521
- const bg = gradientRgb ? gradientRgb[0] : colorRgb;
1515
+ const bg = colorRgb;
1522
1516
  const baseAlpha = 0.05 * 255;
1523
1517
  const { data } = bgImageData;
1524
1518
  const n = cols * rows;
@@ -1535,18 +1529,14 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
1535
1529
  }
1536
1530
  }
1537
1531
  }
1538
- function sampleGradientRgb(stops, t) {
1539
- const n = stops.length;
1540
- const scaled = Math.max(0, Math.min(1, t)) * (n - 1);
1541
- const i = Math.min(Math.floor(scaled), n - 2);
1542
- const a = stops[i];
1543
- const bStop = stops[i + 1];
1544
- const mix = scaled - i;
1545
- return {
1546
- r: Math.round(a.r + (bStop.r - a.r) * mix),
1547
- g: Math.round(a.g + (bStop.g - a.g) * mix),
1548
- b: Math.round(a.b + (bStop.b - a.b) * mix)
1549
- };
1532
+ function applyColor(color) {
1533
+ if (Array.isArray(color)) {
1534
+ gradientOklab = color.map((c) => parseColorToOklab(c));
1535
+ colorRgb = oklabToRgb(gradientOklab[0]);
1536
+ } else {
1537
+ gradientOklab = null;
1538
+ colorRgb = colorToRgb(color);
1539
+ }
1550
1540
  }
1551
1541
  function calculateBoundaries(skel) {
1552
1542
  const b = computeBoundaries(skel, W, H);
@@ -1600,7 +1590,7 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
1600
1590
  }
1601
1591
  frameImageData.data.set(bgImageData.data);
1602
1592
  const { data } = frameImageData;
1603
- const sineOffset = currentTrailStyle === "gradient-animated" ? 0.15 * Math.sin(animTime / ANIM_PERIOD * 2 * Math.PI) : 0;
1593
+ const timeOffset = currentTrailStyle === "gradient-animated" ? animTime / ANIM_PERIOD : 0;
1604
1594
  const n = cols * rows;
1605
1595
  for (let dotIdx = 0; dotIdx < n; dotIdx++) {
1606
1596
  const intensity = grid[dotIdx];
@@ -1608,9 +1598,8 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
1608
1598
  continue;
1609
1599
  }
1610
1600
  let r, g, b;
1611
- if (gradientRgb !== null) {
1612
- const t = Math.max(0, Math.min(1, intensity + sineOffset));
1613
- ({ r, g, b } = sampleGradientRgb(gradientRgb, t));
1601
+ if (gradientOklab !== null) {
1602
+ ({ r, g, b } = oklabToRgb(getPaletteColor(gradientOklab, intensity, timeOffset)));
1614
1603
  } else {
1615
1604
  ({ r, g, b } = colorRgb);
1616
1605
  }
@@ -1628,17 +1617,20 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
1628
1617
  }
1629
1618
  ctx.putImageData(frameImageData, 0, 0);
1630
1619
  }
1620
+ function completeMorphNow() {
1621
+ engine.completeMorph();
1622
+ morphResolve?.();
1623
+ morphResolve = null;
1624
+ morphReject = null;
1625
+ morphProgress = 0;
1626
+ }
1631
1627
  function renderFrame(deltaTime) {
1632
1628
  if (engine.morphAlpha !== null) {
1633
1629
  morphProgress = Math.min(1, morphProgress + deltaTime / (morphDurationMs / 1e3));
1634
1630
  engine.setMorphAlpha(morphProgress);
1635
1631
  calculateBoundaries(engine.getSarmalSkeleton());
1636
1632
  if (morphProgress >= 1) {
1637
- engine.completeMorph();
1638
- morphResolve?.();
1639
- morphResolve = null;
1640
- morphReject = null;
1641
- morphProgress = 0;
1633
+ completeMorphNow();
1642
1634
  calculateBoundaries(engine.getSarmalSkeleton());
1643
1635
  }
1644
1636
  } else if (engine.isLiveSkeleton) {
@@ -1656,6 +1648,8 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
1656
1648
  renderFrame(deltaTime);
1657
1649
  animationId = requestAnimationFrame(loop);
1658
1650
  }
1651
+ validateBaseRenderOptions({ trailColor: initialColor });
1652
+ applyColor(initialColor);
1659
1653
  calculateBoundaries(engine.getSarmalSkeleton());
1660
1654
  computePixelMask();
1661
1655
  frameImageData = new ImageData(W, H);
@@ -1704,11 +1698,7 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
1704
1698
  */
1705
1699
  morphTo(target, opts) {
1706
1700
  if (morphResolve !== null) {
1707
- engine.completeMorph();
1708
- morphResolve();
1709
- morphResolve = null;
1710
- morphReject = null;
1711
- morphProgress = 0;
1701
+ completeMorphNow();
1712
1702
  }
1713
1703
  morphDurationMs = opts?.duration ?? DEFAULT_MORPH_DURATION_MS;
1714
1704
  morphProgress = 0;
@@ -1729,13 +1719,7 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
1729
1719
  validateBaseRenderOptions(partial);
1730
1720
  let needsRebuildBg = false;
1731
1721
  if (partial.trailColor !== void 0) {
1732
- if (Array.isArray(partial.trailColor)) {
1733
- gradientRgb = partial.trailColor.map(colorToRgb);
1734
- colorRgb = gradientRgb[0];
1735
- } else {
1736
- gradientRgb = null;
1737
- colorRgb = colorToRgb(partial.trailColor);
1738
- }
1722
+ applyColor(partial.trailColor);
1739
1723
  needsRebuildBg = true;
1740
1724
  }
1741
1725
  if (partial.trailStyle !== void 0) {
@@ -1747,9 +1731,13 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
1747
1731
  if (needsRebuildBg) {
1748
1732
  buildBgImageData();
1749
1733
  }
1750
- if (currentTrailStyle !== "default" && gradientRgb === null) {
1734
+ if (currentTrailStyle !== "default" && gradientOklab === null) {
1735
+ console.warn(
1736
+ `[sarmal] dot matrix: trailColor is a single color but trailStyle is "${currentTrailStyle}"; the trail will render as a solid color. Pass an array of hex colors to use a real gradient.`
1737
+ );
1738
+ } else if (currentTrailStyle === "default" && gradientOklab !== null) {
1751
1739
  console.warn(
1752
- "[sarmal] dot matrix: gradient trailStyle has no effect without a trailColor array"
1740
+ '[sarmal] dot matrix: trailColor is an array but trailStyle is "default"; only the first color will be used. Pass a gradient trailStyle to use the whole palette.'
1753
1741
  );
1754
1742
  }
1755
1743
  }