@opendata-ai/openchart-engine 8.0.0-rc.5 → 8.0.0-rc.7
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 +126 -36
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/annotation-behavior.test.ts +131 -0
- package/src/annotations/geometry.ts +7 -1
- package/src/annotations/resolve-text.ts +6 -0
- package/src/compiler/__tests__/validate-did-you-mean.test.ts +84 -0
- package/src/compiler/__tests__/validate-near-miss.test.ts +162 -0
- package/src/compiler/validate.ts +155 -27
- package/src/geo/__tests__/compile-map.test.ts +49 -0
- package/src/geo/compile-map.ts +24 -7
package/dist/index.js
CHANGED
|
@@ -244,7 +244,10 @@ function refreshConnector(connector, bounds, markerRadius) {
|
|
|
244
244
|
}
|
|
245
245
|
const exit = connectorExit(bounds, endpoint.x, endpoint.y);
|
|
246
246
|
if (!exit) return void 0;
|
|
247
|
-
const from = {
|
|
247
|
+
const from = {
|
|
248
|
+
x: exit.x + (connector.fromOffset?.dx ?? 0),
|
|
249
|
+
y: exit.y + (connector.fromOffset?.dy ?? 0)
|
|
250
|
+
};
|
|
248
251
|
const gap = connectorPullbackGap(markerRadius, connector.arrow);
|
|
249
252
|
const cdx = endpoint.x - from.x;
|
|
250
253
|
const cdy = endpoint.y - from.y;
|
|
@@ -506,6 +509,10 @@ function resolveTextAnnotation(annotation, scales, chartArea, isDark, measure =
|
|
|
506
509
|
from,
|
|
507
510
|
to,
|
|
508
511
|
endpoint,
|
|
512
|
+
fromOffset: annotation.connectorOffset?.from ? {
|
|
513
|
+
dx: annotation.connectorOffset.from.dx ?? 0,
|
|
514
|
+
dy: annotation.connectorOffset.from.dy ?? 0
|
|
515
|
+
} : void 0,
|
|
509
516
|
stroke: connectorStroke,
|
|
510
517
|
style: connectorStyle,
|
|
511
518
|
arrow: connectorArrow,
|
|
@@ -10729,6 +10736,7 @@ import {
|
|
|
10729
10736
|
MARK_ENCODING_RULES,
|
|
10730
10737
|
MARK_TYPES,
|
|
10731
10738
|
resolveSchemeName as resolveSchemeName2,
|
|
10739
|
+
SEQUENTIAL_PALETTES,
|
|
10732
10740
|
SUPPORTED_SCHEME_NAMES
|
|
10733
10741
|
} from "@opendata-ai/openchart-core";
|
|
10734
10742
|
var VALID_FIELD_TYPES = /* @__PURE__ */ new Set(["quantitative", "temporal", "nominal", "ordinal"]);
|
|
@@ -10787,6 +10795,53 @@ function didYouMean(field, columns) {
|
|
|
10787
10795
|
const match = nearestColumn(field, columns);
|
|
10788
10796
|
return match ? ` Did you mean "${match}"?` : "";
|
|
10789
10797
|
}
|
|
10798
|
+
function checkSchemeName(channelObj, channelPath, errors) {
|
|
10799
|
+
const scale = channelObj.scale;
|
|
10800
|
+
if (scale && typeof scale.scheme === "string" && !resolveSchemeName2(scale.scheme)) {
|
|
10801
|
+
errors.push({
|
|
10802
|
+
message: `Spec error: ${channelPath}.scale.scheme "${scale.scheme}" is not a supported scheme name`,
|
|
10803
|
+
path: `${channelPath}.scale.scheme`,
|
|
10804
|
+
code: "INVALID_VALUE",
|
|
10805
|
+
suggestion: `Use one of the supported scheme names: ${[...SUPPORTED_SCHEME_NAMES].join(", ")}. Or provide explicit colors via scale.range.`
|
|
10806
|
+
});
|
|
10807
|
+
}
|
|
10808
|
+
}
|
|
10809
|
+
function checkSchemeUnused(encoding, errors, familyNote, suggestion) {
|
|
10810
|
+
for (const [channel, ch] of Object.entries(encoding)) {
|
|
10811
|
+
if (!ch || typeof ch !== "object" || Array.isArray(ch)) continue;
|
|
10812
|
+
const scale = ch.scale;
|
|
10813
|
+
if (scale && typeof scale.scheme === "string") {
|
|
10814
|
+
errors.push({
|
|
10815
|
+
message: `Spec error: encoding.${channel}.scale.scheme has no effect \u2014 ${familyNote}`,
|
|
10816
|
+
path: `encoding.${channel}.scale.scheme`,
|
|
10817
|
+
code: "INVALID_VALUE",
|
|
10818
|
+
suggestion
|
|
10819
|
+
});
|
|
10820
|
+
}
|
|
10821
|
+
}
|
|
10822
|
+
}
|
|
10823
|
+
var MAP_PALETTE_NAMES = Object.keys(SEQUENTIAL_PALETTES).join(", ");
|
|
10824
|
+
function checkMapSchemeName(channelObj, channelPath, errors) {
|
|
10825
|
+
const scale = channelObj.scale;
|
|
10826
|
+
if (!scale || typeof scale.scheme !== "string") return;
|
|
10827
|
+
if (channelObj.type === "nominal" || channelObj.type === "ordinal") {
|
|
10828
|
+
errors.push({
|
|
10829
|
+
message: `Spec error: ${channelPath}.scale.scheme has no effect \u2014 categorical map colors come from scale.range and scale.domain`,
|
|
10830
|
+
path: `${channelPath}.scale.scheme`,
|
|
10831
|
+
code: "INVALID_VALUE",
|
|
10832
|
+
suggestion: "Remove scale.scheme. To customize categorical map colors, provide explicit colors via scale.range (with scale.domain for category order)."
|
|
10833
|
+
});
|
|
10834
|
+
return;
|
|
10835
|
+
}
|
|
10836
|
+
if (!(scale.scheme in SEQUENTIAL_PALETTES)) {
|
|
10837
|
+
errors.push({
|
|
10838
|
+
message: `Spec error: ${channelPath}.scale.scheme "${scale.scheme}" is not a supported map palette`,
|
|
10839
|
+
path: `${channelPath}.scale.scheme`,
|
|
10840
|
+
code: "INVALID_VALUE",
|
|
10841
|
+
suggestion: `Maps support the sequential palettes: ${MAP_PALETTE_NAMES}. The default is "blue".`
|
|
10842
|
+
});
|
|
10843
|
+
}
|
|
10844
|
+
}
|
|
10790
10845
|
var VALID_RANGE_STYLES = /* @__PURE__ */ new Set(["dumbbell", "arrow", "bar"]);
|
|
10791
10846
|
function validateRangeSpec(spec, errors) {
|
|
10792
10847
|
const encoding = spec.encoding;
|
|
@@ -11148,15 +11203,7 @@ function validateChartSpec(spec, errors) {
|
|
|
11148
11203
|
suggestion: `Use one of: ${[...VALID_FIELD_TYPES].join(", ")}`
|
|
11149
11204
|
});
|
|
11150
11205
|
}
|
|
11151
|
-
|
|
11152
|
-
if (channelScale && typeof channelScale.scheme === "string" && !resolveSchemeName2(channelScale.scheme)) {
|
|
11153
|
-
errors.push({
|
|
11154
|
-
message: `Spec error: encoding.${channel}.scale.scheme "${channelScale.scheme}" is not a supported scheme name`,
|
|
11155
|
-
path: `encoding.${channel}.scale.scheme`,
|
|
11156
|
-
code: "INVALID_VALUE",
|
|
11157
|
-
suggestion: `Use one of the supported scheme names: ${[...SUPPORTED_SCHEME_NAMES].join(", ")}. Or provide explicit colors via scale.range.`
|
|
11158
|
-
});
|
|
11159
|
-
}
|
|
11206
|
+
checkSchemeName(channelObj, `encoding.${channel}`, errors);
|
|
11160
11207
|
if (channelRule && channelObj.type && channelRule.allowedTypes.length > 0) {
|
|
11161
11208
|
if (!channelRule.allowedTypes.includes(channelObj.type)) {
|
|
11162
11209
|
errors.push({
|
|
@@ -11482,7 +11529,7 @@ function validateGraphSpec(spec, errors) {
|
|
|
11482
11529
|
message: `Spec error: edges[${i}].source "${edge.source}" does not reference an existing node id`,
|
|
11483
11530
|
path: `edges[${i}].source`,
|
|
11484
11531
|
code: "DATA_FIELD_MISSING",
|
|
11485
|
-
suggestion: `Use one of the existing node ids: ${[...nodeIds].slice(0, 5).join(", ")}${nodeIds.size > 5 ? "..." : ""}`
|
|
11532
|
+
suggestion: `Use one of the existing node ids: ${[...nodeIds].slice(0, 5).join(", ")}${nodeIds.size > 5 ? "..." : ""}.${didYouMean(edge.source, [...nodeIds])}`
|
|
11486
11533
|
});
|
|
11487
11534
|
}
|
|
11488
11535
|
if (typeof edge.target !== "string" || edge.target === "") {
|
|
@@ -11497,7 +11544,7 @@ function validateGraphSpec(spec, errors) {
|
|
|
11497
11544
|
message: `Spec error: edges[${i}].target "${edge.target}" does not reference an existing node id`,
|
|
11498
11545
|
path: `edges[${i}].target`,
|
|
11499
11546
|
code: "DATA_FIELD_MISSING",
|
|
11500
|
-
suggestion: `Use one of the existing node ids: ${[...nodeIds].slice(0, 5).join(", ")}${nodeIds.size > 5 ? "..." : ""}`
|
|
11547
|
+
suggestion: `Use one of the existing node ids: ${[...nodeIds].slice(0, 5).join(", ")}${nodeIds.size > 5 ? "..." : ""}.${didYouMean(edge.target, [...nodeIds])}`
|
|
11501
11548
|
});
|
|
11502
11549
|
}
|
|
11503
11550
|
}
|
|
@@ -11515,7 +11562,7 @@ function validateGraphSpec(spec, errors) {
|
|
|
11515
11562
|
message: `Spec error: encoding.${channel}.field "${ch.field}" does not exist on nodes. Available fields: ${[...nodeFields].join(", ")}`,
|
|
11516
11563
|
path: `encoding.${channel}.field`,
|
|
11517
11564
|
code: "DATA_FIELD_MISSING",
|
|
11518
|
-
suggestion: `Use one of the node fields: ${[...nodeFields].join(", ")}`
|
|
11565
|
+
suggestion: `Use one of the node fields: ${[...nodeFields].join(", ")}.${didYouMean(ch.field, [...nodeFields])}`
|
|
11519
11566
|
});
|
|
11520
11567
|
}
|
|
11521
11568
|
}
|
|
@@ -11527,10 +11574,16 @@ function validateGraphSpec(spec, errors) {
|
|
|
11527
11574
|
message: `Spec error: encoding.${channel}.field "${ch.field}" does not exist on edges. Available fields: ${[...edgeFields].join(", ")}`,
|
|
11528
11575
|
path: `encoding.${channel}.field`,
|
|
11529
11576
|
code: "DATA_FIELD_MISSING",
|
|
11530
|
-
suggestion: `Use one of the edge fields: ${[...edgeFields].join(", ")}`
|
|
11577
|
+
suggestion: `Use one of the edge fields: ${[...edgeFields].join(", ")}.${didYouMean(ch.field, [...edgeFields])}`
|
|
11531
11578
|
});
|
|
11532
11579
|
}
|
|
11533
11580
|
}
|
|
11581
|
+
checkSchemeUnused(
|
|
11582
|
+
encoding,
|
|
11583
|
+
errors,
|
|
11584
|
+
"graph colors come from scale.range and scale.domain",
|
|
11585
|
+
"Remove scale.scheme. To customize graph colors, provide explicit colors via scale.range."
|
|
11586
|
+
);
|
|
11534
11587
|
}
|
|
11535
11588
|
if (spec.layout && typeof spec.layout === "object") {
|
|
11536
11589
|
const layout = spec.layout;
|
|
@@ -11584,7 +11637,8 @@ function validateSankeySpec(spec, errors) {
|
|
|
11584
11637
|
}
|
|
11585
11638
|
const encoding = spec.encoding;
|
|
11586
11639
|
const dataColumns = new Set(Object.keys(firstRow));
|
|
11587
|
-
const
|
|
11640
|
+
const columnList = [...dataColumns];
|
|
11641
|
+
const availableColumns = columnList.join(", ");
|
|
11588
11642
|
for (const channel of ["source", "target", "value"]) {
|
|
11589
11643
|
const ch = encoding[channel];
|
|
11590
11644
|
if (!ch || typeof ch !== "object") {
|
|
@@ -11592,7 +11646,7 @@ function validateSankeySpec(spec, errors) {
|
|
|
11592
11646
|
message: `Spec error: sankey encoding requires "${channel}" channel`,
|
|
11593
11647
|
path: `encoding.${channel}`,
|
|
11594
11648
|
code: "MISSING_FIELD",
|
|
11595
|
-
suggestion: `Add encoding.${channel} with a field from your data (${availableColumns}). Example: ${channel}: { field: "${[
|
|
11649
|
+
suggestion: `Add encoding.${channel} with a field from your data (${availableColumns}). Example: ${channel}: { field: "${columnList[0] ?? "myField"}", type: "${channel === "value" ? "quantitative" : "nominal"}" }`
|
|
11596
11650
|
});
|
|
11597
11651
|
continue;
|
|
11598
11652
|
}
|
|
@@ -11610,10 +11664,16 @@ function validateSankeySpec(spec, errors) {
|
|
|
11610
11664
|
message: `Spec error: encoding.${channel}.field "${ch.field}" does not exist in data. Available columns: ${availableColumns}`,
|
|
11611
11665
|
path: `encoding.${channel}.field`,
|
|
11612
11666
|
code: "DATA_FIELD_MISSING",
|
|
11613
|
-
suggestion: `Use one of the available data columns: ${availableColumns}`
|
|
11667
|
+
suggestion: `Use one of the available data columns: ${availableColumns}.${didYouMean(ch.field, columnList)}`
|
|
11614
11668
|
});
|
|
11615
11669
|
}
|
|
11616
11670
|
}
|
|
11671
|
+
checkSchemeUnused(
|
|
11672
|
+
encoding,
|
|
11673
|
+
errors,
|
|
11674
|
+
"sankey node colors cycle the theme categorical palette",
|
|
11675
|
+
"Remove scale.scheme. To customize sankey colors, set theme.colors.categorical."
|
|
11676
|
+
);
|
|
11617
11677
|
if (spec.darkMode !== void 0 && !VALID_DARK_MODES.has(spec.darkMode)) {
|
|
11618
11678
|
errors.push({
|
|
11619
11679
|
message: 'Spec error: darkMode must be "auto", "force", or "off"',
|
|
@@ -11673,7 +11733,8 @@ function validateTileMapSpec(spec, errors) {
|
|
|
11673
11733
|
}
|
|
11674
11734
|
const encoding = spec.encoding;
|
|
11675
11735
|
const dataColumns = new Set(Object.keys(firstRow));
|
|
11676
|
-
const
|
|
11736
|
+
const columnList = [...dataColumns];
|
|
11737
|
+
const availableColumns = columnList.join(", ");
|
|
11677
11738
|
for (const channel of ["state", "value"]) {
|
|
11678
11739
|
const ch = encoding[channel];
|
|
11679
11740
|
if (!ch || typeof ch !== "object") {
|
|
@@ -11681,7 +11742,7 @@ function validateTileMapSpec(spec, errors) {
|
|
|
11681
11742
|
message: `Spec error: tilemap encoding requires "${channel}" channel`,
|
|
11682
11743
|
path: `encoding.${channel}`,
|
|
11683
11744
|
code: "MISSING_FIELD",
|
|
11684
|
-
suggestion: `Add encoding.${channel} with a field from your data (${availableColumns}). Example: ${channel}: { field: "${[
|
|
11745
|
+
suggestion: `Add encoding.${channel} with a field from your data (${availableColumns}). Example: ${channel}: { field: "${columnList[0] ?? "myField"}", type: "${channel === "value" ? "quantitative" : "nominal"}" }`
|
|
11685
11746
|
});
|
|
11686
11747
|
continue;
|
|
11687
11748
|
}
|
|
@@ -11699,11 +11760,19 @@ function validateTileMapSpec(spec, errors) {
|
|
|
11699
11760
|
message: `Spec error: encoding.${channel}.field "${ch.field}" does not exist in data. Available columns: ${availableColumns}`,
|
|
11700
11761
|
path: `encoding.${channel}.field`,
|
|
11701
11762
|
code: "DATA_FIELD_MISSING",
|
|
11702
|
-
suggestion: `Use one of the available data columns: ${availableColumns}`
|
|
11763
|
+
suggestion: `Use one of the available data columns: ${availableColumns}.${didYouMean(ch.field, columnList)}`
|
|
11703
11764
|
});
|
|
11704
11765
|
}
|
|
11705
11766
|
}
|
|
11706
11767
|
}
|
|
11768
|
+
if (spec.encoding && typeof spec.encoding === "object") {
|
|
11769
|
+
checkSchemeUnused(
|
|
11770
|
+
spec.encoding,
|
|
11771
|
+
errors,
|
|
11772
|
+
"tilemap fills come from the top-level palette property",
|
|
11773
|
+
`Remove scale.scheme and set the top-level palette property instead, e.g. palette: "green". Supported: ${MAP_PALETTE_NAMES}.`
|
|
11774
|
+
);
|
|
11775
|
+
}
|
|
11707
11776
|
if (spec.darkMode !== void 0 && !VALID_DARK_MODES.has(spec.darkMode)) {
|
|
11708
11777
|
errors.push({
|
|
11709
11778
|
message: 'Spec error: darkMode must be "auto", "force", or "off"',
|
|
@@ -11742,6 +11811,16 @@ function validateMapSpec(spec, errors) {
|
|
|
11742
11811
|
});
|
|
11743
11812
|
return;
|
|
11744
11813
|
}
|
|
11814
|
+
const mapEncoding = spec.encoding;
|
|
11815
|
+
if (mapEncoding.color && typeof mapEncoding.color === "object") {
|
|
11816
|
+
checkMapSchemeName(mapEncoding.color, "encoding.color", errors);
|
|
11817
|
+
}
|
|
11818
|
+
if (spec.points && typeof spec.points === "object") {
|
|
11819
|
+
const pointsLayer = spec.points;
|
|
11820
|
+
if (pointsLayer.color && typeof pointsLayer.color === "object") {
|
|
11821
|
+
checkMapSchemeName(pointsLayer.color, "points.color", errors);
|
|
11822
|
+
}
|
|
11823
|
+
}
|
|
11745
11824
|
if ("focus" in geo && geo.focus !== void 0 && geo.focus !== null) {
|
|
11746
11825
|
const focus = geo.focus;
|
|
11747
11826
|
if (typeof focus === "string" || typeof focus === "number") {
|
|
@@ -11951,7 +12030,8 @@ function validateBarListSpec(spec, errors) {
|
|
|
11951
12030
|
}
|
|
11952
12031
|
const encoding = spec.encoding;
|
|
11953
12032
|
const dataColumns = new Set(Object.keys(firstRow));
|
|
11954
|
-
const
|
|
12033
|
+
const columnList = [...dataColumns];
|
|
12034
|
+
const availableColumns = columnList.join(", ");
|
|
11955
12035
|
for (const channel of ["label", "value"]) {
|
|
11956
12036
|
const ch = encoding[channel];
|
|
11957
12037
|
if (!ch || typeof ch !== "object") {
|
|
@@ -11959,7 +12039,7 @@ function validateBarListSpec(spec, errors) {
|
|
|
11959
12039
|
message: `Spec error: barlist encoding requires "${channel}" channel`,
|
|
11960
12040
|
path: `encoding.${channel}`,
|
|
11961
12041
|
code: "MISSING_FIELD",
|
|
11962
|
-
suggestion: `Add encoding.${channel} with a field from your data (${availableColumns}). Example: ${channel}: { field: "${[
|
|
12042
|
+
suggestion: `Add encoding.${channel} with a field from your data (${availableColumns}). Example: ${channel}: { field: "${columnList[0] ?? "myField"}", type: "${channel === "value" ? "quantitative" : "nominal"}" }`
|
|
11963
12043
|
});
|
|
11964
12044
|
continue;
|
|
11965
12045
|
}
|
|
@@ -11977,7 +12057,7 @@ function validateBarListSpec(spec, errors) {
|
|
|
11977
12057
|
message: `Spec error: encoding.${channel}.field "${ch.field}" does not exist in data. Available columns: ${availableColumns}`,
|
|
11978
12058
|
path: `encoding.${channel}.field`,
|
|
11979
12059
|
code: "DATA_FIELD_MISSING",
|
|
11980
|
-
suggestion: `Use one of the available data columns: ${availableColumns}`
|
|
12060
|
+
suggestion: `Use one of the available data columns: ${availableColumns}.${didYouMean(ch.field, columnList)}`
|
|
11981
12061
|
});
|
|
11982
12062
|
}
|
|
11983
12063
|
}
|
|
@@ -11990,10 +12070,16 @@ function validateBarListSpec(spec, errors) {
|
|
|
11990
12070
|
message: `Spec error: encoding.${channel}.field "${field}" does not exist in data. Available columns: ${availableColumns}`,
|
|
11991
12071
|
path: `encoding.${channel}.field`,
|
|
11992
12072
|
code: "DATA_FIELD_MISSING",
|
|
11993
|
-
suggestion: `Use one of the available data columns: ${availableColumns}`
|
|
12073
|
+
suggestion: `Use one of the available data columns: ${availableColumns}.${didYouMean(field, columnList)}`
|
|
11994
12074
|
});
|
|
11995
12075
|
}
|
|
11996
12076
|
}
|
|
12077
|
+
checkSchemeUnused(
|
|
12078
|
+
encoding,
|
|
12079
|
+
errors,
|
|
12080
|
+
"bar list colors cycle the built-in barlist palette",
|
|
12081
|
+
"Remove scale.scheme. Bar list colors are not configurable via encoding; they cycle the built-in palette."
|
|
12082
|
+
);
|
|
11997
12083
|
if (spec.darkMode !== void 0 && !VALID_DARK_MODES.has(spec.darkMode)) {
|
|
11998
12084
|
errors.push({
|
|
11999
12085
|
message: 'Spec error: darkMode must be "auto", "force", or "off"',
|
|
@@ -15779,7 +15865,7 @@ import {
|
|
|
15779
15865
|
HPAD_COMPACT_FRACTION as HPAD_COMPACT_FRACTION2,
|
|
15780
15866
|
HPAD_COMPACT_MIN as HPAD_COMPACT_MIN2,
|
|
15781
15867
|
resolveTheme as resolveTheme3,
|
|
15782
|
-
SEQUENTIAL_PALETTES
|
|
15868
|
+
SEQUENTIAL_PALETTES as SEQUENTIAL_PALETTES2
|
|
15783
15869
|
} from "@opendata-ai/openchart-core";
|
|
15784
15870
|
|
|
15785
15871
|
// ../../node_modules/.bun/d3-geo@3.1.1/node_modules/d3-geo/src/math.js
|
|
@@ -18011,6 +18097,7 @@ function compileMap(spec, options) {
|
|
|
18011
18097
|
fullArea,
|
|
18012
18098
|
mapAreaHeight,
|
|
18013
18099
|
legendReserveGap,
|
|
18100
|
+
legendPosition,
|
|
18014
18101
|
showLegend,
|
|
18015
18102
|
droppedFeatures
|
|
18016
18103
|
});
|
|
@@ -18063,7 +18150,7 @@ function compileMap(spec, options) {
|
|
|
18063
18150
|
}
|
|
18064
18151
|
if (colorValues.length > 0) {
|
|
18065
18152
|
const palette = pts.color.scale?.scheme ?? "blue";
|
|
18066
|
-
const paletteStops = [...
|
|
18153
|
+
const paletteStops = [...SEQUENTIAL_PALETTES2[palette] ?? SEQUENTIAL_PALETTES2.blue];
|
|
18067
18154
|
const qScale = quantile2().domain(colorValues).range(paletteStops);
|
|
18068
18155
|
pointColorScale = (val) => {
|
|
18069
18156
|
const v = Number(val);
|
|
@@ -18420,7 +18507,7 @@ function buildQuantitativeMarks(opts) {
|
|
|
18420
18507
|
if (!Number.isNaN(v)) values.push(v);
|
|
18421
18508
|
}
|
|
18422
18509
|
}
|
|
18423
|
-
const paletteStops = [...
|
|
18510
|
+
const paletteStops = [...SEQUENTIAL_PALETTES2[palette] ?? SEQUENTIAL_PALETTES2.blue];
|
|
18424
18511
|
const colorScale = quantile2().domain(values).range(paletteStops);
|
|
18425
18512
|
const marks = [];
|
|
18426
18513
|
let animIndex = 0;
|
|
@@ -18491,6 +18578,7 @@ function buildCategoricalMarks(opts) {
|
|
|
18491
18578
|
fullArea,
|
|
18492
18579
|
mapAreaHeight,
|
|
18493
18580
|
legendReserveGap,
|
|
18581
|
+
legendPosition,
|
|
18494
18582
|
showLegend,
|
|
18495
18583
|
droppedFeatures
|
|
18496
18584
|
} = opts;
|
|
@@ -18584,14 +18672,14 @@ function buildCategoricalMarks(opts) {
|
|
|
18584
18672
|
shape: "square"
|
|
18585
18673
|
}));
|
|
18586
18674
|
const legendX = fullArea.x;
|
|
18587
|
-
const legendY = fullArea.y + mapAreaHeight + legendReserveGap;
|
|
18675
|
+
const legendY = legendPosition === "bottom" ? fullArea.y + mapAreaHeight + legendReserveGap : fullArea.y + legendReserveGap;
|
|
18588
18676
|
const legendWidth = fullArea.width;
|
|
18589
18677
|
const swatchSize = 10;
|
|
18590
18678
|
const swatchGap = 6;
|
|
18591
18679
|
const entryGap = 16;
|
|
18592
18680
|
legend = {
|
|
18593
18681
|
type: "categorical",
|
|
18594
|
-
position:
|
|
18682
|
+
position: legendPosition,
|
|
18595
18683
|
bounds: { x: legendX, y: legendY, width: legendWidth, height: swatchSize + 6 },
|
|
18596
18684
|
labelStyle,
|
|
18597
18685
|
entries,
|
|
@@ -18623,13 +18711,15 @@ function resolveFocus(focus, features, pointMarks, warnings) {
|
|
|
18623
18711
|
let maxX2 = -Infinity;
|
|
18624
18712
|
let maxY2 = -Infinity;
|
|
18625
18713
|
for (const p of matched) {
|
|
18626
|
-
minX2 = Math.min(minX2, p.cx
|
|
18627
|
-
minY2 = Math.min(minY2, p.cy
|
|
18628
|
-
maxX2 = Math.max(maxX2, p.cx
|
|
18629
|
-
maxY2 = Math.max(maxY2, p.cy
|
|
18714
|
+
minX2 = Math.min(minX2, p.cx);
|
|
18715
|
+
minY2 = Math.min(minY2, p.cy);
|
|
18716
|
+
maxX2 = Math.max(maxX2, p.cx);
|
|
18717
|
+
maxY2 = Math.max(maxY2, p.cy);
|
|
18630
18718
|
}
|
|
18719
|
+
const w = Math.max(maxX2 - minX2, 1);
|
|
18720
|
+
const h = Math.max(maxY2 - minY2, 1);
|
|
18631
18721
|
return {
|
|
18632
|
-
target: { x: minX2, y: minY2, width:
|
|
18722
|
+
target: { x: minX2, y: minY2, width: w, height: h, padding: padding2 },
|
|
18633
18723
|
// No feature ids: focus-dim is a feature concept, so a points focus
|
|
18634
18724
|
// dims no features (there are no "other" features to mute).
|
|
18635
18725
|
ids: []
|
|
@@ -21347,7 +21437,7 @@ import {
|
|
|
21347
21437
|
HPAD_COMPACT_MIN as HPAD_COMPACT_MIN4,
|
|
21348
21438
|
pickLabelColor as pickLabelColor4,
|
|
21349
21439
|
resolveTheme as resolveTheme6,
|
|
21350
|
-
SEQUENTIAL_PALETTES as
|
|
21440
|
+
SEQUENTIAL_PALETTES as SEQUENTIAL_PALETTES3
|
|
21351
21441
|
} from "@opendata-ai/openchart-core";
|
|
21352
21442
|
var TILE_CORNER_RADIUS = 6;
|
|
21353
21443
|
var TILE_STROKE_WIDTH = 1;
|
|
@@ -21425,7 +21515,7 @@ function compileQuantitative(tilemapSpec, options, theme, chrome, fullArea, isDa
|
|
|
21425
21515
|
const values = Array.from(stateValueMap.values());
|
|
21426
21516
|
const min4 = values.length > 0 ? Math.min(...values) : 0;
|
|
21427
21517
|
const max4 = values.length > 0 ? Math.max(...values) : 100;
|
|
21428
|
-
const paletteStops = [...
|
|
21518
|
+
const paletteStops = [...SEQUENTIAL_PALETTES3[tilemapSpec.palette] ?? SEQUENTIAL_PALETTES3.blue];
|
|
21429
21519
|
const baseColor = isDarkMode ? paletteStops[0] : paletteStops[paletteStops.length - 1];
|
|
21430
21520
|
const opacityRange = isDarkMode ? [0.15, 1] : [0.2, 1];
|
|
21431
21521
|
const opacityScale = linear2().domain([min4, max4]).range(opacityRange).clamp(true);
|