@sarmal/core 0.30.0 → 0.33.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 +115 -31
  2. package/dist/auto-init.cjs.map +1 -1
  3. package/dist/auto-init.js +115 -31
  4. package/dist/auto-init.js.map +1 -1
  5. package/dist/cli.js +8 -7
  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 +122 -34
  38. package/dist/index.cjs.map +1 -1
  39. package/dist/index.d.cts +3 -3
  40. package/dist/index.d.ts +3 -3
  41. package/dist/index.js +122 -34
  42. package/dist/index.js.map +1 -1
  43. package/dist/{renderer-shared-OR--cv-t.d.ts → renderer-shared-Bdca4O4G.d.ts} +8 -4
  44. package/dist/{renderer-shared-jqw_Q1WO.d.cts → renderer-shared-Ke9BeK1P.d.cts} +8 -4
  45. package/dist/terminal.cjs +8 -7
  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 +8 -7
  50. package/dist/terminal.js.map +1 -1
  51. package/dist/{types-zbxUgcmZ.d.cts → types-BBuUk6nn.d.cts} +9 -0
  52. package/dist/{types-zbxUgcmZ.d.ts → types-BBuUk6nn.d.ts} +9 -0
  53. package/package.json +1 -1
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
- import { B as BaseRendererOptions, E as Engine, S as SarmalInstance, C as CurveDef, R as RendererOptions, a as ControlPoint, P as Point, b as SarmalOptions } from './types-zbxUgcmZ.cjs';
2
- export { J as JumpOptions, c as RuntimeRenderOptions, d as SeekOptions, T as TrailColor, e as TrailStyle } from './types-zbxUgcmZ.cjs';
1
+ import { B as BaseRendererOptions, E as Engine, S as SarmalInstance, C as CurveDef, R as RendererOptions, a as ControlPoint, P as Point, b as SarmalOptions } from './types-BBuUk6nn.cjs';
2
+ export { J as JumpOptions, c as RuntimeRenderOptions, d as SeekOptions, T as TrailColor, e as TrailStyle } from './types-BBuUk6nn.cjs';
3
3
  export { CurveName, curves } from './curves/index.cjs';
4
- export { B as BoundaryResult, S as SarmalPalette, c as computeBoundaries, p as palettes } from './renderer-shared-jqw_Q1WO.cjs';
4
+ export { B as BoundaryResult, S as SarmalPalette, c as computeBoundaries, p as palettes } from './renderer-shared-Ke9BeK1P.cjs';
5
5
  export { artemis2 } from './curves/artemis2.cjs';
6
6
  export { astroid } from './curves/astroid.cjs';
7
7
  export { deltoid } from './curves/deltoid.cjs';
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { B as BaseRendererOptions, E as Engine, S as SarmalInstance, C as CurveDef, R as RendererOptions, a as ControlPoint, P as Point, b as SarmalOptions } from './types-zbxUgcmZ.js';
2
- export { J as JumpOptions, c as RuntimeRenderOptions, d as SeekOptions, T as TrailColor, e as TrailStyle } from './types-zbxUgcmZ.js';
1
+ import { B as BaseRendererOptions, E as Engine, S as SarmalInstance, C as CurveDef, R as RendererOptions, a as ControlPoint, P as Point, b as SarmalOptions } from './types-BBuUk6nn.js';
2
+ export { J as JumpOptions, c as RuntimeRenderOptions, d as SeekOptions, T as TrailColor, e as TrailStyle } from './types-BBuUk6nn.js';
3
3
  export { CurveName, curves } from './curves/index.js';
4
- export { B as BoundaryResult, S as SarmalPalette, c as computeBoundaries, p as palettes } from './renderer-shared-OR--cv-t.js';
4
+ export { B as BoundaryResult, S as SarmalPalette, c as computeBoundaries, p as palettes } from './renderer-shared-Bdca4O4G.js';
5
5
  export { artemis2 } from './curves/artemis2.js';
