@opendata-ai/openchart-engine 6.15.1 → 6.17.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.
package/dist/index.js CHANGED
@@ -596,7 +596,7 @@ function evaluateFieldPredicate(datum, pred) {
596
596
  return pred.valid ? isValid : !isValid;
597
597
  }
598
598
  if (pred.equal !== void 0) {
599
- return value2 === pred.equal;
599
+ return value2 == pred.equal;
600
600
  }
601
601
  const numValue = Number(value2);
602
602
  if (pred.lt !== void 0) {
@@ -616,7 +616,7 @@ function evaluateFieldPredicate(datum, pred) {
616
616
  return numValue >= min4 && numValue <= max4;
617
617
  }
618
618
  if (pred.oneOf !== void 0) {
619
- return pred.oneOf.includes(value2);
619
+ return pred.oneOf.some((v) => v == value2);
620
620
  }
621
621
  return true;
622
622
  }
@@ -7776,9 +7776,9 @@ import {
7776
7776
  formatNumber as formatNumber6
7777
7777
  } from "@opendata-ai/openchart-core";
7778
7778
  var TICK_COUNTS = {
7779
- full: 10,
7780
- reduced: 7,
7781
- minimal: 3
7779
+ full: 12,
7780
+ reduced: 8,
7781
+ minimal: 4
7782
7782
  };
7783
7783
  var HEIGHT_MINIMAL_THRESHOLD = 120;
7784
7784
  var HEIGHT_REDUCED_THRESHOLD = 200;
@@ -8123,7 +8123,7 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
8123
8123
  }
8124
8124
  }
8125
8125
  if (maxLabelWidth > 0) {
8126
- margins.right = Math.max(margins.right, padding + maxLabelWidth + 16);
8126
+ margins.right = Math.max(margins.right, padding + maxLabelWidth + 8);
8127
8127
  }
8128
8128
  }
8129
8129
  }
