@pixerate/editor 0.165.0 → 0.166.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 (46) hide show
  1. package/dist/agent/index.cjs +34 -34
  2. package/dist/agent/index.js +5 -5
  3. package/dist/canvas/index.cjs +6 -6
  4. package/dist/canvas/index.js +2 -2
  5. package/dist/chart/controller.d.cts +29 -0
  6. package/dist/chart/controller.d.ts +29 -0
  7. package/dist/chart/index.cjs +301 -179
  8. package/dist/chart/index.d.cts +1 -0
  9. package/dist/chart/index.d.ts +1 -0
  10. package/dist/chart/index.js +132 -10
  11. package/dist/chart/layout-families.d.cts +7 -0
  12. package/dist/chart/layout-families.d.ts +7 -0
  13. package/dist/chart/layout-shared.d.cts +5 -0
  14. package/dist/chart/layout-shared.d.ts +5 -0
  15. package/dist/chart/race.d.cts +26 -0
  16. package/dist/chart/race.d.ts +26 -0
  17. package/dist/chart/schemas.d.cts +2 -0
  18. package/dist/chart/schemas.d.ts +2 -0
  19. package/dist/chart/spec.d.cts +1 -1
  20. package/dist/chart/spec.d.ts +1 -1
  21. package/dist/chart/types.d.cts +6 -2
  22. package/dist/chart/types.d.ts +6 -2
  23. package/dist/{chunk-FEU2XVQH.js → chunk-5UNQDC3Q.js} +5 -2
  24. package/dist/{chunk-64VWWR5U.cjs → chunk-6FYIFGBW.cjs} +16 -16
  25. package/dist/{chunk-UVXTOZ2B.cjs → chunk-BPX4Z3N3.cjs} +12 -3
  26. package/dist/{chunk-MKXK6E4O.cjs → chunk-CHLV7UFP.cjs} +51 -51
  27. package/dist/{chunk-X5W645RI.js → chunk-DFCAR7AW.js} +3 -3
  28. package/dist/{chunk-2ZRN43IN.js → chunk-FR432ROA.js} +12 -3
  29. package/dist/{chunk-ODFCS7HF.cjs → chunk-HXOBOHH2.cjs} +8 -8
  30. package/dist/{chunk-V5GSY3NC.js → chunk-ITANXMZD.js} +78 -2
  31. package/dist/{chunk-TVQW26AV.cjs → chunk-MZFZSVUJ.cjs} +26 -23
  32. package/dist/{chunk-N7NBGT2Y.js → chunk-NQQDGGXY.js} +2 -2
  33. package/dist/{chunk-Q25WAFTD.cjs → chunk-SZWVMB3B.cjs} +21 -18
  34. package/dist/{chunk-QO2T6KA5.cjs → chunk-UUUTEVX6.cjs} +116 -40
  35. package/dist/{chunk-IMRXC7OA.cjs → chunk-V5L2G22R.cjs} +153 -77
  36. package/dist/{chunk-2J5VLJHC.js → chunk-VB2CY6EG.js} +3 -3
  37. package/dist/{chunk-CRFSQWKQ.js → chunk-XNU45TYA.js} +4 -1
  38. package/dist/{chunk-FRBRLKNQ.js → chunk-YUFTVNLX.js} +78 -2
  39. package/dist/export/index.cjs +4 -4
  40. package/dist/export/index.js +3 -3
  41. package/dist/extensions/index.cjs +7 -7
  42. package/dist/extensions/index.js +6 -6
  43. package/dist/index.cjs +13 -13
  44. package/dist/index.js +7 -7
  45. package/package.json +1 -1
  46. package/skills/pixerate-chart/SKILL.md +20 -2
@@ -12,7 +12,7 @@
12
12
 
13
13
 
14
14
 
15
- var _chunkUVXTOZ2Bcjs = require('./chunk-UVXTOZ2B.cjs');
15
+ var _chunkBPX4Z3N3cjs = require('./chunk-BPX4Z3N3.cjs');
16
16
 
17
17
 
18
18
  var _chunk55AKPTLMcjs = require('./chunk-55AKPTLM.cjs');
