@opendata-ai/openchart-engine 6.10.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 +72 -26
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/charts/bar/compute.ts +9 -5
- package/src/charts/bar/labels.ts +2 -1
- package/src/charts/column/compute.ts +9 -5
- 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 +2 -2
- package/src/tooltips/compute.ts +11 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opendata-ai/openchart-engine",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.11.0",
|
|
4
4
|
"description": "Headless compiler for openchart: spec validation, data compilation, scales, and layout",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Riley Hilliard",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"typecheck": "tsc --noEmit"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@opendata-ai/openchart-core": "6.
|
|
48
|
+
"@opendata-ai/openchart-core": "6.11.0",
|
|
49
49
|
"d3-array": "^3.2.0",
|
|
50
50
|
"d3-format": "^3.1.2",
|
|
51
51
|
"d3-interpolate": "^3.0.0",
|
|
@@ -10,12 +10,13 @@ import type {
|
|
|
10
10
|
ConditionalValueDef,
|
|
11
11
|
DataRow,
|
|
12
12
|
Encoding,
|
|
13
|
+
GradientDef,
|
|
13
14
|
LayoutStrategy,
|
|
14
15
|
MarkAria,
|
|
15
16
|
Rect,
|
|
16
17
|
RectMark,
|
|
17
18
|
} from '@opendata-ai/openchart-core';
|
|
18
|
-
import { abbreviateNumber, formatNumber } from '@opendata-ai/openchart-core';
|
|
19
|
+
import { abbreviateNumber, formatNumber, isGradientDef } from '@opendata-ai/openchart-core';
|
|
19
20
|
import type { ScaleBand, ScaleLinear } from 'd3-scale';
|
|
20
21
|
|
|
21
22
|
import type { NormalizedChartSpec } from '../../compiler/types';
|
|
@@ -339,11 +340,14 @@ function computeSimpleBars(
|
|
|
339
340
|
const bandY = yScale(category);
|
|
340
341
|
if (bandY === undefined) continue;
|
|
341
342
|
|
|
342
|
-
let color: string;
|
|
343
|
+
let color: string | GradientDef;
|
|
343
344
|
if (conditionalColor) {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
345
|
+
const resolved = resolveConditionalValue(row, conditionalColor);
|
|
346
|
+
if (resolved != null) {
|
|
347
|
+
color = isGradientDef(resolved) ? resolved : String(resolved);
|
|
348
|
+
} else {
|
|
349
|
+
color = getColor(scales, '__default__');
|
|
350
|
+
}
|
|
347
351
|
} else if (sequentialColor) {
|
|
348
352
|
color = getSequentialColor(scales, value);
|
|
349
353
|
} else {
|
package/src/charts/bar/labels.ts
CHANGED
|
@@ -20,6 +20,7 @@ import type {
|
|
|
20
20
|
import {
|
|
21
21
|
buildD3Formatter,
|
|
22
22
|
estimateTextWidth,
|
|
23
|
+
getRepresentativeColor,
|
|
23
24
|
resolveCollisions,
|
|
24
25
|
} from '@opendata-ai/openchart-core';
|
|
25
26
|
|
|
@@ -141,7 +142,7 @@ export function computeBarLabels(
|
|
|
141
142
|
} else {
|
|
142
143
|
// Outside: just past the bar's right edge
|
|
143
144
|
anchorX = mark.x + mark.width + LABEL_PADDING;
|
|
144
|
-
fill = mark.fill;
|
|
145
|
+
fill = getRepresentativeColor(mark.fill);
|
|
145
146
|
textAnchor = 'start';
|
|
146
147
|
}
|
|
147
148
|
|
|
@@ -14,12 +14,13 @@ import type {
|
|
|
14
14
|
ConditionalValueDef,
|
|
15
15
|
DataRow,
|
|
16
16
|
Encoding,
|
|
17
|
+
GradientDef,
|
|
17
18
|
LayoutStrategy,
|
|
18
19
|
MarkAria,
|
|
19
20
|
Rect,
|
|
20
21
|
RectMark,
|
|
21
22
|
} from '@opendata-ai/openchart-core';
|
|
22
|
-
import { abbreviateNumber, formatNumber } from '@opendata-ai/openchart-core';
|
|
23
|
+
import { abbreviateNumber, formatNumber, isGradientDef } from '@opendata-ai/openchart-core';
|
|
23
24
|
import type { ScaleBand, ScaleLinear } from 'd3-scale';
|
|
24
25
|
import type { NormalizedChartSpec } from '../../compiler/types';
|
|
25
26
|
import type { ResolvedScales } from '../../layout/scales';
|
|
@@ -169,11 +170,14 @@ function computeSimpleColumns(
|
|
|
169
170
|
const bandX = xScale(category);
|
|
170
171
|
if (bandX === undefined) continue;
|
|
171
172
|
|
|
172
|
-
let color: string;
|
|
173
|
+
let color: string | GradientDef;
|
|
173
174
|
if (conditionalColor) {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
175
|
+
const resolved = resolveConditionalValue(row, conditionalColor);
|
|
176
|
+
if (resolved != null) {
|
|
177
|
+
color = isGradientDef(resolved) ? resolved : String(resolved);
|
|
178
|
+
} else {
|
|
179
|
+
color = getColor(scales, '__default__');
|
|
180
|
+
}
|
|
177
181
|
} else if (sequentialColor) {
|
|
178
182
|
color = getSequentialColor(scales, value);
|
|
179
183
|
} else {
|
|
@@ -20,6 +20,7 @@ import type {
|
|
|
20
20
|
import {
|
|
21
21
|
buildD3Formatter,
|
|
22
22
|
estimateTextWidth,
|
|
23
|
+
getRepresentativeColor,
|
|
23
24
|
resolveCollisions,
|
|
24
25
|
} from '@opendata-ai/openchart-core';
|
|
25
26
|
|
|
@@ -99,7 +100,7 @@ export function computeColumnLabels(
|
|
|
99
100
|
fontFamily: 'system-ui, -apple-system, sans-serif',
|
|
100
101
|
fontSize: LABEL_FONT_SIZE,
|
|
101
102
|
fontWeight: LABEL_FONT_WEIGHT,
|
|
102
|
-
fill: mark.fill,
|
|
103
|
+
fill: getRepresentativeColor(mark.fill),
|
|
103
104
|
lineHeight: 1.2,
|
|
104
105
|
textAnchor: 'middle',
|
|
105
106
|
dominantBaseline: isNegative ? 'hanging' : 'auto',
|
package/src/charts/dot/labels.ts
CHANGED
|
@@ -17,7 +17,11 @@ import type {
|
|
|
17
17
|
Rect,
|
|
18
18
|
ResolvedLabel,
|
|
19
19
|
} from '@opendata-ai/openchart-core';
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
estimateTextWidth,
|
|
22
|
+
getRepresentativeColor,
|
|
23
|
+
resolveCollisions,
|
|
24
|
+
} from '@opendata-ai/openchart-core';
|
|
21
25
|
|
|
22
26
|
// ---------------------------------------------------------------------------
|
|
23
27
|
// Constants
|
|
@@ -74,7 +78,7 @@ export function computeDotLabels(
|
|
|
74
78
|
fontFamily: 'system-ui, -apple-system, sans-serif',
|
|
75
79
|
fontSize: LABEL_FONT_SIZE,
|
|
76
80
|
fontWeight: LABEL_FONT_WEIGHT,
|
|
77
|
-
fill: mark.fill,
|
|
81
|
+
fill: getRepresentativeColor(mark.fill),
|
|
78
82
|
lineHeight: 1.2,
|
|
79
83
|
textAnchor: 'start',
|
|
80
84
|
dominantBaseline: 'central',
|
package/src/charts/line/area.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type { AreaMark, DataRow, Encoding, MarkAria, Rect } from '@opendata-ai/openchart-core';
|
|
10
|
+
import { getRepresentativeColor } from '@opendata-ai/openchart-core';
|
|
10
11
|
import type { ScaleLinear } from 'd3-scale';
|
|
11
12
|
import { area, line, stack, stackOffsetNone, stackOrderNone } from 'd3-shape';
|
|
12
13
|
|
|
@@ -122,7 +123,7 @@ function computeSingleArea(
|
|
|
122
123
|
topPath: topPathStr,
|
|
123
124
|
fill: color,
|
|
124
125
|
fillOpacity: DEFAULT_FILL_OPACITY,
|
|
125
|
-
stroke: color,
|
|
126
|
+
stroke: getRepresentativeColor(color),
|
|
126
127
|
strokeWidth: 2,
|
|
127
128
|
seriesKey: seriesKey === '__default__' ? undefined : seriesKey,
|
|
128
129
|
data: validPoints.map((p) => p.row),
|
|
@@ -258,7 +259,7 @@ function computeStackedArea(
|
|
|
258
259
|
topPath: topPathStr,
|
|
259
260
|
fill: color,
|
|
260
261
|
fillOpacity: 0.7, // Higher opacity for stacked so layers are visible
|
|
261
|
-
stroke: color,
|
|
262
|
+
stroke: getRepresentativeColor(color),
|
|
262
263
|
strokeWidth: 1,
|
|
263
264
|
seriesKey,
|
|
264
265
|
data: layer.map((d) => {
|
|
@@ -10,12 +10,14 @@
|
|
|
10
10
|
import type {
|
|
11
11
|
DataRow,
|
|
12
12
|
Encoding,
|
|
13
|
+
GradientDef,
|
|
13
14
|
LayoutStrategy,
|
|
14
15
|
LineMark,
|
|
15
16
|
MarkAria,
|
|
16
17
|
PointMark,
|
|
17
18
|
Rect,
|
|
18
19
|
} from '@opendata-ai/openchart-core';
|
|
20
|
+
import { getRepresentativeColor } from '@opendata-ai/openchart-core';
|
|
19
21
|
import { line } from 'd3-shape';
|
|
20
22
|
|
|
21
23
|
import type { NormalizedChartSpec } from '../../compiler/types';
|
|
@@ -68,9 +70,10 @@ export function computeLineMarks(
|
|
|
68
70
|
|
|
69
71
|
for (const [seriesKey, rows] of groups) {
|
|
70
72
|
// For sequential color, use a mid-range color for the line stroke
|
|
71
|
-
const color = isSequentialColor
|
|
73
|
+
const color: string | GradientDef = isSequentialColor
|
|
72
74
|
? getSequentialColor(scales, _getMidValue(rows, sequentialColorField!))
|
|
73
75
|
: getColor(scales, seriesKey);
|
|
76
|
+
const strokeColor = getRepresentativeColor(color);
|
|
74
77
|
|
|
75
78
|
// Sort rows by x-axis field so lines draw left-to-right
|
|
76
79
|
const sortedRows = sortByField(rows, xChannel.field);
|
|
@@ -165,7 +168,7 @@ export function computeLineMarks(
|
|
|
165
168
|
type: 'line',
|
|
166
169
|
points: allPoints,
|
|
167
170
|
path: combinedPath,
|
|
168
|
-
stroke:
|
|
171
|
+
stroke: strokeColor,
|
|
169
172
|
strokeWidth: styleOverride?.strokeWidth ?? DEFAULT_STROKE_WIDTH,
|
|
170
173
|
strokeDasharray,
|
|
171
174
|
opacity: styleOverride?.opacity,
|
|
@@ -8,17 +8,21 @@
|
|
|
8
8
|
|
|
9
9
|
import type {
|
|
10
10
|
ArcMark,
|
|
11
|
+
ConditionalValueDef,
|
|
11
12
|
DataRow,
|
|
12
13
|
Encoding,
|
|
14
|
+
GradientDef,
|
|
13
15
|
LayoutStrategy,
|
|
14
16
|
MarkAria,
|
|
15
17
|
Rect,
|
|
16
18
|
} from '@opendata-ai/openchart-core';
|
|
19
|
+
import { isConditionalDef, isGradientDef } from '@opendata-ai/openchart-core';
|
|
17
20
|
import type { PieArcDatum } from 'd3-shape';
|
|
18
21
|
import { arc as d3Arc, pie as d3Pie } from 'd3-shape';
|
|
19
22
|
|
|
20
23
|
import type { NormalizedChartSpec } from '../../compiler/types';
|
|
21
24
|
import type { ResolvedScales } from '../../layout/scales';
|
|
25
|
+
import { resolveConditionalValue } from '../../transforms/conditional';
|
|
22
26
|
|
|
23
27
|
// ---------------------------------------------------------------------------
|
|
24
28
|
// Constants
|
|
@@ -109,6 +113,10 @@ export function computePieMarks(
|
|
|
109
113
|
const valueChannel = encoding.y ?? encoding.x;
|
|
110
114
|
const categoryField =
|
|
111
115
|
encoding.color && 'field' in encoding.color ? encoding.color.field : undefined;
|
|
116
|
+
const conditionalColor =
|
|
117
|
+
encoding.color && isConditionalDef(encoding.color)
|
|
118
|
+
? (encoding.color as ConditionalValueDef)
|
|
119
|
+
: undefined;
|
|
112
120
|
|
|
113
121
|
if (!valueChannel) return [];
|
|
114
122
|
|
|
@@ -190,9 +198,22 @@ export function computePieMarks(
|
|
|
190
198
|
const arcDatum = arcs[i];
|
|
191
199
|
const slice = arcDatum.data;
|
|
192
200
|
|
|
193
|
-
// Get color
|
|
194
|
-
let color: string;
|
|
195
|
-
if (
|
|
201
|
+
// Get color: conditional (supports gradients) > scale > default palette
|
|
202
|
+
let color: string | GradientDef;
|
|
203
|
+
if (conditionalColor) {
|
|
204
|
+
const resolved = resolveConditionalValue(
|
|
205
|
+
slice.originalRow as Record<string, unknown>,
|
|
206
|
+
conditionalColor,
|
|
207
|
+
);
|
|
208
|
+
if (resolved != null) {
|
|
209
|
+
color = isGradientDef(resolved) ? resolved : String(resolved);
|
|
210
|
+
} else if (scales.color && categoryField) {
|
|
211
|
+
const colorScale = scales.color.scale as (v: string) => string;
|
|
212
|
+
color = colorScale(slice.label);
|
|
213
|
+
} else {
|
|
214
|
+
color = DEFAULT_PALETTE[i % DEFAULT_PALETTE.length];
|
|
215
|
+
}
|
|
216
|
+
} else if (scales.color && categoryField) {
|
|
196
217
|
const colorScale = scales.color.scale as (v: string) => string;
|
|
197
218
|
color = colorScale(slice.label);
|
|
198
219
|
} else {
|
package/src/charts/rule/index.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type { Encoding, Mark, MarkAria, Rect, RuleMarkLayout } from '@opendata-ai/openchart-core';
|
|
10
|
+
import { getRepresentativeColor } from '@opendata-ai/openchart-core';
|
|
10
11
|
|
|
11
12
|
import type { NormalizedChartSpec } from '../../compiler/types';
|
|
12
13
|
import type { ResolvedScales } from '../../layout/scales';
|
|
@@ -84,9 +85,11 @@ export function computeRuleMarks(
|
|
|
84
85
|
if (y2Val != null) y2 = y2Val;
|
|
85
86
|
}
|
|
86
87
|
|
|
87
|
-
const color =
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
const color = getRepresentativeColor(
|
|
89
|
+
colorField
|
|
90
|
+
? getColor(scales, String(row[colorField] ?? '__default__'))
|
|
91
|
+
: getColor(scales, '__default__'),
|
|
92
|
+
);
|
|
90
93
|
|
|
91
94
|
const strokeDashEncoding =
|
|
92
95
|
encoding.strokeDash && 'field' in encoding.strokeDash ? encoding.strokeDash : undefined;
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import type {
|
|
11
11
|
Encoding,
|
|
12
12
|
FieldType,
|
|
13
|
+
GradientDef,
|
|
13
14
|
LayoutStrategy,
|
|
14
15
|
MarkAria,
|
|
15
16
|
PointMark,
|
|
@@ -139,7 +140,7 @@ export function computeScatterMarks(
|
|
|
139
140
|
if (cx === undefined || cy === undefined) continue;
|
|
140
141
|
|
|
141
142
|
const category = colorField && !isSequentialColor ? String(row[colorField] ?? '') : undefined;
|
|
142
|
-
let color: string;
|
|
143
|
+
let color: string | GradientDef;
|
|
143
144
|
if (isSequentialColor && colorField) {
|
|
144
145
|
const val = Number(row[colorField]);
|
|
145
146
|
color = Number.isFinite(val)
|
package/src/charts/text/index.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type { Encoding, Mark, MarkAria, TextMarkLayout } from '@opendata-ai/openchart-core';
|
|
10
|
+
import { getRepresentativeColor } from '@opendata-ai/openchart-core';
|
|
10
11
|
|
|
11
12
|
import type { NormalizedChartSpec } from '../../compiler/types';
|
|
12
13
|
import type { ResolvedScales } from '../../layout/scales';
|
|
@@ -52,9 +53,11 @@ export function computeTextMarks(
|
|
|
52
53
|
const text = String(row[textChannel.field] ?? '');
|
|
53
54
|
if (!text) continue;
|
|
54
55
|
|
|
55
|
-
const color =
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
const color = getRepresentativeColor(
|
|
57
|
+
colorField
|
|
58
|
+
? getColor(scales, String(row[colorField] ?? '__default__'))
|
|
59
|
+
: getColor(scales, '__default__'),
|
|
60
|
+
);
|
|
58
61
|
|
|
59
62
|
const fontSize = sizeEncoding
|
|
60
63
|
? Math.max(8, Math.min(48, Number(row[sizeEncoding.field]) || 12))
|
package/src/charts/tick/index.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type { Encoding, Mark, MarkAria, Rect, TickMarkLayout } from '@opendata-ai/openchart-core';
|
|
10
|
+
import { getRepresentativeColor } from '@opendata-ai/openchart-core';
|
|
10
11
|
|
|
11
12
|
import type { NormalizedChartSpec } from '../../compiler/types';
|
|
12
13
|
import type { ResolvedScales } from '../../layout/scales';
|
|
@@ -48,9 +49,11 @@ export function computeTickMarks(
|
|
|
48
49
|
const yVal = scaleValue(scales.y.scale, scales.y.type, row[yChannel.field]);
|
|
49
50
|
if (xVal == null || yVal == null) continue;
|
|
50
51
|
|
|
51
|
-
const color =
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
const color = getRepresentativeColor(
|
|
53
|
+
colorField
|
|
54
|
+
? getColor(scales, String(row[colorField] ?? '__default__'))
|
|
55
|
+
: getColor(scales, '__default__'),
|
|
56
|
+
);
|
|
54
57
|
|
|
55
58
|
const aria: MarkAria = {
|
|
56
59
|
label: `${row[xChannel.field]}, ${row[yChannel.field]}`,
|
package/src/charts/utils.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* data grouping, color lookup, and shared constants.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type { DataRow } from '@opendata-ai/openchart-core';
|
|
8
|
+
import type { DataRow, GradientDef } from '@opendata-ai/openchart-core';
|
|
9
9
|
import type { ScaleBand, ScaleLinear, ScalePoint, ScaleTime } from 'd3-scale';
|
|
10
10
|
import type { D3Scale, ResolvedScales } from '../layout/scales';
|
|
11
11
|
|
|
@@ -143,7 +143,7 @@ export function getColor(
|
|
|
143
143
|
key: string,
|
|
144
144
|
_index?: number,
|
|
145
145
|
fallback: string = DEFAULT_COLOR,
|
|
146
|
-
): string {
|
|
146
|
+
): string | GradientDef {
|
|
147
147
|
if (scales.color && key !== '__default__') {
|
|
148
148
|
const colorScale = scales.color.scale as (v: string) => string;
|
|
149
149
|
return colorScale(key);
|
|
@@ -159,7 +159,7 @@ export function getSequentialColor(
|
|
|
159
159
|
scales: ResolvedScales,
|
|
160
160
|
value: number,
|
|
161
161
|
fallback: string = DEFAULT_COLOR,
|
|
162
|
-
): string {
|
|
162
|
+
): string | GradientDef {
|
|
163
163
|
if (scales.color?.type === 'sequential') {
|
|
164
164
|
const colorScale = scales.color.scale as unknown as (v: number) => string;
|
|
165
165
|
return colorScale(value);
|
package/src/compile.ts
CHANGED
|
@@ -386,8 +386,9 @@ export function compileChart(spec: unknown, options: CompileOptions): ChartLayou
|
|
|
386
386
|
}
|
|
387
387
|
}
|
|
388
388
|
|
|
389
|
-
// Set default color for single-series charts
|
|
390
|
-
|
|
389
|
+
// Set default color for single-series charts. If the user set a fill on the mark def
|
|
390
|
+
// (string or gradient), that takes priority over the theme's first categorical color.
|
|
391
|
+
scales.defaultColor = chartSpec.markDef.fill ?? theme.colors.categorical[0];
|
|
391
392
|
|
|
392
393
|
// Arc charts (pie/donut) don't use axes or gridlines
|
|
393
394
|
const isRadial = chartSpec.markType === 'arc';
|
package/src/layout/scales.ts
CHANGED
|
@@ -99,8 +99,8 @@ export interface ResolvedScales {
|
|
|
99
99
|
y?: ResolvedScale;
|
|
100
100
|
color?: ResolvedScale;
|
|
101
101
|
size?: ResolvedScale;
|
|
102
|
-
/** Default color for single-series charts (first categorical palette color). */
|
|
103
|
-
defaultColor?: string;
|
|
102
|
+
/** Default color for single-series charts (first categorical palette color or markDef.fill gradient). */
|
|
103
|
+
defaultColor?: string | import('@opendata-ai/openchart-core').GradientDef;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
// ---------------------------------------------------------------------------
|
package/src/tooltips/compute.ts
CHANGED
|
@@ -19,7 +19,12 @@ import type {
|
|
|
19
19
|
TooltipContent,
|
|
20
20
|
TooltipField,
|
|
21
21
|
} from '@opendata-ai/openchart-core';
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
buildTemporalFormatter,
|
|
24
|
+
formatDate,
|
|
25
|
+
formatNumber,
|
|
26
|
+
getRepresentativeColor,
|
|
27
|
+
} from '@opendata-ai/openchart-core';
|
|
23
28
|
import { format as d3Format } from 'd3-format';
|
|
24
29
|
|
|
25
30
|
import type { NormalizedChartSpec } from '../compiler/types';
|
|
@@ -155,7 +160,7 @@ function tooltipsForPoint(
|
|
|
155
160
|
markIndex: number,
|
|
156
161
|
): Array<[string, TooltipContent]> {
|
|
157
162
|
const title = getTooltipTitle(mark.data, encoding);
|
|
158
|
-
const fields = buildFields(mark.data, encoding, mark.fill);
|
|
163
|
+
const fields = buildFields(mark.data, encoding, getRepresentativeColor(mark.fill));
|
|
159
164
|
|
|
160
165
|
return [[`point-${markIndex}`, { title, fields }]];
|
|
161
166
|
}
|
|
@@ -166,7 +171,7 @@ function tooltipsForRect(
|
|
|
166
171
|
markIndex: number,
|
|
167
172
|
): Array<[string, TooltipContent]> {
|
|
168
173
|
const title = getTooltipTitle(mark.data, encoding);
|
|
169
|
-
const fields = buildFields(mark.data, encoding, mark.fill);
|
|
174
|
+
const fields = buildFields(mark.data, encoding, getRepresentativeColor(mark.fill));
|
|
170
175
|
|
|
171
176
|
return [[`rect-${markIndex}`, { title, fields }]];
|
|
172
177
|
}
|
|
@@ -187,14 +192,14 @@ function tooltipsForArc(
|
|
|
187
192
|
fields.push({
|
|
188
193
|
label: categoryName,
|
|
189
194
|
value: formatValue(row[encoding.y.field], encoding.y.type, encoding.y.axis?.format),
|
|
190
|
-
color: mark.fill,
|
|
195
|
+
color: getRepresentativeColor(mark.fill),
|
|
191
196
|
});
|
|
192
197
|
}
|
|
193
198
|
} else if (encoding.y) {
|
|
194
199
|
fields.push({
|
|
195
200
|
label: encoding.y.field,
|
|
196
201
|
value: formatValue(row[encoding.y.field], encoding.y.type, encoding.y.axis?.format),
|
|
197
|
-
color: mark.fill,
|
|
202
|
+
color: getRepresentativeColor(mark.fill),
|
|
198
203
|
});
|
|
199
204
|
}
|
|
200
205
|
|
|
@@ -214,7 +219,7 @@ function tooltipsForArea(
|
|
|
214
219
|
for (const dp of mark.dataPoints) {
|
|
215
220
|
dp.tooltip = {
|
|
216
221
|
title: getTooltipTitle(dp.datum, encoding),
|
|
217
|
-
fields: buildFields(dp.datum, encoding, mark.fill),
|
|
222
|
+
fields: buildFields(dp.datum, encoding, getRepresentativeColor(mark.fill)),
|
|
218
223
|
};
|
|
219
224
|
}
|
|
220
225
|
}
|