6
6
  export { astroid } from './curves/astroid.js';
7
7
  export { deltoid } from './curves/deltoid.js';
package/dist/index.js CHANGED
@@ -373,11 +373,15 @@ function enginePassthroughs(engine) {
373
373
  }
374
374
  var palettes = {
375
375
  bard: ["#a855f7", "#3b82f6", "#14b8a6", "#ec4899"],
376
- sunset: ["#f97316", "#dc2626", "#9333ea", "#f472b6"],
376
+ carnival: ["#ff6b6b", "#4ecdc4", "#ffe66d"],
377
377
  ocean: ["#1e3a8a", "#06b6d4", "#22d3ee", "#e0f2fe"],
378
+ sunset: ["#f97316", "#dc2626", "#9333ea", "#f472b6"],
378
379
  ice: ["#1e3a8a", "#67e8f9"],
379
- fire: ["#7f1d1d", "#fbbf24"],
380
- forest: ["#14532d", "#86efac"]
380
+ rocketpop: ["#08b8cd", "#ffffff", "#ff001f"],
381
+ neon: ["#00e5ff", "#7c3aed", "#e040fb"],
382
+ vaporwave: ["#ff71ce", "#01cdfe", "#b967ff"],
383
+ pastel: ["#c4b5fd", "#fbcfe8", "#bae6fd"],
384
+ sakura: ["#fff1f2", "#fda4af", "#fb7185"]
381
385
  };
382
386
  function hexToRgb(hex) {
383
387
  const n = parseInt(hex.slice(1), 16);
@@ -412,6 +416,49 @@ function parseColorToRgb(s) {
412
416
  }
413
417
  return null;
414
418
  }
