@opendata-ai/openchart-engine 7.1.4 → 7.2.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.d.ts CHANGED
@@ -298,7 +298,7 @@ interface NormalizedChartSpec {
298
298
  metrics?: _opendata_ai_openchart_core.Metric[];
299
299
  annotations: Annotation[];
300
300
  /** Normalized label configuration with defaults applied. density, format, and prefix are always set; offsets and color stay optional. */
301
- labels: Required<Pick<LabelConfig, 'density' | 'format' | 'prefix'>> & Pick<LabelConfig, 'offsets' | 'color'>;
301
+ labels: Required<Pick<LabelConfig, 'density' | 'format' | 'prefix'>> & Pick<LabelConfig, 'offsets' | 'color' | 'fontSize' | 'suffix'>;
302
302
  /** Legend configuration (position override). */
303
303
  legend?: LegendConfig;
304
304
  /** Right-side endpoint labels column config (multi-series line/area only). */
package/dist/index.js CHANGED
@@ -1778,7 +1778,8 @@ var LABEL_FONT_SIZE = 11;
1778
1778
  var LABEL_FONT_WEIGHT = 600;
1779
1779
  var LABEL_PADDING = 6;
1780
1780
  var MIN_WIDTH_FOR_INSIDE_LABEL = 40;
1781
- function computeBarLabels(marks, _chartArea, density = "auto", labelFormat, labelPrefix, valueField, labelColor, darkMode = false) {
1781
+ function computeBarLabels(marks, _chartArea, density = "auto", labelFormat, labelPrefix, valueField, labelColor, darkMode = false, fontSize, labelSuffix) {
1782
+ const FONT_SIZE = fontSize ?? LABEL_FONT_SIZE;
1782
1783
  const targetMarks = filterByDensity(marks, density);
1783
1784
  const candidates = [];
1784
1785
  const fitsInSegment = [];
@@ -1804,8 +1805,9 @@ function computeBarLabels(marks, _chartArea, density = "auto", labelFormat, labe
1804
1805
  }
1805
1806
  }
1806
1807
  if (labelPrefix) valuePart = labelPrefix + valuePart;
1807
- const textWidth = estimateTextWidth4(valuePart, LABEL_FONT_SIZE, LABEL_FONT_WEIGHT);
1808
- const textHeight = LABEL_FONT_SIZE * 1.2;
1808
+ if (labelSuffix) valuePart = valuePart + labelSuffix;
1809
+ const textWidth = estimateTextWidth4(valuePart, FONT_SIZE, LABEL_FONT_WEIGHT);
1810
+ const textHeight = FONT_SIZE * 1.2;
1809
1811
  const isStacked2 = mark.stackGroup !== void 0;
1810
1812
  const isInside = mark.width >= MIN_WIDTH_FOR_INSIDE_LABEL;
1811
1813
  const isNegative = Number.isFinite(rawNum) ? rawNum < 0 : false;
@@ -1850,7 +1852,7 @@ function computeBarLabels(marks, _chartArea, density = "auto", labelFormat, labe
1850
1852
  priority: "data",
1851
1853
  style: {
1852
1854
  fontFamily: "system-ui, -apple-system, sans-serif",
1853
- fontSize: LABEL_FONT_SIZE,
1855
+ fontSize: FONT_SIZE,
1854
1856
  fontWeight: LABEL_FONT_WEIGHT,
1855
1857
  fill,
1856
1858
  lineHeight: 1.2,
@@ -1909,7 +1911,9 @@ var barRenderer = (spec, scales, chartArea, strategy, theme) => {
1909
1911
  spec.labels.prefix,
1910
1912
  valueField,
1911
1913
  spec.labels.color,
1912
- theme.isDark
1914
+ theme.isDark,
1915
+ spec.labels.fontSize,
1916
+ spec.labels.suffix
1913
1917
  );
1914
1918
  for (let i = 0; i < marks.length && i < labels.length; i++) {
1915
1919
  marks[i].label = labels[i];
@@ -2214,7 +2218,8 @@ import {
2214
2218
  var LABEL_FONT_SIZE2 = 10;
2215
2219
  var LABEL_FONT_WEIGHT2 = 600;
2216
2220
  var LABEL_OFFSET_Y = 8;
2217
- function computeColumnLabels(marks, _chartArea, density = "auto", labelFormat, labelPrefix, valueField, labelColor) {
2221
+ function computeColumnLabels(marks, _chartArea, density = "auto", labelFormat, labelPrefix, valueField, labelColor, fontSize, labelSuffix) {
2222
+ const FONT_SIZE = fontSize ?? LABEL_FONT_SIZE2;
2218
2223
  const targetMarks = filterByDensity(marks, density);
2219
2224
  const formatter = buildD3Formatter2(labelFormat);
2220
2225
  const candidates = [];
@@ -2238,11 +2243,12 @@ function computeColumnLabels(marks, _chartArea, density = "auto", labelFormat, l
2238
2243
  valuePart = rawValue;
2239
2244
  }
2240
2245
  }
2241
- if (labelPrefix) valuePart = labelPrefix + valuePart;
2242
2246
  const numericValue = parseFloat(valuePart);
2243
2247
  const isNegative = Number.isFinite(numericValue) && numericValue < 0;
2244
- const textWidth = estimateTextWidth5(valuePart, LABEL_FONT_SIZE2, LABEL_FONT_WEIGHT2);
2245
- const textHeight = LABEL_FONT_SIZE2 * 1.2;
2248
+ if (labelPrefix) valuePart = labelPrefix + valuePart;
2249
+ if (labelSuffix) valuePart = valuePart + labelSuffix;
2250
+ const textWidth = estimateTextWidth5(valuePart, FONT_SIZE, LABEL_FONT_WEIGHT2);
2251
+ const textHeight = FONT_SIZE * 1.2;
2246
2252
  const anchorX = mark.x + mark.width / 2;
2247
2253
  const anchorY = isNegative ? mark.y + mark.height + LABEL_OFFSET_Y : mark.y - LABEL_OFFSET_Y - textHeight;
2248
2254
  candidates.push({
@@ -2254,7 +2260,7 @@ function computeColumnLabels(marks, _chartArea, density = "auto", labelFormat, l
2254
2260
  priority: "data",
2255
2261
  style: {
2256
2262
  fontFamily: "system-ui, -apple-system, sans-serif",
2257
- fontSize: LABEL_FONT_SIZE2,
2263
+ fontSize: FONT_SIZE,
2258
2264
  fontWeight: LABEL_FONT_WEIGHT2,
2259
2265
  fill: labelColor ?? getRepresentativeColor2(mark.fill),
2260
2266
  lineHeight: 1.2,
@@ -2287,7 +2293,9 @@ var columnRenderer = (spec, scales, chartArea, strategy, _theme) => {
2287
2293
  spec.labels.format,
2288
2294
  spec.labels.prefix,
2289
2295
  valueField,
2290
- spec.labels.color
2296
+ spec.labels.color,
2297
+ spec.labels.fontSize,
2298
+ spec.labels.suffix
2291
2299
  );
2292
2300
  for (let i = 0; i < marks.length && i < labels.length; i++) {
2293
2301
  marks[i].label = labels[i];
@@ -7287,8 +7295,10 @@ function normalizeLabels(labels) {
7287
7295
  density: labels.density ?? "auto",
7288
7296
  format: labels.format ?? "",
7289
7297
  prefix: labels.prefix ?? "",
7298
+ suffix: labels.suffix,
7290
7299
  offsets: labels.offsets,
7291
- color: labels.color
7300
+ color: labels.color,
7301
+ fontSize: labels.fontSize
7292
7302
  };
7293
7303
  }
7294
7304
  function normalizeChartSpec(spec, warnings) {
@@ -9758,22 +9768,23 @@ var TEMPORAL_SCALE_TYPES = /* @__PURE__ */ new Set(["time", "utc"]);
9758
9768
  function formatTickLabel(value2, resolvedScale) {
9759
9769
  const axisConfig = resolvedScale.channel.axis || void 0;
9760
9770
  const formatStr = axisConfig?.format;
9771
+ const suffix = axisConfig?.labelSuffix ?? "";
9761
9772
  if (TEMPORAL_SCALE_TYPES.has(resolvedScale.type)) {
9762
9773
  const temporalFmt = buildTemporalFormatter(formatStr);
9763
- if (temporalFmt) return temporalFmt(value2);
9774
+ if (temporalFmt) return temporalFmt(value2) + suffix;
9764
9775
  const useUtc = resolvedScale.type === "utc";
9765
- return formatDate(value2, void 0, void 0, useUtc);
9776
+ return formatDate(value2, void 0, void 0, useUtc) + suffix;
9766
9777
  }
9767
9778
  if (NUMERIC_SCALE_TYPES.has(resolvedScale.type)) {
9768
9779
  const num = value2;
9769
9780
  if (formatStr) {
9770
9781
  const fmt = buildD3Formatter5(formatStr);
9771
- if (fmt) return fmt(num);
9782
+ if (fmt) return fmt(num) + suffix;
9772
9783
  }
9773
- if (Math.abs(num) >= 1e3) return abbreviateNumber2(num);
9774
- return formatNumber3(num);
9784
+ if (Math.abs(num) >= 1e3) return abbreviateNumber2(num) + suffix;
9785
+ return formatNumber3(num) + suffix;
9775
9786
  }
9776
- return String(value2);
9787
+ return String(value2) + suffix;
9777
9788
  }
9778
9789
  function continuousTicks(resolvedScale, density, targetCount) {
9779
9790
  const scale = resolvedScale.scale;
@@ -10426,7 +10437,8 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
10426
10437
  const labelHeight = Math.min(rotatedHeight, 120);
10427
10438
  xAxisHeight = hasXAxisLabel ? labelHeight + 20 : labelHeight;
10428
10439
  } else {
10429
- xAxisHeight = hasXAxisLabel ? 48 : 26;
10440
+ const base = theme.spacing.xAxisHeight;
10441
+ xAxisHeight = hasXAxisLabel ? base + 22 : base;
10430
10442
  }
10431
10443
  const yAxisCfgPre = encoding.y?.axis ?? void 0;
10432
10444
  const yTickPositionExplicitPre = yAxisCfgPre?.tickPosition;