@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 +1 -1
- package/dist/index.js +31 -19
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/__snapshots__/compile-snapshot.test.ts.snap +48 -42
- package/src/charts/bar/index.ts +2 -0
- package/src/charts/bar/labels.ts +7 -3
- package/src/charts/column/index.ts +2 -0
- package/src/charts/column/labels.ts +9 -5
- package/src/compiler/normalize.ts +2 -0
- package/src/compiler/types.ts +1 -1
- package/src/layout/axes/ticks.ts +7 -6
- package/src/layout/dimensions.ts +2 -1
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
|
-
|
|
1808
|
-
const
|
|
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:
|
|
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
|
-
|
|
2245
|
-
|
|
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:
|
|
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
|
-
|
|
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;
|