419
+ var OKLCH_RE = /^oklch\(\s*([\d.]+)\s+([\d.]+)\s+([\d.]+)(?:\s*\/\s*[\d.]+)?\s*\)$/i;
420
+ function parseOklchToOklab(s) {
421
+ const m = OKLCH_RE.exec(s.trim());
422
+ if (!m) {
423
+ return null;
424
+ }
425
+ const L = parseFloat(m[1]);
426
+ const C = parseFloat(m[2]);
427
+ const H = parseFloat(m[3]);
428
+ if (Number.isNaN(L) || Number.isNaN(C) || Number.isNaN(H)) {
429
+ return null;
430
+ }
431
+ const clampedL = Math.max(0, Math.min(1, L));
432
+ const clampedC = Math.max(0, Math.min(0.4, C));
433
+ const H_rad = H * (Math.PI / 180);
434
+ return {
435
+ L: clampedL,
436
+ a: clampedC * Math.cos(H_rad),
437
+ b: clampedC * Math.sin(H_rad)
438
+ };
439
+ }
440
+ function parseColorToOklab(s) {
441
+ const oklab = parseOklchToOklab(s);
442
+ if (oklab !== null) {
443
+ return oklab;
444
+ }
445
+ const rgb = parseColorToRgb(s);
446
+ if (rgb === null) {
447
+ return null;
448
+ }
449
+ return rgbToOklab(rgb);
450
+ }
451
+ function colorToRgb(color) {
452
+ const rgb = parseColorToRgb(color);
453
+ if (rgb !== null) {
454
+ return rgb;
455
+ }
456
+ const lab = parseOklchToOklab(color);
457
+ if (lab !== null) {
458
+ return oklabToRgb(lab);
459
+ }
460
+ throw new Error(`[sarmal] unrecognized color "${color}"`);
461
+ }
415
462
  function srgbByteToLinear(c) {
416
463
  const n = c / 255;
417
464
  return n <= 0.04045 ? n / 12.92 : Math.pow((n + 0.055) / 1.055, 2.4);
@@ -449,26 +496,25 @@ var lerpOklab = (a, b, t) => {
449
496
  if (t >= 1) {
450
497
  return b;
451
498
  }
452
- const la = rgbToOklab(a), lb = rgbToOklab(b);
453
- return oklabToRgb({
454
- L: la.L + (lb.L - la.L) * t,
455
- a: la.a + (lb.a - la.a) * t,
456
- b: la.b + (lb.b - la.b) * t
457
- });
499
+ return {
500
+ L: a.L + (b.L - a.L) * t,
501
+ a: a.a + (b.a - a.a) * t,
502
+ b: a.b + (b.b - a.b) * t
503
+ };
458
504
  };
459
505
  function getPaletteColor(palette, position, timeOffset = 0) {
460
506
  if (palette.length === 0) {
461
- return { r: 255, g: 255, b: 255 };
507
+ return { L: 1, a: 0, b: 0 };
462
508
  }
463
509
  if (palette.length === 1) {
464
- return hexToRgb(palette[0]);
510
+ return palette[0];
465
511
  }
466
512
  const cyclePos = ((position + timeOffset) % 1 + 1) % 1;
467
513
  const scaled = cyclePos * palette.length;
468
514
  const idx = Math.floor(scaled);
469
515
  const t = scaled - idx;
470
- const c1 = hexToRgb(palette[idx % palette.length]);
471
- const c2 = hexToRgb(palette[(idx + 1) % palette.length]);
516
+ const c1 = palette[idx % palette.length];
517
+ const c2 = palette[(idx + 1) % palette.length];
472
518
  return lerpOklab(c1, c2, t);
473
519
  }
474
520
  var TRAIL_STYLES = ["default", "gradient-static", "gradient-animated"];
@@ -477,7 +523,8 @@ var RENDER_OPTION_KEYS = /* @__PURE__ */ new Set([
477
523
  "headColor",
478
524
  "skeletonColor",
479
525
  "trailStyle",
480
- "headRadius"
526
+ "headRadius",
527
+ "trailWidth"
481
528
  ]);
482
529
  function validateRenderOptions(partial) {
483
530
  for (const key of Object.keys(partial)) {
@@ -500,12 +547,15 @@ function validateRenderOptions(partial) {
500
547
  if (partial.headRadius !== void 0) {
501
548
  assertHeadRadius(partial.headRadius);
502
549
  }
550
+ if (partial.trailWidth !== void 0) {
551
+ assertTrailWidth(partial.trailWidth);
552
+ }
503
553
  }
504
554
  function assertTrailColor(value) {
505
555
  if (typeof value === "string") {
506
- if (parseColorToRgb(value) === null) {
556
+ if (parseColorToOklab(value) === null) {
507
557
  throw new TypeError(
508
- `[sarmal] setRenderOptions: trailColor must be a valid color string (#rrggbb, #rgb, rgb(), rgba()), got "${value}"`
558
+ `[sarmal] setRenderOptions: trailColor must be a valid color string (#rrggbb, #rgb, rgb(), rgba(), oklch()), got "${value}"`
509
559
  );
510
560
  }
511
561
  return;
@@ -518,25 +568,25 @@ function assertTrailColor(value) {
518
568
  }
519
569
  for (let i = 0; i < value.length; i++) {
520
570
  const entry = value[i];
521
- if (typeof entry !== "string" || parseColorToRgb(entry) === null) {
571
+ if (typeof entry !== "string" || parseColorToOklab(entry) === null) {
522
572
  throw new TypeError(
523
- `[sarmal] setRenderOptions: trailColor[${i}] must be a valid color string (#rrggbb, #rgb, rgb(), rgba()), got ${JSON.stringify(entry)}`
573
+ `[sarmal] setRenderOptions: trailColor[${i}] must be a valid color string (#rrggbb, #rgb, rgb(), rgba(), oklch()), got ${JSON.stringify(entry)}`
524
574
  );
525
575
  }
526
576
  }
527
577
  return;
528
578
  }
529
579
  throw new TypeError(
530
- `[sarmal] setRenderOptions: trailColor must be a valid color string (#rrggbb, #rgb, rgb(), rgba()) or an array of color strings, got ${JSON.stringify(value)}`
580
+ `[sarmal] setRenderOptions: trailColor must be a valid color string (#rrggbb, #rgb, rgb(), rgba(), oklch()) or an array of color strings, got ${JSON.stringify(value)}`
531
581
  );
532
582
  }
533
583
  function assertHeadColor(value) {
534
584
  if (value === null) {
535
585
  return;
536
586
  }
537
- if (typeof value !== "string" || parseColorToRgb(value) === null) {
587
+ if (typeof value !== "string" || parseColorToOklab(value) === null) {
538
588
  throw new TypeError(
539
- `[sarmal] setRenderOptions: headColor must be a valid color string (#rrggbb, #rgb, rgb(), rgba()) or null, got ${JSON.stringify(value)}`
589
+ `[sarmal] setRenderOptions: headColor must be a valid color string (#rrggbb, #rgb, rgb(), rgba(), oklch()) or null, got ${JSON.stringify(value)}`
540
590
  );
541
591
  }
542
592
  }
@@ -544,9 +594,9 @@ function assertSkeletonColor(value) {
544
594
  if (value === "transparent") {
545
595
  return;
546
596
  }
547
- if (typeof value !== "string" || parseColorToRgb(value) === null) {
597
+ if (typeof value !== "string" || parseColorToOklab(value) === null) {
548
598
  throw new TypeError(
549
- `[sarmal] setRenderOptions: skeletonColor must be a valid color string (#rrggbb, #rgb, rgb(), rgba()) or "transparent", got ${JSON.stringify(value)}`
599
+ `[sarmal] setRenderOptions: skeletonColor must be a valid color string (#rrggbb, #rgb, rgb(), rgba(), oklch()) or "transparent", got ${JSON.stringify(value)}`
550
600
  );
551
601
  }
552
602
  }
@@ -569,6 +619,18 @@ function assertHeadRadius(value) {
569
619
  );
570
620
  }
571
621
  }
622
+ function assertTrailWidth(value) {
623
+ if (typeof value !== "number") {
624
+ throw new TypeError(
625
+ `[sarmal] setRenderOptions: trailWidth must be a number, got ${JSON.stringify(value)}`
626
+ );
627
+ }
628
+ if (!Number.isFinite(value) || value <= 0) {
629
+ throw new TypeError(
630
+ `[sarmal] setRenderOptions: trailWidth must be a finite positive number, got ${value}`
631
+ );
632
+ }
633
+ }
572
634
  function resolveTrailMainColor(trailColor) {
573
635
  return typeof trailColor === "string" ? trailColor : trailColor[0];
574
636
  }
@@ -581,7 +643,7 @@ function resolveHeadColor(trailColor, trailStyle) {
581
643
  }
582
644
  const palette = resolveTrailPalette(trailColor);
583
645
  const last = palette[palette.length - 1];
584
- const { r, g, b } = parseColorToRgb(last);
646
+ const { r, g, b } = colorToRgb(last);
585
647
  return `rgb(${r},${g},${b})`;
586
648
  }
587
649
  function warnIfTrailColorMismatch(trailColor, trailStyle) {
@@ -602,8 +664,8 @@ function warnIfTrailColorMismatch(trailColor, trailStyle) {
602
664
  var getHeadDotRadius = (w, h) => Math.max(1, 3 * Math.sqrt(Math.min(w, h) / 160));
603
665
  var WHITE_HEX = "#ffffff";
604
666
  function colorToRgbComponents(color) {
605
- const c = parseColorToRgb(color);
606
- return `${c.r},${c.g},${c.b}`;
667
+ const { r, g, b } = colorToRgb(color);
668
+ return `${r},${g},${b}`;
607
669
  }
608
670
  function applyDprSizing(target, logicalWidth, logicalHeight, dpr) {
609
671
  target.style.width = `${logicalWidth}px`;
@@ -625,6 +687,7 @@ function createRenderer(options) {
625
687
  let headColor = userHeadColor ?? resolveHeadColor(trailColor, trailStyle);
626
688
  let trailSolidRgb = colorToRgbComponents(resolveTrailMainColor(trailColor));
627
689
  let trailPalette = resolveTrailPalette(trailColor);
690
+ let trailPaletteOklab = trailPalette.map((c) => parseColorToOklab(c));
628
691
  warnIfTrailColorMismatch(trailColor, trailStyle);
629
692
  const dpr = typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1;
630
693
  function setupCanvas() {
@@ -636,7 +699,14 @@ function createRenderer(options) {
636
699
  setupCanvas();
637
700
  let logicalWidth = canvas.width / dpr;
638
701
  let logicalHeight = canvas.height / dpr;
702
+ if (options.headRadius !== void 0) {
703
+ validateRenderOptions({ headRadius: options.headRadius });
704
+ }
705
+ if (options.trailWidth !== void 0) {
706
+ validateRenderOptions({ trailWidth: options.trailWidth });
707
+ }
639
708
  let headRadius = options.headRadius ?? getHeadDotRadius(logicalWidth, logicalHeight);
709
+ let trailWidth = options.trailWidth ?? 1;
640
710
  let skeleton = [];
641
711
  let skeletonCanvas = null;
642
712
  let trail = [];
@@ -730,14 +800,16 @@ function createRenderer(options) {
730
800
  i,
731
801
  trailCount,
732
802
  toX,
733
- toY
803
+ toY,
804
+ TRAIL_MIN_WIDTH * trailWidth,
805
+ TRAIL_MAX_WIDTH * trailWidth
734
806
  );
735
807
  if (trailStyle === "default") {
736
808
  ctx.fillStyle = `rgba(${trailSolidRgb},${opacity})`;
737
809
  } else {
738
810
  const timeOffset = trailStyle === "gradient-animated" ? gradientAnimTime * 5e-4 : 0;
739
- const color = getPaletteColor(trailPalette, progress, timeOffset);
740
- ctx.fillStyle = `rgba(${color.r},${color.g},${color.b},${opacity})`;
811
+ const { r, g, b } = oklabToRgb(getPaletteColor(trailPaletteOklab, progress, timeOffset));
812
+ ctx.fillStyle = `rgba(${r},${g},${b},${opacity})`;
741
813
  }
742
814
  ctx.beginPath();
743
815
  ctx.moveTo(l0x, l0y);
@@ -871,6 +943,7 @@ function createRenderer(options) {
871
943
  trailColor = partial.trailColor;
872
944
  trailSolidRgb = colorToRgbComponents(resolveTrailMainColor(trailColor));
873
945
  trailPalette = resolveTrailPalette(trailColor);
946
+ trailPaletteOklab = trailPalette.map((c) => parseColorToOklab(c));
874
947
  }
875
948
  if (partial.skeletonColor !== void 0) {
876
949
  skeletonColor = partial.skeletonColor;
@@ -887,6 +960,9 @@ function createRenderer(options) {
887
960
  if (partial.headRadius !== void 0) {
888
961
  headRadius = partial.headRadius;
889
962
  }
963
+ if (partial.trailWidth !== void 0) {
964
+ trailWidth = partial.trailWidth;
965
+ }
890
966
  if (userHeadColor === null) {
891
967
  headColor = resolveHeadColor(trailColor, trailStyle);
892
968
  } else {
@@ -954,8 +1030,8 @@ function el(tag) {
954
1030
  return document.createElementNS("http://www.w3.org/2000/svg", tag);
955
1031
  }
956
1032
  function colorToRgbAttr(color) {
957
- const c = parseColorToRgb(color);
958
- return `rgb(${c.r},${c.g},${c.b})`;
1033
+ const { r, g, b } = colorToRgb(color);
1034
+ return `rgb(${r},${g},${b})`;
959
1035
  }
960
1036
  function createSVGRenderer(options) {
961
1037
  const { container, engine } = options;
@@ -973,6 +1049,7 @@ function createSVGRenderer(options) {
973
1049
  let headRadius;
974
1050
  let trailSolid = colorToRgbAttr(resolveTrailMainColor(trailColor));
975
1051
  let trailPalette = resolveTrailPalette(trailColor);
1052
+ let trailPaletteOklab = trailPalette.map((c) => parseColorToOklab(c));
976
1053
  const ariaLabel = options.ariaLabel ?? "Loading";
977
1054
  warnIfTrailColorMismatch(trailColor, trailStyle);
978
1055
  const viewSize = 100;
@@ -984,7 +1061,14 @@ function createSVGRenderer(options) {
984
1061
  const svgTrailMinWidth = TRAIL_MIN_WIDTH * viewSize / containerPx;
985
1062
  const svgTrailMaxWidth = TRAIL_MAX_WIDTH * viewSize / containerPx;
986
1063
  const svgSkeletonStrokeWidth = String(SKELETON_STROKE_WIDTH_PX * viewSize / containerPx);
1064
+ if (options.headRadius !== void 0) {
1065
+ validateRenderOptions({ headRadius: options.headRadius });
1066
+ }
1067
+ if (options.trailWidth !== void 0) {
1068
+ validateRenderOptions({ trailWidth: options.trailWidth });
1069
+ }
987
1070
  headRadius = options.headRadius ?? SVG_DEFAULT_HEAD_RADIUS;
1071
+ let trailWidth = options.trailWidth ?? 1;
988
1072
  container.setAttribute("viewBox", `0 0 ${viewSize} ${viewSize}`);
989
1073
  container.setAttribute("role", "img");
990
1074
  container.setAttribute("aria-label", ariaLabel);
@@ -1079,15 +1163,15 @@ function createSVGRenderer(options) {
1079
1163
  trailCount,
1080
1164
  px,
1081
1165
  py,
1082
- svgTrailMinWidth,
1083
- svgTrailMaxWidth
1166
+ svgTrailMinWidth * trailWidth,
1167
+ svgTrailMaxWidth * trailWidth
1084
1168
  );
1085
1169
  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`;
1086
1170
  trailPaths[i].setAttribute("d", d);
1087
1171
  trailPaths[i].setAttribute("fill-opacity", opacity.toFixed(3));
1088
1172
  if (trailStyle !== "default") {
1089
1173
  const timeOffset = trailStyle === "gradient-animated" ? gradientAnimTime * 5e-4 : 0;
1090
- const { r, g, b } = getPaletteColor(trailPalette, progress, timeOffset);
1174
+ const { r, g, b } = oklabToRgb(getPaletteColor(trailPaletteOklab, progress, timeOffset));
1091
1175
  trailPaths[i].setAttribute("fill", `rgb(${r},${g},${b})`);
1092
1176
  }
1093
1177
  }
@@ -1239,6 +1323,7 @@ function createSVGRenderer(options) {
1239
1323
  trailColor = partial.trailColor;
1240
1324
  trailSolid = colorToRgbAttr(resolveTrailMainColor(trailColor));
1241
1325
  trailPalette = resolveTrailPalette(trailColor);
1326
+ trailPaletteOklab = trailPalette.map((c) => parseColorToOklab(c));
1242
1327
  if (trailStyle === "default") {
1243
1328
  for (const p of trailPaths) {
1244
1329
  p.setAttribute("fill", trailSolid);
@@ -1271,6 +1356,9 @@ function createSVGRenderer(options) {
1271
1356
  headRadius = partial.headRadius;
1272
1357
  headCircle.setAttribute("r", String(headRadius));
1273
1358
  }
1359
+ if (partial.trailWidth !== void 0) {
1360
+ trailWidth = partial.trailWidth;
1361
+ }
1274
1362
  if (userHeadColor === null) {
1275
1363
  headColor = resolveHeadColor(trailColor, trailStyle);
1276
1364
  } else {