@opendata-ai/openchart-engine 6.9.0 → 6.11.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 +2 -10
- package/dist/index.js +198 -28
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/charts/bar/__tests__/compute.test.ts +92 -0
- package/src/charts/bar/compute.ts +92 -5
- package/src/charts/bar/labels.ts +2 -1
- package/src/charts/column/__tests__/compute.test.ts +66 -0
- package/src/charts/column/compute.ts +98 -6
- package/src/charts/column/labels.ts +2 -1
- package/src/charts/dot/labels.ts +6 -2
- package/src/charts/line/area.ts +3 -2
- package/src/charts/line/compute.ts +5 -2
- package/src/charts/pie/compute.ts +24 -3
- package/src/charts/rule/index.ts +6 -3
- package/src/charts/scatter/compute.ts +2 -1
- package/src/charts/text/index.ts +6 -3
- package/src/charts/tick/index.ts +6 -3
- package/src/charts/utils.ts +3 -3
- package/src/compile.ts +3 -2
- package/src/layout/scales.ts +12 -4
- package/src/tooltips/compute.ts +11 -6
package/dist/index.d.ts
CHANGED
|
@@ -354,14 +354,6 @@ declare function validateSpec(spec: unknown): ValidationResult;
|
|
|
354
354
|
*/
|
|
355
355
|
declare function compile(spec: unknown): CompileResult;
|
|
356
356
|
|
|
357
|
-
/**
|
|
358
|
-
* Scale computation from encoding spec + data.
|
|
359
|
-
*
|
|
360
|
-
* Creates D3 scales that map data values to pixel positions.
|
|
361
|
-
* Temporal -> scaleTime(), quantitative -> scaleLinear(),
|
|
362
|
-
* nominal/ordinal -> scaleBand() or scaleOrdinal(), depending on context.
|
|
363
|
-
*/
|
|
364
|
-
|
|
365
357
|
/** Continuous D3 scales (linear, time, log, pow, sqrt, symlog) that support .ticks() and .nice(). */
|
|
366
358
|
type D3ContinuousScale = ScaleLinear<number, number> | ScaleTime<number, number> | ScaleLogarithmic<number, number> | ScalePower<number, number> | ScaleSymLog<number, number>;
|
|
367
359
|
/** Discretizing D3 scales (quantile, quantize, threshold). */
|
|
@@ -392,8 +384,8 @@ interface ResolvedScales {
|
|
|
392
384
|
y?: ResolvedScale;
|
|
393
385
|
color?: ResolvedScale;
|
|
394
386
|
size?: ResolvedScale;
|
|
395
|
-
/** Default color for single-series charts (first categorical palette color). */
|
|
396
|
-
defaultColor?: string;
|
|
387
|
+
/** Default color for single-series charts (first categorical palette color or markDef.fill gradient). */
|
|
388
|
+
defaultColor?: string | _opendata_ai_openchart_core.GradientDef;
|
|
397
389
|
}
|
|
398
390
|
|
|
399
391
|
/**
|
package/dist/index.js
CHANGED
|
@@ -590,7 +590,7 @@ function computeAnnotations(spec, scales, chartArea, strategy, isDark = false, o
|
|
|
590
590
|
}
|
|
591
591
|
|
|
592
592
|
// src/charts/bar/compute.ts
|
|
593
|
-
import { abbreviateNumber, formatNumber } from "@opendata-ai/openchart-core";
|
|
593
|
+
import { abbreviateNumber, formatNumber, isGradientDef } from "@opendata-ai/openchart-core";
|
|
594
594
|
|
|
595
595
|
// src/transforms/predicates.ts
|
|
596
596
|
function isFieldPredicate(pred) {
|
|
@@ -774,6 +774,20 @@ function computeBarMarks(spec, scales, _chartArea, _strategy) {
|
|
|
774
774
|
const categoryGroups = groupByField(spec.data, yChannel.field);
|
|
775
775
|
const needsStacking = Array.from(categoryGroups.values()).some((rows) => rows.length > 1);
|
|
776
776
|
if (needsStacking) {
|
|
777
|
+
const stackDisabled = xChannel.stack === null || xChannel.stack === false;
|
|
778
|
+
if (stackDisabled) {
|
|
779
|
+
return computeGroupedBars(
|
|
780
|
+
spec.data,
|
|
781
|
+
xChannel.field,
|
|
782
|
+
yChannel.field,
|
|
783
|
+
colorField,
|
|
784
|
+
xScale,
|
|
785
|
+
yScale,
|
|
786
|
+
bandwidth,
|
|
787
|
+
baseline,
|
|
788
|
+
scales
|
|
789
|
+
);
|
|
790
|
+
}
|
|
777
791
|
return computeStackedBars(
|
|
778
792
|
spec.data,
|
|
779
793
|
xChannel.field,
|
|
@@ -834,6 +848,51 @@ function computeStackedBars(data, valueField, categoryField, colorField, xScale,
|
|
|
834
848
|
}
|
|
835
849
|
return marks;
|
|
836
850
|
}
|
|
851
|
+
function computeGroupedBars(data, valueField, categoryField, colorField, xScale, yScale, bandwidth, baseline, scales) {
|
|
852
|
+
const marks = [];
|
|
853
|
+
const categoryGroups = groupByField(data, categoryField);
|
|
854
|
+
const groupIndexMap = /* @__PURE__ */ new Map();
|
|
855
|
+
for (const row of data) {
|
|
856
|
+
const key = String(row[colorField] ?? "");
|
|
857
|
+
if (!groupIndexMap.has(key)) {
|
|
858
|
+
groupIndexMap.set(key, groupIndexMap.size);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
const groupCount = groupIndexMap.size;
|
|
862
|
+
if (groupCount === 0) return marks;
|
|
863
|
+
const gap = Math.min(1, bandwidth * 0.05);
|
|
864
|
+
const subBandHeight = Math.max((bandwidth - gap * (groupCount - 1)) / groupCount, MIN_BAR_WIDTH);
|
|
865
|
+
for (const [category, rows] of categoryGroups) {
|
|
866
|
+
const bandY = yScale(category);
|
|
867
|
+
if (bandY === void 0) continue;
|
|
868
|
+
for (const row of rows) {
|
|
869
|
+
const groupKey = String(row[colorField] ?? "");
|
|
870
|
+
const value2 = Number(row[valueField] ?? 0);
|
|
871
|
+
if (!Number.isFinite(value2)) continue;
|
|
872
|
+
const groupIndex = groupIndexMap.get(groupKey) ?? 0;
|
|
873
|
+
const color2 = getColor(scales, groupKey);
|
|
874
|
+
const xPos = value2 >= 0 ? baseline : xScale(value2);
|
|
875
|
+
const barWidth = Math.max(Math.abs(xScale(value2) - baseline), MIN_BAR_WIDTH);
|
|
876
|
+
const subY = bandY + groupIndex * (subBandHeight + gap);
|
|
877
|
+
const aria = {
|
|
878
|
+
label: `${category}, ${groupKey}: ${formatBarValue(value2)}`
|
|
879
|
+
};
|
|
880
|
+
marks.push({
|
|
881
|
+
type: "rect",
|
|
882
|
+
x: xPos,
|
|
883
|
+
y: subY,
|
|
884
|
+
width: barWidth,
|
|
885
|
+
height: subBandHeight,
|
|
886
|
+
fill: color2,
|
|
887
|
+
cornerRadius: 2,
|
|
888
|
+
data: row,
|
|
889
|
+
aria,
|
|
890
|
+
orient: "horizontal"
|
|
891
|
+
});
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
return marks;
|
|
895
|
+
}
|
|
837
896
|
function computeColoredBars(data, valueField, categoryField, colorField, xScale, yScale, bandwidth, baseline, scales) {
|
|
838
897
|
const marks = [];
|
|
839
898
|
for (const row of data) {
|
|
@@ -874,9 +933,12 @@ function computeSimpleBars(data, valueField, categoryField, xScale, yScale, band
|
|
|
874
933
|
if (bandY === void 0) continue;
|
|
875
934
|
let color2;
|
|
876
935
|
if (conditionalColor) {
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
936
|
+
const resolved = resolveConditionalValue(row, conditionalColor);
|
|
937
|
+
if (resolved != null) {
|
|
938
|
+
color2 = isGradientDef(resolved) ? resolved : String(resolved);
|
|
939
|
+
} else {
|
|
940
|
+
color2 = getColor(scales, "__default__");
|
|
941
|
+
}
|
|
880
942
|
} else if (sequentialColor) {
|
|
881
943
|
color2 = getSequentialColor(scales, value2);
|
|
882
944
|
} else {
|
|
@@ -907,6 +969,7 @@ function computeSimpleBars(data, valueField, categoryField, xScale, yScale, band
|
|
|
907
969
|
import {
|
|
908
970
|
buildD3Formatter,
|
|
909
971
|
estimateTextWidth as estimateTextWidth2,
|
|
972
|
+
getRepresentativeColor,
|
|
910
973
|
resolveCollisions
|
|
911
974
|
} from "@opendata-ai/openchart-core";
|
|
912
975
|
var SUFFIX_MULTIPLIERS = {
|
|
@@ -965,7 +1028,7 @@ function computeBarLabels(marks, _chartArea, density = "auto", labelFormat, labe
|
|
|
965
1028
|
textAnchor = "end";
|
|
966
1029
|
} else {
|
|
967
1030
|
anchorX = mark.x + mark.width + LABEL_PADDING;
|
|
968
|
-
fill = mark.fill;
|
|
1031
|
+
fill = getRepresentativeColor(mark.fill);
|
|
969
1032
|
textAnchor = "start";
|
|
970
1033
|
}
|
|
971
1034
|
const anchorY = mark.y + mark.height / 2;
|
|
@@ -1044,7 +1107,7 @@ var barRenderer = (spec, scales, chartArea, strategy, _theme) => {
|
|
|
1044
1107
|
};
|
|
1045
1108
|
|
|
1046
1109
|
// src/charts/column/compute.ts
|
|
1047
|
-
import { abbreviateNumber as abbreviateNumber2, formatNumber as formatNumber2 } from "@opendata-ai/openchart-core";
|
|
1110
|
+
import { abbreviateNumber as abbreviateNumber2, formatNumber as formatNumber2, isGradientDef as isGradientDef2 } from "@opendata-ai/openchart-core";
|
|
1048
1111
|
var MIN_COLUMN_HEIGHT = 1;
|
|
1049
1112
|
function formatColumnValue(value2) {
|
|
1050
1113
|
if (Math.abs(value2) >= 1e3) return abbreviateNumber2(value2);
|
|
@@ -1072,6 +1135,20 @@ function computeColumnMarks(spec, scales, _chartArea, _strategy) {
|
|
|
1072
1135
|
const categoryGroups = groupByField(spec.data, xChannel.field);
|
|
1073
1136
|
const needsStacking = Array.from(categoryGroups.values()).some((rows) => rows.length > 1);
|
|
1074
1137
|
if (needsStacking) {
|
|
1138
|
+
const stackDisabled = yChannel.stack === null || yChannel.stack === false;
|
|
1139
|
+
if (stackDisabled) {
|
|
1140
|
+
return computeGroupedColumns(
|
|
1141
|
+
spec.data,
|
|
1142
|
+
xChannel.field,
|
|
1143
|
+
yChannel.field,
|
|
1144
|
+
colorField,
|
|
1145
|
+
xScale,
|
|
1146
|
+
yScale,
|
|
1147
|
+
bandwidth,
|
|
1148
|
+
baseline,
|
|
1149
|
+
scales
|
|
1150
|
+
);
|
|
1151
|
+
}
|
|
1075
1152
|
return computeStackedColumns(
|
|
1076
1153
|
spec.data,
|
|
1077
1154
|
xChannel.field,
|
|
@@ -1119,9 +1196,12 @@ function computeSimpleColumns(data, categoryField, valueField, xScale, yScale, b
|
|
|
1119
1196
|
if (bandX === void 0) continue;
|
|
1120
1197
|
let color2;
|
|
1121
1198
|
if (conditionalColor) {
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1199
|
+
const resolved = resolveConditionalValue(row, conditionalColor);
|
|
1200
|
+
if (resolved != null) {
|
|
1201
|
+
color2 = isGradientDef2(resolved) ? resolved : String(resolved);
|
|
1202
|
+
} else {
|
|
1203
|
+
color2 = getColor(scales, "__default__");
|
|
1204
|
+
}
|
|
1125
1205
|
} else if (sequentialColor) {
|
|
1126
1206
|
color2 = getSequentialColor(scales, value2);
|
|
1127
1207
|
} else {
|
|
@@ -1179,6 +1259,55 @@ function computeColoredColumns(data, categoryField, valueField, colorField, xSca
|
|
|
1179
1259
|
}
|
|
1180
1260
|
return marks;
|
|
1181
1261
|
}
|
|
1262
|
+
function computeGroupedColumns(data, categoryField, valueField, colorField, xScale, yScale, bandwidth, baseline, scales) {
|
|
1263
|
+
const marks = [];
|
|
1264
|
+
const categoryGroups = groupByField(data, categoryField);
|
|
1265
|
+
const groupIndexMap = /* @__PURE__ */ new Map();
|
|
1266
|
+
for (const row of data) {
|
|
1267
|
+
const key = String(row[colorField] ?? "");
|
|
1268
|
+
if (!groupIndexMap.has(key)) {
|
|
1269
|
+
groupIndexMap.set(key, groupIndexMap.size);
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
const groupCount = groupIndexMap.size;
|
|
1273
|
+
if (groupCount === 0) return marks;
|
|
1274
|
+
const gap = Math.min(1, bandwidth * 0.05);
|
|
1275
|
+
const subBandWidth = Math.max(
|
|
1276
|
+
(bandwidth - gap * (groupCount - 1)) / groupCount,
|
|
1277
|
+
MIN_COLUMN_HEIGHT
|
|
1278
|
+
);
|
|
1279
|
+
for (const [category, rows] of categoryGroups) {
|
|
1280
|
+
const bandX = xScale(category);
|
|
1281
|
+
if (bandX === void 0) continue;
|
|
1282
|
+
for (const row of rows) {
|
|
1283
|
+
const groupKey = String(row[colorField] ?? "");
|
|
1284
|
+
const value2 = Number(row[valueField] ?? 0);
|
|
1285
|
+
if (!Number.isFinite(value2)) continue;
|
|
1286
|
+
const groupIndex = groupIndexMap.get(groupKey) ?? 0;
|
|
1287
|
+
const color2 = getColor(scales, groupKey);
|
|
1288
|
+
const yPos = yScale(value2);
|
|
1289
|
+
const columnHeight = Math.max(Math.abs(baseline - yPos), MIN_COLUMN_HEIGHT);
|
|
1290
|
+
const y2 = value2 >= 0 ? yPos : baseline;
|
|
1291
|
+
const subX = bandX + groupIndex * (subBandWidth + gap);
|
|
1292
|
+
const aria = {
|
|
1293
|
+
label: `${category}, ${groupKey}: ${formatColumnValue(value2)}`
|
|
1294
|
+
};
|
|
1295
|
+
marks.push({
|
|
1296
|
+
type: "rect",
|
|
1297
|
+
x: subX,
|
|
1298
|
+
y: y2,
|
|
1299
|
+
width: subBandWidth,
|
|
1300
|
+
height: columnHeight,
|
|
1301
|
+
fill: color2,
|
|
1302
|
+
cornerRadius: 2,
|
|
1303
|
+
data: row,
|
|
1304
|
+
aria,
|
|
1305
|
+
orient: "vertical"
|
|
1306
|
+
});
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
return marks;
|
|
1310
|
+
}
|
|
1182
1311
|
function computeStackedColumns(data, categoryField, valueField, colorField, xScale, yScale, bandwidth, _baseline, scales) {
|
|
1183
1312
|
const marks = [];
|
|
1184
1313
|
const categoryGroups = groupByField(data, categoryField);
|
|
@@ -1220,6 +1349,7 @@ function computeStackedColumns(data, categoryField, valueField, colorField, xSca
|
|
|
1220
1349
|
import {
|
|
1221
1350
|
buildD3Formatter as buildD3Formatter2,
|
|
1222
1351
|
estimateTextWidth as estimateTextWidth3,
|
|
1352
|
+
getRepresentativeColor as getRepresentativeColor2,
|
|
1223
1353
|
resolveCollisions as resolveCollisions2
|
|
1224
1354
|
} from "@opendata-ai/openchart-core";
|
|
1225
1355
|
var LABEL_FONT_SIZE2 = 10;
|
|
@@ -1258,7 +1388,7 @@ function computeColumnLabels(marks, _chartArea, density = "auto", labelFormat, l
|
|
|
1258
1388
|
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
1259
1389
|
fontSize: LABEL_FONT_SIZE2,
|
|
1260
1390
|
fontWeight: LABEL_FONT_WEIGHT2,
|
|
1261
|
-
fill: mark.fill,
|
|
1391
|
+
fill: getRepresentativeColor2(mark.fill),
|
|
1262
1392
|
lineHeight: 1.2,
|
|
1263
1393
|
textAnchor: "middle",
|
|
1264
1394
|
dominantBaseline: isNegative ? "hanging" : "auto"
|
|
@@ -1443,7 +1573,11 @@ function computeLollipopMarks(data, valueField, categoryField, xScale, yScale, b
|
|
|
1443
1573
|
}
|
|
1444
1574
|
|
|
1445
1575
|
// src/charts/dot/labels.ts
|
|
1446
|
-
import {
|
|
1576
|
+
import {
|
|
1577
|
+
estimateTextWidth as estimateTextWidth4,
|
|
1578
|
+
getRepresentativeColor as getRepresentativeColor3,
|
|
1579
|
+
resolveCollisions as resolveCollisions3
|
|
1580
|
+
} from "@opendata-ai/openchart-core";
|
|
1447
1581
|
var LABEL_FONT_SIZE3 = 11;
|
|
1448
1582
|
var LABEL_FONT_WEIGHT3 = 600;
|
|
1449
1583
|
var LABEL_OFFSET_X = 10;
|
|
@@ -1470,7 +1604,7 @@ function computeDotLabels(marks, _chartArea, density = "auto", labelPrefix) {
|
|
|
1470
1604
|
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
1471
1605
|
fontSize: LABEL_FONT_SIZE3,
|
|
1472
1606
|
fontWeight: LABEL_FONT_WEIGHT3,
|
|
1473
|
-
fill: mark.fill,
|
|
1607
|
+
fill: getRepresentativeColor3(mark.fill),
|
|
1474
1608
|
lineHeight: 1.2,
|
|
1475
1609
|
textAnchor: "start",
|
|
1476
1610
|
dominantBaseline: "central"
|
|
@@ -1505,6 +1639,9 @@ var dotRenderer = (spec, scales, chartArea, strategy, _theme) => {
|
|
|
1505
1639
|
return marks;
|
|
1506
1640
|
};
|
|
1507
1641
|
|
|
1642
|
+
// src/charts/line/area.ts
|
|
1643
|
+
import { getRepresentativeColor as getRepresentativeColor4 } from "@opendata-ai/openchart-core";
|
|
1644
|
+
|
|
1508
1645
|
// ../../node_modules/.bun/d3-shape@3.2.0/node_modules/d3-shape/src/constant.js
|
|
1509
1646
|
function constant_default(x2) {
|
|
1510
1647
|
return function constant2() {
|
|
@@ -2459,7 +2596,7 @@ function computeSingleArea(spec, scales, _chartArea) {
|
|
|
2459
2596
|
topPath: topPathStr,
|
|
2460
2597
|
fill: color2,
|
|
2461
2598
|
fillOpacity: DEFAULT_FILL_OPACITY,
|
|
2462
|
-
stroke: color2,
|
|
2599
|
+
stroke: getRepresentativeColor4(color2),
|
|
2463
2600
|
strokeWidth: 2,
|
|
2464
2601
|
seriesKey: seriesKey === "__default__" ? void 0 : seriesKey,
|
|
2465
2602
|
data: validPoints.map((p) => p.row),
|
|
@@ -2546,7 +2683,7 @@ function computeStackedArea(spec, scales, chartArea) {
|
|
|
2546
2683
|
fill: color2,
|
|
2547
2684
|
fillOpacity: 0.7,
|
|
2548
2685
|
// Higher opacity for stacked so layers are visible
|
|
2549
|
-
stroke: color2,
|
|
2686
|
+
stroke: getRepresentativeColor4(color2),
|
|
2550
2687
|
strokeWidth: 1,
|
|
2551
2688
|
seriesKey,
|
|
2552
2689
|
data: layer.map((d) => {
|
|
@@ -2573,6 +2710,7 @@ function computeAreaMarks(spec, scales, chartArea) {
|
|
|
2573
2710
|
}
|
|
2574
2711
|
|
|
2575
2712
|
// src/charts/line/compute.ts
|
|
2713
|
+
import { getRepresentativeColor as getRepresentativeColor5 } from "@opendata-ai/openchart-core";
|
|
2576
2714
|
var DEFAULT_STROKE_WIDTH = 2.5;
|
|
2577
2715
|
var DEFAULT_POINT_RADIUS = 3;
|
|
2578
2716
|
function computeLineMarks(spec, scales, _chartArea, _strategy) {
|
|
@@ -2590,6 +2728,7 @@ function computeLineMarks(spec, scales, _chartArea, _strategy) {
|
|
|
2590
2728
|
const marks = [];
|
|
2591
2729
|
for (const [seriesKey, rows] of groups) {
|
|
2592
2730
|
const color2 = isSequentialColor ? getSequentialColor(scales, _getMidValue(rows, sequentialColorField)) : getColor(scales, seriesKey);
|
|
2731
|
+
const strokeColor = getRepresentativeColor5(color2);
|
|
2593
2732
|
const sortedRows = sortByField(rows, xChannel.field);
|
|
2594
2733
|
const pointsWithData = [];
|
|
2595
2734
|
const segments = [];
|
|
@@ -2638,7 +2777,7 @@ function computeLineMarks(spec, scales, _chartArea, _strategy) {
|
|
|
2638
2777
|
type: "line",
|
|
2639
2778
|
points: allPoints,
|
|
2640
2779
|
path: combinedPath,
|
|
2641
|
-
stroke:
|
|
2780
|
+
stroke: strokeColor,
|
|
2642
2781
|
strokeWidth: styleOverride?.strokeWidth ?? DEFAULT_STROKE_WIDTH,
|
|
2643
2782
|
strokeDasharray,
|
|
2644
2783
|
opacity: styleOverride?.opacity,
|
|
@@ -2783,6 +2922,7 @@ var areaRenderer = (spec, scales, chartArea, strategy, _theme) => {
|
|
|
2783
2922
|
};
|
|
2784
2923
|
|
|
2785
2924
|
// src/charts/pie/compute.ts
|
|
2925
|
+
import { isConditionalDef, isGradientDef as isGradientDef3 } from "@opendata-ai/openchart-core";
|
|
2786
2926
|
var SMALL_SLICE_THRESHOLD = 0.03;
|
|
2787
2927
|
var DEFAULT_PALETTE = [
|
|
2788
2928
|
"#1b7fa3",
|
|
@@ -2821,6 +2961,7 @@ function computePieMarks(spec, scales, chartArea, _strategy, isDonut = false) {
|
|
|
2821
2961
|
const encoding = spec.encoding;
|
|
2822
2962
|
const valueChannel = encoding.y ?? encoding.x;
|
|
2823
2963
|
const categoryField = encoding.color && "field" in encoding.color ? encoding.color.field : void 0;
|
|
2964
|
+
const conditionalColor = encoding.color && isConditionalDef(encoding.color) ? encoding.color : void 0;
|
|
2824
2965
|
if (!valueChannel) return [];
|
|
2825
2966
|
let slices = [];
|
|
2826
2967
|
if (categoryField) {
|
|
@@ -2871,7 +3012,20 @@ function computePieMarks(spec, scales, chartArea, _strategy, isDonut = false) {
|
|
|
2871
3012
|
const arcDatum = arcs[i];
|
|
2872
3013
|
const slice2 = arcDatum.data;
|
|
2873
3014
|
let color2;
|
|
2874
|
-
if (
|
|
3015
|
+
if (conditionalColor) {
|
|
3016
|
+
const resolved = resolveConditionalValue(
|
|
3017
|
+
slice2.originalRow,
|
|
3018
|
+
conditionalColor
|
|
3019
|
+
);
|
|
3020
|
+
if (resolved != null) {
|
|
3021
|
+
color2 = isGradientDef3(resolved) ? resolved : String(resolved);
|
|
3022
|
+
} else if (scales.color && categoryField) {
|
|
3023
|
+
const colorScale = scales.color.scale;
|
|
3024
|
+
color2 = colorScale(slice2.label);
|
|
3025
|
+
} else {
|
|
3026
|
+
color2 = DEFAULT_PALETTE[i % DEFAULT_PALETTE.length];
|
|
3027
|
+
}
|
|
3028
|
+
} else if (scales.color && categoryField) {
|
|
2875
3029
|
const colorScale = scales.color.scale;
|
|
2876
3030
|
color2 = colorScale(slice2.label);
|
|
2877
3031
|
} else {
|
|
@@ -3009,6 +3163,7 @@ function clearRenderers() {
|
|
|
3009
3163
|
}
|
|
3010
3164
|
|
|
3011
3165
|
// src/charts/rule/index.ts
|
|
3166
|
+
import { getRepresentativeColor as getRepresentativeColor6 } from "@opendata-ai/openchart-core";
|
|
3012
3167
|
function computeRuleMarks(spec, scales, chartArea) {
|
|
3013
3168
|
const encoding = spec.encoding;
|
|
3014
3169
|
const xChannel = encoding.x;
|
|
@@ -3051,7 +3206,9 @@ function computeRuleMarks(spec, scales, chartArea) {
|
|
|
3051
3206
|
const y2Val = scaleValue(scales.y.scale, scales.y.type, row[y2Channel.field]);
|
|
3052
3207
|
if (y2Val != null) y2 = y2Val;
|
|
3053
3208
|
}
|
|
3054
|
-
const color2 =
|
|
3209
|
+
const color2 = getRepresentativeColor6(
|
|
3210
|
+
colorField ? getColor(scales, String(row[colorField] ?? "__default__")) : getColor(scales, "__default__")
|
|
3211
|
+
);
|
|
3055
3212
|
const strokeDashEncoding = encoding.strokeDash && "field" in encoding.strokeDash ? encoding.strokeDash : void 0;
|
|
3056
3213
|
const strokeDasharray = strokeDashEncoding ? String(row[strokeDashEncoding.field] ?? "") : void 0;
|
|
3057
3214
|
const aria = {
|
|
@@ -5858,6 +6015,7 @@ var scatterRenderer = (spec, scales, chartArea, strategy, _theme) => {
|
|
|
5858
6015
|
};
|
|
5859
6016
|
|
|
5860
6017
|
// src/charts/text/index.ts
|
|
6018
|
+
import { getRepresentativeColor as getRepresentativeColor7 } from "@opendata-ai/openchart-core";
|
|
5861
6019
|
function computeTextMarks(spec, scales) {
|
|
5862
6020
|
const encoding = spec.encoding;
|
|
5863
6021
|
const xChannel = encoding.x;
|
|
@@ -5883,7 +6041,9 @@ function computeTextMarks(spec, scales) {
|
|
|
5883
6041
|
}
|
|
5884
6042
|
const text = String(row[textChannel.field] ?? "");
|
|
5885
6043
|
if (!text) continue;
|
|
5886
|
-
const color2 =
|
|
6044
|
+
const color2 = getRepresentativeColor7(
|
|
6045
|
+
colorField ? getColor(scales, String(row[colorField] ?? "__default__")) : getColor(scales, "__default__")
|
|
6046
|
+
);
|
|
5887
6047
|
const fontSize = sizeEncoding ? Math.max(8, Math.min(48, Number(row[sizeEncoding.field]) || 12)) : 12;
|
|
5888
6048
|
const aria = {
|
|
5889
6049
|
label: text
|
|
@@ -5908,6 +6068,7 @@ var textRenderer = (spec, scales, _chartArea, _strategy, _theme) => {
|
|
|
5908
6068
|
};
|
|
5909
6069
|
|
|
5910
6070
|
// src/charts/tick/index.ts
|
|
6071
|
+
import { getRepresentativeColor as getRepresentativeColor8 } from "@opendata-ai/openchart-core";
|
|
5911
6072
|
var DEFAULT_TICK_LENGTH = 18;
|
|
5912
6073
|
function computeTickMarks(spec, scales, _chartArea) {
|
|
5913
6074
|
const encoding = spec.encoding;
|
|
@@ -5923,7 +6084,9 @@ function computeTickMarks(spec, scales, _chartArea) {
|
|
|
5923
6084
|
const xVal = scaleValue(scales.x.scale, scales.x.type, row[xChannel.field]);
|
|
5924
6085
|
const yVal = scaleValue(scales.y.scale, scales.y.type, row[yChannel.field]);
|
|
5925
6086
|
if (xVal == null || yVal == null) continue;
|
|
5926
|
-
const color2 =
|
|
6087
|
+
const color2 = getRepresentativeColor8(
|
|
6088
|
+
colorField ? getColor(scales, String(row[colorField] ?? "__default__")) : getColor(scales, "__default__")
|
|
6089
|
+
);
|
|
5927
6090
|
const aria = {
|
|
5928
6091
|
label: `${row[xChannel.field]}, ${row[yChannel.field]}`
|
|
5929
6092
|
};
|
|
@@ -8130,7 +8293,8 @@ function computeScales(spec, chartArea, data) {
|
|
|
8130
8293
|
}
|
|
8131
8294
|
if (encoding.x) {
|
|
8132
8295
|
let xData = data;
|
|
8133
|
-
|
|
8296
|
+
const xStackDisabled = encoding.x.stack === null || encoding.x.stack === false;
|
|
8297
|
+
if (spec.markType === "bar" && encoding.color && encoding.x.type === "quantitative" && !xStackDisabled) {
|
|
8134
8298
|
const yField = encoding.y?.field;
|
|
8135
8299
|
const xField = encoding.x.field;
|
|
8136
8300
|
if (yField) {
|
|
@@ -8158,7 +8322,8 @@ function computeScales(spec, chartArea, data) {
|
|
|
8158
8322
|
if (encoding.y) {
|
|
8159
8323
|
let yData = data;
|
|
8160
8324
|
const isVerticalBar = spec.markType === "bar" && (encoding.x?.type === "nominal" || encoding.x?.type === "ordinal") && encoding.y.type === "quantitative";
|
|
8161
|
-
|
|
8325
|
+
const yStackDisabled = encoding.y.stack === null || encoding.y.stack === false;
|
|
8326
|
+
if ((isVerticalBar || spec.markType === "area") && encoding.color && encoding.y.type === "quantitative" && !yStackDisabled) {
|
|
8162
8327
|
const xField = encoding.x?.field;
|
|
8163
8328
|
const yField = encoding.y.field;
|
|
8164
8329
|
if (xField) {
|
|
@@ -9958,7 +10123,12 @@ function compileTableLayout(spec, options, theme) {
|
|
|
9958
10123
|
}
|
|
9959
10124
|
|
|
9960
10125
|
// src/tooltips/compute.ts
|
|
9961
|
-
import {
|
|
10126
|
+
import {
|
|
10127
|
+
buildTemporalFormatter as buildTemporalFormatter2,
|
|
10128
|
+
formatDate as formatDate3,
|
|
10129
|
+
formatNumber as formatNumber6,
|
|
10130
|
+
getRepresentativeColor as getRepresentativeColor9
|
|
10131
|
+
} from "@opendata-ai/openchart-core";
|
|
9962
10132
|
function formatValue(value2, fieldType, format2) {
|
|
9963
10133
|
if (value2 == null) return "";
|
|
9964
10134
|
if (fieldType === "temporal" || value2 instanceof Date) {
|
|
@@ -10042,12 +10212,12 @@ function tooltipsForLine(mark, encoding, _markIndex) {
|
|
|
10042
10212
|
}
|
|
10043
10213
|
function tooltipsForPoint(mark, encoding, markIndex) {
|
|
10044
10214
|
const title = getTooltipTitle(mark.data, encoding);
|
|
10045
|
-
const fields = buildFields(mark.data, encoding, mark.fill);
|
|
10215
|
+
const fields = buildFields(mark.data, encoding, getRepresentativeColor9(mark.fill));
|
|
10046
10216
|
return [[`point-${markIndex}`, { title, fields }]];
|
|
10047
10217
|
}
|
|
10048
10218
|
function tooltipsForRect(mark, encoding, markIndex) {
|
|
10049
10219
|
const title = getTooltipTitle(mark.data, encoding);
|
|
10050
|
-
const fields = buildFields(mark.data, encoding, mark.fill);
|
|
10220
|
+
const fields = buildFields(mark.data, encoding, getRepresentativeColor9(mark.fill));
|
|
10051
10221
|
return [[`rect-${markIndex}`, { title, fields }]];
|
|
10052
10222
|
}
|
|
10053
10223
|
function tooltipsForArc(mark, encoding, markIndex) {
|
|
@@ -10060,14 +10230,14 @@ function tooltipsForArc(mark, encoding, markIndex) {
|
|
|
10060
10230
|
fields.push({
|
|
10061
10231
|
label: categoryName,
|
|
10062
10232
|
value: formatValue(row[encoding.y.field], encoding.y.type, encoding.y.axis?.format),
|
|
10063
|
-
color: mark.fill
|
|
10233
|
+
color: getRepresentativeColor9(mark.fill)
|
|
10064
10234
|
});
|
|
10065
10235
|
}
|
|
10066
10236
|
} else if (encoding.y) {
|
|
10067
10237
|
fields.push({
|
|
10068
10238
|
label: encoding.y.field,
|
|
10069
10239
|
value: formatValue(row[encoding.y.field], encoding.y.type, encoding.y.axis?.format),
|
|
10070
|
-
color: mark.fill
|
|
10240
|
+
color: getRepresentativeColor9(mark.fill)
|
|
10071
10241
|
});
|
|
10072
10242
|
}
|
|
10073
10243
|
const title = colorEnc ? String(row[colorEnc.field] ?? "") : void 0;
|
|
@@ -10078,7 +10248,7 @@ function tooltipsForArea(mark, encoding, _markIndex) {
|
|
|
10078
10248
|
for (const dp of mark.dataPoints) {
|
|
10079
10249
|
dp.tooltip = {
|
|
10080
10250
|
title: getTooltipTitle(dp.datum, encoding),
|
|
10081
|
-
fields: buildFields(dp.datum, encoding, mark.fill)
|
|
10251
|
+
fields: buildFields(dp.datum, encoding, getRepresentativeColor9(mark.fill))
|
|
10082
10252
|
};
|
|
10083
10253
|
}
|
|
10084
10254
|
}
|
|
@@ -10506,7 +10676,7 @@ function compileChart(spec, options) {
|
|
|
10506
10676
|
);
|
|
10507
10677
|
}
|
|
10508
10678
|
}
|
|
10509
|
-
scales.defaultColor = theme.colors.categorical[0];
|
|
10679
|
+
scales.defaultColor = chartSpec.markDef.fill ?? theme.colors.categorical[0];
|
|
10510
10680
|
const isRadial = chartSpec.markType === "arc";
|
|
10511
10681
|
const axes = isRadial ? { x: void 0, y: void 0 } : computeAxes(scales, chartArea, strategy, theme, options.measureText);
|
|
10512
10682
|
if (!isRadial) {
|