@pixerate/editor 0.162.0 → 0.163.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 (81) hide show
  1. package/README.md +1 -1
  2. package/dist/agent/index.cjs +34 -34
  3. package/dist/agent/index.js +5 -5
  4. package/dist/animation-editor/index.cjs +57 -57
  5. package/dist/animation-editor/index.js +3 -3
  6. package/dist/{brushstrokeRender-Q4LI22QV.js → brushstrokeRender-7LXCU7PD.js} +2 -2
  7. package/dist/{brushstrokeRender-5WANQIG4.cjs → brushstrokeRender-VO4ZTWVA.cjs} +5 -5
  8. package/dist/canvas/index.cjs +14 -14
  9. package/dist/canvas/index.js +3 -3
  10. package/dist/chart/commands.d.cts +2 -1
  11. package/dist/chart/commands.d.ts +2 -1
  12. package/dist/chart/controller.d.cts +109 -1
  13. package/dist/chart/controller.d.ts +109 -1
  14. package/dist/chart/index.cjs +605 -130
  15. package/dist/chart/index.d.cts +1 -0
  16. package/dist/chart/index.d.ts +1 -0
  17. package/dist/chart/index.js +490 -15
  18. package/dist/chart/layout-annotations.d.cts +29 -0
  19. package/dist/chart/layout-annotations.d.ts +29 -0
  20. package/dist/chart/layout-families.d.cts +23 -0
  21. package/dist/chart/layout-families.d.ts +23 -0
  22. package/dist/chart/mermaid.d.cts +2 -1
  23. package/dist/chart/mermaid.d.ts +2 -1
  24. package/dist/chart/schemas.d.cts +13 -0
  25. package/dist/chart/schemas.d.ts +13 -0
  26. package/dist/chart/spec.d.cts +30 -5
  27. package/dist/chart/spec.d.ts +30 -5
  28. package/dist/chart/stats.d.cts +9 -1
  29. package/dist/chart/stats.d.ts +9 -1
  30. package/dist/chart/tools.d.cts +1 -1
  31. package/dist/chart/tools.d.ts +1 -1
  32. package/dist/chart/tree.d.cts +62 -0
  33. package/dist/chart/tree.d.ts +62 -0
  34. package/dist/chart/types.d.cts +77 -3
  35. package/dist/chart/types.d.ts +77 -3
  36. package/dist/{chunk-7YBDRJXT.cjs → chunk-22KLZZGH.cjs} +8 -8
  37. package/dist/{chunk-LQLZHP6F.js → chunk-36OKQDCF.js} +7 -4
  38. package/dist/{chunk-HLOKB7WW.js → chunk-3NEZJCBY.js} +366 -6
  39. package/dist/{chunk-GWV4T5NZ.js → chunk-3VLOOO3G.js} +1 -1
  40. package/dist/{chunk-3GJH2MGH.cjs → chunk-5AARIS3R.cjs} +35 -35
  41. package/dist/{chunk-EVPZ5IKN.js → chunk-5FNGLV2D.js} +65 -3
  42. package/dist/{chunk-EQ46F75O.cjs → chunk-D54JHQK2.cjs} +51 -51
  43. package/dist/{chunk-NO5QQDHZ.js → chunk-DAPQGA55.js} +2 -2
  44. package/dist/{chunk-3IHNXRUV.cjs → chunk-GKNEJ6EN.cjs} +399 -67
  45. package/dist/{chunk-236TKNUR.cjs → chunk-JCXMJUQO.cjs} +2 -2
  46. package/dist/{chunk-4NGVHHJB.cjs → chunk-NZD2MZJC.cjs} +80 -18
  47. package/dist/{chunk-CX6JLDFC.js → chunk-OXERWBKE.js} +3 -3
  48. package/dist/{chunk-32MMQYCQ.cjs → chunk-PA3IMPPS.cjs} +81 -81
  49. package/dist/{chunk-7CKPUUN4.js → chunk-POR54B55.js} +61 -10
  50. package/dist/{chunk-KGTF55R3.js → chunk-QY4KUDMY.js} +1 -1
  51. package/dist/{chunk-LL3H5XUH.cjs → chunk-R3P2M7HU.cjs} +367 -7
  52. package/dist/{chunk-HDGBM7EA.cjs → chunk-SBQVEBSU.cjs} +580 -53
  53. package/dist/{chunk-2TKHLX6H.js → chunk-SET6KJOP.js} +1 -1
  54. package/dist/{chunk-XDCFJEU7.js → chunk-SZA42R4N.js} +346 -14
  55. package/dist/{chunk-GLMP22FT.js → chunk-TALQONZ5.js} +3 -3
  56. package/dist/{chunk-GNK7SESQ.cjs → chunk-V7GWZIZK.cjs} +7 -4
  57. package/dist/{chunk-EYVVIZJ3.cjs → chunk-WTW7QRTS.cjs} +1 -1
  58. package/dist/{chunk-NA4UVVJ4.cjs → chunk-YGG7WDWT.cjs} +76 -25
  59. package/dist/{chunk-JGKCC5OF.cjs → chunk-YQ5C5BVK.cjs} +10 -9
  60. package/dist/{chunk-EY22AY6R.cjs → chunk-YSAGBIRW.cjs} +16 -16
  61. package/dist/{chunk-A5UCR2TO.js → chunk-YXKLVD56.js} +10 -9
  62. package/dist/{chunk-DTSTNRPH.js → chunk-Z4P2RBMJ.js} +536 -9
  63. package/dist/{chunk-45XXVHVG.js → chunk-ZZGPYNS2.js} +1 -1
  64. package/dist/export/index.cjs +4 -4
  65. package/dist/export/index.js +3 -3
  66. package/dist/extensions/index.cjs +7 -7
  67. package/dist/extensions/index.js +6 -6
  68. package/dist/image-editor/index.cjs +638 -638
  69. package/dist/image-editor/index.js +4 -4
  70. package/dist/index.cjs +13 -13
  71. package/dist/index.js +7 -7
  72. package/dist/paint/index.cjs +2 -2
  73. package/dist/paint/index.js +1 -1
  74. package/dist/paint-editor/index.cjs +129 -149
  75. package/dist/paint-editor/index.js +5 -25
  76. package/dist/vector/index.cjs +948 -948
  77. package/dist/vector/index.js +3 -3
  78. package/package.json +3 -3
  79. package/skills/pixerate-canvas/SKILL.md +16 -0
  80. package/skills/pixerate-chart/SKILL.md +92 -9
  81. package/skills/pixerate-paint-editor/SKILL.md +0 -2
@@ -2,11 +2,13 @@ import {
2
2
  chartFamily,
3
3
  chartRgbToHex,
4
4
  chartSeriesType,
5
+ chartTreeFromRows,
6
+ chartVariesColors,
5
7
  defaultChartAxis,
6
8
  isCartesianChart,
7
9
  normalizeChartSpec,
8
10
  parseChartColor
9
- } from "./chunk-HLOKB7WW.js";
11
+ } from "./chunk-3NEZJCBY.js";
10
12
 
