@opendata-ai/openchart-engine 8.0.0-rc.12 → 8.0.0-rc.3
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 +0 -7
- package/dist/index.js +161 -579
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/src/__test-fixtures__/specs.ts +182 -0
- package/src/__tests__/__snapshots__/compile-snapshot.test.ts.snap +2339 -0
- package/src/__tests__/annotation-behavior.test.ts +721 -0
- package/src/__tests__/axes.test.ts +1579 -0
- package/src/__tests__/compile-animation.test.ts +161 -0
- package/src/__tests__/compile-chart.test.ts +1303 -0
- package/src/__tests__/compile-footnotes.test.ts +277 -0
- package/src/__tests__/compile-layer.test.ts +969 -0
- package/src/__tests__/compile-snapshot.test.ts +156 -0
- package/src/__tests__/compound-labels.test.ts +147 -0
- package/src/__tests__/dimensions.test.ts +918 -0
- package/src/__tests__/encoding-sugar.test.ts +390 -0
- package/src/__tests__/facet.test.ts +215 -0
- package/src/__tests__/helpers/invariants.ts +299 -0
- package/src/__tests__/known-bugs.test.ts +566 -0
- package/src/__tests__/layout-fuzz.test.ts +358 -0
- package/src/__tests__/layout-invariants.test.ts +535 -0
- package/src/__tests__/legend.test.ts +721 -0
- package/src/__tests__/mark-keys.test.ts +294 -0
- package/src/__tests__/ranking-recipes.test.ts +260 -0
- package/src/__tests__/rotation.test.ts +83 -0
- package/src/__tests__/scales.test.ts +323 -0
- package/src/__tests__/series-search.test.ts +92 -0
- package/src/__tests__/spec-sugar.test.ts +801 -0
- package/src/__tests__/you-draw-it.test.ts +160 -0
- package/src/annotations/__tests__/compute.test.ts +1672 -0
- package/src/annotations/__tests__/geometry.test.ts +66 -0
- package/src/annotations/__tests__/placement-fuzz.test.ts +256 -0
- package/src/annotations/__tests__/placement-invariants.test.ts +345 -0
- package/src/annotations/__tests__/placement.test.ts +316 -0
- package/src/annotations/__tests__/resolve-text.test.ts +788 -0
- package/src/annotations/__tests__/rich-text.test.ts +91 -0
- package/src/annotations/__tests__/thinning.test.ts +285 -0
- package/src/annotations/collisions.ts +326 -0
- package/src/annotations/compute.ts +333 -0
- package/src/annotations/constants.ts +162 -0
- package/src/annotations/geometry.ts +370 -0
- package/src/annotations/move.ts +135 -0
- package/src/annotations/placement.ts +636 -0
- package/src/annotations/position.ts +131 -0
- package/src/annotations/resolve-range.ts +117 -0
- package/src/annotations/resolve-refline.ts +157 -0
- package/src/annotations/resolve-text.ts +539 -0
- package/src/annotations/rich-text.ts +65 -0
- package/src/annotations/thinning.ts +190 -0
- package/src/barlist/__tests__/compile-barlist.test.ts +200 -0
- package/src/barlist/compile-barlist.ts +391 -0
- package/src/barlist/types.ts +28 -0
- package/src/charts/__tests__/post-process.test.ts +237 -0
- package/src/charts/__tests__/registry.test.ts +116 -0
- package/src/charts/__tests__/utils.test.ts +195 -0
- package/src/charts/_shared/__tests__/density-filter.test.ts +32 -0
- package/src/charts/_shared/density-filter.ts +26 -0
- package/src/charts/_shared/format-label-value.ts +16 -0
- package/src/charts/bar/__tests__/compute.test.ts +934 -0
- package/src/charts/bar/__tests__/gradient-orient.test.ts +127 -0
- package/src/charts/bar/__tests__/labels.test.ts +292 -0
- package/src/charts/bar/compute.ts +539 -0
- package/src/charts/bar/index.ts +60 -0
- package/src/charts/bar/labels.ts +311 -0
- package/src/charts/beeswarm/__tests__/compute.test.ts +280 -0
- package/src/charts/beeswarm/__tests__/dodge.test.ts +148 -0
- package/src/charts/beeswarm/compute.ts +203 -0
- package/src/charts/beeswarm/dodge.ts +155 -0
- package/src/charts/beeswarm/index.ts +32 -0
- package/src/charts/builtin.ts +75 -0
- package/src/charts/calendar/__tests__/compute.test.ts +417 -0
- package/src/charts/calendar/compute.ts +319 -0
- package/src/charts/calendar/index.ts +32 -0
- package/src/charts/column/__tests__/compute.test.ts +540 -0
- package/src/charts/column/__tests__/labels.test.ts +179 -0
- package/src/charts/column/compute.ts +493 -0
- package/src/charts/column/index.ts +53 -0
- package/src/charts/column/labels.ts +229 -0
- package/src/charts/dot/__tests__/compute.test.ts +380 -0
- package/src/charts/dot/__tests__/labels.test.ts +98 -0
- package/src/charts/dot/compute.ts +285 -0
- package/src/charts/dot/index.ts +62 -0
- package/src/charts/dot/labels.ts +121 -0
- package/src/charts/line/__tests__/compute.test.ts +1194 -0
- package/src/charts/line/__tests__/curves.test.ts +51 -0
- package/src/charts/line/__tests__/labels.test.ts +94 -0
- package/src/charts/line/__tests__/mark-options.test.ts +175 -0
- package/src/charts/line/area.ts +484 -0
- package/src/charts/line/compute.ts +356 -0
- package/src/charts/line/curves.ts +85 -0
- package/src/charts/line/index.ts +176 -0
- package/src/charts/line/labels.ts +177 -0
- package/src/charts/parliament/__tests__/compute.test.ts +411 -0
- package/src/charts/parliament/compute.ts +313 -0
- package/src/charts/parliament/index.ts +32 -0
- package/src/charts/pie/__tests__/compute.test.ts +384 -0
- package/src/charts/pie/__tests__/labels.test.ts +132 -0
- package/src/charts/pie/compute.ts +324 -0
- package/src/charts/pie/index.ts +49 -0
- package/src/charts/pie/labels.ts +143 -0
- package/src/charts/post-process.ts +229 -0
- package/src/charts/range/__tests__/compute.test.ts +486 -0
- package/src/charts/range/compute.ts +273 -0
- package/src/charts/range/index.ts +82 -0
- package/src/charts/range/labels.ts +169 -0
- package/src/charts/rect/__tests__/compute.test.ts +120 -0
- package/src/charts/rect/index.ts +127 -0
- package/src/charts/registry.ts +72 -0
- package/src/charts/rule/index.ts +139 -0
- package/src/charts/scatter/__tests__/compute.test.ts +488 -0
- package/src/charts/scatter/__tests__/trendline.test.ts +191 -0
- package/src/charts/scatter/compute.ts +192 -0
- package/src/charts/scatter/index.ts +46 -0
- package/src/charts/scatter/trendline.ts +100 -0
- package/src/charts/text/__tests__/compute.test.ts +307 -0
- package/src/charts/text/index.ts +141 -0
- package/src/charts/tick/__tests__/compute.test.ts +75 -0
- package/src/charts/tick/index.ts +99 -0
- package/src/charts/utils.ts +170 -0
- package/src/charts/waffle/__tests__/compute.test.ts +305 -0
- package/src/charts/waffle/compute.ts +197 -0
- package/src/charts/waffle/index.ts +31 -0
- package/src/compile/__tests__/color-scale-range.test.ts +158 -0
- package/src/compile/__tests__/color-scale-reverse.test.ts +89 -0
- package/src/compile/__tests__/data-clip.test.ts +127 -0
- package/src/compile/__tests__/fill-patterns.test.ts +154 -0
- package/src/compile/__tests__/size-scale.test.ts +108 -0
- package/src/compile/__tests__/watermark-obstacle.test.ts +93 -0
- package/src/compile/color-scale-range.ts +101 -0
- package/src/compile/data-clip.ts +48 -0
- package/src/compile/fill-patterns.ts +74 -0
- package/src/compile/layer.ts +626 -0
- package/src/compile/size-scale.ts +141 -0
- package/src/compile/spec-sugar.ts +758 -0
- package/src/compile/watermark-obstacle.ts +54 -0
- package/src/compile/you-draw-it.ts +123 -0
- package/src/compile.ts +1450 -0
- package/src/compiler/__tests__/a11y-warnings.test.ts +148 -0
- package/src/compiler/__tests__/animation.test.ts +177 -0
- package/src/compiler/__tests__/compile.test.ts +87 -0
- package/src/compiler/__tests__/fixtures/vl-parity/axis-null.json +19 -0
- package/src/compiler/__tests__/fixtures/vl-parity/color-value.json +20 -0
- package/src/compiler/__tests__/fixtures/vl-parity/count-aggregate.json +22 -0
- package/src/compiler/__tests__/fixtures/vl-parity/data-values.json +19 -0
- package/src/compiler/__tests__/fixtures/vl-parity/layer-axis-null.json +14 -0
- package/src/compiler/__tests__/fixtures/vl-parity/layer-count.json +34 -0
- package/src/compiler/__tests__/fixtures/vl-parity/layer-data-values.json +22 -0
- package/src/compiler/__tests__/fixtures/vl-parity/layer-legend-null.json +41 -0
- package/src/compiler/__tests__/fixtures/vl-parity/layer-scheme.json +38 -0
- package/src/compiler/__tests__/fixtures/vl-parity/layer-sort.json +28 -0
- package/src/compiler/__tests__/fixtures/vl-parity/layer-theta.json +28 -0
- package/src/compiler/__tests__/fixtures/vl-parity/layer-title.json +30 -0
- package/src/compiler/__tests__/fixtures/vl-parity/layer-value-def.json +29 -0
- package/src/compiler/__tests__/fixtures/vl-parity/legend-null.json +32 -0
- package/src/compiler/__tests__/fixtures/vl-parity/scheme.json +25 -0
- package/src/compiler/__tests__/fixtures/vl-parity/sort-by-value.json +19 -0
- package/src/compiler/__tests__/fixtures/vl-parity/theta-arc.json +19 -0
- package/src/compiler/__tests__/fixtures/vl-parity/title-subtitle.json +21 -0
- package/src/compiler/__tests__/fixtures/vl-parity/width-height.json +23 -0
- package/src/compiler/__tests__/keys.test.ts +83 -0
- package/src/compiler/__tests__/normalize-highlight.test.ts +103 -0
- package/src/compiler/__tests__/normalize.test.ts +399 -0
- package/src/compiler/__tests__/sparkline-defaults.test.ts +153 -0
- package/src/compiler/__tests__/validate-did-you-mean.test.ts +86 -0
- package/src/compiler/__tests__/validate-highlight.test.ts +112 -0
- package/src/compiler/__tests__/validate-near-miss.test.ts +89 -0
- package/src/compiler/__tests__/validate.test.ts +629 -0
- package/src/compiler/__tests__/vl-parity.test.ts +68 -0
- package/src/compiler/a11y-warnings.ts +110 -0
- package/src/compiler/animation.ts +142 -0
- package/src/compiler/index.ts +47 -0
- package/src/compiler/keys.ts +55 -0
- package/src/compiler/normalize.ts +734 -0
- package/src/compiler/sparkline-defaults.ts +138 -0
- package/src/compiler/types.ts +241 -0
- package/src/compiler/validate.ts +1871 -0
- package/src/endpoint-labels/__tests__/compute.test.ts +587 -0
- package/src/endpoint-labels/compute.ts +621 -0
- package/src/endpoint-labels/constants.ts +54 -0
- package/src/endpoint-labels/format.ts +60 -0
- package/src/endpoint-labels/predict.ts +139 -0
- package/src/format/__tests__/field-format.test.ts +164 -0
- package/src/format/field-format.ts +27 -0
- package/src/geo/__tests__/compile-map.test.ts +832 -0
- package/src/geo/compile-map.ts +1243 -0
- package/src/geo/join.ts +115 -0
- package/src/geo/projections.ts +45 -0
- package/src/geo/types.ts +26 -0
- package/src/graphs/__tests__/community.test.ts +228 -0
- package/src/graphs/__tests__/compile-graph.test.ts +396 -0
- package/src/graphs/__tests__/encoding.test.ts +415 -0
- package/src/graphs/community.ts +92 -0
- package/src/graphs/compile-graph.ts +329 -0
- package/src/graphs/encoding.ts +356 -0
- package/src/graphs/types.ts +106 -0
- package/src/index.ts +177 -0
- package/src/layout/__tests__/metrics.test.ts +97 -0
- package/src/layout/__tests__/scales-highlight.test.ts +192 -0
- package/src/layout/axes/rotation.ts +152 -0
- package/src/layout/axes/thinning.ts +98 -0
- package/src/layout/axes/ticks.ts +409 -0
- package/src/layout/axes.ts +757 -0
- package/src/layout/dimensions.ts +912 -0
- package/src/layout/facet.ts +91 -0
- package/src/layout/gridlines.ts +84 -0
- package/src/layout/metrics.ts +132 -0
- package/src/layout/plan.ts +631 -0
- package/src/layout/scales.ts +1053 -0
- package/src/layout/shared.ts +44 -0
- package/src/legend/__tests__/continuous.test.ts +318 -0
- package/src/legend/__tests__/redundancy.test.ts +108 -0
- package/src/legend/__tests__/size.test.ts +348 -0
- package/src/legend/__tests__/suppression.test.ts +382 -0
- package/src/legend/compute.ts +747 -0
- package/src/legend/continuous.ts +327 -0
- package/src/legend/size.ts +407 -0
- package/src/legend/suppression.ts +226 -0
- package/src/legend/wrap.ts +117 -0
- package/src/sankey/__tests__/compile-sankey.test.ts +458 -0
- package/src/sankey/__tests__/layout.test.ts +165 -0
- package/src/sankey/__tests__/node-label-wrap.test.ts +114 -0
- package/src/sankey/__tests__/node-sort.test.ts +45 -0
- package/src/sankey/compile-sankey.ts +706 -0
- package/src/sankey/layout.ts +184 -0
- package/src/sankey/types.ts +41 -0
- package/src/tables/__tests__/bar-column.test.ts +147 -0
- package/src/tables/__tests__/category-colors.test.ts +230 -0
- package/src/tables/__tests__/compile-table.test.ts +236 -0
- package/src/tables/__tests__/format-cells.test.ts +143 -0
- package/src/tables/__tests__/heatmap.test.ts +148 -0
- package/src/tables/__tests__/pagination.test.ts +78 -0
- package/src/tables/__tests__/search.test.ts +94 -0
- package/src/tables/__tests__/sort.test.ts +107 -0
- package/src/tables/__tests__/sparkline.test.ts +122 -0
- package/src/tables/bar-column.ts +94 -0
- package/src/tables/category-colors.ts +78 -0
- package/src/tables/compile-table.ts +427 -0
- package/src/tables/format-cells.ts +115 -0
- package/src/tables/heatmap.ts +141 -0
- package/src/tables/pagination.ts +46 -0
- package/src/tables/search.ts +66 -0
- package/src/tables/sort.ts +69 -0
- package/src/tables/sparkline.ts +113 -0
- package/src/tables/utils.ts +16 -0
- package/src/tilemap/__tests__/compile-tilemap.test.ts +576 -0
- package/src/tilemap/compile-tilemap.ts +755 -0
- package/src/tilemap/layout.ts +172 -0
- package/src/tilemap/types.ts +33 -0
- package/src/tooltips/__tests__/compute.test.ts +582 -0
- package/src/tooltips/compute.ts +700 -0
- package/src/transforms/__tests__/aggregate.test.ts +159 -0
- package/src/transforms/__tests__/bin.test.ts +88 -0
- package/src/transforms/__tests__/calculate.test.ts +146 -0
- package/src/transforms/__tests__/conditional.test.ts +127 -0
- package/src/transforms/__tests__/filter-relative.test.ts +202 -0
- package/src/transforms/__tests__/filter.test.ts +59 -0
- package/src/transforms/__tests__/fold.test.ts +79 -0
- package/src/transforms/__tests__/index.test.ts +93 -0
- package/src/transforms/__tests__/predicates.test.ts +193 -0
- package/src/transforms/__tests__/timeunit.test.ts +129 -0
- package/src/transforms/__tests__/window.test.ts +286 -0
- package/src/transforms/aggregate.ts +131 -0
- package/src/transforms/bin.ts +87 -0
- package/src/transforms/calculate.ts +60 -0
- package/src/transforms/conditional.ts +46 -0
- package/src/transforms/filter.ts +122 -0
- package/src/transforms/fold.ts +49 -0
- package/src/transforms/index.ts +60 -0
- package/src/transforms/predicates.ts +123 -0
- package/src/transforms/timeunit.ts +88 -0
- package/src/transforms/window.ts +185 -0
package/dist/index.js
CHANGED
|
@@ -244,10 +244,7 @@ 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 = {
|
|
248
|
-
x: exit.x + (connector.fromOffset?.dx ?? 0),
|
|
249
|
-
y: exit.y + (connector.fromOffset?.dy ?? 0)
|
|
250
|
-
};
|
|
247
|
+
const from = { x: exit.x, y: exit.y };
|
|
251
248
|
const gap = connectorPullbackGap(markerRadius, connector.arrow);
|
|
252
249
|
const cdx = endpoint.x - from.x;
|
|
253
250
|
const cdy = endpoint.y - from.y;
|
|
@@ -509,10 +506,6 @@ function resolveTextAnnotation(annotation, scales, chartArea, isDark, measure =
|
|
|
509
506
|
from,
|
|
510
507
|
to,
|
|
511
508
|
endpoint,
|
|
512
|
-
fromOffset: annotation.connectorOffset?.from ? {
|
|
513
|
-
dx: annotation.connectorOffset.from.dx ?? 0,
|
|
514
|
-
dy: annotation.connectorOffset.from.dy ?? 0
|
|
515
|
-
} : void 0,
|
|
516
509
|
stroke: connectorStroke,
|
|
517
510
|
style: connectorStyle,
|
|
518
511
|
arrow: connectorArrow,
|
|
@@ -9846,16 +9839,7 @@ function expandChannelSugar(spec, warnings) {
|
|
|
9846
9839
|
}
|
|
9847
9840
|
return result;
|
|
9848
9841
|
}
|
|
9849
|
-
var COUNT_GROUP_CHANNELS = [
|
|
9850
|
-
"x",
|
|
9851
|
-
"y",
|
|
9852
|
-
"color",
|
|
9853
|
-
"detail",
|
|
9854
|
-
"strokeDash",
|
|
9855
|
-
"facet",
|
|
9856
|
-
"row",
|
|
9857
|
-
"column"
|
|
9858
|
-
];
|
|
9842
|
+
var COUNT_GROUP_CHANNELS = ["x", "y", "color", "detail", "strokeDash", "facet"];
|
|
9859
9843
|
function expandCountAggregate(spec) {
|
|
9860
9844
|
const encoding = spec.encoding;
|
|
9861
9845
|
if (!encoding || typeof encoding !== "object") return spec;
|
|
@@ -10482,7 +10466,6 @@ function normalizeChartSpec(spec, warnings) {
|
|
|
10482
10466
|
data: spec.data,
|
|
10483
10467
|
encoding,
|
|
10484
10468
|
chrome: normalizeChrome(spec.chrome),
|
|
10485
|
-
chromeLayout: spec.chromeLayout,
|
|
10486
10469
|
metrics: spec.metrics,
|
|
10487
10470
|
seriesSearch: normalizeSeriesSearch(spec, encoding, warnings),
|
|
10488
10471
|
youDrawIt: normalizeYouDrawIt(spec),
|
|
@@ -10746,7 +10729,6 @@ import {
|
|
|
10746
10729
|
MARK_ENCODING_RULES,
|
|
10747
10730
|
MARK_TYPES,
|
|
10748
10731
|
resolveSchemeName as resolveSchemeName2,
|
|
10749
|
-
SEQUENTIAL_PALETTES,
|
|
10750
10732
|
SUPPORTED_SCHEME_NAMES
|
|
10751
10733
|
} from "@opendata-ai/openchart-core";
|
|
10752
10734
|
var VALID_FIELD_TYPES = /* @__PURE__ */ new Set(["quantitative", "temporal", "nominal", "ordinal"]);
|
|
@@ -10805,53 +10787,6 @@ function didYouMean(field, columns) {
|
|
|
10805
10787
|
const match = nearestColumn(field, columns);
|
|
10806
10788
|
return match ? ` Did you mean "${match}"?` : "";
|
|
10807
10789
|
}
|
|
10808
|
-
function checkSchemeName(channelObj, channelPath, errors) {
|
|
10809
|
-
const scale = channelObj.scale;
|
|
10810
|
-
if (scale && typeof scale.scheme === "string" && !resolveSchemeName2(scale.scheme)) {
|
|
10811
|
-
errors.push({
|
|
10812
|
-
message: `Spec error: ${channelPath}.scale.scheme "${scale.scheme}" is not a supported scheme name`,
|
|
10813
|
-
path: `${channelPath}.scale.scheme`,
|
|
10814
|
-
code: "INVALID_VALUE",
|
|
10815
|
-
suggestion: `Use one of the supported scheme names: ${[...SUPPORTED_SCHEME_NAMES].join(", ")}. Or provide explicit colors via scale.range.`
|
|
10816
|
-
});
|
|
10817
|
-
}
|
|
10818
|
-
}
|
|
10819
|
-
function checkSchemeUnused(encoding, errors, familyNote, suggestion) {
|
|
10820
|
-
for (const [channel, ch] of Object.entries(encoding)) {
|
|
10821
|
-
if (!ch || typeof ch !== "object" || Array.isArray(ch)) continue;
|
|
10822
|
-
const scale = ch.scale;
|
|
10823
|
-
if (scale && typeof scale.scheme === "string") {
|
|
10824
|
-
errors.push({
|
|
10825
|
-
message: `Spec error: encoding.${channel}.scale.scheme has no effect \u2014 ${familyNote}`,
|
|
10826
|
-
path: `encoding.${channel}.scale.scheme`,
|
|
10827
|
-
code: "INVALID_VALUE",
|
|
10828
|
-
suggestion
|
|
10829
|
-
});
|
|
10830
|
-
}
|
|
10831
|
-
}
|
|
10832
|
-
}
|
|
10833
|
-
var MAP_PALETTE_NAMES = Object.keys(SEQUENTIAL_PALETTES).join(", ");
|
|
10834
|
-
function checkMapSchemeName(channelObj, channelPath, errors) {
|
|
10835
|
-
const scale = channelObj.scale;
|
|
10836
|
-
if (!scale || typeof scale.scheme !== "string") return;
|
|
10837
|
-
if (channelObj.type === "nominal" || channelObj.type === "ordinal") {
|
|
10838
|
-
errors.push({
|
|
10839
|
-
message: `Spec error: ${channelPath}.scale.scheme has no effect \u2014 categorical map colors come from scale.range and scale.domain`,
|
|
10840
|
-
path: `${channelPath}.scale.scheme`,
|
|
10841
|
-
code: "INVALID_VALUE",
|
|
10842
|
-
suggestion: "Remove scale.scheme. To customize categorical map colors, provide explicit colors via scale.range (with scale.domain for category order)."
|
|
10843
|
-
});
|
|
10844
|
-
return;
|
|
10845
|
-
}
|
|
10846
|
-
if (!(scale.scheme in SEQUENTIAL_PALETTES)) {
|
|
10847
|
-
errors.push({
|
|
10848
|
-
message: `Spec error: ${channelPath}.scale.scheme "${scale.scheme}" is not a supported map palette`,
|
|
10849
|
-
path: `${channelPath}.scale.scheme`,
|
|
10850
|
-
code: "INVALID_VALUE",
|
|
10851
|
-
suggestion: `Maps support the sequential palettes: ${MAP_PALETTE_NAMES}. The default is "blue".`
|
|
10852
|
-
});
|
|
10853
|
-
}
|
|
10854
|
-
}
|
|
10855
10790
|
var VALID_RANGE_STYLES = /* @__PURE__ */ new Set(["dumbbell", "arrow", "bar"]);
|
|
10856
10791
|
function validateRangeSpec(spec, errors) {
|
|
10857
10792
|
const encoding = spec.encoding;
|
|
@@ -11213,7 +11148,15 @@ function validateChartSpec(spec, errors) {
|
|
|
11213
11148
|
suggestion: `Use one of: ${[...VALID_FIELD_TYPES].join(", ")}`
|
|
11214
11149
|
});
|
|
11215
11150
|
}
|
|
11216
|
-
|
|
11151
|
+
const channelScale = channelObj.scale;
|
|
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
|
+
}
|
|
11217
11160
|
if (channelRule && channelObj.type && channelRule.allowedTypes.length > 0) {
|
|
11218
11161
|
if (!channelRule.allowedTypes.includes(channelObj.type)) {
|
|
11219
11162
|
errors.push({
|
|
@@ -11327,52 +11270,6 @@ function validateChartSpec(spec, errors) {
|
|
|
11327
11270
|
}
|
|
11328
11271
|
}
|
|
11329
11272
|
}
|
|
11330
|
-
for (const channel of ["row", "column"]) {
|
|
11331
|
-
const ch = encoding[channel];
|
|
11332
|
-
if (ch && typeof ch === "object") {
|
|
11333
|
-
const facetCh = ch;
|
|
11334
|
-
if (!facetCh.field || typeof facetCh.field !== "string") {
|
|
11335
|
-
errors.push({
|
|
11336
|
-
message: `Spec error: encoding.${channel}.field is required and must be a non-empty string`,
|
|
11337
|
-
path: `encoding.${channel}.field`,
|
|
11338
|
-
code: "MISSING_FIELD",
|
|
11339
|
-
suggestion: `Add a field property to encoding.${channel} (e.g. { field: "category", type: "nominal" })`
|
|
11340
|
-
});
|
|
11341
|
-
} else if (!dataColumns.has(facetCh.field) && !transformFields.has(facetCh.field)) {
|
|
11342
|
-
errors.push({
|
|
11343
|
-
message: `Spec error: encoding.${channel}.field "${facetCh.field}" does not exist in data. Available columns: ${availableColumns}`,
|
|
11344
|
-
path: `encoding.${channel}.field`,
|
|
11345
|
-
code: "DATA_FIELD_MISSING",
|
|
11346
|
-
suggestion: `Use one of the available data columns: ${availableColumns}.${didYouMean(facetCh.field, columnList)}`
|
|
11347
|
-
});
|
|
11348
|
-
}
|
|
11349
|
-
if (!facetCh.type || facetCh.type !== "nominal" && facetCh.type !== "ordinal") {
|
|
11350
|
-
errors.push({
|
|
11351
|
-
message: `Spec error: encoding.${channel}.type must be "nominal" or "ordinal"${facetCh.type ? `, got "${facetCh.type}"` : ""}`,
|
|
11352
|
-
path: `encoding.${channel}.type`,
|
|
11353
|
-
code: facetCh.type ? "INVALID_VALUE" : "MISSING_FIELD",
|
|
11354
|
-
suggestion: `Set encoding.${channel}.type to "nominal" or "ordinal"`
|
|
11355
|
-
});
|
|
11356
|
-
}
|
|
11357
|
-
if (encoding.facet && typeof encoding.facet === "object") {
|
|
11358
|
-
errors.push({
|
|
11359
|
-
message: `Spec error: encoding.${channel} and encoding.facet cannot be used together`,
|
|
11360
|
-
path: `encoding.${channel}`,
|
|
11361
|
-
code: "INVALID_VALUE",
|
|
11362
|
-
suggestion: `Use either encoding.${channel} or encoding.facet, not both`
|
|
11363
|
-
});
|
|
11364
|
-
}
|
|
11365
|
-
const otherChannel = channel === "row" ? "column" : "row";
|
|
11366
|
-
if (encoding[otherChannel]) {
|
|
11367
|
-
errors.push({
|
|
11368
|
-
message: "Spec error: encoding.row and encoding.column cannot be used together (cross-product faceting is not yet supported)",
|
|
11369
|
-
path: `encoding.${channel}`,
|
|
11370
|
-
code: "INVALID_VALUE",
|
|
11371
|
-
suggestion: "Use encoding.facet with columns for grid layout, or use only row or column"
|
|
11372
|
-
});
|
|
11373
|
-
}
|
|
11374
|
-
}
|
|
11375
|
-
}
|
|
11376
11273
|
if (spec.darkMode !== void 0 && !VALID_DARK_MODES.has(spec.darkMode)) {
|
|
11377
11274
|
errors.push({
|
|
11378
11275
|
message: `Spec error: darkMode must be "auto", "force", or "off"`,
|
|
@@ -11585,7 +11482,7 @@ function validateGraphSpec(spec, errors) {
|
|
|
11585
11482
|
message: `Spec error: edges[${i}].source "${edge.source}" does not reference an existing node id`,
|
|
11586
11483
|
path: `edges[${i}].source`,
|
|
11587
11484
|
code: "DATA_FIELD_MISSING",
|
|
11588
|
-
suggestion: `Use one of the existing node ids: ${[...nodeIds].slice(0, 5).join(", ")}${nodeIds.size > 5 ? "..." : ""}
|
|
11485
|
+
suggestion: `Use one of the existing node ids: ${[...nodeIds].slice(0, 5).join(", ")}${nodeIds.size > 5 ? "..." : ""}`
|
|
11589
11486
|
});
|
|
11590
11487
|
}
|
|
11591
11488
|
if (typeof edge.target !== "string" || edge.target === "") {
|
|
@@ -11600,7 +11497,7 @@ function validateGraphSpec(spec, errors) {
|
|
|
11600
11497
|
message: `Spec error: edges[${i}].target "${edge.target}" does not reference an existing node id`,
|
|
11601
11498
|
path: `edges[${i}].target`,
|
|
11602
11499
|
code: "DATA_FIELD_MISSING",
|
|
11603
|
-
suggestion: `Use one of the existing node ids: ${[...nodeIds].slice(0, 5).join(", ")}${nodeIds.size > 5 ? "..." : ""}
|
|
11500
|
+
suggestion: `Use one of the existing node ids: ${[...nodeIds].slice(0, 5).join(", ")}${nodeIds.size > 5 ? "..." : ""}`
|
|
11604
11501
|
});
|
|
11605
11502
|
}
|
|
11606
11503
|
}
|
|
@@ -11618,7 +11515,7 @@ function validateGraphSpec(spec, errors) {
|
|
|
11618
11515
|
message: `Spec error: encoding.${channel}.field "${ch.field}" does not exist on nodes. Available fields: ${[...nodeFields].join(", ")}`,
|
|
11619
11516
|
path: `encoding.${channel}.field`,
|
|
11620
11517
|
code: "DATA_FIELD_MISSING",
|
|
11621
|
-
suggestion: `Use one of the node fields: ${[...nodeFields].join(", ")}
|
|
11518
|
+
suggestion: `Use one of the node fields: ${[...nodeFields].join(", ")}`
|
|
11622
11519
|
});
|
|
11623
11520
|
}
|
|
11624
11521
|
}
|
|
@@ -11630,16 +11527,10 @@ function validateGraphSpec(spec, errors) {
|
|
|
11630
11527
|
message: `Spec error: encoding.${channel}.field "${ch.field}" does not exist on edges. Available fields: ${[...edgeFields].join(", ")}`,
|
|
11631
11528
|
path: `encoding.${channel}.field`,
|
|
11632
11529
|
code: "DATA_FIELD_MISSING",
|
|
11633
|
-
suggestion: `Use one of the edge fields: ${[...edgeFields].join(", ")}
|
|
11530
|
+
suggestion: `Use one of the edge fields: ${[...edgeFields].join(", ")}`
|
|
11634
11531
|
});
|
|
11635
11532
|
}
|
|
11636
11533
|
}
|
|
11637
|
-
checkSchemeUnused(
|
|
11638
|
-
encoding,
|
|
11639
|
-
errors,
|
|
11640
|
-
"graph colors come from scale.range and scale.domain",
|
|
11641
|
-
"Remove scale.scheme. To customize graph colors, provide explicit colors via scale.range."
|
|
11642
|
-
);
|
|
11643
11534
|
}
|
|
11644
11535
|
if (spec.layout && typeof spec.layout === "object") {
|
|
11645
11536
|
const layout = spec.layout;
|
|
@@ -11693,8 +11584,7 @@ function validateSankeySpec(spec, errors) {
|
|
|
11693
11584
|
}
|
|
11694
11585
|
const encoding = spec.encoding;
|
|
11695
11586
|
const dataColumns = new Set(Object.keys(firstRow));
|
|
11696
|
-
const
|
|
11697
|
-
const availableColumns = columnList.join(", ");
|
|
11587
|
+
const availableColumns = [...dataColumns].join(", ");
|
|
11698
11588
|
for (const channel of ["source", "target", "value"]) {
|
|
11699
11589
|
const ch = encoding[channel];
|
|
11700
11590
|
if (!ch || typeof ch !== "object") {
|
|
@@ -11702,7 +11592,7 @@ function validateSankeySpec(spec, errors) {
|
|
|
11702
11592
|
message: `Spec error: sankey encoding requires "${channel}" channel`,
|
|
11703
11593
|
path: `encoding.${channel}`,
|
|
11704
11594
|
code: "MISSING_FIELD",
|
|
11705
|
-
suggestion: `Add encoding.${channel} with a field from your data (${availableColumns}). Example: ${channel}: { field: "${
|
|
11595
|
+
suggestion: `Add encoding.${channel} with a field from your data (${availableColumns}). Example: ${channel}: { field: "${[...dataColumns][0] ?? "myField"}", type: "${channel === "value" ? "quantitative" : "nominal"}" }`
|
|
11706
11596
|
});
|
|
11707
11597
|
continue;
|
|
11708
11598
|
}
|
|
@@ -11720,16 +11610,10 @@ function validateSankeySpec(spec, errors) {
|
|
|
11720
11610
|
message: `Spec error: encoding.${channel}.field "${ch.field}" does not exist in data. Available columns: ${availableColumns}`,
|
|
11721
11611
|
path: `encoding.${channel}.field`,
|
|
11722
11612
|
code: "DATA_FIELD_MISSING",
|
|
11723
|
-
suggestion: `Use one of the available data columns: ${availableColumns}
|
|
11613
|
+
suggestion: `Use one of the available data columns: ${availableColumns}`
|
|
11724
11614
|
});
|
|
11725
11615
|
}
|
|
11726
11616
|
}
|
|
11727
|
-
checkSchemeUnused(
|
|
11728
|
-
encoding,
|
|
11729
|
-
errors,
|
|
11730
|
-
"sankey node colors cycle the theme categorical palette",
|
|
11731
|
-
"Remove scale.scheme. To customize sankey colors, set theme.colors.categorical."
|
|
11732
|
-
);
|
|
11733
11617
|
if (spec.darkMode !== void 0 && !VALID_DARK_MODES.has(spec.darkMode)) {
|
|
11734
11618
|
errors.push({
|
|
11735
11619
|
message: 'Spec error: darkMode must be "auto", "force", or "off"',
|
|
@@ -11789,8 +11673,7 @@ function validateTileMapSpec(spec, errors) {
|
|
|
11789
11673
|
}
|
|
11790
11674
|
const encoding = spec.encoding;
|
|
11791
11675
|
const dataColumns = new Set(Object.keys(firstRow));
|
|
11792
|
-
const
|
|
11793
|
-
const availableColumns = columnList.join(", ");
|
|
11676
|
+
const availableColumns = [...dataColumns].join(", ");
|
|
11794
11677
|
for (const channel of ["state", "value"]) {
|
|
11795
11678
|
const ch = encoding[channel];
|
|
11796
11679
|
if (!ch || typeof ch !== "object") {
|
|
@@ -11798,7 +11681,7 @@ function validateTileMapSpec(spec, errors) {
|
|
|
11798
11681
|
message: `Spec error: tilemap encoding requires "${channel}" channel`,
|
|
11799
11682
|
path: `encoding.${channel}`,
|
|
11800
11683
|
code: "MISSING_FIELD",
|
|
11801
|
-
suggestion: `Add encoding.${channel} with a field from your data (${availableColumns}). Example: ${channel}: { field: "${
|
|
11684
|
+
suggestion: `Add encoding.${channel} with a field from your data (${availableColumns}). Example: ${channel}: { field: "${[...dataColumns][0] ?? "myField"}", type: "${channel === "value" ? "quantitative" : "nominal"}" }`
|
|
11802
11685
|
});
|
|
11803
11686
|
continue;
|
|
11804
11687
|
}
|
|
@@ -11816,19 +11699,11 @@ function validateTileMapSpec(spec, errors) {
|
|
|
11816
11699
|
message: `Spec error: encoding.${channel}.field "${ch.field}" does not exist in data. Available columns: ${availableColumns}`,
|
|
11817
11700
|
path: `encoding.${channel}.field`,
|
|
11818
11701
|
code: "DATA_FIELD_MISSING",
|
|
11819
|
-
suggestion: `Use one of the available data columns: ${availableColumns}
|
|
11702
|
+
suggestion: `Use one of the available data columns: ${availableColumns}`
|
|
11820
11703
|
});
|
|
11821
11704
|
}
|
|
11822
11705
|
}
|
|
11823
11706
|
}
|
|
11824
|
-
if (spec.encoding && typeof spec.encoding === "object") {
|
|
11825
|
-
checkSchemeUnused(
|
|
11826
|
-
spec.encoding,
|
|
11827
|
-
errors,
|
|
11828
|
-
"tilemap fills come from the top-level palette property",
|
|
11829
|
-
`Remove scale.scheme and set the top-level palette property instead, e.g. palette: "green". Supported: ${MAP_PALETTE_NAMES}.`
|
|
11830
|
-
);
|
|
11831
|
-
}
|
|
11832
11707
|
if (spec.darkMode !== void 0 && !VALID_DARK_MODES.has(spec.darkMode)) {
|
|
11833
11708
|
errors.push({
|
|
11834
11709
|
message: 'Spec error: darkMode must be "auto", "force", or "off"',
|
|
@@ -11867,16 +11742,6 @@ function validateMapSpec(spec, errors) {
|
|
|
11867
11742
|
});
|
|
11868
11743
|
return;
|
|
11869
11744
|
}
|
|
11870
|
-
const mapEncoding = spec.encoding;
|
|
11871
|
-
if (mapEncoding.color && typeof mapEncoding.color === "object") {
|
|
11872
|
-
checkMapSchemeName(mapEncoding.color, "encoding.color", errors);
|
|
11873
|
-
}
|
|
11874
|
-
if (spec.points && typeof spec.points === "object") {
|
|
11875
|
-
const pointsLayer = spec.points;
|
|
11876
|
-
if (pointsLayer.color && typeof pointsLayer.color === "object") {
|
|
11877
|
-
checkMapSchemeName(pointsLayer.color, "points.color", errors);
|
|
11878
|
-
}
|
|
11879
|
-
}
|
|
11880
11745
|
if ("focus" in geo && geo.focus !== void 0 && geo.focus !== null) {
|
|
11881
11746
|
const focus = geo.focus;
|
|
11882
11747
|
if (typeof focus === "string" || typeof focus === "number") {
|
|
@@ -11893,31 +11758,12 @@ function validateMapSpec(spec, errors) {
|
|
|
11893
11758
|
}
|
|
11894
11759
|
} else if (typeof focus === "object") {
|
|
11895
11760
|
const focusObj = focus;
|
|
11896
|
-
if ("
|
|
11897
|
-
const pts = focusObj.points;
|
|
11898
|
-
const isSubset = typeof pts === "object" && pts !== null && typeof pts.field === "string" && "value" in pts;
|
|
11899
|
-
if (pts !== true && !isSubset) {
|
|
11900
|
-
errors.push({
|
|
11901
|
-
message: "Spec error: geo.focus.points must be true or { field: string, value: string | number }",
|
|
11902
|
-
path: "geo.focus.points",
|
|
11903
|
-
code: "INVALID_TYPE",
|
|
11904
|
-
suggestion: 'Use { points: true } to fit all points, or { points: { field: "rating", value: "F" } } to fit a subset.'
|
|
11905
|
-
});
|
|
11906
|
-
}
|
|
11907
|
-
if (focusObj.padding !== void 0 && typeof focusObj.padding !== "number") {
|
|
11908
|
-
errors.push({
|
|
11909
|
-
message: "Spec error: geo.focus.padding must be a number",
|
|
11910
|
-
path: "geo.focus.padding",
|
|
11911
|
-
code: "INVALID_TYPE",
|
|
11912
|
-
suggestion: "Provide padding as a number in map-local units, e.g. padding: 16"
|
|
11913
|
-
});
|
|
11914
|
-
}
|
|
11915
|
-
} else if (!("features" in focusObj) || focusObj.features == null) {
|
|
11761
|
+
if (!("features" in focusObj) || focusObj.features == null) {
|
|
11916
11762
|
errors.push({
|
|
11917
|
-
message: 'Spec error: geo.focus object must have a "features"
|
|
11763
|
+
message: 'Spec error: geo.focus object must have a "features" property',
|
|
11918
11764
|
path: "geo.focus.features",
|
|
11919
11765
|
code: "MISSING_FIELD",
|
|
11920
|
-
suggestion: 'Provide feature id(s) to focus on, e.g. { features: "36", padding: 32 }
|
|
11766
|
+
suggestion: 'Provide feature id(s) to focus on, e.g. geo: { focus: { features: "36", padding: 32 } }'
|
|
11921
11767
|
});
|
|
11922
11768
|
} else {
|
|
11923
11769
|
const feats = focusObj.features;
|
|
@@ -11951,34 +11797,30 @@ function validateMapSpec(spec, errors) {
|
|
|
11951
11797
|
}
|
|
11952
11798
|
} else {
|
|
11953
11799
|
errors.push({
|
|
11954
|
-
message: "Spec error: geo.focus must be a string, number, array of ids, or object with { features, padding? }
|
|
11800
|
+
message: "Spec error: geo.focus must be a string, number, array of ids, or object with { features, padding? }",
|
|
11955
11801
|
path: "geo.focus",
|
|
11956
11802
|
code: "INVALID_TYPE",
|
|
11957
|
-
suggestion: 'Use a feature id, array of ids, { features: "36", padding: 16 }
|
|
11803
|
+
suggestion: 'Use a feature id, array of ids, or { features: "36", padding: 16 }. Pass null to clear focus.'
|
|
11958
11804
|
});
|
|
11959
11805
|
}
|
|
11960
11806
|
}
|
|
11961
11807
|
const encoding = spec.encoding;
|
|
11962
11808
|
const hasPoints = spec.points && typeof spec.points === "object" && !Array.isArray(spec.points);
|
|
11963
|
-
const specData = spec.data;
|
|
11964
|
-
const isBasemapOnly = hasPoints && (!specData || specData.length === 0);
|
|
11965
11809
|
const keyCh = encoding.key;
|
|
11966
|
-
if (!
|
|
11967
|
-
|
|
11968
|
-
|
|
11969
|
-
|
|
11970
|
-
|
|
11971
|
-
|
|
11972
|
-
|
|
11973
|
-
|
|
11974
|
-
|
|
11975
|
-
|
|
11976
|
-
|
|
11977
|
-
|
|
11978
|
-
|
|
11979
|
-
|
|
11980
|
-
});
|
|
11981
|
-
}
|
|
11810
|
+
if (!keyCh || typeof keyCh !== "object") {
|
|
11811
|
+
errors.push({
|
|
11812
|
+
message: 'Spec error: map encoding requires "key" channel',
|
|
11813
|
+
path: "encoding.key",
|
|
11814
|
+
code: "MISSING_FIELD",
|
|
11815
|
+
suggestion: 'Add encoding.key, e.g. key: { field: "id", type: "nominal" }'
|
|
11816
|
+
});
|
|
11817
|
+
} else if (!keyCh.field || typeof keyCh.field !== "string") {
|
|
11818
|
+
errors.push({
|
|
11819
|
+
message: 'Spec error: encoding.key must have a "field" string',
|
|
11820
|
+
path: "encoding.key.field",
|
|
11821
|
+
code: "MISSING_FIELD",
|
|
11822
|
+
suggestion: 'Add a field name, e.g. key: { field: "id" }'
|
|
11823
|
+
});
|
|
11982
11824
|
}
|
|
11983
11825
|
const colorCh = encoding.color;
|
|
11984
11826
|
if (!hasPoints) {
|
|
@@ -12033,17 +11875,6 @@ function validateMapSpec(spec, errors) {
|
|
|
12033
11875
|
});
|
|
12034
11876
|
}
|
|
12035
11877
|
}
|
|
12036
|
-
for (const ch of ["size", "color", "key"]) {
|
|
12037
|
-
const enc = points[ch];
|
|
12038
|
-
if (enc && typeof enc === "object" && (!enc.field || typeof enc.field !== "string")) {
|
|
12039
|
-
errors.push({
|
|
12040
|
-
message: `Spec error: points.${ch} must have a "field" string when provided`,
|
|
12041
|
-
path: `points.${ch}.field`,
|
|
12042
|
-
code: "MISSING_FIELD",
|
|
12043
|
-
suggestion: `Add a field name, e.g. ${ch}: { field: "myField" }`
|
|
12044
|
-
});
|
|
12045
|
-
}
|
|
12046
|
-
}
|
|
12047
11878
|
}
|
|
12048
11879
|
}
|
|
12049
11880
|
function validateBarListSpec(spec, errors) {
|
|
@@ -12086,8 +11917,7 @@ function validateBarListSpec(spec, errors) {
|
|
|
12086
11917
|
}
|
|
12087
11918
|
const encoding = spec.encoding;
|
|
12088
11919
|
const dataColumns = new Set(Object.keys(firstRow));
|
|
12089
|
-
const
|
|
12090
|
-
const availableColumns = columnList.join(", ");
|
|
11920
|
+
const availableColumns = [...dataColumns].join(", ");
|
|
12091
11921
|
for (const channel of ["label", "value"]) {
|
|
12092
11922
|
const ch = encoding[channel];
|
|
12093
11923
|
if (!ch || typeof ch !== "object") {
|
|
@@ -12095,7 +11925,7 @@ function validateBarListSpec(spec, errors) {
|
|
|
12095
11925
|
message: `Spec error: barlist encoding requires "${channel}" channel`,
|
|
12096
11926
|
path: `encoding.${channel}`,
|
|
12097
11927
|
code: "MISSING_FIELD",
|
|
12098
|
-
suggestion: `Add encoding.${channel} with a field from your data (${availableColumns}). Example: ${channel}: { field: "${
|
|
11928
|
+
suggestion: `Add encoding.${channel} with a field from your data (${availableColumns}). Example: ${channel}: { field: "${[...dataColumns][0] ?? "myField"}", type: "${channel === "value" ? "quantitative" : "nominal"}" }`
|
|
12099
11929
|
});
|
|
12100
11930
|
continue;
|
|
12101
11931
|
}
|
|
@@ -12113,7 +11943,7 @@ function validateBarListSpec(spec, errors) {
|
|
|
12113
11943
|
message: `Spec error: encoding.${channel}.field "${ch.field}" does not exist in data. Available columns: ${availableColumns}`,
|
|
12114
11944
|
path: `encoding.${channel}.field`,
|
|
12115
11945
|
code: "DATA_FIELD_MISSING",
|
|
12116
|
-
suggestion: `Use one of the available data columns: ${availableColumns}
|
|
11946
|
+
suggestion: `Use one of the available data columns: ${availableColumns}`
|
|
12117
11947
|
});
|
|
12118
11948
|
}
|
|
12119
11949
|
}
|
|
@@ -12126,16 +11956,10 @@ function validateBarListSpec(spec, errors) {
|
|
|
12126
11956
|
message: `Spec error: encoding.${channel}.field "${field}" does not exist in data. Available columns: ${availableColumns}`,
|
|
12127
11957
|
path: `encoding.${channel}.field`,
|
|
12128
11958
|
code: "DATA_FIELD_MISSING",
|
|
12129
|
-
suggestion: `Use one of the available data columns: ${availableColumns}
|
|
11959
|
+
suggestion: `Use one of the available data columns: ${availableColumns}`
|
|
12130
11960
|
});
|
|
12131
11961
|
}
|
|
12132
11962
|
}
|
|
12133
|
-
checkSchemeUnused(
|
|
12134
|
-
encoding,
|
|
12135
|
-
errors,
|
|
12136
|
-
"bar list colors cycle the built-in barlist palette",
|
|
12137
|
-
"Remove scale.scheme. Bar list colors are not configurable via encoding; they cycle the built-in palette."
|
|
12138
|
-
);
|
|
12139
11963
|
if (spec.darkMode !== void 0 && !VALID_DARK_MODES.has(spec.darkMode)) {
|
|
12140
11964
|
errors.push({
|
|
12141
11965
|
message: 'Spec error: darkMode must be "auto", "force", or "off"',
|
|
@@ -12349,36 +12173,6 @@ ${errorMessages}`);
|
|
|
12349
12173
|
return { spec: normalized, warnings };
|
|
12350
12174
|
}
|
|
12351
12175
|
|
|
12352
|
-
// src/layout/shared.ts
|
|
12353
|
-
function chromeToInput(chrome) {
|
|
12354
|
-
return {
|
|
12355
|
-
eyebrow: chrome.eyebrow,
|
|
12356
|
-
title: chrome.title,
|
|
12357
|
-
subtitle: chrome.subtitle,
|
|
12358
|
-
source: chrome.source,
|
|
12359
|
-
byline: chrome.byline,
|
|
12360
|
-
footer: chrome.footer,
|
|
12361
|
-
brand: chrome.brand
|
|
12362
|
-
};
|
|
12363
|
-
}
|
|
12364
|
-
function scalePadding(basePadding, width, height) {
|
|
12365
|
-
const minDim = Math.min(width, height);
|
|
12366
|
-
if (minDim >= 500) return basePadding;
|
|
12367
|
-
if (minDim <= 200) return Math.max(Math.round(basePadding * 0.5), 4);
|
|
12368
|
-
const t = (minDim - 200) / 300;
|
|
12369
|
-
return Math.max(Math.round(basePadding * (0.5 + t * 0.5)), 4);
|
|
12370
|
-
}
|
|
12371
|
-
function bottomMargin(bottomHeight, padding, xAxisHeight) {
|
|
12372
|
-
return padding + bottomHeight + xAxisHeight;
|
|
12373
|
-
}
|
|
12374
|
-
var INLINE_TICK_OVERHANG_PAD = 6;
|
|
12375
|
-
function resolveChromeLayout(spec, options) {
|
|
12376
|
-
const encoding = spec?.encoding;
|
|
12377
|
-
const isFaceted = !!(encoding?.facet || encoding?.row || encoding?.column);
|
|
12378
|
-
if (isFaceted) return "subtract";
|
|
12379
|
-
return spec?.chromeLayout ?? options?.chromeLayout ?? "subtract";
|
|
12380
|
-
}
|
|
12381
|
-
|
|
12382
12176
|
// src/barlist/compile-barlist.ts
|
|
12383
12177
|
var DEFAULT_ROW_GAP = 8;
|
|
12384
12178
|
var LABEL_BAR_GAP = 12;
|
|
@@ -12426,19 +12220,14 @@ function compileBarList(spec, options) {
|
|
|
12426
12220
|
watermark
|
|
12427
12221
|
);
|
|
12428
12222
|
const padding = theme.spacing.padding;
|
|
12429
|
-
const chromeLayout = resolveChromeLayout(
|
|
12430
|
-
spec,
|
|
12431
|
-
options
|
|
12432
|
-
);
|
|
12433
|
-
const grownHeight = chromeLayout === "grow" ? options.height + chrome.topHeight + chrome.bottomHeight : options.height;
|
|
12434
12223
|
const fullArea = {
|
|
12435
12224
|
x: padding,
|
|
12436
12225
|
y: padding + chrome.topHeight,
|
|
12437
12226
|
width: options.width - padding * 2,
|
|
12438
|
-
height:
|
|
12227
|
+
height: options.height - chrome.topHeight - chrome.bottomHeight - padding * 2
|
|
12439
12228
|
};
|
|
12440
12229
|
if (fullArea.width <= 0 || fullArea.height <= 0) {
|
|
12441
|
-
return emptyLayout2(chrome, theme,
|
|
12230
|
+
return emptyLayout2(chrome, theme, options, watermark);
|
|
12442
12231
|
}
|
|
12443
12232
|
const labelField = barlistSpec.encoding.label.field;
|
|
12444
12233
|
const valueField = barlistSpec.encoding.value.field;
|
|
@@ -12623,7 +12412,7 @@ function compileBarList(spec, options) {
|
|
|
12623
12412
|
a11y,
|
|
12624
12413
|
theme,
|
|
12625
12414
|
width: options.width,
|
|
12626
|
-
height:
|
|
12415
|
+
height: options.height,
|
|
12627
12416
|
animation: resolvedAnimation,
|
|
12628
12417
|
watermark,
|
|
12629
12418
|
measureText
|
|
@@ -13915,8 +13704,7 @@ function computeLegendContent(spec, strategy, theme, availableWidth, availableHe
|
|
|
13915
13704
|
fill: theme.colors.text,
|
|
13916
13705
|
lineHeight: 1.3
|
|
13917
13706
|
};
|
|
13918
|
-
const
|
|
13919
|
-
const resolvedPosition = specPosition ?? (strategy.legendPosition === "right" ? "right" : "top");
|
|
13707
|
+
const resolvedPosition = spec.legend?.position ?? (strategy.legendPosition === "right" ? "right" : "top");
|
|
13920
13708
|
if (entries.length === 0) {
|
|
13921
13709
|
return emptyContent(resolvedPosition, theme);
|
|
13922
13710
|
}
|
|
@@ -14917,6 +14705,30 @@ function computeAxes(scales, chartArea, strategy, theme, measureText, dataContex
|
|
|
14917
14705
|
return result;
|
|
14918
14706
|
}
|
|
14919
14707
|
|
|
14708
|
+
// src/layout/shared.ts
|
|
14709
|
+
function chromeToInput(chrome) {
|
|
14710
|
+
return {
|
|
14711
|
+
eyebrow: chrome.eyebrow,
|
|
14712
|
+
title: chrome.title,
|
|
14713
|
+
subtitle: chrome.subtitle,
|
|
14714
|
+
source: chrome.source,
|
|
14715
|
+
byline: chrome.byline,
|
|
14716
|
+
footer: chrome.footer,
|
|
14717
|
+
brand: chrome.brand
|
|
14718
|
+
};
|
|
14719
|
+
}
|
|
14720
|
+
function scalePadding(basePadding, width, height) {
|
|
14721
|
+
const minDim = Math.min(width, height);
|
|
14722
|
+
if (minDim >= 500) return basePadding;
|
|
14723
|
+
if (minDim <= 200) return Math.max(Math.round(basePadding * 0.5), 4);
|
|
14724
|
+
const t = (minDim - 200) / 300;
|
|
14725
|
+
return Math.max(Math.round(basePadding * (0.5 + t * 0.5)), 4);
|
|
14726
|
+
}
|
|
14727
|
+
function bottomMargin(bottomHeight, padding, xAxisHeight) {
|
|
14728
|
+
return padding + bottomHeight + xAxisHeight;
|
|
14729
|
+
}
|
|
14730
|
+
var INLINE_TICK_OVERHANG_PAD = 6;
|
|
14731
|
+
|
|
14920
14732
|
// src/layout/plan.ts
|
|
14921
14733
|
function createMeasureFn(measureText) {
|
|
14922
14734
|
if (measureText) {
|
|
@@ -15138,9 +14950,7 @@ function resolveLayoutPlan(chartSpec, renderSpec, options, theme, strategy, wate
|
|
|
15138
14950
|
if (hasTopLegend) topMargin += TOP_LEGEND_GAP_ABOVE + legendContent.height + gap;
|
|
15139
14951
|
topMargin += effectiveTopAxisGap;
|
|
15140
14952
|
const bMargin = bottomMargin(chrome.bottomHeight, padding, xAxisExtent);
|
|
15141
|
-
const
|
|
15142
|
-
const effectiveHeight = chromeLayout === "grow" ? height + chrome.topHeight + chrome.bottomHeight : height;
|
|
15143
|
-
const chartHeight = Math.max(0, effectiveHeight - topMargin - bMargin);
|
|
14953
|
+
const chartHeight = Math.max(0, height - topMargin - bMargin);
|
|
15144
14954
|
const rightMargin = hPad + (isRadial ? hPad : axisMargin);
|
|
15145
14955
|
const rightAxisReserve = options.rightAxisReserve ?? 0;
|
|
15146
14956
|
const provisionalArea = {
|
|
@@ -15701,10 +15511,6 @@ function buildPrimarySpec(leaves, layerSpec) {
|
|
|
15701
15511
|
...leaves[0],
|
|
15702
15512
|
data: allData,
|
|
15703
15513
|
chrome: layerSpec.chrome ?? leaves[0].chrome,
|
|
15704
|
-
// Annotations come from the parent LayerSpec when present, otherwise
|
|
15705
|
-
// the first flattened leaf's. Later leaves' annotations are silently
|
|
15706
|
-
// dropped. The dual-axis path (compileLayerIndependent) explicitly
|
|
15707
|
-
// clears the secondary axis spec's annotations.
|
|
15708
15514
|
annotations: layerSpec.annotations ?? leaves[0].annotations,
|
|
15709
15515
|
labels: layerSpec.labels ?? leaves[0].labels,
|
|
15710
15516
|
legend: layerSpec.legend ?? leaves[0].legend,
|
|
@@ -15939,7 +15745,7 @@ import {
|
|
|
15939
15745
|
HPAD_COMPACT_FRACTION as HPAD_COMPACT_FRACTION2,
|
|
15940
15746
|
HPAD_COMPACT_MIN as HPAD_COMPACT_MIN2,
|
|
15941
15747
|
resolveTheme as resolveTheme3,
|
|
15942
|
-
SEQUENTIAL_PALETTES
|
|
15748
|
+
SEQUENTIAL_PALETTES
|
|
15943
15749
|
} from "@opendata-ai/openchart-core";
|
|
15944
15750
|
|
|
15945
15751
|
// ../../node_modules/.bun/d3-geo@3.1.1/node_modules/d3-geo/src/math.js
|
|
@@ -17917,32 +17723,13 @@ function joinDataToFeatures(features, data, dataKeyField, featureIdField) {
|
|
|
17917
17723
|
|
|
17918
17724
|
// src/geo/projections.ts
|
|
17919
17725
|
var MERCATOR_FIT_MIN_LAT = -60;
|
|
17920
|
-
function createProjection(type, width, height, geojson
|
|
17726
|
+
function createProjection(type, width, height, geojson) {
|
|
17921
17727
|
if (type === "identity") {
|
|
17922
|
-
if (inset > 0) {
|
|
17923
|
-
return identity_default4().fitExtent(
|
|
17924
|
-
[
|
|
17925
|
-
[inset, inset],
|
|
17926
|
-
[width - inset, height - inset]
|
|
17927
|
-
],
|
|
17928
|
-
geojson
|
|
17929
|
-
);
|
|
17930
|
-
}
|
|
17931
17728
|
return identity_default4().fitSize([width, height], geojson);
|
|
17932
17729
|
}
|
|
17933
17730
|
const projection2 = type === "albersUsa" ? albersUsa_default() : type === "equalEarth" ? equalEarth_default() : mercator_default();
|
|
17934
17731
|
const fitGeometry = type === "mercator" ? excludePolarFeatures(geojson) : geojson;
|
|
17935
|
-
|
|
17936
|
-
projection2.fitExtent(
|
|
17937
|
-
[
|
|
17938
|
-
[inset, inset],
|
|
17939
|
-
[width - inset, height - inset]
|
|
17940
|
-
],
|
|
17941
|
-
fitGeometry
|
|
17942
|
-
);
|
|
17943
|
-
} else {
|
|
17944
|
-
projection2.fitSize([width, height], fitGeometry);
|
|
17945
|
-
}
|
|
17732
|
+
projection2.fitSize([width, height], fitGeometry);
|
|
17946
17733
|
return projection2;
|
|
17947
17734
|
}
|
|
17948
17735
|
function excludePolarFeatures(geojson) {
|
|
@@ -17962,7 +17749,6 @@ function excludePolarFeatures(geojson) {
|
|
|
17962
17749
|
}
|
|
17963
17750
|
|
|
17964
17751
|
// src/geo/compile-map.ts
|
|
17965
|
-
var OVERLAY_LEGEND_INSET = 18;
|
|
17966
17752
|
function validateGeoFeatures(geo) {
|
|
17967
17753
|
if (!geo.features) {
|
|
17968
17754
|
throw new Error(
|
|
@@ -18020,15 +17806,11 @@ function compileMap(spec, options) {
|
|
|
18020
17806
|
watermark
|
|
18021
17807
|
);
|
|
18022
17808
|
const padding = getBreakpoint(options.width) === "compact" ? Math.max(HPAD_COMPACT_MIN2, Math.round(theme.spacing.padding * HPAD_COMPACT_FRACTION2)) : theme.spacing.padding;
|
|
18023
|
-
const chromeLayout = resolveChromeLayout(
|
|
18024
|
-
spec,
|
|
18025
|
-
options
|
|
18026
|
-
);
|
|
18027
17809
|
const fullArea = {
|
|
18028
17810
|
x: padding,
|
|
18029
17811
|
y: padding + chrome.topHeight,
|
|
18030
17812
|
width: options.width - padding * 2,
|
|
18031
|
-
height:
|
|
17813
|
+
height: options.height - chrome.topHeight - chrome.bottomHeight - padding * 2
|
|
18032
17814
|
};
|
|
18033
17815
|
if (fullArea.width <= 0 || fullArea.height <= 0) {
|
|
18034
17816
|
return emptyLayout3(chrome, theme, options, watermark);
|
|
@@ -18039,13 +17821,11 @@ function compileMap(spec, options) {
|
|
|
18039
17821
|
const compileWarnings = [];
|
|
18040
17822
|
const showLegend = mapSpec.legend?.show !== false;
|
|
18041
17823
|
const colorEncoding = mapSpec.encoding.color;
|
|
18042
|
-
const showChoroplethLegend = showLegend && colorEncoding?.legend !== null;
|
|
18043
17824
|
const isQuantitative = colorEncoding?.type === "quantitative";
|
|
18044
17825
|
const legendPosition = mapSpec.legend?.position === "bottom" ? "bottom" : "top";
|
|
18045
|
-
const pointLegendOverlay = mapSpec.legend?.position === "top-left";
|
|
18046
17826
|
let legendBlockHeight = 0;
|
|
18047
17827
|
let continuousContent = null;
|
|
18048
|
-
if (
|
|
17828
|
+
if (showLegend && colorEncoding && isQuantitative) {
|
|
18049
17829
|
const colorValues = [];
|
|
18050
17830
|
for (const row of mapSpec.data) {
|
|
18051
17831
|
const v = row[colorEncoding.field];
|
|
@@ -18068,11 +17848,11 @@ function compileMap(spec, options) {
|
|
|
18068
17848
|
const labelRowHeight = Math.ceil(theme.fonts.sizes.small * 1.3);
|
|
18069
17849
|
legendBlockHeight = continuousContent.barHeight + CONTINUOUS_LABEL_GAP + labelRowHeight;
|
|
18070
17850
|
}
|
|
18071
|
-
} else if (
|
|
17851
|
+
} else if (showLegend && colorEncoding) {
|
|
18072
17852
|
const labelHeight = Math.ceil(theme.fonts.sizes.small * 1.3);
|
|
18073
17853
|
legendBlockHeight = Math.max(10, labelHeight) + 6;
|
|
18074
17854
|
}
|
|
18075
|
-
if (showLegend &&
|
|
17855
|
+
if (showLegend && mapSpec.points?.color) {
|
|
18076
17856
|
if (mapSpec.points.color.type === "quantitative") {
|
|
18077
17857
|
const labelRowHeight = Math.ceil(theme.fonts.sizes.small * 1.3);
|
|
18078
17858
|
legendBlockHeight += CONTINUOUS_BAR_HEIGHT + CONTINUOUS_LABEL_GAP + labelRowHeight + 8;
|
|
@@ -18087,18 +17867,7 @@ function compileMap(spec, options) {
|
|
|
18087
17867
|
return emptyLayout3(chrome, theme, options, watermark);
|
|
18088
17868
|
}
|
|
18089
17869
|
const projectionType = mapSpec.geo.projection;
|
|
18090
|
-
|
|
18091
|
-
if (mapSpec.points) {
|
|
18092
|
-
const sizeRange = mapSpec.points.size?.scale?.range;
|
|
18093
|
-
pointInset = sizeRange ? sizeRange[1] : SIZE_SCALE_DEFAULTS.mapPoint.range[1];
|
|
18094
|
-
}
|
|
18095
|
-
const projection2 = createProjection(
|
|
18096
|
-
projectionType,
|
|
18097
|
-
fullArea.width,
|
|
18098
|
-
mapAreaHeight,
|
|
18099
|
-
geoCollection,
|
|
18100
|
-
pointInset
|
|
18101
|
-
);
|
|
17870
|
+
const projection2 = createProjection(projectionType, fullArea.width, mapAreaHeight, geoCollection);
|
|
18102
17871
|
const pathGen = path_default(projection2);
|
|
18103
17872
|
if (projectionType !== "identity") {
|
|
18104
17873
|
for (const feat of geoFeatures) {
|
|
@@ -18113,24 +17882,20 @@ function compileMap(spec, options) {
|
|
|
18113
17882
|
}
|
|
18114
17883
|
}
|
|
18115
17884
|
}
|
|
18116
|
-
|
|
18117
|
-
|
|
18118
|
-
|
|
18119
|
-
|
|
18120
|
-
|
|
18121
|
-
|
|
18122
|
-
|
|
18123
|
-
|
|
18124
|
-
|
|
18125
|
-
|
|
18126
|
-
|
|
18127
|
-
|
|
18128
|
-
joined = joinResult.joined;
|
|
18129
|
-
const filteredJoinWarnings = mapSpec.data.length === 0 && mapSpec.points ? joinResult.warnings.filter((w) => w.code !== "UNMATCHED_FEATURES") : joinResult.warnings;
|
|
18130
|
-
compileWarnings.push(...filteredJoinWarnings);
|
|
18131
|
-
}
|
|
17885
|
+
const featureObjs = geoFeatures.map((f) => ({
|
|
17886
|
+
id: f.id,
|
|
17887
|
+
properties: f.properties ?? {}
|
|
17888
|
+
}));
|
|
17889
|
+
const { joined, warnings: joinWarnings } = joinDataToFeatures(
|
|
17890
|
+
featureObjs,
|
|
17891
|
+
mapSpec.data,
|
|
17892
|
+
mapSpec.encoding.key.field,
|
|
17893
|
+
mapSpec.geo.idField
|
|
17894
|
+
);
|
|
17895
|
+
const filteredJoinWarnings = mapSpec.data.length === 0 && mapSpec.points ? joinWarnings.filter((w) => w.code !== "UNMATCHED_FEATURES") : joinWarnings;
|
|
17896
|
+
compileWarnings.push(...filteredJoinWarnings);
|
|
18132
17897
|
const droppedFeatures = [];
|
|
18133
|
-
const formatter = buildD3Formatter2(mapSpec.
|
|
17898
|
+
const formatter = buildD3Formatter2(mapSpec.valueFormat) ?? formatNumber3;
|
|
18134
17899
|
const neutralFill = isDarkMode ? "#2a2a2a" : "#e8e8e8";
|
|
18135
17900
|
const neutralStroke = isDarkMode ? "rgba(255,255,255,0.08)" : "rgba(0,0,0,0.06)";
|
|
18136
17901
|
let featureMarks;
|
|
@@ -18158,7 +17923,7 @@ function compileMap(spec, options) {
|
|
|
18158
17923
|
droppedFeatures
|
|
18159
17924
|
});
|
|
18160
17925
|
featureMarks = result.marks;
|
|
18161
|
-
if (
|
|
17926
|
+
if (showLegend && continuousContent) {
|
|
18162
17927
|
const labelStyle = {
|
|
18163
17928
|
fontFamily: theme.fonts.family,
|
|
18164
17929
|
fontSize: theme.fonts.sizes.small,
|
|
@@ -18200,7 +17965,6 @@ function compileMap(spec, options) {
|
|
|
18200
17965
|
pathGen,
|
|
18201
17966
|
joined,
|
|
18202
17967
|
colorField: colorEncoding.field,
|
|
18203
|
-
colorScale: colorEncoding.scale,
|
|
18204
17968
|
isDarkMode: !!isDarkMode,
|
|
18205
17969
|
neutralFill,
|
|
18206
17970
|
neutralStroke,
|
|
@@ -18208,8 +17972,7 @@ function compileMap(spec, options) {
|
|
|
18208
17972
|
fullArea,
|
|
18209
17973
|
mapAreaHeight,
|
|
18210
17974
|
legendReserveGap,
|
|
18211
|
-
|
|
18212
|
-
showLegend: showChoroplethLegend,
|
|
17975
|
+
showLegend,
|
|
18213
17976
|
droppedFeatures
|
|
18214
17977
|
});
|
|
18215
17978
|
featureMarks = result.marks;
|
|
@@ -18261,7 +18024,7 @@ function compileMap(spec, options) {
|
|
|
18261
18024
|
}
|
|
18262
18025
|
if (colorValues.length > 0) {
|
|
18263
18026
|
const palette = pts.color.scale?.scheme ?? "blue";
|
|
18264
|
-
const paletteStops = [...
|
|
18027
|
+
const paletteStops = [...SEQUENTIAL_PALETTES[palette] ?? SEQUENTIAL_PALETTES.blue];
|
|
18265
18028
|
const qScale = quantile2().domain(colorValues).range(paletteStops);
|
|
18266
18029
|
pointColorScale = (val) => {
|
|
18267
18030
|
const v = Number(val);
|
|
@@ -18269,14 +18032,7 @@ function compileMap(spec, options) {
|
|
|
18269
18032
|
};
|
|
18270
18033
|
}
|
|
18271
18034
|
} else {
|
|
18272
|
-
const
|
|
18273
|
-
const explicitRange = pts.color.scale?.range;
|
|
18274
|
-
if (explicitDomain && Array.isArray(explicitDomain)) {
|
|
18275
|
-
for (const cat of explicitDomain) {
|
|
18276
|
-
pointCategories.push(String(cat));
|
|
18277
|
-
}
|
|
18278
|
-
}
|
|
18279
|
-
const seen = new Set(pointCategories);
|
|
18035
|
+
const seen = /* @__PURE__ */ new Set();
|
|
18280
18036
|
for (const row of pts.data) {
|
|
18281
18037
|
const raw = row[pts.color.field];
|
|
18282
18038
|
if (raw != null) {
|
|
@@ -18284,23 +18040,21 @@ function compileMap(spec, options) {
|
|
|
18284
18040
|
if (!seen.has(cat)) {
|
|
18285
18041
|
seen.add(cat);
|
|
18286
18042
|
pointCategories.push(cat);
|
|
18043
|
+
pointCategoryColors.set(
|
|
18044
|
+
cat,
|
|
18045
|
+
CATEGORICAL_PALETTE[(pointCategories.length - 1) % CATEGORICAL_PALETTE.length]
|
|
18046
|
+
);
|
|
18287
18047
|
}
|
|
18288
18048
|
}
|
|
18289
18049
|
}
|
|
18290
|
-
const colorSource = explicitRange && Array.isArray(explicitRange) ? explicitRange : CATEGORICAL_PALETTE;
|
|
18291
|
-
for (let i = 0; i < pointCategories.length; i++) {
|
|
18292
|
-
pointCategoryColors.set(pointCategories[i], colorSource[i % colorSource.length]);
|
|
18293
|
-
}
|
|
18294
18050
|
pointColorScale = (val) => {
|
|
18295
|
-
if (val == null) return
|
|
18296
|
-
return pointCategoryColors.get(String(val)) ??
|
|
18051
|
+
if (val == null) return CATEGORICAL_PALETTE[0];
|
|
18052
|
+
return pointCategoryColors.get(String(val)) ?? CATEGORICAL_PALETTE[0];
|
|
18297
18053
|
};
|
|
18298
18054
|
}
|
|
18299
18055
|
}
|
|
18300
18056
|
const defaultFill = CATEGORICAL_PALETTE[0];
|
|
18301
|
-
const pointOpacity = pts.opacity ?? 0.65;
|
|
18302
18057
|
let animIndex = 0;
|
|
18303
|
-
const droppedPoints = [];
|
|
18304
18058
|
for (let i = 0; i < pts.data.length; i++) {
|
|
18305
18059
|
const row = pts.data[i];
|
|
18306
18060
|
const lon = Number(row[lonField]);
|
|
@@ -18308,7 +18062,11 @@ function compileMap(spec, options) {
|
|
|
18308
18062
|
if (!Number.isFinite(lon) || !Number.isFinite(lat)) continue;
|
|
18309
18063
|
const projected = projection2([lon, lat]);
|
|
18310
18064
|
if (!projected) {
|
|
18311
|
-
|
|
18065
|
+
compileWarnings.push({
|
|
18066
|
+
code: "POINT_NULL_PROJECTION",
|
|
18067
|
+
message: `Point at [${lon}, ${lat}] projects to null and was dropped.`,
|
|
18068
|
+
context: { lon, lat }
|
|
18069
|
+
});
|
|
18312
18070
|
continue;
|
|
18313
18071
|
}
|
|
18314
18072
|
const r = sizeScale ? sizeScale.scale(Number(row[sizeScale.field])) : 5;
|
|
@@ -18323,21 +18081,12 @@ function compileMap(spec, options) {
|
|
|
18323
18081
|
fill,
|
|
18324
18082
|
stroke,
|
|
18325
18083
|
strokeWidth: 1,
|
|
18326
|
-
fillOpacity: pointOpacity,
|
|
18327
18084
|
key,
|
|
18328
18085
|
data: row,
|
|
18329
18086
|
aria: { role: "img", label: key },
|
|
18330
18087
|
animationIndex: animIndex++
|
|
18331
18088
|
});
|
|
18332
18089
|
}
|
|
18333
|
-
if (droppedPoints.length > 0) {
|
|
18334
|
-
const sample = droppedPoints.slice(0, 3).map(([lo, la]) => `[${lo}, ${la}]`).join(", ");
|
|
18335
|
-
compileWarnings.push({
|
|
18336
|
-
code: "POINT_NULL_PROJECTION",
|
|
18337
|
-
message: `${droppedPoints.length} point(s) project to null and were dropped (e.g. ${sample}). This is common with albersUsa which excludes territories. Consider using projection: "mercator" or "equalEarth".`,
|
|
18338
|
-
context: { count: droppedPoints.length, samples: droppedPoints.slice(0, 5) }
|
|
18339
|
-
});
|
|
18340
|
-
}
|
|
18341
18090
|
if (pts.color && pts.color.type !== "quantitative" && pointCategories.length > 0 && showLegend) {
|
|
18342
18091
|
const labelStyle = {
|
|
18343
18092
|
fontFamily: theme.fonts.family,
|
|
@@ -18351,17 +18100,17 @@ function compileMap(spec, options) {
|
|
|
18351
18100
|
color: pointCategoryColors.get(cat),
|
|
18352
18101
|
shape: "circle"
|
|
18353
18102
|
}));
|
|
18354
|
-
const
|
|
18355
|
-
const choroplethLegendGap =
|
|
18356
|
-
const legendX =
|
|
18357
|
-
const legendY =
|
|
18358
|
-
const legendWidth =
|
|
18103
|
+
const choroplethLegendHeight = continuousLegend ? continuousLegend.bounds.height : categoricalLegend ? categoricalLegend.bounds.height : 0;
|
|
18104
|
+
const choroplethLegendGap = choroplethLegendHeight > 0 ? 8 : 0;
|
|
18105
|
+
const legendX = fullArea.x;
|
|
18106
|
+
const legendY = fullArea.y + mapAreaHeight + legendReserveGap + choroplethLegendHeight + choroplethLegendGap;
|
|
18107
|
+
const legendWidth = fullArea.width;
|
|
18359
18108
|
const swatchSize = 10;
|
|
18360
18109
|
const swatchGap = 6;
|
|
18361
18110
|
const entryGap = 16;
|
|
18362
18111
|
pointCategoricalLegend = {
|
|
18363
18112
|
type: "categorical",
|
|
18364
|
-
position:
|
|
18113
|
+
position: "bottom",
|
|
18365
18114
|
bounds: { x: legendX, y: legendY, width: legendWidth, height: swatchSize + 6 },
|
|
18366
18115
|
labelStyle,
|
|
18367
18116
|
entries,
|
|
@@ -18399,10 +18148,10 @@ function compileMap(spec, options) {
|
|
|
18399
18148
|
lineHeight: 1.3,
|
|
18400
18149
|
fontVariant: "tabular-nums"
|
|
18401
18150
|
};
|
|
18402
|
-
const
|
|
18403
|
-
const choroplethLegendGap =
|
|
18404
|
-
const legendX =
|
|
18405
|
-
const legendY =
|
|
18151
|
+
const choroplethLegendHeight = continuousLegend ? continuousLegend.bounds.height : categoricalLegend ? categoricalLegend.bounds.height : 0;
|
|
18152
|
+
const choroplethLegendGap = choroplethLegendHeight > 0 ? 8 : 0;
|
|
18153
|
+
const legendX = fullArea.x;
|
|
18154
|
+
const legendY = fullArea.y + mapAreaHeight + legendReserveGap + choroplethLegendHeight + choroplethLegendGap;
|
|
18406
18155
|
const ptLabelRowHeight = Math.ceil(theme.fonts.sizes.small * 1.3);
|
|
18407
18156
|
const ptLegendHeight = ptContinuousContent.barHeight + CONTINUOUS_LABEL_GAP + ptLabelRowHeight;
|
|
18408
18157
|
const bounds = {
|
|
@@ -18420,7 +18169,7 @@ function compileMap(spec, options) {
|
|
|
18420
18169
|
pointContinuousLegend = {
|
|
18421
18170
|
type: "continuous",
|
|
18422
18171
|
mode: ptContinuousContent.mode,
|
|
18423
|
-
position:
|
|
18172
|
+
position: "bottom",
|
|
18424
18173
|
bounds,
|
|
18425
18174
|
labelStyle,
|
|
18426
18175
|
bar,
|
|
@@ -18518,7 +18267,7 @@ function compileMap(spec, options) {
|
|
|
18518
18267
|
role: "img",
|
|
18519
18268
|
keyboardNavigable: featureMarks.length > 0 || pointMarks.length > 0
|
|
18520
18269
|
};
|
|
18521
|
-
const resolvedFocus = resolveFocus(mapSpec.geo.focus, featureMarks,
|
|
18270
|
+
const resolvedFocus = resolveFocus(mapSpec.geo.focus, featureMarks, compileWarnings);
|
|
18522
18271
|
const resolvedAnimation = resolveAnimation(mapSpec.animation);
|
|
18523
18272
|
const mapAreaY = legendPosition === "top" && legendBlockHeight > 0 ? fullArea.y + legendBlockHeight + legendReserveGap : fullArea.y;
|
|
18524
18273
|
const mapArea = {
|
|
@@ -18618,7 +18367,7 @@ function buildQuantitativeMarks(opts) {
|
|
|
18618
18367
|
if (!Number.isNaN(v)) values.push(v);
|
|
18619
18368
|
}
|
|
18620
18369
|
}
|
|
18621
|
-
const paletteStops = [...
|
|
18370
|
+
const paletteStops = [...SEQUENTIAL_PALETTES[palette] ?? SEQUENTIAL_PALETTES.blue];
|
|
18622
18371
|
const colorScale = quantile2().domain(values).range(paletteStops);
|
|
18623
18372
|
const marks = [];
|
|
18624
18373
|
let animIndex = 0;
|
|
@@ -18681,7 +18430,6 @@ function buildCategoricalMarks(opts) {
|
|
|
18681
18430
|
pathGen,
|
|
18682
18431
|
joined,
|
|
18683
18432
|
colorField,
|
|
18684
|
-
colorScale: scaleConfig,
|
|
18685
18433
|
isDarkMode,
|
|
18686
18434
|
neutralFill,
|
|
18687
18435
|
neutralStroke,
|
|
@@ -18689,18 +18437,11 @@ function buildCategoricalMarks(opts) {
|
|
|
18689
18437
|
fullArea,
|
|
18690
18438
|
mapAreaHeight,
|
|
18691
18439
|
legendReserveGap,
|
|
18692
|
-
legendPosition,
|
|
18693
18440
|
showLegend,
|
|
18694
18441
|
droppedFeatures
|
|
18695
18442
|
} = opts;
|
|
18696
18443
|
const categories = [];
|
|
18697
|
-
const
|
|
18698
|
-
if (explicitDomain && Array.isArray(explicitDomain)) {
|
|
18699
|
-
for (const cat of explicitDomain) {
|
|
18700
|
-
categories.push(String(cat));
|
|
18701
|
-
}
|
|
18702
|
-
}
|
|
18703
|
-
const seen = new Set(categories);
|
|
18444
|
+
const seen = /* @__PURE__ */ new Set();
|
|
18704
18445
|
for (const row of joined.values()) {
|
|
18705
18446
|
const raw = row[colorField];
|
|
18706
18447
|
if (raw != null) {
|
|
@@ -18711,11 +18452,9 @@ function buildCategoricalMarks(opts) {
|
|
|
18711
18452
|
}
|
|
18712
18453
|
}
|
|
18713
18454
|
}
|
|
18714
|
-
const explicitRange = scaleConfig?.range;
|
|
18715
|
-
const colorSource = explicitRange && Array.isArray(explicitRange) ? explicitRange : CATEGORICAL_PALETTE;
|
|
18716
18455
|
const categoryColors = /* @__PURE__ */ new Map();
|
|
18717
18456
|
for (let i = 0; i < categories.length; i++) {
|
|
18718
|
-
categoryColors.set(categories[i],
|
|
18457
|
+
categoryColors.set(categories[i], CATEGORICAL_PALETTE[i % CATEGORICAL_PALETTE.length]);
|
|
18719
18458
|
}
|
|
18720
18459
|
const marks = [];
|
|
18721
18460
|
let animIndex = 0;
|
|
@@ -18783,14 +18522,14 @@ function buildCategoricalMarks(opts) {
|
|
|
18783
18522
|
shape: "square"
|
|
18784
18523
|
}));
|
|
18785
18524
|
const legendX = fullArea.x;
|
|
18786
|
-
const legendY =
|
|
18525
|
+
const legendY = fullArea.y + mapAreaHeight + legendReserveGap;
|
|
18787
18526
|
const legendWidth = fullArea.width;
|
|
18788
18527
|
const swatchSize = 10;
|
|
18789
18528
|
const swatchGap = 6;
|
|
18790
18529
|
const entryGap = 16;
|
|
18791
18530
|
legend = {
|
|
18792
18531
|
type: "categorical",
|
|
18793
|
-
position:
|
|
18532
|
+
position: "bottom",
|
|
18794
18533
|
bounds: { x: legendX, y: legendY, width: legendWidth, height: swatchSize + 6 },
|
|
18795
18534
|
labelStyle,
|
|
18796
18535
|
entries,
|
|
@@ -18802,40 +18541,8 @@ function buildCategoricalMarks(opts) {
|
|
|
18802
18541
|
}
|
|
18803
18542
|
return { marks, legend };
|
|
18804
18543
|
}
|
|
18805
|
-
function resolveFocus(focus, features,
|
|
18544
|
+
function resolveFocus(focus, features, warnings) {
|
|
18806
18545
|
if (focus === null || focus === void 0) return null;
|
|
18807
|
-
if (typeof focus === "object" && !Array.isArray(focus) && "points" in focus) {
|
|
18808
|
-
const filter = focus.points;
|
|
18809
|
-
const matched = filter === true ? pointMarks : pointMarks.filter((p) => p.data[filter.field] === filter.value);
|
|
18810
|
-
if (matched.length === 0) {
|
|
18811
|
-
const detail = filter === true ? "the map has no points to fit" : `no points match { field: "${filter.field}", value: ${JSON.stringify(filter.value)} }`;
|
|
18812
|
-
warnings.push({
|
|
18813
|
-
code: "FOCUS_UNMATCHED",
|
|
18814
|
-
message: `geo.focus.points is set but ${detail}`,
|
|
18815
|
-
context: {}
|
|
18816
|
-
});
|
|
18817
|
-
return null;
|
|
18818
|
-
}
|
|
18819
|
-
const padding2 = focus.padding ?? 16;
|
|
18820
|
-
let minX2 = Infinity;
|
|
18821
|
-
let minY2 = Infinity;
|
|
18822
|
-
let maxX2 = -Infinity;
|
|
18823
|
-
let maxY2 = -Infinity;
|
|
18824
|
-
for (const p of matched) {
|
|
18825
|
-
minX2 = Math.min(minX2, p.cx);
|
|
18826
|
-
minY2 = Math.min(minY2, p.cy);
|
|
18827
|
-
maxX2 = Math.max(maxX2, p.cx);
|
|
18828
|
-
maxY2 = Math.max(maxY2, p.cy);
|
|
18829
|
-
}
|
|
18830
|
-
const w = Math.max(maxX2 - minX2, 1);
|
|
18831
|
-
const h = Math.max(maxY2 - minY2, 1);
|
|
18832
|
-
return {
|
|
18833
|
-
target: { x: minX2, y: minY2, width: w, height: h, padding: padding2 },
|
|
18834
|
-
// No feature ids: focus-dim is a feature concept, so a points focus
|
|
18835
|
-
// dims no features (there are no "other" features to mute).
|
|
18836
|
-
ids: []
|
|
18837
|
-
};
|
|
18838
|
-
}
|
|
18839
18546
|
let ids;
|
|
18840
18547
|
let padding = 16;
|
|
18841
18548
|
if (typeof focus === "string" || typeof focus === "number") {
|
|
@@ -19405,7 +19112,6 @@ function legendLayoutHasContent(legendLayout) {
|
|
|
19405
19112
|
}
|
|
19406
19113
|
var MIN_CHART_WIDTH = 60;
|
|
19407
19114
|
var MIN_CHART_HEIGHT2 = 40;
|
|
19408
|
-
var PLOT_SHARE_MAX = 0.4;
|
|
19409
19115
|
var SERIES_SEARCH_INPUT_HEIGHT = 32;
|
|
19410
19116
|
var SERIES_SEARCH_GAP = 12;
|
|
19411
19117
|
function getMinChartDims(display) {
|
|
@@ -19448,10 +19154,8 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
|
|
|
19448
19154
|
watermark,
|
|
19449
19155
|
bottomLegendReservation
|
|
19450
19156
|
);
|
|
19451
|
-
const chromeLayout = resolveChromeLayout(spec, options);
|
|
19452
|
-
const effectiveHeight = chromeLayout === "grow" ? height + chrome.topHeight + chrome.bottomHeight : height;
|
|
19453
19157
|
if (isSparkline) {
|
|
19454
|
-
const total2 = { x: 0, y: 0, width, height
|
|
19158
|
+
const total2 = { x: 0, y: 0, width, height };
|
|
19455
19159
|
const sparkPad = getSparklinePad(spec);
|
|
19456
19160
|
const xAxisSpace = userExplicit.xAxis ? 26 : 0;
|
|
19457
19161
|
const yAxisSpace = userExplicit.yAxis ? 30 : 0;
|
|
@@ -19475,7 +19179,7 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
|
|
|
19475
19179
|
x: margins2.left,
|
|
19476
19180
|
y: margins2.top,
|
|
19477
19181
|
width: Math.max(0, width - margins2.left - margins2.right),
|
|
19478
|
-
height: Math.max(0,
|
|
19182
|
+
height: Math.max(0, height - margins2.top - margins2.bottom)
|
|
19479
19183
|
};
|
|
19480
19184
|
return {
|
|
19481
19185
|
total: total2,
|
|
@@ -19487,7 +19191,7 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
|
|
|
19487
19191
|
effectiveAxisGap: 0
|
|
19488
19192
|
};
|
|
19489
19193
|
}
|
|
19490
|
-
const total = { x: 0, y: 0, width, height
|
|
19194
|
+
const total = { x: 0, y: 0, width, height };
|
|
19491
19195
|
const isRadial = isAxislessMark2(spec.markType);
|
|
19492
19196
|
const encoding = spec.encoding;
|
|
19493
19197
|
const xAxisSuppressed = encoding.x?.axis === false;
|
|
@@ -19717,11 +19421,10 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
|
|
|
19717
19421
|
x: margins.left,
|
|
19718
19422
|
y: margins.top,
|
|
19719
19423
|
width: Math.max(0, width - margins.left - margins.right),
|
|
19720
|
-
height: Math.max(0,
|
|
19424
|
+
height: Math.max(0, height - margins.top - margins.bottom)
|
|
19721
19425
|
};
|
|
19722
19426
|
const minDims = getMinChartDims(spec.display);
|
|
19723
|
-
|
|
19724
|
-
if ((chartArea.width < minDims.width || chartArea.height < minDims.height || chromeEatsPlot) && chromeMode !== "hidden") {
|
|
19427
|
+
if ((chartArea.width < minDims.width || chartArea.height < minDims.height) && chromeMode !== "hidden") {
|
|
19725
19428
|
const fallbackMode = chromeMode === "full" ? "compact" : "hidden";
|
|
19726
19429
|
const fallbackChrome = computeChrome5(
|
|
19727
19430
|
chromeToInput(spec.chrome),
|
|
@@ -19747,7 +19450,7 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
|
|
|
19747
19450
|
x: margins.left,
|
|
19748
19451
|
y: margins.top,
|
|
19749
19452
|
width: Math.max(0, width - margins.left - margins.right),
|
|
19750
|
-
height: Math.max(0,
|
|
19453
|
+
height: Math.max(0, height - margins.top - margins.bottom)
|
|
19751
19454
|
};
|
|
19752
19455
|
const fallbackMetricsTopY = topPad + fallbackChrome.topHeight;
|
|
19753
19456
|
const fallbackMetricsArea = { x: hPad, width: Math.max(0, width - hPad * 2) };
|
|
@@ -19764,7 +19467,7 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
|
|
|
19764
19467
|
chartArea = {
|
|
19765
19468
|
...chartArea,
|
|
19766
19469
|
y: margins.top,
|
|
19767
|
-
height: Math.max(0,
|
|
19470
|
+
height: Math.max(0, height - margins.top - margins.bottom)
|
|
19768
19471
|
};
|
|
19769
19472
|
}
|
|
19770
19473
|
return {
|
|
@@ -19780,8 +19483,7 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
|
|
|
19780
19483
|
fallbackMetricsArea
|
|
19781
19484
|
) : void 0,
|
|
19782
19485
|
xAxisHeight,
|
|
19783
|
-
effectiveAxisGap: fallbackEffectiveAxisGap
|
|
19784
|
-
chromeStripped: true
|
|
19486
|
+
effectiveAxisGap: fallbackEffectiveAxisGap
|
|
19785
19487
|
};
|
|
19786
19488
|
}
|
|
19787
19489
|
}
|
|
@@ -19793,7 +19495,7 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
|
|
|
19793
19495
|
chartArea = {
|
|
19794
19496
|
...chartArea,
|
|
19795
19497
|
y: margins.top,
|
|
19796
|
-
height: Math.max(0,
|
|
19498
|
+
height: Math.max(0, height - margins.top - margins.bottom)
|
|
19797
19499
|
};
|
|
19798
19500
|
}
|
|
19799
19501
|
return {
|
|
@@ -20545,19 +20247,14 @@ function compileSankey(spec, options) {
|
|
|
20545
20247
|
watermark
|
|
20546
20248
|
);
|
|
20547
20249
|
const padding = theme.spacing.padding;
|
|
20548
|
-
const chromeLayout = resolveChromeLayout(
|
|
20549
|
-
spec,
|
|
20550
|
-
options
|
|
20551
|
-
);
|
|
20552
|
-
const grownHeight = chromeLayout === "grow" ? options.height + chrome.topHeight + chrome.bottomHeight : options.height;
|
|
20553
20250
|
const fullArea = {
|
|
20554
20251
|
x: padding,
|
|
20555
20252
|
y: padding + chrome.topHeight,
|
|
20556
20253
|
width: options.width - padding * 2,
|
|
20557
|
-
height:
|
|
20254
|
+
height: options.height - chrome.topHeight - chrome.bottomHeight - padding * 2
|
|
20558
20255
|
};
|
|
20559
20256
|
if (fullArea.width <= 0 || fullArea.height <= 0) {
|
|
20560
|
-
return emptyLayout4(fullArea, chrome, theme,
|
|
20257
|
+
return emptyLayout4(fullArea, chrome, theme, options, watermark);
|
|
20561
20258
|
}
|
|
20562
20259
|
const sourceField = sankeySpec.encoding.source.field;
|
|
20563
20260
|
const targetField = sankeySpec.encoding.target.field;
|
|
@@ -20597,7 +20294,7 @@ function compileSankey(spec, options) {
|
|
|
20597
20294
|
height: fullArea.height - legend.bounds.height - legendGap2
|
|
20598
20295
|
};
|
|
20599
20296
|
if (area.height <= 0) {
|
|
20600
|
-
return emptyLayout4(area, chrome, theme,
|
|
20297
|
+
return emptyLayout4(area, chrome, theme, options, watermark);
|
|
20601
20298
|
}
|
|
20602
20299
|
const labelFontSize = theme.fonts.sizes.small;
|
|
20603
20300
|
const labelFontWeight = theme.fonts.weights.normal;
|
|
@@ -20749,7 +20446,7 @@ function compileSankey(spec, options) {
|
|
|
20749
20446
|
theme,
|
|
20750
20447
|
dimensions: {
|
|
20751
20448
|
width: options.width,
|
|
20752
|
-
height:
|
|
20449
|
+
height: options.height
|
|
20753
20450
|
},
|
|
20754
20451
|
animation: resolvedAnimation,
|
|
20755
20452
|
watermark,
|
|
@@ -21558,7 +21255,7 @@ import {
|
|
|
21558
21255
|
HPAD_COMPACT_MIN as HPAD_COMPACT_MIN4,
|
|
21559
21256
|
pickLabelColor as pickLabelColor4,
|
|
21560
21257
|
resolveTheme as resolveTheme6,
|
|
21561
|
-
SEQUENTIAL_PALETTES as
|
|
21258
|
+
SEQUENTIAL_PALETTES as SEQUENTIAL_PALETTES2
|
|
21562
21259
|
} from "@opendata-ai/openchart-core";
|
|
21563
21260
|
var TILE_CORNER_RADIUS = 6;
|
|
21564
21261
|
var TILE_STROKE_WIDTH = 1;
|
|
@@ -21568,10 +21265,6 @@ var LEGEND_ENTRY_GAP = 16;
|
|
|
21568
21265
|
function clamp(value2, min4, max4) {
|
|
21569
21266
|
return Math.min(max4, Math.max(min4, value2));
|
|
21570
21267
|
}
|
|
21571
|
-
function growContentHeight(contentHeight, chromeLayout, budgetHeight, chrome) {
|
|
21572
|
-
if (chromeLayout !== "grow") return contentHeight;
|
|
21573
|
-
return Math.max(contentHeight, budgetHeight + chrome.topHeight + chrome.bottomHeight);
|
|
21574
|
-
}
|
|
21575
21268
|
function compileTileMap(spec, options) {
|
|
21576
21269
|
const sugarWarnings = [];
|
|
21577
21270
|
const expandedSpec = spec && typeof spec === "object" && !Array.isArray(spec) ? expandSpecSugar(spec, sugarWarnings) : spec;
|
|
@@ -21608,44 +21301,22 @@ function compileTileMap(spec, options) {
|
|
|
21608
21301
|
watermark
|
|
21609
21302
|
);
|
|
21610
21303
|
const padding = getBreakpoint2(options.width) === "compact" ? Math.max(HPAD_COMPACT_MIN4, Math.round(theme.spacing.padding * HPAD_COMPACT_FRACTION4)) : theme.spacing.padding;
|
|
21611
|
-
const chromeLayout = resolveChromeLayout(
|
|
21612
|
-
spec,
|
|
21613
|
-
options
|
|
21614
|
-
);
|
|
21615
21304
|
const fullArea = {
|
|
21616
21305
|
x: padding,
|
|
21617
21306
|
y: padding + chrome.topHeight,
|
|
21618
21307
|
width: options.width - padding * 2,
|
|
21619
|
-
height:
|
|
21308
|
+
height: options.height - chrome.topHeight - chrome.bottomHeight - padding * 2
|
|
21620
21309
|
};
|
|
21621
21310
|
if (fullArea.width <= 0 || fullArea.height <= 0) {
|
|
21622
21311
|
return emptyLayout5(chrome, theme, options, watermark);
|
|
21623
21312
|
}
|
|
21624
21313
|
const isCategorical = tilemapSpec.encoding.color !== void 0 || tilemapSpec.colors !== void 0;
|
|
21625
21314
|
if (isCategorical) {
|
|
21626
|
-
return compileCategorical(
|
|
21627
|
-
tilemapSpec,
|
|
21628
|
-
options,
|
|
21629
|
-
theme,
|
|
21630
|
-
chrome,
|
|
21631
|
-
fullArea,
|
|
21632
|
-
isDarkMode,
|
|
21633
|
-
watermark,
|
|
21634
|
-
chromeLayout
|
|
21635
|
-
);
|
|
21315
|
+
return compileCategorical(tilemapSpec, options, theme, chrome, fullArea, isDarkMode, watermark);
|
|
21636
21316
|
}
|
|
21637
|
-
return compileQuantitative(
|
|
21638
|
-
tilemapSpec,
|
|
21639
|
-
options,
|
|
21640
|
-
theme,
|
|
21641
|
-
chrome,
|
|
21642
|
-
fullArea,
|
|
21643
|
-
isDarkMode,
|
|
21644
|
-
watermark,
|
|
21645
|
-
chromeLayout
|
|
21646
|
-
);
|
|
21317
|
+
return compileQuantitative(tilemapSpec, options, theme, chrome, fullArea, isDarkMode, watermark);
|
|
21647
21318
|
}
|
|
21648
|
-
function compileQuantitative(tilemapSpec, options, theme, chrome, fullArea, isDarkMode, watermark
|
|
21319
|
+
function compileQuantitative(tilemapSpec, options, theme, chrome, fullArea, isDarkMode, watermark) {
|
|
21649
21320
|
const stateField = tilemapSpec.encoding.state.field;
|
|
21650
21321
|
const valueField = tilemapSpec.encoding.value.field;
|
|
21651
21322
|
const stateValueMap = /* @__PURE__ */ new Map();
|
|
@@ -21662,7 +21333,7 @@ function compileQuantitative(tilemapSpec, options, theme, chrome, fullArea, isDa
|
|
|
21662
21333
|
const values = Array.from(stateValueMap.values());
|
|
21663
21334
|
const min4 = values.length > 0 ? Math.min(...values) : 0;
|
|
21664
21335
|
const max4 = values.length > 0 ? Math.max(...values) : 100;
|
|
21665
|
-
const paletteStops = [...
|
|
21336
|
+
const paletteStops = [...SEQUENTIAL_PALETTES2[tilemapSpec.palette] ?? SEQUENTIAL_PALETTES2.blue];
|
|
21666
21337
|
const baseColor = isDarkMode ? paletteStops[0] : paletteStops[paletteStops.length - 1];
|
|
21667
21338
|
const opacityRange = isDarkMode ? [0.15, 1] : [0.2, 1];
|
|
21668
21339
|
const opacityScale = linear2().domain([min4, max4]).range(opacityRange).clamp(true);
|
|
@@ -21746,12 +21417,7 @@ function compileQuantitative(tilemapSpec, options, theme, chrome, fullArea, isDa
|
|
|
21746
21417
|
};
|
|
21747
21418
|
const resolvedAnimation = resolveAnimation(tilemapSpec.animation);
|
|
21748
21419
|
const padding = fullArea.x;
|
|
21749
|
-
const contentHeight =
|
|
21750
|
-
tileGridOffsetY + tilePositions.gridHeight + legendGap2 + legendTotalHeight + chrome.bottomHeight + padding,
|
|
21751
|
-
chromeLayout,
|
|
21752
|
-
options.height,
|
|
21753
|
-
chrome
|
|
21754
|
-
);
|
|
21420
|
+
const contentHeight = tileGridOffsetY + tilePositions.gridHeight + legendGap2 + legendTotalHeight + chrome.bottomHeight + padding;
|
|
21755
21421
|
return {
|
|
21756
21422
|
area: fullArea,
|
|
21757
21423
|
chrome,
|
|
@@ -21768,7 +21434,7 @@ function compileQuantitative(tilemapSpec, options, theme, chrome, fullArea, isDa
|
|
|
21768
21434
|
measureText: options.measureText ?? ((text, fontSize) => ({ width: estimateTextWidth23(text, fontSize), height: fontSize }))
|
|
21769
21435
|
};
|
|
21770
21436
|
}
|
|
21771
|
-
function compileCategorical(tilemapSpec, options, theme, chrome, fullArea, isDarkMode, watermark
|
|
21437
|
+
function compileCategorical(tilemapSpec, options, theme, chrome, fullArea, isDarkMode, watermark) {
|
|
21772
21438
|
const stateField = tilemapSpec.encoding.state.field;
|
|
21773
21439
|
const colorField = tilemapSpec.encoding.color?.field ?? tilemapSpec.encoding.value.field;
|
|
21774
21440
|
const stateCategoryMap = /* @__PURE__ */ new Map();
|
|
@@ -21887,12 +21553,7 @@ function compileCategorical(tilemapSpec, options, theme, chrome, fullArea, isDar
|
|
|
21887
21553
|
};
|
|
21888
21554
|
const resolvedAnimation = resolveAnimation(tilemapSpec.animation);
|
|
21889
21555
|
const padding = fullArea.x;
|
|
21890
|
-
const contentHeight =
|
|
21891
|
-
tileGridOffsetY + tilePositions.gridHeight + legendGap2 + legendTotalHeight + chrome.bottomHeight + padding,
|
|
21892
|
-
chromeLayout,
|
|
21893
|
-
options.height,
|
|
21894
|
-
chrome
|
|
21895
|
-
);
|
|
21556
|
+
const contentHeight = tileGridOffsetY + tilePositions.gridHeight + legendGap2 + legendTotalHeight + chrome.bottomHeight + padding;
|
|
21896
21557
|
return {
|
|
21897
21558
|
area: fullArea,
|
|
21898
21559
|
chrome,
|
|
@@ -22952,38 +22613,6 @@ function applySparklineDefaults(spec, theme) {
|
|
|
22952
22613
|
}
|
|
22953
22614
|
return { ...spec, markDef: newMarkDef };
|
|
22954
22615
|
}
|
|
22955
|
-
function resolveScaleInvert(resolved) {
|
|
22956
|
-
if (!resolved) return void 0;
|
|
22957
|
-
const { scale, type } = resolved;
|
|
22958
|
-
if (type === "band" || type === "point") {
|
|
22959
|
-
const domain = scale.domain();
|
|
22960
|
-
const positions = domain.map((v) => {
|
|
22961
|
-
const pos = scale(v) ?? 0;
|
|
22962
|
-
return type === "band" ? pos + scale.bandwidth() / 2 : pos;
|
|
22963
|
-
});
|
|
22964
|
-
const range4 = scale.range();
|
|
22965
|
-
return {
|
|
22966
|
-
topPixel: range4[0],
|
|
22967
|
-
bottomPixel: range4[range4.length - 1],
|
|
22968
|
-
topData: 0,
|
|
22969
|
-
bottomData: 0,
|
|
22970
|
-
domain,
|
|
22971
|
-
positions
|
|
22972
|
-
};
|
|
22973
|
-
}
|
|
22974
|
-
const invert = scale.invert;
|
|
22975
|
-
if (typeof invert !== "function") return void 0;
|
|
22976
|
-
const range3 = scale.range();
|
|
22977
|
-
const topPx = range3[0];
|
|
22978
|
-
const bottomPx = range3[range3.length - 1];
|
|
22979
|
-
const topVal = invert.call(scale, topPx);
|
|
22980
|
-
const bottomVal = invert.call(scale, bottomPx);
|
|
22981
|
-
const topData = topVal instanceof Date ? +topVal : Number(topVal);
|
|
22982
|
-
const bottomData = bottomVal instanceof Date ? +bottomVal : Number(bottomVal);
|
|
22983
|
-
if (!Number.isFinite(topData) || !Number.isFinite(bottomData)) return void 0;
|
|
22984
|
-
const scaleType = type;
|
|
22985
|
-
return { topPixel: topPx, bottomPixel: bottomPx, topData, bottomData, scaleType };
|
|
22986
|
-
}
|
|
22987
22616
|
function compileChart(spec, optionsInput) {
|
|
22988
22617
|
const sugarWarnings = [];
|
|
22989
22618
|
const expandedSpec = spec && typeof spec === "object" && !Array.isArray(spec) ? expandSpecSugar(spec, sugarWarnings) : spec;
|
|
@@ -23184,35 +22813,12 @@ function compileChart(spec, optionsInput) {
|
|
|
23184
22813
|
}
|
|
23185
22814
|
};
|
|
23186
22815
|
}
|
|
23187
|
-
let facetDirection = "wrap";
|
|
23188
|
-
const rowChannel = renderSpec.encoding.row;
|
|
23189
|
-
const colChannel = renderSpec.encoding.column;
|
|
23190
|
-
if (rowChannel?.field || colChannel?.field) {
|
|
23191
|
-
const channel = rowChannel?.field ? rowChannel : colChannel;
|
|
23192
|
-
facetDirection = rowChannel?.field ? "row" : "column";
|
|
23193
|
-
const desugared = { ...renderSpec.encoding };
|
|
23194
|
-
delete desugared.row;
|
|
23195
|
-
delete desugared.column;
|
|
23196
|
-
desugared.facet = {
|
|
23197
|
-
field: channel.field,
|
|
23198
|
-
type: channel.type,
|
|
23199
|
-
sort: channel.sort,
|
|
23200
|
-
...facetDirection === "row" ? { columns: 1 } : {}
|
|
23201
|
-
};
|
|
23202
|
-
renderSpec = { ...renderSpec, encoding: desugared };
|
|
23203
|
-
const chartDesugared = { ...chartSpec.encoding };
|
|
23204
|
-
delete chartDesugared.row;
|
|
23205
|
-
delete chartDesugared.column;
|
|
23206
|
-
chartDesugared.facet = desugared.facet;
|
|
23207
|
-
chartSpec = { ...chartSpec, encoding: chartDesugared };
|
|
23208
|
-
}
|
|
23209
22816
|
const facetChannel = renderSpec.encoding.facet;
|
|
23210
22817
|
if (facetChannel?.field) {
|
|
23211
22818
|
return compileFaceted(
|
|
23212
22819
|
chartSpec,
|
|
23213
22820
|
renderSpec,
|
|
23214
22821
|
facetChannel,
|
|
23215
|
-
facetDirection,
|
|
23216
22822
|
options,
|
|
23217
22823
|
theme,
|
|
23218
22824
|
strategy,
|
|
@@ -23277,10 +22883,7 @@ function compileChart(spec, optionsInput) {
|
|
|
23277
22883
|
skipY,
|
|
23278
22884
|
markType: chartSpec.markType,
|
|
23279
22885
|
totalWidth: options.width,
|
|
23280
|
-
|
|
23281
|
-
// against the pre-strip (shorter) plot. Drop them so computeAxes
|
|
23282
|
-
// regenerates against the final (taller) chartArea.
|
|
23283
|
-
precomputedYTicks: !dims.chromeStripped && plan.yTickValues.length > 0 ? plan.yTickValues : void 0
|
|
22886
|
+
precomputedYTicks: plan.yTickValues.length > 0 ? plan.yTickValues : void 0
|
|
23284
22887
|
});
|
|
23285
22888
|
const xAxisExtent = axes.x?.extent ?? 0;
|
|
23286
22889
|
dims.chrome.bottomAnchorY = chartArea.y + chartArea.height + xAxisExtent;
|
|
@@ -23375,8 +22978,6 @@ function compileChart(spec, optionsInput) {
|
|
|
23375
22978
|
);
|
|
23376
22979
|
assignAnimationIndices(marks, resolvedAnimation);
|
|
23377
22980
|
const chrome = footnotes ? { ...dims.chrome, footnotes } : dims.chrome;
|
|
23378
|
-
const xInvert = resolveScaleInvert(scales.x);
|
|
23379
|
-
const yInvert = resolveScaleInvert(scales.y);
|
|
23380
22981
|
return {
|
|
23381
22982
|
area: chartArea,
|
|
23382
22983
|
chrome,
|
|
@@ -23403,21 +23004,16 @@ function compileChart(spec, optionsInput) {
|
|
|
23403
23004
|
theme,
|
|
23404
23005
|
dimensions: {
|
|
23405
23006
|
width: options.width,
|
|
23406
|
-
|
|
23407
|
-
// chrome height so the plot keeps its full budget. In the default
|
|
23408
|
-
// 'subtract' mode total.height === options.height, so this is a no-op.
|
|
23409
|
-
height: dims.total.height
|
|
23007
|
+
height: options.height
|
|
23410
23008
|
},
|
|
23411
23009
|
animation: resolvedAnimation,
|
|
23412
23010
|
watermark,
|
|
23413
23011
|
display: chartSpec.display,
|
|
23414
23012
|
crosshair,
|
|
23415
|
-
measureText: options.measureText
|
|
23416
|
-
...xInvert ? { xInvert } : {},
|
|
23417
|
-
...yInvert ? { yInvert } : {}
|
|
23013
|
+
measureText: options.measureText
|
|
23418
23014
|
};
|
|
23419
23015
|
}
|
|
23420
|
-
function compileFaceted(chartSpec, renderSpec, facetChannel,
|
|
23016
|
+
function compileFaceted(chartSpec, renderSpec, facetChannel, options, theme, strategy, watermark, resolvedAnimation, crosshair, rawSpec, optionsInput) {
|
|
23421
23017
|
const measure = createMeasureFn(options.measureText);
|
|
23422
23018
|
const panelEncoding = { ...renderSpec.encoding };
|
|
23423
23019
|
delete panelEncoding.facet;
|
|
@@ -23463,10 +23059,10 @@ function compileFaceted(chartSpec, renderSpec, facetChannel, facetDirection, opt
|
|
|
23463
23059
|
plan.xAxisExtent,
|
|
23464
23060
|
dims.effectiveAxisGap
|
|
23465
23061
|
);
|
|
23062
|
+
const leftReservation = plan.leftGutter;
|
|
23466
23063
|
const bottomReservation = plan.xAxisExtent;
|
|
23467
|
-
const
|
|
23468
|
-
|
|
23469
|
-
left: 0,
|
|
23064
|
+
const grid = computeFacetGrid(facetValues, facetChannel.columns, chartArea, {
|
|
23065
|
+
left: leftReservation,
|
|
23470
23066
|
bottom: bottomReservation
|
|
23471
23067
|
});
|
|
23472
23068
|
if (!optionsInput.facetHeightGrown && grid.panels.length > 0 && grid.panels[0].area.height < MIN_PANEL_HEIGHT) {
|
|
@@ -23481,10 +23077,8 @@ function compileFaceted(chartSpec, renderSpec, facetChannel, facetDirection, opt
|
|
|
23481
23077
|
}
|
|
23482
23078
|
}
|
|
23483
23079
|
const resolveConfig = chartSpec.resolve;
|
|
23484
|
-
const
|
|
23485
|
-
const
|
|
23486
|
-
const yResolve = resolveConfig?.scale?.y ?? yDefault;
|
|
23487
|
-
const xResolve = resolveConfig?.scale?.x ?? xDefault;
|
|
23080
|
+
const yResolve = resolveConfig?.scale?.y ?? "shared";
|
|
23081
|
+
const xResolve = resolveConfig?.scale?.x ?? "shared";
|
|
23488
23082
|
const fullScales = computeScales(panelSpec, chartArea, renderSpec.data);
|
|
23489
23083
|
const sharedXDomain = xResolve === "shared" && fullScales.x ? fullScales.x.scale.domain() : void 0;
|
|
23490
23084
|
const sharedYDomain = yResolve === "shared" && fullScales.y ? fullScales.y.scale.domain() : void 0;
|
|
@@ -23549,16 +23143,6 @@ function compileFaceted(chartSpec, renderSpec, facetChannel, facetDirection, opt
|
|
|
23549
23143
|
tickMarks: false
|
|
23550
23144
|
};
|
|
23551
23145
|
}
|
|
23552
|
-
const isBottomRow = gridPanel.row === grid.rows - 1;
|
|
23553
|
-
if (xResolve === "shared" && facetDirection === "row" && !isBottomRow && panelAxes.x) {
|
|
23554
|
-
panelAxes.x = {
|
|
23555
|
-
...panelAxes.x,
|
|
23556
|
-
ticks: [],
|
|
23557
|
-
label: void 0,
|
|
23558
|
-
domainLine: false,
|
|
23559
|
-
tickMarks: false
|
|
23560
|
-
};
|
|
23561
|
-
}
|
|
23562
23146
|
const panelMarks = renderer ? renderer(
|
|
23563
23147
|
panelSpecWithDomains,
|
|
23564
23148
|
panelScales,
|
|
@@ -23612,11 +23196,10 @@ function compileFaceted(chartSpec, renderSpec, facetChannel, facetDirection, opt
|
|
|
23612
23196
|
annotations: panelAnnotations,
|
|
23613
23197
|
header: {
|
|
23614
23198
|
text: gridPanel.key,
|
|
23615
|
-
x:
|
|
23199
|
+
x: gridPanel.headerPos.x,
|
|
23616
23200
|
y: gridPanel.headerPos.y,
|
|
23617
23201
|
fontSize: theme.fonts.sizes.body,
|
|
23618
|
-
fontWeight: theme.fonts.weights.medium
|
|
23619
|
-
...facetDirection === "row" ? { textAnchor: "start" } : {}
|
|
23202
|
+
fontWeight: theme.fonts.weights.medium
|
|
23620
23203
|
}
|
|
23621
23204
|
});
|
|
23622
23205
|
}
|
|
@@ -23684,8 +23267,7 @@ function compileFaceted(chartSpec, renderSpec, facetChannel, facetDirection, opt
|
|
|
23684
23267
|
panels: panelLayouts,
|
|
23685
23268
|
facetField: facetChannel.field,
|
|
23686
23269
|
columns: grid.columns,
|
|
23687
|
-
sharedScales: yResolve === "shared" && xResolve === "shared"
|
|
23688
|
-
direction: facetDirection
|
|
23270
|
+
sharedScales: yResolve === "shared" && xResolve === "shared"
|
|
23689
23271
|
}
|
|
23690
23272
|
};
|
|
23691
23273
|
}
|