@@ -8499,14 +8499,18 @@ function buildPointScale(channel, data, rangeStart, rangeEnd) {
8499
8499
  function buildOrdinalColorScale(channel, data, palette) {
8500
8500
  const explicitDomain = channel.scale?.domain;
8501
8501
  const values = explicitDomain ? explicitDomain.map(String) : applyCategoricalSort(uniqueStrings(fieldValues(data, channel.field)), channel.sort);
8502
- const scale = ordinal().domain(values).range(palette);
8502
+ const explicitRange = channel.scale?.range;
8503
+ const colors = explicitRange ?? palette;
8504
+ const scale = ordinal().domain(values).range(colors);
8503
8505
  return { scale, type: "ordinal", channel };
8504
8506
  }
8505
8507
  function buildSequentialColorScale(channel, data, palette) {
8506
8508
  const values = parseNumbers(fieldValues(data, channel.field));
8507
8509
  const domainMin = min2(values) ?? 0;
8508
8510
  const domainMax = max2(values) ?? 1;
8509
- const scale = linear2().domain([domainMin, domainMax]).range([palette[0], palette[palette.length - 1]]).clamp(true);
8511
+ const explicitRange = channel.scale?.range;
8512
+ const colors = explicitRange ?? palette;
8513
+ const scale = linear2().domain([domainMin, domainMax]).range([colors[0], colors[colors.length - 1]]).clamp(true);
8510
8514
  return { scale, type: "sequential", channel };
8511
8515
  }
8512
8516
  function buildPositionalScale(channel, data, rangeStart, rangeEnd, chartType, axis) {
@@ -8730,14 +8734,23 @@ function extractColorEntries(spec, theme) {
8730
8734
  if ("condition" in colorEnc) return [];
8731
8735
  if (colorEnc.type === "quantitative") return [];
8732
8736
  const uniqueValues = [...new Set(spec.data.map((d) => String(d[colorEnc.field])))];
8733
- const palette = theme.colors.categorical;
8737
+ const explicitDomain = colorEnc.scale?.domain;
8738
+ const explicitRange = colorEnc.scale?.range;
8739
+ const palette = explicitRange ?? theme.colors.categorical;
8734
8740
  const shape = swatchShapeForType(spec.markType);
8735
- return uniqueValues.map((value2, i) => ({
8736
- label: value2,
8737
- color: palette[i % palette.length],
8738
- shape,
8739
- active: true
8740
- }));
8741
+ return uniqueValues.map((value2, i) => {
8742
+ let colorIndex = i;
8743
+ if (explicitDomain && explicitRange) {
8744
+ const domainIdx = explicitDomain.indexOf(value2);
8745
+ if (domainIdx >= 0) colorIndex = domainIdx;
8746
+ }
8747
+ return {
8748
+ label: value2,
8749
+ color: palette[colorIndex % palette.length],
8750
+ shape,
8751
+ active: true
8752
+ };
8753
+ });
8741
8754
  }
8742
8755
  function entriesThatFit(entries, maxWidth, maxRows, labelStyle) {
8743
8756
  let row = 1;
@@ -8791,6 +8804,20 @@ function computeLegend(spec, strategy, theme, chartArea, watermark = true) {
8791
8804
  };
8792
8805
  }
8793
8806
  let entries = extractColorEntries(spec, theme);
8807
+ const isLineOrArea = spec.markType === "line" || spec.markType === "area";
8808
+ const hasLabels = spec.labels.density !== "none";
8809
+ const labelsWillRender = strategy.labelMode !== "none";
8810
+ const hasColorEncoding = spec.encoding.color != null;
8811
+ const legendNotForced = spec.legend?.show !== true;
8812
+ if (isLineOrArea && hasLabels && labelsWillRender && hasColorEncoding && legendNotForced) {
8813
+ const isArea = spec.markType === "area";
8814
+ const quantChannel = spec.encoding.y?.type === "quantitative" ? spec.encoding.y : spec.encoding.x;
8815
+ const stackValue2 = quantChannel?.stack;
8816
+ const isStacked = stackValue2 !== null && stackValue2 !== false;
8817
+ if (!isArea || !isStacked) {
8818
+ entries = [];
8819
+ }
8820
+ }
8794
8821
  const labelStyle = {
8795
8822
  fontFamily: theme.fonts.family,
8796
8823
  fontSize: theme.fonts.sizes.small,
@@ -9915,16 +9942,25 @@ function computeCategoryColors(data, column, theme, darkMode) {
9915
9942
  if (raw == null) continue;
9916
9943
  const key = String(raw);
9917
9944
  let bg;
9918
- if (explicitMap[key]) {
9945
+ let isExplicit = false;
9946
+ if (explicitMap[key] != null) {
9947
+ if (explicitMap[key] === "transparent" || explicitMap[key] === "none") {
9948
+ continue;
9949
+ }
9919
9950
  bg = explicitMap[key];
9920
- } else if (autoAssigned.has(key)) {
9921
- bg = autoAssigned.get(key);
9951
+ isExplicit = true;
9952
+ } else if (column.autoAssign) {
9953
+ if (autoAssigned.has(key)) {
9954
+ bg = autoAssigned.get(key);
9955
+ } else {
9956
+ bg = categoricalPalette[nextPaletteIndex % categoricalPalette.length];
9957
+ nextPaletteIndex++;
9958
+ autoAssigned.set(key, bg);
9959
+ }
9922
9960
  } else {
9923
- bg = categoricalPalette[nextPaletteIndex % categoricalPalette.length];
9924
- nextPaletteIndex++;
9925
- autoAssigned.set(key, bg);
9961
+ continue;
9926
9962
  }
9927
- if (darkMode) {
9963
+ if (darkMode && !isExplicit) {
9928
9964
  bg = adaptColorForDarkMode(bg, lightBg, darkBg);
9929
9965
  }
9930
9966
  const textColor = accessibleTextColor(bg);
@@ -11139,16 +11175,21 @@ function compileChart(spec, options) {
11139
11175
  const renderSpec = renderData !== chartSpec.data ? { ...chartSpec, data: renderData } : chartSpec;
11140
11176
  const scales = computeScales(renderSpec, chartArea, renderSpec.data);
11141
11177
  if (scales.color) {
11178
+ const hasExplicitRange = !!(renderSpec.encoding.color && "field" in renderSpec.encoding.color && renderSpec.encoding.color.scale?.range?.length);
11142
11179
  if (scales.color.type === "sequential") {
11143
- const seqStops = Object.values(theme.colors.sequential)[0] ?? theme.colors.categorical;
11144
- scales.color.scale.range([
11145
- seqStops[0],
11146
- seqStops[seqStops.length - 1]
11147
- ]);
11180
+ if (!hasExplicitRange) {
11181
+ const seqStops = Object.values(theme.colors.sequential)[0] ?? theme.colors.categorical;
11182
+ scales.color.scale.range([
11183
+ seqStops[0],
11184
+ seqStops[seqStops.length - 1]
11185
+ ]);
11186
+ }
11148
11187
  } else {
11149
- scales.color.scale.range(
11150
- theme.colors.categorical
11151
- );
11188
+ if (!hasExplicitRange) {
11189
+ scales.color.scale.range(
11190
+ theme.colors.categorical
11191
+ );
11192
+ }
11152
11193
  }
11153
11194
  }
11154
11195
  scales.defaultColor = chartSpec.markDef.fill ?? theme.colors.categorical[0];