11
13
  // src/chart/ooxml.ts
12
14
  var CHART_OOXML_NS = "http://schemas.openxmlformats.org/drawingml/2006/chart";
@@ -295,7 +297,7 @@ function chartFromOoxml(xml, options = {}) {
295
297
  input.orientation = orientation;
296
298
  input.dataLabels = dataLabels;
297
299
  input.points = points || first !== "line";
298
- if (bool(val(groups[0], "varyColors")) && (first === "bar" || first === "line") && series.length === 1) unsupported.push("one colour per point (vary colours)");
300
+ if (bool(val(groups[0], "varyColors")) && !combo && isCartesianChart(first) && series.length === 1) input.varyColors = true;
299
301
  const readAxis = (a, fallback) => {
300
302
  const axis = { ...fallback, format: {} };
301
303
  if (!a) return axis;
@@ -340,6 +342,29 @@ function readChartex(root, issues, unsupported) {
340
342
  const numDim = kids(d, "numDim")[0];
341
343
  const lvl = (dim) => kids(dim, "lvl")[0];
342
344
  const cats = kids(lvl(strDim), "pt").map((p) => p.textContent ?? "");
345
+ const levels = kids(strDim, "lvl").map((l) => {
346
+ const out = [];
347
+ for (const p of kids(l, "pt")) out[Number(p.getAttribute("idx") ?? out.length)] = (p.textContent ?? "").trim();
348
+ return out;
349
+ });
350
+ let paths;
351
+ if (levels.length > 1) {
352
+ const carried = [];
353
+ paths = levels[0].map((_, i) => {
354
+ const path2 = [];
355
+ for (let k = levels.length - 1; k >= 1; k--) {
356
+ const name = levels[k][i];
357
+ if (name) {
358
+ carried[k] = name;
359
+ carried.length = Math.max(carried.length, k + 1);
360
+ for (let j = 1; j < k; j++) carried[j] = "";
361
+ }
362
+ if (carried[k]) path2.push(carried[k]);
363
+ }
364
+ if (levels[0][i]) path2.push(levels[0][i]);
365
+ return path2;
366
+ });
367
+ }
343
368
  const values = [];
344
369
  const nl = lvl(numDim);
345
370
  for (const p of kids(nl, "pt")) {
@@ -347,19 +372,18 @@ function readChartex(root, issues, unsupported) {
347
372
  while (values.length < i) values.push(null);
348
373
  values[i] = numberOf((p.textContent ?? "").trim());
349
374
  }
350
- data.set(id, { categories: cats, values, code: nl?.getAttribute("formatCode") ?? void 0 });
375
+ data.set(id, { categories: cats, values, code: nl?.getAttribute("formatCode") ?? void 0, paths });
351
376
  }
352
377
  const chart = kid(root, "chart");
353
378
  const region = path(chart, "plotArea", "plotAreaRegion");
354
379
  const seriesEls = kids(region, "series");
355
- const layouts = { waterfall: "waterfall", funnel: "funnel", treemap: "treemap", sunburst: "treemap", boxWhisker: "box", clusteredColumn: "histogram", paretoLine: "histogram" };
380
+ const layouts = { waterfall: "waterfall", funnel: "funnel", treemap: "treemap", sunburst: "sunburst", boxWhisker: "box", clusteredColumn: "histogram", paretoLine: "histogram" };
356
381
  const layout = seriesEls[0]?.getAttribute("layoutId") ?? "";
357
382
  const type = layouts[layout];
358
383
  if (!type) {
359
384
  issues.push({ path: "plotArea", message: `The chart layout "${layout || "unknown"}" is not supported.` });
360
385
  return { spec: normalizeChartSpec({}).spec, issues, unsupported: [layout || "unknown chartex layout"], lossless: false };
361
386
  }
362
- if (layout === "sunburst") unsupported.push("sunburst (drawn as a treemap of the innermost level)");
363
387
  if (layout === "paretoLine") unsupported.push("pareto line");
364
388
  const series = [];
365
389
  let categories = [];
@@ -382,6 +406,12 @@ function readChartex(root, issues, unsupported) {
382
406
  categories: categories.length >= longest ? categories : Array.from({ length: longest }, (_, i) => categories[i] ?? `${i + 1}`)
383
407
  };
384
408
  if (type === "waterfall") input.showTotal = false;
409
+ const first = data.get(kid(seriesEls[0], "dataId")?.getAttribute("val") ?? "0");
410
+ if ((type === "treemap" || type === "sunburst") && first?.paths) {
411
+ const treeIssues = [];
412
+ input.tree = chartTreeFromRows(first.paths.map((path2, i) => ({ path: path2, value: first.values[i] ?? 0 })), treeIssues);
413
+ for (const t of treeIssues) issues.push({ path: "chartData", message: t.message });
414
+ }
385
415
  const { spec, issues: specIssues } = normalizeChartSpec(input);
386
416
  issues.push(...specIssues);
387
417
  return { spec, issues, unsupported, lossless: unsupported.length === 0 && specIssues.length === 0 };
@@ -440,10 +470,30 @@ function chartToOoxml(spec) {
440
470
  issues.push(`${spec.type} charts are written as bar charts: DrawingML has no ${spec.type} type (Office 2016 stores it as chartex).`);
441
471
  type = "bar";
442
472
  } else if (family === "treemap") {
443
- issues.push("Treemaps are written as pie charts: DrawingML has no treemap type.");
473
+ issues.push(`Treemaps are written as pie charts${spec.tree.length ? " of the top-level group totals" : ""}: DrawingML has no treemap type.`);
444
474
  type = "pie";
475
+ } else if (family === "sunburst") {
476
+ issues.push(`Sunburst charts are written as doughnut charts of the ${spec.tree.length ? "top-level group totals" : "values"}: DrawingML has no sunburst type (Office 2016 stores it as chartex).`);
477
+ type = "donut";
478
+ } else if (family === "parliament") {
479
+ issues.push("Parliament charts are written as doughnut charts of the seats: DrawingML has no parliament type.");
480
+ type = "donut";
481
+ } else if (family === "slope") {
482
+ issues.push("Slope charts are written as line charts with the two series as lines over the categories: DrawingML has no slope type.");
483
+ type = "line";
484
+ } else if (family === "likert") {
485
+ issues.push("Likert charts are written as 100% stacked horizontal bars: DrawingML has no diverging bar.");
486
+ spec = { ...spec, type: "bar", stacking: "percent", orientation: "horizontal" };
487
+ type = "bar";
445
488
  }
446
489
  const visible = spec.series.filter((s) => !s.hidden);
490
+ const annotations = [
491
+ spec.referenceLines.length || spec.referenceBands.length ? "reference lines and bands" : "",
492
+ spec.series.some((s) => s.callouts) ? "callouts" : "",
493
+ spec.highlight.length ? "the highlight" : "",
494
+ spec.note ? "the note" : ""
495
+ ].filter(Boolean);
496
+ if (annotations.length) issues.push(`${annotations.join(", ").replace(/^./, (c) => c.toUpperCase())} ${annotations.length === 1 && !annotations[0].endsWith("s") ? "is" : "are"} not written: DrawingML has no equivalent.`);
447
497
  if (visible.length < spec.series.length) issues.push(`${spec.series.length - visible.length} hidden series ${spec.series.length - visible.length === 1 ? "is" : "are"} left out.`);
448
498
  const grouping = spec.stacking === "stacked" ? "stacked" : spec.stacking === "percent" ? "percentStacked" : "standard";
449
499
  const ids = { cat: 500000001, val: 500000002, cat2: 500000003, val2: 500000004 };
@@ -512,6 +562,7 @@ function chartToOoxml(spec) {
512
562
  return `<c:ser>${parts.join("")}</c:ser>`;
513
563
  };
514
564
  const dLbls = `<c:dLbls><c:showLegendKey val="0"/><c:showVal val="${spec.dataLabels ? 1 : 0}"/><c:showCatName val="0"/><c:showSerName val="0"/><c:showPercent val="0"/><c:showBubbleSize val="0"/></c:dLbls>`;
565
+ const vary = chartVariesColors(spec) ? 1 : 0;
515
566
  const groupXml = groups.map((g) => {
516
567
  const axes2 = g.secondary ? `<c:axId val="${ids.cat2}"/><c:axId val="${ids.val2}"/>` : `<c:axId val="${ids.cat}"/><c:axId val="${ids.val}"/>`;
517
568
  const sers = g.series.map(({ s, index }) => serXml(g.kind, s, index)).join("");
@@ -521,14 +572,14 @@ function chartToOoxml(spec) {
521
572
  const barsWidth = spec.stacking === "none" ? n - (n - 1) * spec.overlap : 1;
522
573
  const gapPct = Math.round(Math.min(500, spec.gapWidth / Math.max(0.01, 1 - spec.gapWidth) * barsWidth * 100));
523
574
  const overlapPct = spec.stacking === "none" ? Math.round(spec.overlap * 100) : 100;
524
- return `<c:barChart><c:barDir val="${spec.orientation === "horizontal" ? "bar" : "col"}"/><c:grouping val="${spec.stacking === "none" ? "clustered" : grouping}"/><c:varyColors val="0"/>${sers}${dLbls}<c:gapWidth val="${gapPct}"/><c:overlap val="${overlapPct}"/>${axes2}</c:barChart>`;
575
+ return `<c:barChart><c:barDir val="${spec.orientation === "horizontal" ? "bar" : "col"}"/><c:grouping val="${spec.stacking === "none" ? "clustered" : grouping}"/><c:varyColors val="${vary}"/>${sers}${dLbls}<c:gapWidth val="${gapPct}"/><c:overlap val="${overlapPct}"/>${axes2}</c:barChart>`;
525
576
  }
526
577
  case "line":
527
- return `<c:lineChart><c:grouping val="${spec.stacking === "none" ? "standard" : "standard"}"/><c:varyColors val="0"/>${sers}${dLbls}<c:marker val="1"/>${axes2}</c:lineChart>`;
578
+ return `<c:lineChart><c:grouping val="${spec.stacking === "none" ? "standard" : "standard"}"/><c:varyColors val="${vary}"/>${sers}${dLbls}<c:marker val="1"/>${axes2}</c:lineChart>`;
528
579
  case "area":
529
- return `<c:areaChart><c:grouping val="${grouping}"/><c:varyColors val="0"/>${sers}${dLbls}${axes2}</c:areaChart>`;
580
+ return `<c:areaChart><c:grouping val="${grouping}"/><c:varyColors val="${vary}"/>${sers}${dLbls}${axes2}</c:areaChart>`;
530
581
  case "scatter":
531
- return `<c:scatterChart><c:scatterStyle val="lineMarker"/><c:varyColors val="0"/>${sers}${dLbls}${axes2}</c:scatterChart>`;
582
+ return `<c:scatterChart><c:scatterStyle val="lineMarker"/><c:varyColors val="${vary}"/>${sers}${dLbls}${axes2}</c:scatterChart>`;
532
583
  case "bubble":
533
584
  return `<c:bubbleChart><c:varyColors val="0"/>${sers}${dLbls}<c:bubbleScale val="100"/>${axes2}</c:bubbleChart>`;
534
585
  case "radar":
@@ -18,7 +18,7 @@ import {
18
18
  unionBounds,
19
19
  vectorGradientPoints,
20
20
  widthProfileAt
21
- } from "./chunk-2TKHLX6H.js";
21
+ } from "./chunk-SET6KJOP.js";
22
22
  import {
23
23
  segmentLength,
24
24
  segmentParamAtLength,
@@ -224,7 +224,7 @@ function parseChartAmountList(text2) {
224
224
  }
225
225
 
226
226
  // src/chart/spec.ts
227
- var CHART_TYPES = ["bar", "line", "area", "scatter", "bubble", "pie", "donut", "radar", "waterfall", "histogram", "box", "funnel", "treemap"];
227
+ var CHART_TYPES = ["bar", "line", "area", "scatter", "bubble", "pie", "donut", "radar", "waterfall", "histogram", "box", "funnel", "treemap", "sunburst", "slope", "likert", "parliament"];
228
228
  var CHART_MARKERS = ["circle", "square", "diamond", "triangle", "cross", "none"];
229
229
  var CHART_TRENDLINE_TYPES = ["linear", "exponential", "logarithmic", "power", "polynomial", "moving-average"];
230
230
  var CHART_LABEL_POSITIONS = ["auto", "inside", "outside", "center"];
@@ -234,6 +234,9 @@ var CHART_SERIES_TYPES = ["bar", "line", "area", "scatter"];
234
234
  var CHART_STACKINGS = ["none", "stacked", "percent"];
235
235
  var CHART_CURVES = ["linear", "smooth", "step"];
236
236
  var CHART_RADAR_GRATICULES = ["polygon", "circle"];
237
+ var CHART_LIKERT_NEUTRALS = ["split", "separate"];
238
+ var CHART_LIKERT_SORTS = ["none", "positive", "negative"];
239
+ var CHART_REFERENCE_AXES = ["y", "y2", "x"];
237
240
  var CHART_ORIENTATIONS = ["vertical", "horizontal"];
238
241
  var CHART_LEGEND_POSITIONS = ["top", "bottom", "left", "right"];
239
242
  var CHART_NUMBER_STYLES = ["number", "percent", "currency", "compact"];
@@ -250,7 +253,11 @@ var CHART_TYPE_LABELS = {
250
253
  histogram: "Histogram",
251
254
  box: "Box plot",
252
255
  funnel: "Funnel",
253
- treemap: "Treemap"
256
+ treemap: "Treemap",
257
+ slope: "Slope",
258
+ likert: "Likert",
259
+ parliament: "Parliament",
260
+ sunburst: "Sunburst"
254
261
  };
255
262
  var DEFAULT_CHART_PALETTE = ["#4269d0", "#efb118", "#ff725c", "#6cc5b0", "#3ca951", "#ff8ab7", "#a463f2", "#97bbf5", "#9c6b4e", "#9498a0"];
256
263
  var DEFAULT_CHART_THEME = {
@@ -297,6 +304,10 @@ function chartFamily(spec) {
297
304
  case "box":
298
305
  case "funnel":
299
306
  case "treemap":
307
+ case "slope":
308
+ case "likert":
309
+ case "parliament":
310
+ case "sunburst":
300
311
  return spec.type;
301
312
  case "bubble":
302
313
  return "xy";
@@ -305,7 +316,10 @@ function chartFamily(spec) {
305
316
  }
306
317
  }
307
318
  function chartColorsByCategory(type) {
308
- return type === "pie" || type === "donut" || type === "funnel" || type === "treemap";
319
+ return type === "pie" || type === "donut" || type === "funnel" || type === "treemap" || type === "slope" || type === "parliament" || type === "sunburst";
320
+ }
321
+ function chartSpecColorsByCategory(spec) {
322
+ return chartColorsByCategory(spec.type) || chartVariesColors(spec);
309
323
  }
310
324
  function defaultChartAxis(value) {
311
325
  return { show: true, title: "", min: null, max: null, step: null, gridlines: value, format: {} };
@@ -316,17 +330,37 @@ function createChartSpec(partial = {}) {
316
330
  function chartSeriesColor(spec, seriesIndex) {
317
331
  const series = spec.series[seriesIndex];
318
332
  if (_optionalChain([series, 'optionalAccess', _10 => _10.color])) return series.color;
333
+ if (spec.type === "likert") return chartLikertColor(spec.series.length, seriesIndex);
319
334
  return cyclePaletteColor(spec.palette.length ? spec.palette : DEFAULT_CHART_PALETTE, seriesIndex);
320
335
  }
336
+ var LIKERT_NEGATIVE = [["#e66101"], ["#e66101", "#fdb863"], ["#b35806", "#f1a340", "#fee0b6"], ["#b35806", "#e08214", "#fdb863", "#fee0b6"]];
337
+ var LIKERT_POSITIVE = [["#5e3c99"], ["#b2abd2", "#5e3c99"], ["#d8daeb", "#998ec3", "#542788"], ["#d8daeb", "#b2abd2", "#8073ac", "#542788"]];
338
+ var LIKERT_NEUTRAL = "#d4d4d8";
339
+ function chartLikertColor(count, index) {
340
+ const side = Math.floor(count / 2);
341
+ if (count % 2 === 1 && index === side) return LIKERT_NEUTRAL;
342
+ if (!side) return LIKERT_POSITIVE[0][0];
343
+ const ramp = (sets) => sets[Math.min(side, sets.length) - 1];
344
+ const pick2 = (list, k) => list[Math.min(list.length - 1, Math.floor(k * list.length / side))];
345
+ if (index < side) return pick2(ramp(LIKERT_NEGATIVE), index);
346
+ return pick2(ramp(LIKERT_POSITIVE), index - (count - side));
347
+ }
321
348
  function chartSliceColor(spec, index) {
322
349
  return cyclePaletteColor(spec.palette.length ? spec.palette : DEFAULT_CHART_PALETTE, index);
323
350
  }
351
+ function chartVariesColors(spec) {
352
+ return !!spec.varyColors && isCartesianChart(spec.type) && spec.series.filter((s) => !s.hidden).length === 1;
353
+ }
324
354
  function chartPointColor(spec, seriesIndex, index) {
325
- return _optionalChain([spec, 'access', _11 => _11.series, 'access', _12 => _12[seriesIndex], 'optionalAccess', _13 => _13.pointColors, 'optionalAccess', _14 => _14[index]]) || chartSeriesColor(spec, seriesIndex);
355
+ const own = _optionalChain([spec, 'access', _11 => _11.series, 'access', _12 => _12[seriesIndex], 'optionalAccess', _13 => _13.pointColors, 'optionalAccess', _14 => _14[index]]);
356
+ if (own) return own;
357
+ if (spec.type && chartVariesColors(spec)) return chartSliceColor(spec, index);
358
+ return chartSeriesColor(spec, seriesIndex);
326
359
  }
327
360
  function chartSeriesType(spec, series) {
328
361
  if (series.type) return series.type;
329
362
  if (spec.type === "bubble") return "scatter";
363
+ if (spec.type === "slope") return "line";
330
364
  return isCartesianChart(spec.type) ? spec.type : "bar";
331
365
  }
332
366
  function uniqueChartSeriesId(series, base = "series") {
@@ -524,6 +558,16 @@ function normalizeSeries(value, length, used, index, issues) {
524
558
  if (colors.some((c) => c !== null)) series.pointColors = colors;
525
559
  }
526
560
  }
561
+ if (value.callouts !== void 0 && value.callouts !== null) {
562
+ if (!Array.isArray(value.callouts)) issues.push({ path: `${path}.callouts`, message: `${path}.callouts must be an array of labels or nulls, one per category.` });
563
+ else {
564
+ const labels = Array.from({ length }, (_, i) => {
565
+ const c = value.callouts[i];
566
+ return typeof c === "string" && c.trim() ? c : typeof c === "number" ? String(c) : null;
567
+ });
568
+ if (labels.some((c) => c !== null)) series.callouts = labels;
569
+ }
570
+ }
527
571
  if (value.marker !== void 0 && value.marker !== null) series.marker = pick(value.marker, CHART_MARKERS, "circle", `${path}.marker`, issues);
528
572
  if (value.curve !== void 0 && value.curve !== null) series.curve = pick(value.curve, CHART_CURVES, "linear", `${path}.curve`, issues);
529
573
  if (value.dataLabels !== void 0 && value.dataLabels !== null) series.dataLabels = flag(value.dataLabels, false, `${path}.dataLabels`, issues);
@@ -546,6 +590,49 @@ function normalizeSeries(value, length, used, index, issues) {
546
590
  return series;
547
591
  }
548
592
  var key = (value, name) => value[name] !== void 0 && value[name] !== null;
593
+ function referenceCommon(value, path, issues) {
594
+ const out = {};
595
+ const label = text(value.label, "", `${path}.label`, issues);
596
+ if (label) out.label = label;
597
+ if (key(value, "axis")) {
598
+ const axis = pick(value.axis, CHART_REFERENCE_AXES, "y", `${path}.axis`, issues);
599
+ if (axis !== "y") out.axis = axis;
600
+ }
601
+ if (typeof value.color === "string" && value.color.trim()) out.color = value.color.trim();
602
+ else if (key(value, "color")) issues.push({ path: `${path}.color`, message: `${path}.color must be a CSS colour.` });
603
+ return out;
604
+ }
605
+ var finiteNumber = (value) => {
606
+ const n = typeof value === "string" && value.trim() ? Number(value) : value;
607
+ return typeof n === "number" && Number.isFinite(n) ? n : null;
608
+ };
609
+ function normalizeChartReferenceLine(value, path, issues = []) {
610
+ if (!isRecord(value)) {
611
+ issues.push({ path, message: `${path} must be an object with a value, e.g. {"value": 100, "label": "Target"}.` });
612
+ return null;
613
+ }
614
+ const at = finiteNumber(value.value);
615
+ if (at === null) {
616
+ issues.push({ path: `${path}.value`, message: `${path}.value must be a number (where the line crosses the axis).` });
617
+ return null;
618
+ }
619
+ for (const k of Object.keys(value)) if (!["value", "label", "axis", "color"].includes(k)) issues.push({ path: `${path}.${k}`, message: `${path} has no "${k}"; it takes value, label, axis and color.` });
620
+ return { value: at, ...referenceCommon(value, path, issues) };
621
+ }
622
+ function normalizeChartReferenceBand(value, path, issues = []) {
623
+ if (!isRecord(value)) {
624
+ issues.push({ path, message: `${path} must be an object with from and to, e.g. {"from": 80, "to": 120, "label": "Target range"}.` });
625
+ return null;
626
+ }
627
+ const from = finiteNumber(value.from);
628
+ const to = finiteNumber(value.to);
629
+ if (from === null || to === null) {
630
+ issues.push({ path, message: `${path} needs numbers for from and to (the ends of the band on its axis).` });
631
+ return null;
632
+ }
633
+ for (const k of Object.keys(value)) if (!["from", "to", "label", "axis", "color"].includes(k)) issues.push({ path: `${path}.${k}`, message: `${path} has no "${k}"; it takes from, to, label, axis and color.` });
634
+ return { from: Math.min(from, to), to: Math.max(from, to), ...referenceCommon(value, path, issues) };
635
+ }
549
636
  function normalizeChartErrorBars(value, length, path, issues = []) {
550
637
  if (!isRecord(value)) {
551
638
  issues.push({ path, message: `${path} must be an object with a type (${CHART_ERROR_BAR_TYPES.join(", ")}), or null for none.` });
@@ -631,8 +718,14 @@ function normalizeChartSpec(input) {
631
718
  const longest = rawSeries.reduce((n, s) => Math.max(n, isRecord(s) && Array.isArray(s.values) ? s.values.length : 0), 0);
632
719
  categories = Array.from({ length: longest }, (_, i) => `${i + 1}`);
633
720
  }
721
+ const tree = normalizeChartTree(value.tree, issues);
722
+ if (tree.length) categories = tree.map((n) => n.name);
634
723
  const used = /* @__PURE__ */ new Set();
635
724
  const series = rawSeries.map((s, i) => normalizeSeries(s, categories.length, used, i, issues)).filter((s) => s !== null);
725
+ if (tree.length) {
726
+ if (!series.length) series.push({ id: uniqueChartSeriesId(series), name: "Values", values: [] });
727
+ series[0] = { ...series[0], values: tree.map(chartTreeTotal) };
728
+ }
636
729
  let palette = [...DEFAULT_CHART_PALETTE];
637
730
  if (Array.isArray(value.palette)) {
638
731
  const colors = value.palette.filter((c) => typeof c === "string" && c.trim() !== "");
@@ -655,6 +748,32 @@ function normalizeChartSpec(input) {
655
748
  if (Number.isInteger(b) && b >= 1 && b <= 500) bins = b;
656
749
  else issues.push({ path: "bins", message: "bins must be a whole number from 1 to 500, or null for automatic." });
657
750
  }
751
+ const highlight = [];
752
+ if (Array.isArray(value.highlight)) {
753
+ for (const h of value.highlight) {
754
+ if (typeof h === "string" || typeof h === "number") {
755
+ const name = String(h);
756
+ if (!highlight.includes(name)) highlight.push(name);
757
+ } else issues.push({ path: "highlight", message: "highlight must list category labels or series names." });
758
+ }
759
+ } else if (value.highlight !== void 0 && value.highlight !== null) issues.push({ path: "highlight", message: "highlight must be an array of category labels or series names." });
760
+ const listOf = (name, read) => {
761
+ const raw = value[name];
762
+ if (raw === void 0 || raw === null) return [];
763
+ if (!Array.isArray(raw)) {
764
+ issues.push({ path: name, message: `${name} must be an array.` });
765
+ return [];
766
+ }
767
+ return raw.map((item, i) => read(item, `${name}[${i}]`, issues)).filter((x) => x !== null);
768
+ };
769
+ const referenceLines = listOf("referenceLines", normalizeChartReferenceLine);
770
+ const referenceBands = listOf("referenceBands", normalizeChartReferenceBand);
771
+ let parliamentMajority = null;
772
+ if (value.parliamentMajority !== void 0 && value.parliamentMajority !== null) {
773
+ const m = Number(value.parliamentMajority);
774
+ if (Number.isInteger(m) && m >= 1) parliamentMajority = m;
775
+ else issues.push({ path: "parliamentMajority", message: "parliamentMajority must be a whole number of seats, 1 or more, or null for half plus one." });
776
+ }
658
777
  let radarTicks = null;
659
778
  if (value.radarTicks !== void 0 && value.radarTicks !== null) {
660
779
  const t = Number(value.radarTicks);
@@ -685,7 +804,19 @@ function normalizeChartSpec(input) {
685
804
  bins,
686
805
  showTotal: flag(value.showTotal, true, "showTotal", issues),
687
806
  radarTicks,
688
- radarGraticule: pick(value.radarGraticule, CHART_RADAR_GRATICULES, "polygon", "radarGraticule", issues)
807
+ radarGraticule: pick(value.radarGraticule, CHART_RADAR_GRATICULES, "polygon", "radarGraticule", issues),
808
+ note: text(value.note, "", "note", issues),
809
+ highlight,
810
+ referenceLines,
811
+ referenceBands,
812
+ varyColors: flag(value.varyColors, false, "varyColors", issues),
813
+ likertNeutral: pick(value.likertNeutral, CHART_LIKERT_NEUTRALS, "split", "likertNeutral", issues),
814
+ likertSort: pick(value.likertSort, CHART_LIKERT_SORTS, "none", "likertSort", issues),
815
+ parliamentArc: fraction("parliamentArc", 180, 90, 360),
816
+ parliamentMajority,
817
+ parliamentLabel: text(value.parliamentLabel, "", "parliamentLabel", issues),
818
+ tree,
819
+ sunburstLabel: text(value.sunburstLabel, "", "sunburstLabel", issues)
689
820
  };
690
821
  if (spec.stacking === "percent")
691
822
  for (const name of ["yAxis", "yAxis2"]) {
@@ -705,7 +836,11 @@ function cloneChartSpec(spec) {
705
836
  yAxis: { ...spec.yAxis, format: { ...spec.yAxis.format } },
706
837
  yAxis2: { ...spec.yAxis2, format: { ...spec.yAxis2.format } },
707
838
  legend: { ...spec.legend },
708
- palette: [...spec.palette]
839
+ palette: [...spec.palette],
840
+ highlight: [...spec.highlight],
841
+ referenceLines: spec.referenceLines.map((l) => ({ ...l })),
842
+ referenceBands: spec.referenceBands.map((b) => ({ ...b })),
843
+ tree: cloneChartTree(spec.tree)
709
844
  };
710
845
  }
711
846
  function cloneChartSeries(series) {
@@ -713,6 +848,7 @@ function cloneChartSeries(series) {
713
848
  if (series.x) copy.x = [...series.x];
714
849
  if (series.sizes) copy.sizes = [...series.sizes];
715
850
  if (series.pointColors) copy.pointColors = [...series.pointColors];
851
+ if (series.callouts) copy.callouts = [...series.callouts];
716
852
  if (series.format) copy.format = { ...series.format };
717
853
  if (series.trendlines) copy.trendlines = series.trendlines.map((t) => ({ ...t }));
718
854
  for (const name of ["errorBars", "xErrorBars"]) {
@@ -773,6 +909,230 @@ function chartColorInputValue(color) {
773
909
  return "#000000";
774
910
  }
775
911
 
912
+ // src/chart/tree.ts
913
+ var MAX_CHART_TREE_DEPTH = 6;
914
+ var MAX_CHART_TREE_NODES = 5e3;
915
+ var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
916
+ function normalizeChartTree(value, issues = [], path = "tree") {
917
+ if (value === void 0 || value === null) return [];
918
+ if (!Array.isArray(value)) {
919
+ issues.push({ path, message: `${path} must be an array of nodes such as {"name": "Europe", "children": [{"name": "France", "value": 40}]}.` });
920
+ return [];
921
+ }
922
+ let count = 0;
923
+ const read = (list, at, depth) => {
924
+ const out = [];
925
+ const names = /* @__PURE__ */ new Set();
926
+ list.forEach((raw, i) => {
927
+ const where = `${at}[${i}]`;
928
+ if (!isRecord2(raw)) {
929
+ issues.push({ path: where, message: `${where} must be an object with a name and a value or children.` });
930
+ return;
931
+ }
932
+ const name = typeof raw.name === "number" ? String(raw.name) : typeof raw.name === "string" ? raw.name.trim() : "";
933
+ if (!name) {
934
+ issues.push({ path: `${where}.name`, message: `${where} needs a name.` });
935
+ return;
936
+ }
937
+ if (names.has(name)) {
938
+ issues.push({ path: `${where}.name`, message: `"${name}" appears twice under the same group in ${at}; sibling names must be unique, so the second was left out.` });
939
+ return;
940
+ }
941
+ if (++count > MAX_CHART_TREE_NODES) {
942
+ if (count === MAX_CHART_TREE_NODES + 1) issues.push({ path, message: `The tree has more than ${MAX_CHART_TREE_NODES} nodes; the rest were left out.` });
943
+ return;
944
+ }
945
+ names.add(name);
946
+ for (const k of Object.keys(raw)) if (!["name", "value", "children", "color"].includes(k)) issues.push({ path: `${where}.${k}`, message: `${where} has no "${k}"; a node takes name, value, children and color.` });
947
+ const node = { name };
948
+ if (typeof raw.color === "string" && raw.color.trim()) node.color = raw.color.trim();
949
+ if (Array.isArray(raw.children) && raw.children.length) {
950
+ if (depth >= MAX_CHART_TREE_DEPTH) {
951
+ issues.push({ path: `${where}.children`, message: `${where} is more than ${MAX_CHART_TREE_DEPTH} levels deep; its children were left out.` });
952
+ node.value = 0;
953
+ } else {
954
+ if (raw.value !== void 0 && raw.value !== null) issues.push({ path: `${where}.value`, message: `"${name}" is a group: its value is the sum of its children, so the value given was ignored.` });
955
+ const children = read(raw.children, `${where}.children`, depth + 1);
956
+ if (children.length) node.children = children;
957
+ else node.value = 0;
958
+ }
959
+ } else {
960
+ if (raw.children !== void 0 && raw.children !== null && !Array.isArray(raw.children)) issues.push({ path: `${where}.children`, message: `${where}.children must be an array of nodes.` });
961
+ const v = parseChartValue(raw.value);
962
+ if (raw.value === void 0 || raw.value === null) node.value = 0;
963
+ else if (typeof v === "number" && v >= 0) node.value = v;
964
+ else {
965
+ issues.push({ path: `${where}.value`, message: `"${name}" needs a value of 0 or more; got ${JSON.stringify(raw.value)}.` });
966
+ node.value = 0;
967
+ }
968
+ }
969
+ out.push(node);
970
+ });
971
+ return out;
972
+ };
973
+ return read(value, path, 1);
974
+ }
975
+ function chartTreeTotal(node) {
976
+ return node.children ? node.children.reduce((t, c) => t + chartTreeTotal(c), 0) : _nullishCoalesce(node.value, () => ( 0));
977
+ }
978
+ function chartTreeDepth(tree) {
979
+ return tree.reduce((d, n) => Math.max(d, 1 + (n.children ? chartTreeDepth(n.children) : 0)), 0);
980
+ }
981
+ function findChartTreeNode(tree, path) {
982
+ let list = tree;
983
+ let node;
984
+ for (const name of path) {
985
+ node = _optionalChain([list, 'optionalAccess', _18 => _18.find, 'call', _19 => _19((n) => n.name === name)]);
986
+ if (!node) return void 0;
987
+ list = node.children;
988
+ }
989
+ return node;
990
+ }
991
+ function chartTreeToRows(tree) {
992
+ const out = [];
993
+ const walk = (list, prefix) => {
994
+ for (const n of list) {
995
+ if (n.children) walk(n.children, [...prefix, n.name]);
996
+ else out.push({ path: [...prefix, n.name], value: _nullishCoalesce(n.value, () => ( 0)) });
997
+ }
998
+ };
999
+ walk(tree, []);
1000
+ return out;
1001
+ }
1002
+ function chartTreeFromRows(rows, issues = []) {
1003
+ const tree = [];
1004
+ rows.forEach((row, r) => {
1005
+ const path = [];
1006
+ for (const cell of row.path) {
1007
+ const name = cell === null || cell === void 0 ? "" : String(cell).trim();
1008
+ if (!name) break;
1009
+ path.push(name);
1010
+ }
1011
+ if (!path.length) return;
1012
+ if (path.length > MAX_CHART_TREE_DEPTH) {
1013
+ issues.push({ path: `rows[${r}]`, message: `Row ${r + 1} is ${path.length} levels deep; the tree keeps at most ${MAX_CHART_TREE_DEPTH}, so the row was left out.` });
1014
+ return;
1015
+ }
1016
+ const v = parseChartValue(row.value);
1017
+ if (row.value !== null && row.value !== void 0 && String(row.value).trim() !== "" && !(typeof v === "number" && v >= 0)) {
1018
+ issues.push({ path: `rows[${r}]`, message: `Row ${r + 1} (${path.join(" / ")}) needs a value of 0 or more; got ${JSON.stringify(row.value)}. It was counted as 0.` });
1019
+ }
1020
+ const value = typeof v === "number" && v >= 0 ? v : 0;
1021
+ let list = tree;
1022
+ for (let k = 0; k < path.length; k++) {
1023
+ const last = k === path.length - 1;
1024
+ let node = list.find((n) => n.name === path[k]);
1025
+ if (!node) {
1026
+ node = last ? { name: path[k], value } : { name: path[k], children: [] };
1027
+ list.push(node);
1028
+ if (last) return;
1029
+ } else if (last) {
1030
+ issues.push({ path: `rows[${r}]`, message: `Row ${r + 1} (${path.join(" / ")}) ${node.children ? "names a group that already has items" : "repeats an earlier row"}; it was left out.` });
1031
+ return;
1032
+ } else if (!node.children) {
1033
+ issues.push({ path: `rows[${r}]`, message: `Row ${r + 1} puts items under "${path.slice(0, k + 1).join(" / ")}", which an earlier row made an item with its own value; it was left out.` });
1034
+ return;
1035
+ }
1036
+ list = node.children;
1037
+ }
1038
+ });
1039
+ return tree;
1040
+ }
1041
+ function chartTreeFromTable(rows, options = {}, issues = []) {
1042
+ const grid = rows.filter((r) => r.some((c) => c !== null && c !== void 0 && String(c).trim() !== ""));
1043
+ if (!grid.length) return [];
1044
+ const width = Math.max(...grid.map((r) => r.length));
1045
+ if (width < 2) {
1046
+ issues.push({ path: "rows", message: "A tree table needs at least two columns: names, then values." });
1047
+ return [];
1048
+ }
1049
+ const header = _nullishCoalesce(options.header, () => ( "auto"));
1050
+ const skip = header === true || header === "auto" && typeof parseChartValue(grid[0][width - 1]) !== "number";
1051
+ const body = skip ? grid.slice(1) : grid;
1052
+ let above = [];
1053
+ return chartTreeFromRows(
1054
+ body.map((r) => {
1055
+ const cells = Array.from({ length: width - 1 }, (_, k) => r[k] === null || r[k] === void 0 ? "" : String(r[k]).trim());
1056
+ const first = cells.findIndex((c) => c !== "");
1057
+ if (first < 0) return { path: [], value: r[width - 1] };
1058
+ const own = [];
1059
+ for (const c of cells.slice(first)) {
1060
+ if (!c) break;
1061
+ own.push(c);
1062
+ }
1063
+ const path = [...above.slice(0, first), ...own];
1064
+ above = path;
1065
+ return { path, value: r[width - 1] };
1066
+ }),
1067
+ issues
1068
+ );
1069
+ }
1070
+ function chartTreeFromSeries(categories, values) {
1071
+ const seen = /* @__PURE__ */ new Set();
1072
+ const out = [];
1073
+ categories.forEach((c, i) => {
1074
+ const name = c.trim() || `${i + 1}`;
1075
+ if (seen.has(name)) return;
1076
+ seen.add(name);
1077
+ const v = values[i];
1078
+ out.push({ name, value: v !== null && v !== void 0 && Number.isFinite(v) && v > 0 ? v : 0 });
1079
+ });
1080
+ return out;
1081
+ }
1082
+ function cloneChartTree(tree) {
1083
+ return tree.map((n) => ({ ...n, ...n.children ? { children: cloneChartTree(n.children) } : {} }));
1084
+ }
1085
+ function chartTreeColumnLabels(depth) {
1086
+ if (depth <= 1) return ["Item"];
1087
+ return Array.from({ length: depth }, (_, k) => k === 0 ? "Group" : k === depth - 1 ? "Item" : `Level ${k + 1}`);
1088
+ }
1089
+ function setChartTreeRowName(rows, row, level, name) {
1090
+ return rows.map((r, i) => {
1091
+ if (i !== row) return { path: [...r.path], value: r.value };
1092
+ const path = [...r.path];
1093
+ while (path.length <= level) path.push("");
1094
+ path[level] = name.trim();
1095
+ return { path, value: r.value };
1096
+ });
1097
+ }
1098
+ function setChartTreeRowValue(rows, row, value) {
1099
+ return rows.map((r, i) => ({ path: [...r.path], value: i === row ? value : r.value }));
1100
+ }
1101
+ function addChartTreeRow(rows) {
1102
+ const parent = rows.length ? rows[rows.length - 1].path.slice(0, -1) : [];
1103
+ const taken = new Set(rows.filter((r) => r.path.length === parent.length + 1 && parent.every((p, k) => r.path[k] === p)).map((r) => r.path[parent.length]));
1104
+ let n = rows.length + 1;
1105
+ while (taken.has(`Item ${n}`)) n++;
1106
+ return [...rows.map((r) => ({ path: [...r.path], value: r.value })), { path: [...parent, `Item ${n}`], value: 0 }];
1107
+ }
1108
+ function removeChartTreeRow(rows, row) {
1109
+ return rows.filter((_, i) => i !== row).map((r) => ({ path: [...r.path], value: r.value }));
1110
+ }
1111
+
1112
+
1113
+
1114
+
1115
+
1116
+
1117
+
1118
+
1119
+
1120
+
1121
+
1122
+
1123
+
1124
+
1125
+
1126
+
1127
+
1128
+
1129
+
1130
+
1131
+
1132
+
1133
+
1134
+
1135
+
776
1136
 
777
1137
 
778
1138
 
@@ -834,4 +1194,4 @@ function chartColorInputValue(color) {
834
1194
 
835
1195
 
836
1196
 
837
- exports.parseChartColor = parseChartColor; exports.chartRgbToHex = chartRgbToHex; exports.shadeChartColor = shadeChartColor; exports.CHART_PALETTE_SHADES = CHART_PALETTE_SHADES; exports.cyclePaletteColor = cyclePaletteColor; exports.chartLuminance = chartLuminance; exports.chartContrastRatio = chartContrastRatio; exports.chartTextOn = chartTextOn; exports.chartRgbToOklab = chartRgbToOklab; exports.chartColorDistance = chartColorDistance; exports.simulateChartVision = simulateChartVision; exports.checkChartColors = checkChartColors; exports.CHART_ERROR_BAR_TYPES = CHART_ERROR_BAR_TYPES; exports.CHART_ERROR_BAR_DIRECTIONS = CHART_ERROR_BAR_DIRECTIONS; exports.CHART_ERROR_BAR_LABELS = CHART_ERROR_BAR_LABELS; exports.defaultChartErrorBarValue = defaultChartErrorBarValue; exports.chartErrorAmounts = chartErrorAmounts; exports.describeChartErrorBars = describeChartErrorBars; exports.chartErrorBarsOfType = chartErrorBarsOfType; exports.formatChartAmountList = formatChartAmountList; exports.parseChartAmountList = parseChartAmountList; exports.CHART_TYPES = CHART_TYPES; exports.CHART_MARKERS = CHART_MARKERS; exports.CHART_TRENDLINE_TYPES = CHART_TRENDLINE_TYPES; exports.CHART_LABEL_POSITIONS = CHART_LABEL_POSITIONS; exports.CHART_AXIS_KINDS = CHART_AXIS_KINDS; exports.CHART_AXIS_SCALES = CHART_AXIS_SCALES; exports.CHART_SERIES_TYPES = CHART_SERIES_TYPES; exports.CHART_STACKINGS = CHART_STACKINGS; exports.CHART_CURVES = CHART_CURVES; exports.CHART_RADAR_GRATICULES = CHART_RADAR_GRATICULES; exports.CHART_ORIENTATIONS = CHART_ORIENTATIONS; exports.CHART_LEGEND_POSITIONS = CHART_LEGEND_POSITIONS; exports.CHART_NUMBER_STYLES = CHART_NUMBER_STYLES; exports.CHART_TYPE_LABELS = CHART_TYPE_LABELS; exports.DEFAULT_CHART_PALETTE = DEFAULT_CHART_PALETTE; exports.DEFAULT_CHART_THEME = DEFAULT_CHART_THEME; exports.CSS_VARIABLE_CHART_THEME = CSS_VARIABLE_CHART_THEME; exports.isCartesianChart = isCartesianChart; exports.isXyChart = isXyChart; exports.chartFamily = chartFamily; exports.chartColorsByCategory = chartColorsByCategory; exports.defaultChartAxis = defaultChartAxis; exports.createChartSpec = createChartSpec; exports.chartSeriesColor = chartSeriesColor; exports.chartSliceColor = chartSliceColor; exports.chartPointColor = chartPointColor; exports.chartSeriesType = chartSeriesType; exports.uniqueChartSeriesId = uniqueChartSeriesId; exports.parseChartValue = parseChartValue; exports.normalizeChartAxis = normalizeChartAxis; exports.normalizeChartValues = normalizeChartValues; exports.normalizeChartErrorBars = normalizeChartErrorBars; exports.normalizeChartTrendline = normalizeChartTrendline; exports.normalizeChartSpec = normalizeChartSpec; exports.cloneChartSpec = cloneChartSpec; exports.cloneChartSeries = cloneChartSeries; exports.chartDataFromTable = chartDataFromTable; exports.chartDataToTable = chartDataToTable; exports.chartColorInputValue = chartColorInputValue;
1197
+ exports.parseChartColor = parseChartColor; exports.chartRgbToHex = chartRgbToHex; exports.shadeChartColor = shadeChartColor; exports.CHART_PALETTE_SHADES = CHART_PALETTE_SHADES; exports.cyclePaletteColor = cyclePaletteColor; exports.chartLuminance = chartLuminance; exports.chartContrastRatio = chartContrastRatio; exports.chartTextOn = chartTextOn; exports.chartRgbToOklab = chartRgbToOklab; exports.chartColorDistance = chartColorDistance; exports.simulateChartVision = simulateChartVision; exports.checkChartColors = checkChartColors; exports.CHART_ERROR_BAR_TYPES = CHART_ERROR_BAR_TYPES; exports.CHART_ERROR_BAR_DIRECTIONS = CHART_ERROR_BAR_DIRECTIONS; exports.CHART_ERROR_BAR_LABELS = CHART_ERROR_BAR_LABELS; exports.defaultChartErrorBarValue = defaultChartErrorBarValue; exports.chartErrorAmounts = chartErrorAmounts; exports.describeChartErrorBars = describeChartErrorBars; exports.chartErrorBarsOfType = chartErrorBarsOfType; exports.formatChartAmountList = formatChartAmountList; exports.parseChartAmountList = parseChartAmountList; exports.MAX_CHART_TREE_DEPTH = MAX_CHART_TREE_DEPTH; exports.MAX_CHART_TREE_NODES = MAX_CHART_TREE_NODES; exports.normalizeChartTree = normalizeChartTree; exports.chartTreeTotal = chartTreeTotal; exports.chartTreeDepth = chartTreeDepth; exports.findChartTreeNode = findChartTreeNode; exports.chartTreeToRows = chartTreeToRows; exports.chartTreeFromRows = chartTreeFromRows; exports.chartTreeFromTable = chartTreeFromTable; exports.chartTreeFromSeries = chartTreeFromSeries; exports.cloneChartTree = cloneChartTree; exports.chartTreeColumnLabels = chartTreeColumnLabels; exports.setChartTreeRowName = setChartTreeRowName; exports.setChartTreeRowValue = setChartTreeRowValue; exports.addChartTreeRow = addChartTreeRow; exports.removeChartTreeRow = removeChartTreeRow; exports.CHART_TYPES = CHART_TYPES; exports.CHART_MARKERS = CHART_MARKERS; exports.CHART_TRENDLINE_TYPES = CHART_TRENDLINE_TYPES; exports.CHART_LABEL_POSITIONS = CHART_LABEL_POSITIONS; exports.CHART_AXIS_KINDS = CHART_AXIS_KINDS; exports.CHART_AXIS_SCALES = CHART_AXIS_SCALES; exports.CHART_SERIES_TYPES = CHART_SERIES_TYPES; exports.CHART_STACKINGS = CHART_STACKINGS; exports.CHART_CURVES = CHART_CURVES; exports.CHART_RADAR_GRATICULES = CHART_RADAR_GRATICULES; exports.CHART_LIKERT_NEUTRALS = CHART_LIKERT_NEUTRALS; exports.CHART_LIKERT_SORTS = CHART_LIKERT_SORTS; exports.CHART_REFERENCE_AXES = CHART_REFERENCE_AXES; exports.CHART_ORIENTATIONS = CHART_ORIENTATIONS; exports.CHART_LEGEND_POSITIONS = CHART_LEGEND_POSITIONS; exports.CHART_NUMBER_STYLES = CHART_NUMBER_STYLES; exports.CHART_TYPE_LABELS = CHART_TYPE_LABELS; exports.DEFAULT_CHART_PALETTE = DEFAULT_CHART_PALETTE; exports.DEFAULT_CHART_THEME = DEFAULT_CHART_THEME; exports.CSS_VARIABLE_CHART_THEME = CSS_VARIABLE_CHART_THEME; exports.isCartesianChart = isCartesianChart; exports.isXyChart = isXyChart; exports.chartFamily = chartFamily; exports.chartColorsByCategory = chartColorsByCategory; exports.chartSpecColorsByCategory = chartSpecColorsByCategory; exports.defaultChartAxis = defaultChartAxis; exports.createChartSpec = createChartSpec; exports.chartSeriesColor = chartSeriesColor; exports.chartLikertColor = chartLikertColor; exports.chartSliceColor = chartSliceColor; exports.chartVariesColors = chartVariesColors; exports.chartPointColor = chartPointColor; exports.chartSeriesType = chartSeriesType; exports.uniqueChartSeriesId = uniqueChartSeriesId; exports.parseChartValue = parseChartValue; exports.normalizeChartAxis = normalizeChartAxis; exports.normalizeChartValues = normalizeChartValues; exports.normalizeChartReferenceLine = normalizeChartReferenceLine; exports.normalizeChartReferenceBand = normalizeChartReferenceBand; exports.normalizeChartErrorBars = normalizeChartErrorBars; exports.normalizeChartTrendline = normalizeChartTrendline; exports.normalizeChartSpec = normalizeChartSpec; exports.cloneChartSpec = cloneChartSpec; exports.cloneChartSeries = cloneChartSeries; exports.chartDataFromTable = chartDataFromTable; exports.chartDataToTable = chartDataToTable; exports.chartColorInputValue = chartColorInputValue;