@@ -1239,7 +1239,7 @@ function layoutCartesian(ctx, area, visible) {
1239
1239
  const { spec, theme, marks, measure, fs } = ctx;
1240
1240
  const horizontal = spec.orientation === "horizontal";
1241
1241
  const n = spec.categories.length;
1242
- const types = new Map(visible.map((s) => [s.id, _chunkUVXTOZ2Bcjs.chartSeriesType.call(void 0, spec, s)]));
1242
+ const types = new Map(visible.map((s) => [s.id, _chunkBPX4Z3N3cjs.chartSeriesType.call(void 0, spec, s)]));
1243
1243
  const stacked = spec.stacking !== "none";
1244
1244
  const percent = spec.stacking === "percent";
1245
1245
  const onSecondary = (s) => s.axis === "secondary";
@@ -1276,7 +1276,7 @@ function layoutCartesian(ctx, area, visible) {
1276
1276
  const stack = stacks.get(s.id);
1277
1277
  errors.set(
1278
1278
  s.id,
1279
- _chunkUVXTOZ2Bcjs.chartErrorAmounts.call(void 0, s.errorBars, s.values).map((e, i) => {
1279
+ _chunkBPX4Z3N3cjs.chartErrorAmounts.call(void 0, s.errorBars, s.values).map((e, i) => {
1280
1280
  const raw = s.values[i];
1281
1281
  const seg = _optionalChain([stack, 'optionalAccess', _11 => _11.segments, 'access', _12 => _12[i]]);
1282
1282
  if (!e || raw === null || stack && !seg) return null;
@@ -1346,7 +1346,7 @@ function layoutCartesian(ctx, area, visible) {
1346
1346
  const drawOrder = [...visible].sort((a, b) => order(types.get(a.id)) - order(types.get(b.id)));
1347
1347
  for (const s of drawOrder) {
1348
1348
  const si = spec.series.indexOf(s);
1349
- const color = _chunkUVXTOZ2Bcjs.chartSeriesColor.call(void 0, spec, si);
1349
+ const color = _chunkBPX4Z3N3cjs.chartSeriesColor.call(void 0, spec, si);
1350
1350
  const type = types.get(s.id);
1351
1351
  const stack = stacks.get(s.id);
1352
1352
  const selSeries = ctx.seriesSelected(s.id);
@@ -1372,7 +1372,7 @@ function layoutCartesian(ctx, area, visible) {
1372
1372
  const selected = ctx.isSelected(target);
1373
1373
  const [x, y] = map({ c: c0, v: Math.min(a, b) });
1374
1374
  const rect = horizontal ? { x: Math.min(a, b), y: c0, width: Math.abs(b - a), height: cw } : { x, y, width: cw, height: Math.abs(b - a) };
1375
- const fill = _chunkUVXTOZ2Bcjs.chartPointColor.call(void 0, spec, si, i);
1375
+ const fill = _chunkBPX4Z3N3cjs.chartPointColor.call(void 0, spec, si, i);
1376
1376
  marks.push({
1377
1377
  kind: "rect",
1378
1378
  key: `bar-${s.id}-${i}`,
@@ -1451,7 +1451,7 @@ function layoutCartesian(ctx, area, visible) {
1451
1451
  const target = { kind: "point", seriesId: s.id, index: i };
1452
1452
  const selected = ctx.isSelected(target);
1453
1453
  const r = type === "scatter" ? 4.5 : 3.5;
1454
- const pointColor = _chunkUVXTOZ2Bcjs.chartPointColor.call(void 0, spec, si, i);
1454
+ const pointColor = _chunkBPX4Z3N3cjs.chartPointColor.call(void 0, spec, si, i);
1455
1455
  const fill = showDots ? type === "scatter" ? pointColor : theme.surface : "transparent";
1456
1456
  marks.push(
1457
1457
  pointMark({ key: `point-${s.id}-${i}`, target, selected: selected || selSeries, opacity: type === "scatter" ? 0.85 : void 0 }, showDots ? marker : "hit", cx, cy, showDots ? r : 6, fill, showDots ? pointColor : void 0, 2)
@@ -1524,8 +1524,8 @@ function layoutXy(ctx, area, visible) {
1524
1524
  const yErrors = /* @__PURE__ */ new Map();
1525
1525
  const xErrors = /* @__PURE__ */ new Map();
1526
1526
  for (const { s } of all) {
1527
- if (s.errorBars) yErrors.set(s.id, _chunkUVXTOZ2Bcjs.chartErrorAmounts.call(void 0, s.errorBars, s.values));
1528
- if (s.xErrorBars) xErrors.set(s.id, _chunkUVXTOZ2Bcjs.chartErrorAmounts.call(void 0, s.xErrorBars, s.values.map((_, i) => _nullishCoalesce(_optionalChain([s, 'access', _29 => _29.x, 'optionalAccess', _30 => _30[i]]), () => ( (bubble || !s.x ? i + 1 : null))))));
1527
+ if (s.errorBars) yErrors.set(s.id, _chunkBPX4Z3N3cjs.chartErrorAmounts.call(void 0, s.errorBars, s.values));
1528
+ if (s.xErrorBars) xErrors.set(s.id, _chunkBPX4Z3N3cjs.chartErrorAmounts.call(void 0, s.xErrorBars, s.values.map((_, i) => _nullishCoalesce(_optionalChain([s, 'access', _29 => _29.x, 'optionalAccess', _30 => _30[i]]), () => ( (bubble || !s.x ? i + 1 : null))))));
1529
1529
  }
1530
1530
  let xlo = Infinity;
1531
1531
  let xhi = -Infinity;
@@ -1608,8 +1608,8 @@ function layoutXy(ctx, area, visible) {
1608
1608
  const trendLabels = [];
1609
1609
  for (const { s, pts } of all) {
1610
1610
  const si = spec.series.indexOf(s);
1611
- const color = _chunkUVXTOZ2Bcjs.chartSeriesColor.call(void 0, spec, si);
1612
- const type = _chunkUVXTOZ2Bcjs.chartSeriesType.call(void 0, spec, s);
1611
+ const color = _chunkBPX4Z3N3cjs.chartSeriesColor.call(void 0, spec, si);
1612
+ const type = _chunkBPX4Z3N3cjs.chartSeriesType.call(void 0, spec, s);
1613
1613
  const selSeries = ctx.seriesSelected(s.id);
1614
1614
  const seriesTarget = { kind: "series", seriesId: s.id };
1615
1615
  if (type === "line" || type === "area") {
@@ -1634,7 +1634,7 @@ function layoutXy(ctx, area, visible) {
1634
1634
  }
1635
1635
  const target = { kind: "point", seriesId: s.id, index: p.i };
1636
1636
  const selected = ctx.isSelected(target);
1637
- const pointColor = _chunkUVXTOZ2Bcjs.chartPointColor.call(void 0, spec, si, p.i);
1637
+ const pointColor = _chunkBPX4Z3N3cjs.chartPointColor.call(void 0, spec, si, p.i);
1638
1638
  const r = bubble ? maxSize > 0 && p.size !== null && p.size > 0 ? Math.max(2, Math.sqrt(p.size / maxSize) * maxR) : 2 : 4.5;
1639
1639
  if (bubble) marks.push({ kind: "circle", key: `point-${s.id}-${p.i}`, role: "point", cx, cy, r, fill: pointColor, stroke: pointColor, strokeWidth: 1, opacity: 0.6, target, selected: selected || selSeries });
1640
1640
  else marks.push(pointMark({ key: `point-${s.id}-${p.i}`, target, selected: selected || selSeries, opacity: 0.85 }, marker === "none" ? "hit" : marker, cx, cy, marker === "none" ? 6 : r, marker === "none" ? "transparent" : pointColor, marker === "none" ? void 0 : pointColor, 2));
@@ -1677,8 +1677,40 @@ function trendlineLegendItems(spec, color) {
1677
1677
  );
1678
1678
  }
1679
1679
 
1680
+ // src/chart/race.ts
1681
+ function chartRaceValueAt(series, index) {
1682
+ for (let i = Math.min(index, series.values.length - 1); i >= 0; i--) {
1683
+ const v = series.values[i];
1684
+ if (v !== null && v !== void 0 && Number.isFinite(v)) return v;
1685
+ }
1686
+ return 0;
1687
+ }
1688
+ function chartRaceMoment(count, frame) {
1689
+ const last = Math.max(0, count - 1);
1690
+ const at = frame === null || frame === void 0 || !Number.isFinite(frame) ? last : Math.max(0, Math.min(last, frame));
1691
+ const from = Math.floor(at);
1692
+ const to = Math.min(last, from + 1);
1693
+ return { from, to, t: at - from, at };
1694
+ }
1695
+ function chartRaceRanking(spec, frame) {
1696
+ const visible = spec.series.filter((s) => !s.hidden);
1697
+ const { from, to, t } = chartRaceMoment(spec.categories.length, frame);
1698
+ const rankAt = (i) => {
1699
+ const order2 = visible.map((s, k) => ({ id: s.id, v: chartRaceValueAt(s, i), k })).sort((a, b) => b.v - a.v || a.k - b.k);
1700
+ return new Map(order2.map((o, r) => [o.id, r]));
1701
+ };
1702
+ const r0 = rankAt(from);
1703
+ const r1 = rankAt(to);
1704
+ const near = t < 0.5 ? r0 : r1;
1705
+ return visible.map((s) => {
1706
+ const a = chartRaceValueAt(s, from);
1707
+ const b = chartRaceValueAt(s, to);
1708
+ return { seriesId: s.id, name: s.name, value: a + (b - a) * t, position: r0.get(s.id) + (r1.get(s.id) - r0.get(s.id)) * t, rank: near.get(s.id) };
1709
+ }).sort((a, b) => a.position - b.position || b.value - a.value);
1710
+ }
1711
+
1680
1712
  // src/chart/layout-families.ts
1681
- var sliceColor = (ctx, series, i) => _optionalChain([series, 'access', _45 => _45.pointColors, 'optionalAccess', _46 => _46[i]]) || _chunkUVXTOZ2Bcjs.chartSliceColor.call(void 0, ctx.spec, i);
1713
+ var sliceColor = (ctx, series, i) => _optionalChain([series, 'access', _45 => _45.pointColors, 'optionalAccess', _46 => _46[i]]) || _chunkBPX4Z3N3cjs.chartSliceColor.call(void 0, ctx.spec, i);
1682
1714
  function layoutPie(ctx, area, series) {
1683
1715
  const { spec, theme, marks, fs, selection } = ctx;
1684
1716
  const values = spec.categories.map((_, i) => {
@@ -1794,7 +1826,7 @@ function layoutRadar(ctx, area, visible) {
1794
1826
  });
1795
1827
  for (const s of visible) {
1796
1828
  const si = spec.series.indexOf(s);
1797
- const color = _chunkUVXTOZ2Bcjs.chartSeriesColor.call(void 0, spec, si);
1829
+ const color = _chunkBPX4Z3N3cjs.chartSeriesColor.call(void 0, spec, si);
1798
1830
  const selSeries = ctx.seriesSelected(s.id);
1799
1831
  const pts = s.values.map((v, i) => v !== null && Number.isFinite(v) ? at(i, rOf(v)) : null);
1800
1832
  const present = pts.filter((p) => p !== null);
@@ -1844,7 +1876,7 @@ function layoutWaterfall(ctx, area, series) {
1844
1876
  });
1845
1877
  const { band, catCenter, map, value } = frame;
1846
1878
  const w = band * (1 - spec.gapWidth);
1847
- const color = _chunkUVXTOZ2Bcjs.chartSeriesColor.call(void 0, spec, spec.series.indexOf(series));
1879
+ const color = _chunkBPX4Z3N3cjs.chartSeriesColor.call(void 0, spec, spec.series.indexOf(series));
1848
1880
  const format = _nullishCoalesce(series.format, () => ( spec.yAxis.format));
1849
1881
  const labelsOn = _nullishCoalesce(series.dataLabels, () => ( spec.dataLabels));
1850
1882
  let prevEnd = null;
@@ -1903,7 +1935,7 @@ function layoutHistogram(ctx, area, visible) {
1903
1935
  const gap = k > 1 ? band * spec.gapWidth * 0.5 : 0;
1904
1936
  const w = (band - gap) / k;
1905
1937
  visible.forEach((s, si) => {
1906
- const color = _chunkUVXTOZ2Bcjs.chartSeriesColor.call(void 0, spec, spec.series.indexOf(s));
1938
+ const color = _chunkBPX4Z3N3cjs.chartSeriesColor.call(void 0, spec, spec.series.indexOf(s));
1907
1939
  const target = { kind: "series", seriesId: s.id };
1908
1940
  const selected = ctx.seriesSelected(s.id);
1909
1941
  counts[si].forEach((c, b) => {
@@ -1934,7 +1966,7 @@ function layoutBox(ctx, area, visible) {
1934
1966
  visible.forEach((s, i) => {
1935
1967
  const st = stats[i];
1936
1968
  if (!st) return;
1937
- const color = _chunkUVXTOZ2Bcjs.chartSeriesColor.call(void 0, spec, spec.series.indexOf(s));
1969
+ const color = _chunkBPX4Z3N3cjs.chartSeriesColor.call(void 0, spec, spec.series.indexOf(s));
1938
1970
  const target = { kind: "series", seriesId: s.id };
1939
1971
  const selected = ctx.seriesSelected(s.id);
1940
1972
  const c = catCenter(i);
@@ -2153,7 +2185,7 @@ function layoutLikert(ctx, area, visible) {
2153
2185
  if (x1 - x0 <= 0) return;
2154
2186
  const target = { kind: "point", seriesId: s.id, index: i };
2155
2187
  const selected = ctx.isSelected(target);
2156
- const fill = _optionalChain([s, 'access', _48 => _48.pointColors, 'optionalAccess', _49 => _49[i]]) || _chunkUVXTOZ2Bcjs.chartSeriesColor.call(void 0, spec, spec.series.indexOf(s));
2188
+ const fill = _optionalChain([s, 'access', _48 => _48.pointColors, 'optionalAccess', _49 => _49[i]]) || _chunkBPX4Z3N3cjs.chartSeriesColor.call(void 0, spec, spec.series.indexOf(s));
2157
2189
  const rect = { x: x0, y, width: x1 - x0, height: barH };
2158
2190
  marks.push({ kind: "rect", key, role: "bar", ...rect, fill, target, selected: selected || ctx.seriesSelected(s.id) || catSelected });
2159
2191
  if (selected) ctx.outline(`${key}-selection`, { x: rect.x - 2, y: rect.y - 2, width: rect.width + 4, height: rect.height + 4 });
@@ -2252,8 +2284,8 @@ function layoutParliament(ctx, area, series) {
2252
2284
  }
2253
2285
  function treeColor(ctx, series, node, group, base, shade) {
2254
2286
  if (node.color) return node.color;
2255
- if (base === null) return _optionalChain([series, 'optionalAccess', _50 => _50.pointColors, 'optionalAccess', _51 => _51[group]]) || _chunkUVXTOZ2Bcjs.chartSliceColor.call(void 0, ctx.spec, group);
2256
- return _chunkUVXTOZ2Bcjs.shadeChartColor.call(void 0, base, shade);
2287
+ if (base === null) return _optionalChain([series, 'optionalAccess', _50 => _50.pointColors, 'optionalAccess', _51 => _51[group]]) || _chunkBPX4Z3N3cjs.chartSliceColor.call(void 0, ctx.spec, group);
2288
+ return _chunkBPX4Z3N3cjs.shadeChartColor.call(void 0, base, shade);
2257
2289
  }
2258
2290
  function layoutTreemapTree(ctx, area, series) {
2259
2291
  const { spec, marks, theme, fs, measure } = ctx;
@@ -2261,7 +2293,7 @@ function layoutTreemapTree(ctx, area, series) {
2261
2293
  const labelsOn = _nullishCoalesce(_optionalChain([series, 'optionalAccess', _53 => _53.dataLabels]), () => ( true));
2262
2294
  let unlabelled = 0;
2263
2295
  const draw = (nodes, rect, key, group, base) => {
2264
- const rects = chartSquarify(nodes.map(_chunkUVXTOZ2Bcjs.chartTreeTotal), rect);
2296
+ const rects = chartSquarify(nodes.map(_chunkBPX4Z3N3cjs.chartTreeTotal), rect);
2265
2297
  nodes.forEach((node, k) => {
2266
2298
  const r = rects[k];
2267
2299
  if (r.width <= 0.5 || r.height <= 0.5) return;
@@ -2296,10 +2328,10 @@ function layoutTreemapTree(ctx, area, series) {
2296
2328
  }
2297
2329
  function layoutSunburst(ctx, area, series) {
2298
2330
  const { spec, marks, theme, fs, measure } = ctx;
2299
- const tree = spec.tree.length ? spec.tree : _chunkUVXTOZ2Bcjs.chartTreeFromSeries.call(void 0, spec.categories, _nullishCoalesce(_optionalChain([series, 'optionalAccess', _55 => _55.values]), () => ( [])));
2331
+ const tree = spec.tree.length ? spec.tree : _chunkBPX4Z3N3cjs.chartTreeFromSeries.call(void 0, spec.categories, _nullishCoalesce(_optionalChain([series, 'optionalAccess', _55 => _55.values]), () => ( [])));
2300
2332
  const indexOf = new Map(spec.categories.map((c, i) => [c.trim() || `${i + 1}`, i]));
2301
- const depth = _chunkUVXTOZ2Bcjs.chartTreeDepth.call(void 0, tree);
2302
- const total = tree.reduce((t, n) => t + _chunkUVXTOZ2Bcjs.chartTreeTotal.call(void 0, n), 0);
2333
+ const depth = _chunkBPX4Z3N3cjs.chartTreeDepth.call(void 0, tree);
2334
+ const total = tree.reduce((t, n) => t + _chunkBPX4Z3N3cjs.chartTreeTotal.call(void 0, n), 0);
2303
2335
  const cx = area.x + area.width / 2;
2304
2336
  const cy = area.y + area.height / 2;
2305
2337
  const outer = Math.max(8, Math.min(area.width, area.height) / 2 - 4);
@@ -2313,10 +2345,10 @@ function layoutSunburst(ctx, area, series) {
2313
2345
  const format = _nullishCoalesce(_optionalChain([series, 'optionalAccess', _56 => _56.format]), () => ( spec.yAxis.format));
2314
2346
  let unlabelled = 0;
2315
2347
  const walk = (nodes, start, sweep, level, key, group, base) => {
2316
- const sum = nodes.reduce((t, n) => t + _chunkUVXTOZ2Bcjs.chartTreeTotal.call(void 0, n), 0);
2348
+ const sum = nodes.reduce((t, n) => t + _chunkBPX4Z3N3cjs.chartTreeTotal.call(void 0, n), 0);
2317
2349
  let at = start;
2318
2350
  nodes.forEach((node, k) => {
2319
- const value = _chunkUVXTOZ2Bcjs.chartTreeTotal.call(void 0, node);
2351
+ const value = _chunkBPX4Z3N3cjs.chartTreeTotal.call(void 0, node);
2320
2352
  if (!(value > 0) || !sum) return;
2321
2353
  const a0 = at;
2322
2354
  const a1 = at + sweep * value / sum;
@@ -2388,7 +2420,7 @@ function layoutSankey(ctx, area, series) {
2388
2420
  y += value[i] * ky + pad;
2389
2421
  }
2390
2422
  }
2391
- const color = (i) => _optionalChain([series, 'optionalAccess', _61 => _61.pointColors, 'optionalAccess', _62 => _62[i]]) || _chunkUVXTOZ2Bcjs.chartSliceColor.call(void 0, spec, i);
2423
+ const color = (i) => _optionalChain([series, 'optionalAccess', _61 => _61.pointColors, 'optionalAccess', _62 => _62[i]]) || _chunkBPX4Z3N3cjs.chartSliceColor.call(void 0, spec, i);
2392
2424
  const named = new Set(spec.highlight);
2393
2425
  const lit = nodes.map((n) => named.has(n));
2394
2426
  const dimLinks = lit.some(Boolean);
@@ -2441,17 +2473,56 @@ function layoutSankey(ctx, area, series) {
2441
2473
  if (hidden) ctx.warn("labels-truncated", `${hidden} node label${hidden === 1 ? " was" : "s were"} shortened to fit between the columns.`);
2442
2474
  return { plot: area };
2443
2475
  }
2476
+ function layoutBarRace(ctx, area, frame) {
2477
+ const { spec, theme, marks, fs, measure } = ctx;
2478
+ const top = spec.raceTopN;
2479
+ const moment = chartRaceMoment(spec.categories.length, frame);
2480
+ const ranking = chartRaceRanking(spec, frame);
2481
+ const shown = ranking.filter((e) => e.position < top);
2482
+ const labelW = Math.min(area.width * 0.3, Math.max(0, ...ranking.map((e) => measure(e.name, fs)))) + 8;
2483
+ const tickH = spec.yAxis.show ? fs * 1.6 : 4;
2484
+ const plot = { x: area.x + labelW, y: area.y + tickH, width: Math.max(1, area.width - labelW - fs * 4), height: Math.max(1, area.height - tickH) };
2485
+ const lead = Math.max(1e-9, ...shown.map((e) => e.value));
2486
+ const max = spec.yAxis.max !== null && spec.yAxis.max > 0 ? spec.yAxis.max : lead * 1.08;
2487
+ const xOf = (v) => plot.x + Math.max(0, Math.min(max, v)) / max * plot.width;
2488
+ const ticks = niceScale(0, max, 5).ticks.filter((t) => t <= max);
2489
+ const axisTarget = { kind: "axis", axis: "y" };
2490
+ const format = spec.yAxis.format;
2491
+ ticks.forEach((t, k) => {
2492
+ if (spec.yAxis.gridlines) marks.push({ kind: "line", key: `grid-y-${k}`, role: "grid", x1: xOf(t), y1: plot.y, x2: xOf(t), y2: plot.y + plot.height, stroke: theme.grid, strokeWidth: 1 });
2493
+ if (spec.yAxis.show) marks.push({ kind: "text", key: `tick-y-${k}`, role: "tick-label", x: xOf(t), y: area.y, text: formatChartNumber(t, format, _nullishCoalesce(format.decimals, () => ( stepDecimals(ticks[1] - ticks[0] || 1)))), anchor: "middle", baseline: "top", size: fs - 1, fill: theme.mutedText, target: axisTarget });
2494
+ });
2495
+ const label = _nullishCoalesce(spec.categories[moment.t < 0.5 ? moment.from : moment.to], () => ( ""));
2496
+ const timeSize = Math.min(theme.titleSize * 3, plot.height * 0.2, plot.width * 0.5 / Math.max(1, label.length * 0.6));
2497
+ marks.push({ kind: "text", key: "race-time", role: "race-time", x: plot.x + plot.width, y: plot.y + plot.height - 4, text: label, anchor: "end", baseline: "bottom", size: timeSize, weight: 700, fill: theme.mutedText, opacity: 0.55, target: { kind: "category", index: moment.t < 0.5 ? moment.from : moment.to } });
2498
+ const band = plot.height / top;
2499
+ const barH = Math.max(2, band * (1 - Math.min(0.8, spec.gapWidth)));
2500
+ const index = Math.round(moment.at);
2501
+ for (const e of shown) {
2502
+ const si = spec.series.findIndex((s2) => s2.id === e.seriesId);
2503
+ const s = spec.series[si];
2504
+ const y = plot.y + e.position * band + (band - barH) / 2;
2505
+ const target = { kind: "point", seriesId: e.seriesId, index };
2506
+ const selected = ctx.isSelected(target) || ctx.seriesSelected(e.seriesId);
2507
+ const width = Math.max(0, xOf(e.value) - plot.x);
2508
+ marks.push({ kind: "rect", key: `bar-${e.seriesId}`, role: "bar", x: plot.x, y, width, height: barH, fill: _chunkBPX4Z3N3cjs.chartSeriesColor.call(void 0, spec, si), radius: Math.min(3, barH / 4), target, selected, ...selected ? { stroke: theme.selection, strokeWidth: 1.5 } : {} });
2509
+ marks.push({ kind: "text", key: `label-name-${e.seriesId}`, role: "tick-label", x: plot.x - 6, y: y + barH / 2, text: truncate(e.name, labelW - 8, fs, measure), anchor: "end", baseline: "middle", size: fs, fill: selected ? theme.selection : theme.text, target: { kind: "series", seriesId: e.seriesId } });
2510
+ if (_nullishCoalesce(s.dataLabels, () => ( true))) marks.push({ kind: "text", key: `label-${e.seriesId}`, role: "data-label", x: plot.x + width + 5, y: y + barH / 2, text: formatChartNumber(e.value, _nullishCoalesce(s.format, () => ( format)), _nullishCoalesce((_nullishCoalesce(s.format, () => ( format))).decimals, () => ( (Math.abs(e.value) >= 100 ? 0 : void 0)))), anchor: "start", baseline: "middle", size: fs - 1, fill: theme.text, target });
2511
+ }
2512
+ if (ranking.length > top) ctx.warn("values-skipped", `The race shows the top ${top} of ${ranking.length} names at each moment (raceTopN).`);
2513
+ return { plot, valueScale: { axis: "x", domain: [0, max], range: [plot.x, plot.x + plot.width], ticks } };
2514
+ }
2444
2515
 
2445
2516
  // src/chart/layout.ts
2446
2517
  function legendItems(spec, ctx) {
2447
- const family = _chunkUVXTOZ2Bcjs.chartFamily.call(void 0, spec);
2448
- if (spec.type === "funnel" || spec.type === "slope" || spec.type === "sankey") return [];
2449
- if (_chunkUVXTOZ2Bcjs.chartSpecColorsByCategory.call(void 0, spec)) {
2518
+ const family = _chunkBPX4Z3N3cjs.chartFamily.call(void 0, spec);
2519
+ if (spec.type === "funnel" || spec.type === "slope" || spec.type === "sankey" || spec.type === "barrace") return [];
2520
+ if (_chunkBPX4Z3N3cjs.chartSpecColorsByCategory.call(void 0, spec)) {
2450
2521
  const first = spec.series.find((s) => !s.hidden);
2451
2522
  const seats = (i) => Math.max(0, Math.round(_nullishCoalesce(_optionalChain([first, 'optionalAccess', _66 => _66.values, 'access', _67 => _67[i]]), () => ( 0))));
2452
2523
  return spec.categories.map((c, i) => ({
2453
2524
  label: spec.type === "parliament" ? `${c} ${seats(i)}` : c,
2454
- color: _optionalChain([first, 'optionalAccess', _68 => _68.pointColors, 'optionalAccess', _69 => _69[i]]) || _chunkUVXTOZ2Bcjs.chartSliceColor.call(void 0, spec, i),
2525
+ color: _optionalChain([first, 'optionalAccess', _68 => _68.pointColors, 'optionalAccess', _69 => _69[i]]) || _chunkBPX4Z3N3cjs.chartSliceColor.call(void 0, spec, i),
2455
2526
  target: { kind: "category", index: i },
2456
2527
  faded: false,
2457
2528
  selected: ctx.isSelected({ kind: "category", index: i }),
@@ -2465,17 +2536,17 @@ function legendItems(spec, ctx) {
2465
2536
  return [
2466
2537
  { label: "Increase", color: ctx.theme.positive, target, faded: false, selected: false, shape: "square" },
2467
2538
  { label: "Decrease", color: ctx.theme.negative, target, faded: false, selected: false, shape: "square" },
2468
- { label: "Total", color: _chunkUVXTOZ2Bcjs.chartSeriesColor.call(void 0, spec, spec.series.indexOf(first)), target, faded: false, selected: false, shape: "square" }
2539
+ { label: "Total", color: _chunkBPX4Z3N3cjs.chartSeriesColor.call(void 0, spec, spec.series.indexOf(first)), target, faded: false, selected: false, shape: "square" }
2469
2540
  ];
2470
2541
  }
2471
2542
  if (family === "box") return [];
2472
- const trends = trendlineLegendItems(spec, (i) => _chunkUVXTOZ2Bcjs.chartSeriesColor.call(void 0, spec, i));
2543
+ const trends = trendlineLegendItems(spec, (i) => _chunkBPX4Z3N3cjs.chartSeriesColor.call(void 0, spec, i));
2473
2544
  const items = [];
2474
2545
  spec.series.forEach((s, i) => {
2475
- const type = _chunkUVXTOZ2Bcjs.chartSeriesType.call(void 0, spec, s);
2546
+ const type = _chunkBPX4Z3N3cjs.chartSeriesType.call(void 0, spec, s);
2476
2547
  items.push({
2477
2548
  label: s.name,
2478
- color: _chunkUVXTOZ2Bcjs.chartSeriesColor.call(void 0, spec, i),
2549
+ color: _chunkBPX4Z3N3cjs.chartSeriesColor.call(void 0, spec, i),
2479
2550
  target: { kind: "series", seriesId: s.id },
2480
2551
  faded: !!s.hidden,
2481
2552
  selected: ctx.seriesSelected(s.id),
@@ -2488,7 +2559,7 @@ function legendItems(spec, ctx) {
2488
2559
  function layoutChart(spec, options) {
2489
2560
  const width = Math.max(1, Number.isFinite(options.width) ? options.width : 1);
2490
2561
  const height = Math.max(1, Number.isFinite(options.height) ? options.height : 1);
2491
- const theme = { ..._chunkUVXTOZ2Bcjs.DEFAULT_CHART_THEME, ...options.theme };
2562
+ const theme = { ..._chunkBPX4Z3N3cjs.DEFAULT_CHART_THEME, ...options.theme };
2492
2563
  const selection = _nullishCoalesce(options.selection, () => ( null));
2493
2564
  const marks = [];
2494
2565
  const warnings = [];
@@ -2527,17 +2598,17 @@ function layoutChart(spec, options) {
2527
2598
  if (spec.title) titleMark("title", spec.title, theme.titleSize, 600, theme.text);
2528
2599
  if (spec.subtitle) titleMark("subtitle", spec.subtitle, fs + 1, 400, theme.mutedText);
2529
2600
  if (spec.title || spec.subtitle) top += 6;
2530
- const family = _chunkUVXTOZ2Bcjs.chartFamily.call(void 0, spec);
2601
+ const family = _chunkBPX4Z3N3cjs.chartFamily.call(void 0, spec);
2531
2602
  const visible = spec.series.filter((s) => !s.hidden);
2532
2603
  const items = legendItems(spec, ctx);
2533
2604
  let area = { x: pad, y: top, width: width - pad * 2, height: height - top - pad - noteHeight(spec, fs) };
2534
2605
  const seriesLegend = family === "cartesian" || family === "xy" || family === "radar" || family === "histogram";
2535
2606
  const hasTrend = items.some((i) => i.shape === "dash");
2536
- const showLegend = spec.legend.show && items.length > 0 && (!seriesLegend || _chunkUVXTOZ2Bcjs.chartVariesColors.call(void 0, spec) || spec.series.length > 1 || spec.series.some((s) => s.hidden) || hasTrend);
2607
+ const showLegend = spec.legend.show && items.length > 0 && (!seriesLegend || _chunkBPX4Z3N3cjs.chartVariesColors.call(void 0, spec) || spec.series.length > 1 || spec.series.some((s) => s.hidden) || hasTrend);
2537
2608
  if (showLegend) area = layoutLegend(items, spec.legend.position, area, ctx, ctx.isSelected({ kind: "legend" }));
2538
2609
  const finish = (result) => {
2539
2610
  if (result.plot.width > 0) {
2540
- if (chartAnnotationFamily(_chunkUVXTOZ2Bcjs.chartFamily.call(void 0, spec))) drawCallouts(ctx, result.plot);
2611
+ if (chartAnnotationFamily(_chunkBPX4Z3N3cjs.chartFamily.call(void 0, spec))) drawCallouts(ctx, result.plot);
2541
2612
  else if (spec.referenceLines.length || spec.referenceBands.length || spec.series.some((s) => s.callouts))
2542
2613
  ctx.warn("annotations-skipped", `Reference lines, bands and callouts are drawn on bar, line, area, scatter and bubble charts; this ${spec.type} chart leaves them out.`);
2543
2614
  }
@@ -2585,6 +2656,8 @@ function layoutChart(spec, options) {
2585
2656
  return finish(layoutFunnel(ctx, area, visible[0]));
2586
2657
  case "treemap":
2587
2658
  return finish(spec.tree.length ? layoutTreemapTree(ctx, area, spec.series[0]) : layoutTreemap(ctx, area, visible[0]));
2659
+ case "barrace":
2660
+ return finish(layoutBarRace(ctx, area, options.raceFrame));
2588
2661
  case "sankey":
2589
2662
  if (!spec.links.length) {
2590
2663
  ctx.warn("type-fallback", "A Sankey diagram needs flows (set_chart_links); it is drawn as a bar chart until then.");
@@ -2701,7 +2774,7 @@ function addReadout(ctx, readout, plot) {
2701
2774
  } else return;
2702
2775
  const axis = series.axis === "secondary" ? spec.yAxis2 : spec.yAxis;
2703
2776
  const x = _optionalChain([series, 'access', _75 => _75.x, 'optionalAccess', _76 => _76[readout.index]]);
2704
- const text = x !== null && x !== void 0 && _chunkUVXTOZ2Bcjs.chartFamily.call(void 0, spec) === "xy" ? `${formatChartNumber(x, spec.xAxis.format)}, ${formatChartNumber(value, axis.format)}` : `${_nullishCoalesce(spec.categories[readout.index], () => ( ""))}: ${formatChartNumber(value, _nullishCoalesce(series.format, () => ( axis.format)))}`;
2777
+ const text = x !== null && x !== void 0 && _chunkBPX4Z3N3cjs.chartFamily.call(void 0, spec) === "xy" ? `${formatChartNumber(x, spec.xAxis.format)}, ${formatChartNumber(value, axis.format)}` : `${_nullishCoalesce(spec.categories[readout.index], () => ( ""))}: ${formatChartNumber(value, _nullishCoalesce(series.format, () => ( axis.format)))}`;
2705
2778
  const w = measure(text, fs, 600) + 10;
2706
2779
  const h = fs + 8;
2707
2780
  const bx = Math.max(plot.x, Math.min(plot.x + plot.width - w, ax - w / 2));
@@ -2798,4 +2871,7 @@ function snapChartValue(scene, value, step, ticks = _nullishCoalesce(_optionalCh
2798
2871
 
2799
2872
 
2800
2873
 
2801
- exports.parseChartDate = parseChartDate; exports.CHART_DATE_STEPS = CHART_DATE_STEPS; exports.formatChartDate = formatChartDate; exports.chartDateLabels = chartDateLabels; exports.compileChartFormatCode = compileChartFormatCode; exports.formatChartValueWithCode = formatChartValueWithCode; exports.chartSerialToDate = chartSerialToDate; exports.chartDateToSerial = chartDateToSerial; exports.niceStep = niceStep; exports.niceScale = niceScale; exports.stepDecimals = stepDecimals; exports.formatChartNumber = formatChartNumber; exports.linearMap = linearMap; exports.niceLogScale = niceLogScale; exports.chartScaleToPixel = chartScaleToPixel; exports.chartScaleFromPixel = chartScaleFromPixel; exports.estimateChartTextWidth = estimateChartTextWidth; exports.sameChartSelection = sameChartSelection; exports.contrastingTextColor = contrastingTextColor; exports.r2 = r2; exports.chartHistogram = chartHistogram; exports.chartQuantile = chartQuantile; exports.suggestChartReferences = suggestChartReferences; exports.chartBoxStats = chartBoxStats; exports.chartSquarify = chartSquarify; exports.decimateChartPoints = decimateChartPoints; exports.summarizeChartSeries = summarizeChartSeries; exports.fitChartTrendline = fitChartTrendline; exports.trendNumberText = trendNumberText; exports.chartMovingAverage = chartMovingAverage; exports.chartTrendlineName = chartTrendlineName; exports.chartSupportsTrendlines = chartSupportsTrendlines; exports.MAX_CHART_DATA_LABELS = MAX_CHART_DATA_LABELS; exports.MAX_CHART_LINE_POINTS = MAX_CHART_LINE_POINTS; exports.MAX_CHART_MARKERS = MAX_CHART_MARKERS; exports.layoutChart = layoutChart; exports.chartValueAtPoint = chartValueAtPoint; exports.chartXAtPoint = chartXAtPoint; exports.snapChartValue = snapChartValue;
2874
+
2875
+
2876
+
2877
+ exports.parseChartDate = parseChartDate; exports.CHART_DATE_STEPS = CHART_DATE_STEPS; exports.formatChartDate = formatChartDate; exports.chartDateLabels = chartDateLabels; exports.compileChartFormatCode = compileChartFormatCode; exports.formatChartValueWithCode = formatChartValueWithCode; exports.chartSerialToDate = chartSerialToDate; exports.chartDateToSerial = chartDateToSerial; exports.niceStep = niceStep; exports.niceScale = niceScale; exports.stepDecimals = stepDecimals; exports.formatChartNumber = formatChartNumber; exports.linearMap = linearMap; exports.niceLogScale = niceLogScale; exports.chartScaleToPixel = chartScaleToPixel; exports.chartScaleFromPixel = chartScaleFromPixel; exports.estimateChartTextWidth = estimateChartTextWidth; exports.sameChartSelection = sameChartSelection; exports.contrastingTextColor = contrastingTextColor; exports.r2 = r2; exports.chartHistogram = chartHistogram; exports.chartQuantile = chartQuantile; exports.suggestChartReferences = suggestChartReferences; exports.chartBoxStats = chartBoxStats; exports.chartSquarify = chartSquarify; exports.decimateChartPoints = decimateChartPoints; exports.summarizeChartSeries = summarizeChartSeries; exports.fitChartTrendline = fitChartTrendline; exports.trendNumberText = trendNumberText; exports.chartMovingAverage = chartMovingAverage; exports.chartTrendlineName = chartTrendlineName; exports.chartSupportsTrendlines = chartSupportsTrendlines; exports.MAX_CHART_DATA_LABELS = MAX_CHART_DATA_LABELS; exports.MAX_CHART_LINE_POINTS = MAX_CHART_LINE_POINTS; exports.MAX_CHART_MARKERS = MAX_CHART_MARKERS; exports.chartRaceValueAt = chartRaceValueAt; exports.chartRaceMoment = chartRaceMoment; exports.chartRaceRanking = chartRaceRanking; exports.layoutChart = layoutChart; exports.chartValueAtPoint = chartValueAtPoint; exports.chartXAtPoint = chartXAtPoint; exports.snapChartValue = snapChartValue;