@opendata-ai/openchart-engine 8.0.0-rc.8 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +149 -12
- package/dist/index.js +894 -171
- package/dist/index.js.map +1 -1
- package/package.json +3 -4
- package/src/__test-fixtures__/specs.ts +0 -182
- package/src/__tests__/__snapshots__/compile-snapshot.test.ts.snap +0 -2339
- package/src/__tests__/annotation-behavior.test.ts +0 -852
- package/src/__tests__/axes.test.ts +0 -1579
- package/src/__tests__/compile-animation.test.ts +0 -161
- package/src/__tests__/compile-chart.test.ts +0 -1303
- package/src/__tests__/compile-footnotes.test.ts +0 -277
- package/src/__tests__/compile-layer.test.ts +0 -969
- package/src/__tests__/compile-snapshot.test.ts +0 -156
- package/src/__tests__/compound-labels.test.ts +0 -147
- package/src/__tests__/dimensions.test.ts +0 -918
- package/src/__tests__/encoding-sugar.test.ts +0 -390
- package/src/__tests__/facet.test.ts +0 -215
- package/src/__tests__/helpers/invariants.ts +0 -299
- package/src/__tests__/known-bugs.test.ts +0 -566
- package/src/__tests__/layout-fuzz.test.ts +0 -358
- package/src/__tests__/layout-invariants.test.ts +0 -535
- package/src/__tests__/legend.test.ts +0 -721
- package/src/__tests__/mark-keys.test.ts +0 -294
- package/src/__tests__/ranking-recipes.test.ts +0 -260
- package/src/__tests__/rotation.test.ts +0 -83
- package/src/__tests__/scales.test.ts +0 -323
- package/src/__tests__/series-search.test.ts +0 -92
- package/src/__tests__/spec-sugar.test.ts +0 -801
- package/src/__tests__/you-draw-it.test.ts +0 -160
- package/src/annotations/__tests__/compute.test.ts +0 -1672
- package/src/annotations/__tests__/geometry.test.ts +0 -66
- package/src/annotations/__tests__/placement-fuzz.test.ts +0 -256
- package/src/annotations/__tests__/placement-invariants.test.ts +0 -345
- package/src/annotations/__tests__/placement.test.ts +0 -316
- package/src/annotations/__tests__/resolve-text.test.ts +0 -788
- package/src/annotations/__tests__/rich-text.test.ts +0 -91
- package/src/annotations/__tests__/thinning.test.ts +0 -285
- package/src/annotations/collisions.ts +0 -326
- package/src/annotations/compute.ts +0 -333
- package/src/annotations/constants.ts +0 -162
- package/src/annotations/geometry.ts +0 -376
- package/src/annotations/move.ts +0 -135
- package/src/annotations/placement.ts +0 -636
- package/src/annotations/position.ts +0 -131
- package/src/annotations/resolve-range.ts +0 -117
- package/src/annotations/resolve-refline.ts +0 -157
- package/src/annotations/resolve-text.ts +0 -545
- package/src/annotations/rich-text.ts +0 -65
- package/src/annotations/thinning.ts +0 -190
- package/src/barlist/__tests__/compile-barlist.test.ts +0 -200
- package/src/barlist/compile-barlist.ts +0 -391
- package/src/barlist/types.ts +0 -28
- package/src/charts/__tests__/post-process.test.ts +0 -237
- package/src/charts/__tests__/registry.test.ts +0 -116
- package/src/charts/__tests__/utils.test.ts +0 -195
- package/src/charts/_shared/__tests__/density-filter.test.ts +0 -32
- package/src/charts/_shared/density-filter.ts +0 -26
- package/src/charts/_shared/format-label-value.ts +0 -16
- package/src/charts/bar/__tests__/compute.test.ts +0 -934
- package/src/charts/bar/__tests__/gradient-orient.test.ts +0 -127
- package/src/charts/bar/__tests__/labels.test.ts +0 -292
- package/src/charts/bar/compute.ts +0 -539
- package/src/charts/bar/index.ts +0 -60
- package/src/charts/bar/labels.ts +0 -311
- package/src/charts/beeswarm/__tests__/compute.test.ts +0 -280
- package/src/charts/beeswarm/__tests__/dodge.test.ts +0 -148
- package/src/charts/beeswarm/compute.ts +0 -203
- package/src/charts/beeswarm/dodge.ts +0 -155
- package/src/charts/beeswarm/index.ts +0 -32
- package/src/charts/builtin.ts +0 -75
- package/src/charts/calendar/__tests__/compute.test.ts +0 -417
- package/src/charts/calendar/compute.ts +0 -319
- package/src/charts/calendar/index.ts +0 -32
- package/src/charts/column/__tests__/compute.test.ts +0 -540
- package/src/charts/column/__tests__/labels.test.ts +0 -179
- package/src/charts/column/compute.ts +0 -493
- package/src/charts/column/index.ts +0 -53
- package/src/charts/column/labels.ts +0 -229
- package/src/charts/dot/__tests__/compute.test.ts +0 -380
- package/src/charts/dot/__tests__/labels.test.ts +0 -98
- package/src/charts/dot/compute.ts +0 -285
- package/src/charts/dot/index.ts +0 -62
- package/src/charts/dot/labels.ts +0 -121
- package/src/charts/line/__tests__/compute.test.ts +0 -1194
- package/src/charts/line/__tests__/curves.test.ts +0 -51
- package/src/charts/line/__tests__/labels.test.ts +0 -94
- package/src/charts/line/__tests__/mark-options.test.ts +0 -175
- package/src/charts/line/area.ts +0 -484
- package/src/charts/line/compute.ts +0 -356
- package/src/charts/line/curves.ts +0 -85
- package/src/charts/line/index.ts +0 -176
- package/src/charts/line/labels.ts +0 -177
- package/src/charts/parliament/__tests__/compute.test.ts +0 -411
- package/src/charts/parliament/compute.ts +0 -313
- package/src/charts/parliament/index.ts +0 -32
- package/src/charts/pie/__tests__/compute.test.ts +0 -384
- package/src/charts/pie/__tests__/labels.test.ts +0 -132
- package/src/charts/pie/compute.ts +0 -324
- package/src/charts/pie/index.ts +0 -49
- package/src/charts/pie/labels.ts +0 -143
- package/src/charts/post-process.ts +0 -229
- package/src/charts/range/__tests__/compute.test.ts +0 -486
- package/src/charts/range/compute.ts +0 -273
- package/src/charts/range/index.ts +0 -82
- package/src/charts/range/labels.ts +0 -169
- package/src/charts/rect/__tests__/compute.test.ts +0 -120
- package/src/charts/rect/index.ts +0 -127
- package/src/charts/registry.ts +0 -72
- package/src/charts/rule/index.ts +0 -139
- package/src/charts/scatter/__tests__/compute.test.ts +0 -488
- package/src/charts/scatter/__tests__/trendline.test.ts +0 -191
- package/src/charts/scatter/compute.ts +0 -192
- package/src/charts/scatter/index.ts +0 -46
- package/src/charts/scatter/trendline.ts +0 -100
- package/src/charts/text/__tests__/compute.test.ts +0 -307
- package/src/charts/text/index.ts +0 -141
- package/src/charts/tick/__tests__/compute.test.ts +0 -75
- package/src/charts/tick/index.ts +0 -99
- package/src/charts/utils.ts +0 -170
- package/src/charts/waffle/__tests__/compute.test.ts +0 -305
- package/src/charts/waffle/compute.ts +0 -197
- package/src/charts/waffle/index.ts +0 -31
- package/src/compile/__tests__/color-scale-range.test.ts +0 -158
- package/src/compile/__tests__/color-scale-reverse.test.ts +0 -89
- package/src/compile/__tests__/data-clip.test.ts +0 -127
- package/src/compile/__tests__/fill-patterns.test.ts +0 -154
- package/src/compile/__tests__/size-scale.test.ts +0 -108
- package/src/compile/__tests__/watermark-obstacle.test.ts +0 -93
- package/src/compile/color-scale-range.ts +0 -101
- package/src/compile/data-clip.ts +0 -48
- package/src/compile/fill-patterns.ts +0 -74
- package/src/compile/layer.ts +0 -626
- package/src/compile/size-scale.ts +0 -141
- package/src/compile/spec-sugar.ts +0 -758
- package/src/compile/watermark-obstacle.ts +0 -54
- package/src/compile/you-draw-it.ts +0 -123
- package/src/compile.ts +0 -1450
- package/src/compiler/__tests__/a11y-warnings.test.ts +0 -148
- package/src/compiler/__tests__/animation.test.ts +0 -177
- package/src/compiler/__tests__/compile.test.ts +0 -87
- package/src/compiler/__tests__/fixtures/vl-parity/axis-null.json +0 -19
- package/src/compiler/__tests__/fixtures/vl-parity/color-value.json +0 -20
- package/src/compiler/__tests__/fixtures/vl-parity/count-aggregate.json +0 -22
- package/src/compiler/__tests__/fixtures/vl-parity/data-values.json +0 -19
- package/src/compiler/__tests__/fixtures/vl-parity/layer-axis-null.json +0 -14
- package/src/compiler/__tests__/fixtures/vl-parity/layer-count.json +0 -34
- package/src/compiler/__tests__/fixtures/vl-parity/layer-data-values.json +0 -22
- package/src/compiler/__tests__/fixtures/vl-parity/layer-legend-null.json +0 -41
- package/src/compiler/__tests__/fixtures/vl-parity/layer-scheme.json +0 -38
- package/src/compiler/__tests__/fixtures/vl-parity/layer-sort.json +0 -28
- package/src/compiler/__tests__/fixtures/vl-parity/layer-theta.json +0 -28
- package/src/compiler/__tests__/fixtures/vl-parity/layer-title.json +0 -30
- package/src/compiler/__tests__/fixtures/vl-parity/layer-value-def.json +0 -29
- package/src/compiler/__tests__/fixtures/vl-parity/legend-null.json +0 -32
- package/src/compiler/__tests__/fixtures/vl-parity/scheme.json +0 -25
- package/src/compiler/__tests__/fixtures/vl-parity/sort-by-value.json +0 -19
- package/src/compiler/__tests__/fixtures/vl-parity/theta-arc.json +0 -19
- package/src/compiler/__tests__/fixtures/vl-parity/title-subtitle.json +0 -21
- package/src/compiler/__tests__/fixtures/vl-parity/width-height.json +0 -23
- package/src/compiler/__tests__/keys.test.ts +0 -83
- package/src/compiler/__tests__/normalize-highlight.test.ts +0 -103
- package/src/compiler/__tests__/normalize.test.ts +0 -399
- package/src/compiler/__tests__/sparkline-defaults.test.ts +0 -153
- package/src/compiler/__tests__/validate-did-you-mean.test.ts +0 -170
- package/src/compiler/__tests__/validate-highlight.test.ts +0 -112
- package/src/compiler/__tests__/validate-near-miss.test.ts +0 -251
- package/src/compiler/__tests__/validate.test.ts +0 -629
- package/src/compiler/__tests__/vl-parity.test.ts +0 -68
- package/src/compiler/a11y-warnings.ts +0 -110
- package/src/compiler/animation.ts +0 -142
- package/src/compiler/index.ts +0 -47
- package/src/compiler/keys.ts +0 -55
- package/src/compiler/normalize.ts +0 -734
- package/src/compiler/sparkline-defaults.ts +0 -138
- package/src/compiler/types.ts +0 -241
- package/src/compiler/validate.ts +0 -2041
- package/src/endpoint-labels/__tests__/compute.test.ts +0 -587
- package/src/endpoint-labels/compute.ts +0 -621
- package/src/endpoint-labels/constants.ts +0 -54
- package/src/endpoint-labels/format.ts +0 -60
- package/src/endpoint-labels/predict.ts +0 -139
- package/src/format/__tests__/field-format.test.ts +0 -164
- package/src/format/field-format.ts +0 -27
- package/src/geo/__tests__/compile-map.test.ts +0 -1004
- package/src/geo/compile-map.ts +0 -1341
- package/src/geo/join.ts +0 -115
- package/src/geo/projections.ts +0 -45
- package/src/geo/types.ts +0 -26
- package/src/graphs/__tests__/community.test.ts +0 -228
- package/src/graphs/__tests__/compile-graph.test.ts +0 -396
- package/src/graphs/__tests__/encoding.test.ts +0 -415
- package/src/graphs/community.ts +0 -92
- package/src/graphs/compile-graph.ts +0 -329
- package/src/graphs/encoding.ts +0 -356
- package/src/graphs/types.ts +0 -106
- package/src/index.ts +0 -177
- package/src/layout/__tests__/metrics.test.ts +0 -97
- package/src/layout/__tests__/scales-highlight.test.ts +0 -192
- package/src/layout/axes/rotation.ts +0 -152
- package/src/layout/axes/thinning.ts +0 -98
- package/src/layout/axes/ticks.ts +0 -409
- package/src/layout/axes.ts +0 -757
- package/src/layout/dimensions.ts +0 -912
- package/src/layout/facet.ts +0 -91
- package/src/layout/gridlines.ts +0 -84
- package/src/layout/metrics.ts +0 -132
- package/src/layout/plan.ts +0 -631
- package/src/layout/scales.ts +0 -1053
- package/src/layout/shared.ts +0 -44
- package/src/legend/__tests__/continuous.test.ts +0 -318
- package/src/legend/__tests__/redundancy.test.ts +0 -108
- package/src/legend/__tests__/size.test.ts +0 -348
- package/src/legend/__tests__/suppression.test.ts +0 -382
- package/src/legend/compute.ts +0 -747
- package/src/legend/continuous.ts +0 -327
- package/src/legend/size.ts +0 -407
- package/src/legend/suppression.ts +0 -226
- package/src/legend/wrap.ts +0 -117
- package/src/sankey/__tests__/compile-sankey.test.ts +0 -458
- package/src/sankey/__tests__/layout.test.ts +0 -165
- package/src/sankey/__tests__/node-label-wrap.test.ts +0 -114
- package/src/sankey/__tests__/node-sort.test.ts +0 -45
- package/src/sankey/compile-sankey.ts +0 -706
- package/src/sankey/layout.ts +0 -184
- package/src/sankey/types.ts +0 -41
- package/src/tables/__tests__/bar-column.test.ts +0 -147
- package/src/tables/__tests__/category-colors.test.ts +0 -230
- package/src/tables/__tests__/compile-table.test.ts +0 -236
- package/src/tables/__tests__/format-cells.test.ts +0 -143
- package/src/tables/__tests__/heatmap.test.ts +0 -148
- package/src/tables/__tests__/pagination.test.ts +0 -78
- package/src/tables/__tests__/search.test.ts +0 -94
- package/src/tables/__tests__/sort.test.ts +0 -107
- package/src/tables/__tests__/sparkline.test.ts +0 -122
- package/src/tables/bar-column.ts +0 -94
- package/src/tables/category-colors.ts +0 -78
- package/src/tables/compile-table.ts +0 -427
- package/src/tables/format-cells.ts +0 -115
- package/src/tables/heatmap.ts +0 -141
- package/src/tables/pagination.ts +0 -46
- package/src/tables/search.ts +0 -66
- package/src/tables/sort.ts +0 -69
- package/src/tables/sparkline.ts +0 -113
- package/src/tables/utils.ts +0 -16
- package/src/tilemap/__tests__/compile-tilemap.test.ts +0 -576
- package/src/tilemap/compile-tilemap.ts +0 -755
- package/src/tilemap/layout.ts +0 -172
- package/src/tilemap/types.ts +0 -33
- package/src/tooltips/__tests__/compute.test.ts +0 -582
- package/src/tooltips/compute.ts +0 -700
- package/src/transforms/__tests__/aggregate.test.ts +0 -159
- package/src/transforms/__tests__/bin.test.ts +0 -88
- package/src/transforms/__tests__/calculate.test.ts +0 -146
- package/src/transforms/__tests__/conditional.test.ts +0 -127
- package/src/transforms/__tests__/filter-relative.test.ts +0 -202
- package/src/transforms/__tests__/filter.test.ts +0 -59
- package/src/transforms/__tests__/fold.test.ts +0 -79
- package/src/transforms/__tests__/index.test.ts +0 -93
- package/src/transforms/__tests__/predicates.test.ts +0 -193
- package/src/transforms/__tests__/timeunit.test.ts +0 -129
- package/src/transforms/__tests__/window.test.ts +0 -286
- package/src/transforms/aggregate.ts +0 -131
- package/src/transforms/bin.ts +0 -87
- package/src/transforms/calculate.ts +0 -60
- package/src/transforms/conditional.ts +0 -46
- package/src/transforms/filter.ts +0 -122
- package/src/transforms/fold.ts +0 -49
- package/src/transforms/index.ts +0 -60
- package/src/transforms/predicates.ts +0 -123
- package/src/transforms/timeunit.ts +0 -88
- package/src/transforms/window.ts +0 -185
package/dist/index.js
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
getHeightClass,
|
|
10
10
|
getLayoutStrategy,
|
|
11
11
|
isAxislessMark as isAxislessMark3,
|
|
12
|
+
MAX_SR_TABLE_ROWS,
|
|
12
13
|
resolveTheme as resolveTheme7
|
|
13
14
|
} from "@opendata-ai/openchart-core";
|
|
14
15
|
|
|
@@ -8559,6 +8560,11 @@ function computePieLabels(marks, _chartArea, density = "auto", _textFill = "#333
|
|
|
8559
8560
|
width: textWidth,
|
|
8560
8561
|
height: textHeight,
|
|
8561
8562
|
priority: "data",
|
|
8563
|
+
// Index into the ORIGINAL marks array, not `targetMarks`. Density
|
|
8564
|
+
// filtering drops slices and resolveCollisions re-sorts by priority, so
|
|
8565
|
+
// the returned labels line up with neither. Callers assign by this index
|
|
8566
|
+
// instead of zipping positionally.
|
|
8567
|
+
index: marks.indexOf(mark),
|
|
8562
8568
|
style: {
|
|
8563
8569
|
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
8564
8570
|
fontSize: LABEL_FONT_SIZE5,
|
|
@@ -8580,14 +8586,16 @@ function computePieLabels(marks, _chartArea, density = "auto", _textFill = "#333
|
|
|
8580
8586
|
x: c.anchorX,
|
|
8581
8587
|
y: c.anchorY,
|
|
8582
8588
|
style: c.style,
|
|
8583
|
-
visible: true
|
|
8589
|
+
visible: true,
|
|
8590
|
+
...c.index !== void 0 ? { index: c.index } : {}
|
|
8584
8591
|
}));
|
|
8585
8592
|
} else {
|
|
8586
8593
|
resolved = resolveCollisions5(candidates);
|
|
8587
8594
|
}
|
|
8588
|
-
for (let i = 0; i < resolved.length
|
|
8595
|
+
for (let i = 0; i < resolved.length; i++) {
|
|
8589
8596
|
const label = resolved[i];
|
|
8590
|
-
const mark =
|
|
8597
|
+
const mark = label.index !== void 0 ? marks[label.index] : void 0;
|
|
8598
|
+
if (!mark) continue;
|
|
8591
8599
|
if (label.visible) {
|
|
8592
8600
|
label.connector = {
|
|
8593
8601
|
from: { x: label.x, y: label.y },
|
|
@@ -8605,16 +8613,16 @@ function computePieLabels(marks, _chartArea, density = "auto", _textFill = "#333
|
|
|
8605
8613
|
var pieRenderer = (spec, scales, chartArea, strategy, theme) => {
|
|
8606
8614
|
const marks = computePieMarks(spec, scales, chartArea, strategy, false);
|
|
8607
8615
|
const labels = computePieLabels(marks, chartArea, spec.labels.density, theme.colors.text);
|
|
8608
|
-
for (
|
|
8609
|
-
marks[
|
|
8616
|
+
for (const label of labels) {
|
|
8617
|
+
if (label.index !== void 0 && marks[label.index]) marks[label.index].label = label;
|
|
8610
8618
|
}
|
|
8611
8619
|
return marks;
|
|
8612
8620
|
};
|
|
8613
8621
|
var donutRenderer = (spec, scales, chartArea, strategy, theme) => {
|
|
8614
8622
|
const marks = computePieMarks(spec, scales, chartArea, strategy, true);
|
|
8615
8623
|
const labels = computePieLabels(marks, chartArea, spec.labels.density, theme.colors.text);
|
|
8616
|
-
for (
|
|
8617
|
-
marks[
|
|
8624
|
+
for (const label of labels) {
|
|
8625
|
+
if (label.index !== void 0 && marks[label.index]) marks[label.index].label = label;
|
|
8618
8626
|
}
|
|
8619
8627
|
return marks;
|
|
8620
8628
|
};
|
|
@@ -9062,6 +9070,7 @@ var ruleRenderer = (spec, scales, chartArea, _strategy, _theme) => {
|
|
|
9062
9070
|
};
|
|
9063
9071
|
|
|
9064
9072
|
// src/charts/scatter/compute.ts
|
|
9073
|
+
import { isOpaqueColor } from "@opendata-ai/openchart-core";
|
|
9065
9074
|
var DEFAULT_POINT_RADIUS2 = 5;
|
|
9066
9075
|
function resolvePosition2(value2, channelType, scale) {
|
|
9067
9076
|
switch (channelType) {
|
|
@@ -9087,7 +9096,7 @@ function resolvePosition2(value2, channelType, scale) {
|
|
|
9087
9096
|
}
|
|
9088
9097
|
}
|
|
9089
9098
|
}
|
|
9090
|
-
function computeScatterMarks(spec, scales, _chartArea, _strategy) {
|
|
9099
|
+
function computeScatterMarks(spec, scales, _chartArea, _strategy, theme) {
|
|
9091
9100
|
const encoding = spec.encoding;
|
|
9092
9101
|
const xChannel = encoding.x;
|
|
9093
9102
|
const yChannel = encoding.y;
|
|
@@ -9105,6 +9114,10 @@ function computeScatterMarks(spec, scales, _chartArea, _strategy) {
|
|
|
9105
9114
|
const sizeField = sizeEnc?.field;
|
|
9106
9115
|
const resolvedSize = buildSizeScale(sizeEnc, spec.data, SIZE_SCALE_DEFAULTS.point);
|
|
9107
9116
|
const sizeScale = resolvedSize?.scale;
|
|
9117
|
+
const constFill = spec.markDef.fill;
|
|
9118
|
+
const constSize = spec.markDef.size;
|
|
9119
|
+
const bg = theme?.colors?.background;
|
|
9120
|
+
const defaultStroke = bg && isOpaqueColor(bg) ? bg : "#ffffff";
|
|
9108
9121
|
const keyEnc = encoding.key && "field" in encoding.key ? encoding.key : void 0;
|
|
9109
9122
|
const keyField = keyEnc?.field;
|
|
9110
9123
|
const marks = [];
|
|
@@ -9119,10 +9132,12 @@ function computeScatterMarks(spec, scales, _chartArea, _strategy) {
|
|
|
9119
9132
|
if (isSequentialColor && colorField) {
|
|
9120
9133
|
const val = Number(row[colorField]);
|
|
9121
9134
|
color2 = Number.isFinite(val) ? getSequentialColor(scales, val) : getColor(scales, "__default__");
|
|
9122
|
-
} else {
|
|
9135
|
+
} else if (colorField) {
|
|
9123
9136
|
color2 = getColor(scales, category ?? "__default__");
|
|
9137
|
+
} else {
|
|
9138
|
+
color2 = constFill ?? getColor(scales, "__default__");
|
|
9124
9139
|
}
|
|
9125
|
-
let radius = DEFAULT_POINT_RADIUS2;
|
|
9140
|
+
let radius = constSize != null ? constSize : DEFAULT_POINT_RADIUS2;
|
|
9126
9141
|
if (sizeScale && sizeField) {
|
|
9127
9142
|
const sizeVal = Number(row[sizeField]);
|
|
9128
9143
|
if (Number.isFinite(sizeVal)) {
|
|
@@ -9143,9 +9158,9 @@ function computeScatterMarks(spec, scales, _chartArea, _strategy) {
|
|
|
9143
9158
|
cy,
|
|
9144
9159
|
r: radius,
|
|
9145
9160
|
fill: color2,
|
|
9146
|
-
stroke:
|
|
9147
|
-
strokeWidth: 1,
|
|
9148
|
-
fillOpacity: 0.7,
|
|
9161
|
+
stroke: spec.markDef.stroke ?? defaultStroke,
|
|
9162
|
+
strokeWidth: spec.markDef.strokeWidth ?? 1,
|
|
9163
|
+
fillOpacity: spec.markDef.opacity ?? 0.7,
|
|
9149
9164
|
data: row,
|
|
9150
9165
|
aria
|
|
9151
9166
|
});
|
|
@@ -9186,7 +9201,7 @@ function linearRegression(points) {
|
|
|
9186
9201
|
const intercept = (sumY - slope * sumX) / n;
|
|
9187
9202
|
return { slope, intercept };
|
|
9188
9203
|
}
|
|
9189
|
-
function computeTrendLine(marks) {
|
|
9204
|
+
function computeTrendLine(marks, stroke = TRENDLINE_COLOR, strokeWidth = TRENDLINE_STROKE_WIDTH) {
|
|
9190
9205
|
if (marks.length < 2) return null;
|
|
9191
9206
|
const points = marks.map((m) => ({ x: m.cx, y: m.cy }));
|
|
9192
9207
|
const result = linearRegression(points);
|
|
@@ -9209,8 +9224,8 @@ function computeTrendLine(marks) {
|
|
|
9209
9224
|
{ x: minX, y: y12 },
|
|
9210
9225
|
{ x: maxX, y: y2 }
|
|
9211
9226
|
],
|
|
9212
|
-
stroke
|
|
9213
|
-
strokeWidth
|
|
9227
|
+
stroke,
|
|
9228
|
+
strokeWidth,
|
|
9214
9229
|
strokeDasharray: TRENDLINE_DASH,
|
|
9215
9230
|
data: [],
|
|
9216
9231
|
aria
|
|
@@ -9218,13 +9233,20 @@ function computeTrendLine(marks) {
|
|
|
9218
9233
|
}
|
|
9219
9234
|
|
|
9220
9235
|
// src/charts/scatter/index.ts
|
|
9221
|
-
var scatterRenderer = (spec, scales, chartArea, strategy,
|
|
9222
|
-
const pointMarks = computeScatterMarks(spec, scales, chartArea, strategy);
|
|
9236
|
+
var scatterRenderer = (spec, scales, chartArea, strategy, theme) => {
|
|
9237
|
+
const pointMarks = computeScatterMarks(spec, scales, chartArea, strategy, theme);
|
|
9223
9238
|
const marks = [...pointMarks];
|
|
9224
|
-
|
|
9225
|
-
|
|
9239
|
+
const trendline = spec.markDef?.trendline;
|
|
9240
|
+
if (trendline !== false) {
|
|
9241
|
+
const config = typeof trendline === "object" ? trendline : void 0;
|
|
9242
|
+
const stroke = config?.stroke ?? theme?.colors?.text;
|
|
9243
|
+
const trendLine = computeTrendLine(pointMarks, stroke, config?.strokeWidth);
|
|
9226
9244
|
if (trendLine) {
|
|
9227
|
-
|
|
9245
|
+
if (config?.layer === "above") {
|
|
9246
|
+
marks.push(trendLine);
|
|
9247
|
+
} else {
|
|
9248
|
+
marks.unshift(trendLine);
|
|
9249
|
+
}
|
|
9228
9250
|
}
|
|
9229
9251
|
}
|
|
9230
9252
|
return marks;
|
|
@@ -9704,6 +9726,16 @@ function stripIgnoredKeys(spec, warnings) {
|
|
|
9704
9726
|
const { $schema: _schema, ...rest } = spec;
|
|
9705
9727
|
return rest;
|
|
9706
9728
|
}
|
|
9729
|
+
function stripRemovedMarkRender(spec, warnings) {
|
|
9730
|
+
const mark = spec.mark;
|
|
9731
|
+
if (!mark || typeof mark !== "object" || Array.isArray(mark)) return spec;
|
|
9732
|
+
if (!("render" in mark)) return spec;
|
|
9733
|
+
warnings.push(
|
|
9734
|
+
"[openchart] mark.render was removed in v8. This field is stripped for backward compatibility. Pass { renderer } to createChart() or the compile options instead."
|
|
9735
|
+
);
|
|
9736
|
+
const { render: _render, ...restMark } = mark;
|
|
9737
|
+
return { ...spec, mark: restMark };
|
|
9738
|
+
}
|
|
9707
9739
|
function applyFixedSizeDefault(spec) {
|
|
9708
9740
|
if (typeof spec.width === "number" && typeof spec.height === "number" && spec.responsive === void 0) {
|
|
9709
9741
|
return { ...spec, responsive: false };
|
|
@@ -9846,7 +9878,16 @@ function expandChannelSugar(spec, warnings) {
|
|
|
9846
9878
|
}
|
|
9847
9879
|
return result;
|
|
9848
9880
|
}
|
|
9849
|
-
var COUNT_GROUP_CHANNELS = [
|
|
9881
|
+
var COUNT_GROUP_CHANNELS = [
|
|
9882
|
+
"x",
|
|
9883
|
+
"y",
|
|
9884
|
+
"color",
|
|
9885
|
+
"detail",
|
|
9886
|
+
"strokeDash",
|
|
9887
|
+
"facet",
|
|
9888
|
+
"row",
|
|
9889
|
+
"column"
|
|
9890
|
+
];
|
|
9850
9891
|
function expandCountAggregate(spec) {
|
|
9851
9892
|
const encoding = spec.encoding;
|
|
9852
9893
|
if (!encoding || typeof encoding !== "object") return spec;
|
|
@@ -9965,6 +10006,7 @@ function expandChartSugar(spec, warnings, inheritedData) {
|
|
|
9965
10006
|
out = expandTopLevelTitle(out);
|
|
9966
10007
|
out = expandDescriptionSugar(out);
|
|
9967
10008
|
out = stripIgnoredKeys(out, warnings);
|
|
10009
|
+
out = stripRemovedMarkRender(out, warnings);
|
|
9968
10010
|
out = applyFixedSizeDefault(out);
|
|
9969
10011
|
out = expandAnnotationSugar(out, warnings);
|
|
9970
10012
|
out = expandChannelSugar(out, warnings);
|
|
@@ -10081,6 +10123,12 @@ function resolveAnimation(spec) {
|
|
|
10081
10123
|
const enter = resolvePhase(config.enter, ENTER_DEFAULTS);
|
|
10082
10124
|
const update = resolvePhase(config.update, UPDATE_DEFAULTS);
|
|
10083
10125
|
const exit = resolvePhase(config.exit, EXIT_DEFAULTS);
|
|
10126
|
+
if (update && config.update && typeof config.update === "object" && !Array.isArray(config.update)) {
|
|
10127
|
+
const cap = config.update.maxMarks;
|
|
10128
|
+
if (typeof cap === "number" && Number.isFinite(cap) && cap >= 1) {
|
|
10129
|
+
update.maxMarks = Math.floor(cap);
|
|
10130
|
+
}
|
|
10131
|
+
}
|
|
10084
10132
|
if (!enter && !update && !exit) return void 0;
|
|
10085
10133
|
return {
|
|
10086
10134
|
enter: enter ?? void 0,
|
|
@@ -10122,9 +10170,9 @@ function resolveStagger(stagger, defaults) {
|
|
|
10122
10170
|
import {
|
|
10123
10171
|
isBarListSpec,
|
|
10124
10172
|
isChartSpec,
|
|
10173
|
+
isGeoMapSpec,
|
|
10125
10174
|
isGraphSpec,
|
|
10126
10175
|
isLayerSpec,
|
|
10127
|
-
isMapSpec,
|
|
10128
10176
|
isSankeySpec,
|
|
10129
10177
|
isTableSpec,
|
|
10130
10178
|
isTileMapSpec,
|
|
@@ -10473,6 +10521,7 @@ function normalizeChartSpec(spec, warnings) {
|
|
|
10473
10521
|
data: spec.data,
|
|
10474
10522
|
encoding,
|
|
10475
10523
|
chrome: normalizeChrome(spec.chrome),
|
|
10524
|
+
chromeLayout: spec.chromeLayout,
|
|
10476
10525
|
metrics: spec.metrics,
|
|
10477
10526
|
seriesSearch: normalizeSeriesSearch(spec, encoding, warnings),
|
|
10478
10527
|
youDrawIt: normalizeYouDrawIt(spec),
|
|
@@ -10547,15 +10596,10 @@ function normalizeSankeySpec(spec, _warnings) {
|
|
|
10547
10596
|
};
|
|
10548
10597
|
}
|
|
10549
10598
|
function normalizeGraphSpec(spec) {
|
|
10550
|
-
const
|
|
10599
|
+
const layout = {
|
|
10551
10600
|
type: "force",
|
|
10552
|
-
chargeStrength: -300,
|
|
10553
|
-
linkDistance: 30
|
|
10554
|
-
};
|
|
10555
|
-
const layout = spec.layout ? {
|
|
10556
|
-
...defaultLayout,
|
|
10557
10601
|
...spec.layout
|
|
10558
|
-
}
|
|
10602
|
+
};
|
|
10559
10603
|
return {
|
|
10560
10604
|
type: "graph",
|
|
10561
10605
|
nodes: spec.nodes,
|
|
@@ -10567,7 +10611,10 @@ function normalizeGraphSpec(spec) {
|
|
|
10567
10611
|
annotations: normalizeAnnotations(spec.annotations),
|
|
10568
10612
|
theme: spec.theme ?? {},
|
|
10569
10613
|
darkMode: spec.darkMode ?? "off",
|
|
10570
|
-
watermark: spec.watermark ?? true
|
|
10614
|
+
watermark: spec.watermark ?? true,
|
|
10615
|
+
animation: spec.animation,
|
|
10616
|
+
interaction: spec.interaction,
|
|
10617
|
+
legend: spec.legend
|
|
10571
10618
|
};
|
|
10572
10619
|
}
|
|
10573
10620
|
function normalizeTileMapSpec(spec, warnings) {
|
|
@@ -10623,7 +10670,7 @@ function normalizeTileMapSpec(spec, warnings) {
|
|
|
10623
10670
|
valueFormat: spec.valueFormat
|
|
10624
10671
|
};
|
|
10625
10672
|
}
|
|
10626
|
-
function
|
|
10673
|
+
function normalizeGeoMapSpec(spec, _warnings) {
|
|
10627
10674
|
return {
|
|
10628
10675
|
type: "map",
|
|
10629
10676
|
geo: {
|
|
@@ -10683,8 +10730,8 @@ function normalizeSpec(spec, warnings = []) {
|
|
|
10683
10730
|
if (isTileMapSpec(spec)) {
|
|
10684
10731
|
return normalizeTileMapSpec(spec, warnings);
|
|
10685
10732
|
}
|
|
10686
|
-
if (
|
|
10687
|
-
return
|
|
10733
|
+
if (isGeoMapSpec(spec)) {
|
|
10734
|
+
return normalizeGeoMapSpec(spec, warnings);
|
|
10688
10735
|
}
|
|
10689
10736
|
if (isBarListSpec(spec)) {
|
|
10690
10737
|
return normalizeBarListSpec(spec, warnings);
|
|
@@ -11000,6 +11047,40 @@ function validateCalendarSpec(spec, errors) {
|
|
|
11000
11047
|
seenDays.set(dayKey, i);
|
|
11001
11048
|
}
|
|
11002
11049
|
}
|
|
11050
|
+
var MAX_PLAUSIBLE_POINT_RADIUS = 50;
|
|
11051
|
+
function pointSizeError(path2, value2) {
|
|
11052
|
+
const radius = Math.max(1, Math.round(Math.sqrt(value2 / Math.PI)));
|
|
11053
|
+
return {
|
|
11054
|
+
message: `Spec error: ${path2} is a radius in pixels, and ${value2} would draw a ${Math.round(value2 * 2)}px-wide circle. This usually means the value was written in Vega-Lite's units, where point size is an area in px^2.`,
|
|
11055
|
+
path: path2,
|
|
11056
|
+
code: "INVALID_VALUE",
|
|
11057
|
+
suggestion: `Point sizes are radii in px (default 5, typical 2-12). For the dot a Vega-Lite size of ${value2} draws, use ${radius} (r = sqrt(area / pi)).`
|
|
11058
|
+
};
|
|
11059
|
+
}
|
|
11060
|
+
function validatePointSize(spec, errors) {
|
|
11061
|
+
const markType = typeof spec.mark === "string" ? spec.mark : spec.mark?.type;
|
|
11062
|
+
if (markType !== "point") return;
|
|
11063
|
+
if (spec.mark && typeof spec.mark === "object") {
|
|
11064
|
+
const size = spec.mark.size;
|
|
11065
|
+
if (typeof size === "number" && size > MAX_PLAUSIBLE_POINT_RADIUS) {
|
|
11066
|
+
errors.push(pointSizeError("mark.size", size));
|
|
11067
|
+
}
|
|
11068
|
+
}
|
|
11069
|
+
const sizeEnc = spec.encoding && typeof spec.encoding === "object" ? spec.encoding.size : void 0;
|
|
11070
|
+
if (!sizeEnc || typeof sizeEnc !== "object") return;
|
|
11071
|
+
if (typeof sizeEnc.value === "number" && sizeEnc.value > MAX_PLAUSIBLE_POINT_RADIUS) {
|
|
11072
|
+
errors.push(pointSizeError("encoding.size.value", sizeEnc.value));
|
|
11073
|
+
}
|
|
11074
|
+
const range3 = sizeEnc.scale && typeof sizeEnc.scale === "object" ? sizeEnc.scale.range : void 0;
|
|
11075
|
+
if (Array.isArray(range3)) {
|
|
11076
|
+
const worst = range3.find(
|
|
11077
|
+
(entry) => typeof entry === "number" && entry > MAX_PLAUSIBLE_POINT_RADIUS
|
|
11078
|
+
);
|
|
11079
|
+
if (typeof worst === "number") {
|
|
11080
|
+
errors.push(pointSizeError("encoding.size.scale.range", worst));
|
|
11081
|
+
}
|
|
11082
|
+
}
|
|
11083
|
+
}
|
|
11003
11084
|
function validateChartSpec(spec, errors) {
|
|
11004
11085
|
const markType = typeof spec.mark === "string" ? spec.mark : spec.mark?.type;
|
|
11005
11086
|
if (!Array.isArray(spec.data)) {
|
|
@@ -11105,6 +11186,7 @@ function validateChartSpec(spec, errors) {
|
|
|
11105
11186
|
if (markType === "calendar") {
|
|
11106
11187
|
validateCalendarSpec(spec, errors);
|
|
11107
11188
|
}
|
|
11189
|
+
validatePointSize(spec, errors);
|
|
11108
11190
|
if (Array.isArray(spec.transform)) {
|
|
11109
11191
|
const transforms = spec.transform;
|
|
11110
11192
|
for (let i = 0; i < transforms.length; i++) {
|
|
@@ -11317,6 +11399,52 @@ function validateChartSpec(spec, errors) {
|
|
|
11317
11399
|
}
|
|
11318
11400
|
}
|
|
11319
11401
|
}
|
|
11402
|
+
for (const channel of ["row", "column"]) {
|
|
11403
|
+
const ch = encoding[channel];
|
|
11404
|
+
if (ch && typeof ch === "object") {
|
|
11405
|
+
const facetCh = ch;
|
|
11406
|
+
if (!facetCh.field || typeof facetCh.field !== "string") {
|
|
11407
|
+
errors.push({
|
|
11408
|
+
message: `Spec error: encoding.${channel}.field is required and must be a non-empty string`,
|
|
11409
|
+
path: `encoding.${channel}.field`,
|
|
11410
|
+
code: "MISSING_FIELD",
|
|
11411
|
+
suggestion: `Add a field property to encoding.${channel} (e.g. { field: "category", type: "nominal" })`
|
|
11412
|
+
});
|
|
11413
|
+
} else if (!dataColumns.has(facetCh.field) && !transformFields.has(facetCh.field)) {
|
|
11414
|
+
errors.push({
|
|
11415
|
+
message: `Spec error: encoding.${channel}.field "${facetCh.field}" does not exist in data. Available columns: ${availableColumns}`,
|
|
11416
|
+
path: `encoding.${channel}.field`,
|
|
11417
|
+
code: "DATA_FIELD_MISSING",
|
|
11418
|
+
suggestion: `Use one of the available data columns: ${availableColumns}.${didYouMean(facetCh.field, columnList)}`
|
|
11419
|
+
});
|
|
11420
|
+
}
|
|
11421
|
+
if (!facetCh.type || facetCh.type !== "nominal" && facetCh.type !== "ordinal") {
|
|
11422
|
+
errors.push({
|
|
11423
|
+
message: `Spec error: encoding.${channel}.type must be "nominal" or "ordinal"${facetCh.type ? `, got "${facetCh.type}"` : ""}`,
|
|
11424
|
+
path: `encoding.${channel}.type`,
|
|
11425
|
+
code: facetCh.type ? "INVALID_VALUE" : "MISSING_FIELD",
|
|
11426
|
+
suggestion: `Set encoding.${channel}.type to "nominal" or "ordinal"`
|
|
11427
|
+
});
|
|
11428
|
+
}
|
|
11429
|
+
if (encoding.facet && typeof encoding.facet === "object") {
|
|
11430
|
+
errors.push({
|
|
11431
|
+
message: `Spec error: encoding.${channel} and encoding.facet cannot be used together`,
|
|
11432
|
+
path: `encoding.${channel}`,
|
|
11433
|
+
code: "INVALID_VALUE",
|
|
11434
|
+
suggestion: `Use either encoding.${channel} or encoding.facet, not both`
|
|
11435
|
+
});
|
|
11436
|
+
}
|
|
11437
|
+
const otherChannel = channel === "row" ? "column" : "row";
|
|
11438
|
+
if (encoding[otherChannel]) {
|
|
11439
|
+
errors.push({
|
|
11440
|
+
message: "Spec error: encoding.row and encoding.column cannot be used together (cross-product faceting is not yet supported)",
|
|
11441
|
+
path: `encoding.${channel}`,
|
|
11442
|
+
code: "INVALID_VALUE",
|
|
11443
|
+
suggestion: "Use encoding.facet with columns for grid layout, or use only row or column"
|
|
11444
|
+
});
|
|
11445
|
+
}
|
|
11446
|
+
}
|
|
11447
|
+
}
|
|
11320
11448
|
if (spec.darkMode !== void 0 && !VALID_DARK_MODES.has(spec.darkMode)) {
|
|
11321
11449
|
errors.push({
|
|
11322
11450
|
message: `Spec error: darkMode must be "auto", "force", or "off"`,
|
|
@@ -11550,14 +11678,28 @@ function validateGraphSpec(spec, errors) {
|
|
|
11550
11678
|
}
|
|
11551
11679
|
if (spec.encoding && typeof spec.encoding === "object") {
|
|
11552
11680
|
const encoding = spec.encoding;
|
|
11553
|
-
const
|
|
11554
|
-
const
|
|
11555
|
-
|
|
11556
|
-
|
|
11557
|
-
|
|
11681
|
+
const nodeFields = /* @__PURE__ */ new Set();
|
|
11682
|
+
for (const node of nodes) {
|
|
11683
|
+
if (node && typeof node === "object") {
|
|
11684
|
+
for (const key of Object.keys(node)) nodeFields.add(key);
|
|
11685
|
+
}
|
|
11686
|
+
}
|
|
11687
|
+
const edgeFields = /* @__PURE__ */ new Set();
|
|
11688
|
+
for (const edge of edges) {
|
|
11689
|
+
if (edge && typeof edge === "object") {
|
|
11690
|
+
for (const key of Object.keys(edge)) edgeFields.add(key);
|
|
11691
|
+
}
|
|
11692
|
+
}
|
|
11693
|
+
const nodeChannels = [
|
|
11694
|
+
"nodeColor",
|
|
11695
|
+
"nodeSize",
|
|
11696
|
+
"nodeOpacity",
|
|
11697
|
+
"nodeLabel",
|
|
11698
|
+
"nodeLabelPriority"
|
|
11699
|
+
];
|
|
11558
11700
|
for (const channel of nodeChannels) {
|
|
11559
11701
|
const ch = encoding[channel];
|
|
11560
|
-
if (ch?.field && typeof ch.field === "string" && !nodeFields.has(ch.field)) {
|
|
11702
|
+
if (ch?.field && typeof ch.field === "string" && nodes.length > 0 && !nodeFields.has(ch.field)) {
|
|
11561
11703
|
errors.push({
|
|
11562
11704
|
message: `Spec error: encoding.${channel}.field "${ch.field}" does not exist on nodes. Available fields: ${[...nodeFields].join(", ")}`,
|
|
11563
11705
|
path: `encoding.${channel}.field`,
|
|
@@ -11566,10 +11708,10 @@ function validateGraphSpec(spec, errors) {
|
|
|
11566
11708
|
});
|
|
11567
11709
|
}
|
|
11568
11710
|
}
|
|
11569
|
-
const edgeChannels = ["edgeColor", "edgeWidth"];
|
|
11711
|
+
const edgeChannels = ["edgeColor", "edgeWidth", "edgeStyle"];
|
|
11570
11712
|
for (const channel of edgeChannels) {
|
|
11571
11713
|
const ch = encoding[channel];
|
|
11572
|
-
if (ch?.field && typeof ch.field === "string" &&
|
|
11714
|
+
if (ch?.field && typeof ch.field === "string" && edges.length > 0 && !edgeFields.has(ch.field)) {
|
|
11573
11715
|
errors.push({
|
|
11574
11716
|
message: `Spec error: encoding.${channel}.field "${ch.field}" does not exist on edges. Available fields: ${[...edgeFields].join(", ")}`,
|
|
11575
11717
|
path: `encoding.${channel}.field`,
|
|
@@ -11782,7 +11924,7 @@ function validateTileMapSpec(spec, errors) {
|
|
|
11782
11924
|
});
|
|
11783
11925
|
}
|
|
11784
11926
|
}
|
|
11785
|
-
function
|
|
11927
|
+
function validateGeoMapSpec(spec, errors) {
|
|
11786
11928
|
if (!spec.geo || typeof spec.geo !== "object") {
|
|
11787
11929
|
errors.push({
|
|
11788
11930
|
message: 'Spec error: map spec requires a "geo" object with a TopoJSON "features" field',
|
|
@@ -12162,6 +12304,22 @@ function validateLayerSpec(spec, errors) {
|
|
|
12162
12304
|
}
|
|
12163
12305
|
}
|
|
12164
12306
|
}
|
|
12307
|
+
function validateAnimation(spec, errors) {
|
|
12308
|
+
const animation = spec.animation;
|
|
12309
|
+
if (!animation || typeof animation !== "object" || Array.isArray(animation)) return;
|
|
12310
|
+
const update = animation.update;
|
|
12311
|
+
if (!update || typeof update !== "object" || Array.isArray(update)) return;
|
|
12312
|
+
const maxMarks = update.maxMarks;
|
|
12313
|
+
if (maxMarks === void 0) return;
|
|
12314
|
+
if (typeof maxMarks !== "number" || !Number.isFinite(maxMarks) || maxMarks < 1) {
|
|
12315
|
+
errors.push({
|
|
12316
|
+
message: `Spec error: animation.update.maxMarks must be a number >= 1, got ${JSON.stringify(maxMarks)}`,
|
|
12317
|
+
path: "animation.update.maxMarks",
|
|
12318
|
+
code: "INVALID_VALUE",
|
|
12319
|
+
suggestion: "Set animation.update.maxMarks to the largest mark count that should still tween, e.g. animation: { update: { maxMarks: 5000 } }. Omit it to use the default of 500."
|
|
12320
|
+
});
|
|
12321
|
+
}
|
|
12322
|
+
}
|
|
12165
12323
|
function validateSpec(spec) {
|
|
12166
12324
|
const errors = [];
|
|
12167
12325
|
if (!spec || typeof spec !== "object" || Array.isArray(spec)) {
|
|
@@ -12266,10 +12424,13 @@ function validateSpec(spec) {
|
|
|
12266
12424
|
} else if (isTileMap) {
|
|
12267
12425
|
validateTileMapSpec(obj, errors);
|
|
12268
12426
|
} else if (isMap) {
|
|
12269
|
-
|
|
12427
|
+
validateGeoMapSpec(obj, errors);
|
|
12270
12428
|
} else if (isBarList) {
|
|
12271
12429
|
validateBarListSpec(obj, errors);
|
|
12272
12430
|
}
|
|
12431
|
+
if (!isGraph) {
|
|
12432
|
+
validateAnimation(obj, errors);
|
|
12433
|
+
}
|
|
12273
12434
|
if (errors.length > 0) {
|
|
12274
12435
|
return { valid: false, errors, normalized: null };
|
|
12275
12436
|
}
|
|
@@ -12293,6 +12454,36 @@ ${errorMessages}`);
|
|
|
12293
12454
|
return { spec: normalized, warnings };
|
|
12294
12455
|
}
|
|
12295
12456
|
|
|
12457
|
+
// src/layout/shared.ts
|
|
12458
|
+
function chromeToInput(chrome) {
|
|
12459
|
+
return {
|
|
12460
|
+
eyebrow: chrome.eyebrow,
|
|
12461
|
+
title: chrome.title,
|
|
12462
|
+
subtitle: chrome.subtitle,
|
|
12463
|
+
source: chrome.source,
|
|
12464
|
+
byline: chrome.byline,
|
|
12465
|
+
footer: chrome.footer,
|
|
12466
|
+
brand: chrome.brand
|
|
12467
|
+
};
|
|
12468
|
+
}
|
|
12469
|
+
function scalePadding(basePadding, width, height) {
|
|
12470
|
+
const minDim = Math.min(width, height);
|
|
12471
|
+
if (minDim >= 500) return basePadding;
|
|
12472
|
+
if (minDim <= 200) return Math.max(Math.round(basePadding * 0.5), 4);
|
|
12473
|
+
const t = (minDim - 200) / 300;
|
|
12474
|
+
return Math.max(Math.round(basePadding * (0.5 + t * 0.5)), 4);
|
|
12475
|
+
}
|
|
12476
|
+
function bottomMargin(bottomHeight, padding, xAxisHeight) {
|
|
12477
|
+
return padding + bottomHeight + xAxisHeight;
|
|
12478
|
+
}
|
|
12479
|
+
var INLINE_TICK_OVERHANG_PAD = 6;
|
|
12480
|
+
function resolveChromeLayout(spec, options) {
|
|
12481
|
+
const encoding = spec?.encoding;
|
|
12482
|
+
const isFaceted = !!(encoding?.facet || encoding?.row || encoding?.column);
|
|
12483
|
+
if (isFaceted) return "subtract";
|
|
12484
|
+
return spec?.chromeLayout ?? options?.chromeLayout ?? "subtract";
|
|
12485
|
+
}
|
|
12486
|
+
|
|
12296
12487
|
// src/barlist/compile-barlist.ts
|
|
12297
12488
|
var DEFAULT_ROW_GAP = 8;
|
|
12298
12489
|
var LABEL_BAR_GAP = 12;
|
|
@@ -12340,14 +12531,19 @@ function compileBarList(spec, options) {
|
|
|
12340
12531
|
watermark
|
|
12341
12532
|
);
|
|
12342
12533
|
const padding = theme.spacing.padding;
|
|
12534
|
+
const chromeLayout = resolveChromeLayout(
|
|
12535
|
+
spec,
|
|
12536
|
+
options
|
|
12537
|
+
);
|
|
12538
|
+
const grownHeight = chromeLayout === "grow" ? options.height + chrome.topHeight + chrome.bottomHeight : options.height;
|
|
12343
12539
|
const fullArea = {
|
|
12344
12540
|
x: padding,
|
|
12345
12541
|
y: padding + chrome.topHeight,
|
|
12346
12542
|
width: options.width - padding * 2,
|
|
12347
|
-
height: options.height - chrome.topHeight - chrome.bottomHeight - padding * 2
|
|
12543
|
+
height: chromeLayout === "grow" ? options.height - padding * 2 : options.height - chrome.topHeight - chrome.bottomHeight - padding * 2
|
|
12348
12544
|
};
|
|
12349
12545
|
if (fullArea.width <= 0 || fullArea.height <= 0) {
|
|
12350
|
-
return emptyLayout2(chrome, theme, options, watermark);
|
|
12546
|
+
return emptyLayout2(chrome, theme, { ...options, height: grownHeight }, watermark);
|
|
12351
12547
|
}
|
|
12352
12548
|
const labelField = barlistSpec.encoding.label.field;
|
|
12353
12549
|
const valueField = barlistSpec.encoding.value.field;
|
|
@@ -12532,7 +12728,7 @@ function compileBarList(spec, options) {
|
|
|
12532
12728
|
a11y,
|
|
12533
12729
|
theme,
|
|
12534
12730
|
width: options.width,
|
|
12535
|
-
height:
|
|
12731
|
+
height: grownHeight,
|
|
12536
12732
|
animation: resolvedAnimation,
|
|
12537
12733
|
watermark,
|
|
12538
12734
|
measureText
|
|
@@ -13660,6 +13856,7 @@ var LEGEND_PADDING = 8;
|
|
|
13660
13856
|
var LEGEND_RIGHT_WIDTH = 120;
|
|
13661
13857
|
var RIGHT_LEGEND_MAX_HEIGHT_RATIO = 0.4;
|
|
13662
13858
|
var TOP_LEGEND_MAX_ROWS = 2;
|
|
13859
|
+
var ARC_LABEL_CROWDING_LIMIT = 21;
|
|
13663
13860
|
function hasLegendContent(content) {
|
|
13664
13861
|
return content.entries.length > 0 || content.continuous != null;
|
|
13665
13862
|
}
|
|
@@ -13817,6 +14014,12 @@ function computeLegendContent(spec, strategy, theme, availableWidth, availableHe
|
|
|
13817
14014
|
}
|
|
13818
14015
|
}
|
|
13819
14016
|
}
|
|
14017
|
+
const density = spec.labels.density;
|
|
14018
|
+
const everySliceLabeled = density === "all" || density === "auto";
|
|
14019
|
+
const uncrowded = seriesCount > 0 && seriesCount <= ARC_LABEL_CROWDING_LIMIT;
|
|
14020
|
+
if (spec.markType === "arc" && everySliceLabeled && uncrowded && !spec.userExplicit?.legend) {
|
|
14021
|
+
entries = [];
|
|
14022
|
+
}
|
|
13820
14023
|
const labelStyle = {
|
|
13821
14024
|
fontFamily: theme.fonts.family,
|
|
13822
14025
|
fontSize: theme.fonts.sizes.small,
|
|
@@ -13824,7 +14027,8 @@ function computeLegendContent(spec, strategy, theme, availableWidth, availableHe
|
|
|
13824
14027
|
fill: theme.colors.text,
|
|
13825
14028
|
lineHeight: 1.3
|
|
13826
14029
|
};
|
|
13827
|
-
const
|
|
14030
|
+
const specPosition = spec.legend?.position === "top-left" ? "top" : spec.legend?.position;
|
|
14031
|
+
const resolvedPosition = specPosition ?? (strategy.legendPosition === "right" ? "right" : "top");
|
|
13828
14032
|
if (entries.length === 0) {
|
|
13829
14033
|
return emptyContent(resolvedPosition, theme);
|
|
13830
14034
|
}
|
|
@@ -14825,30 +15029,6 @@ function computeAxes(scales, chartArea, strategy, theme, measureText, dataContex
|
|
|
14825
15029
|
return result;
|
|
14826
15030
|
}
|
|
14827
15031
|
|
|
14828
|
-
// src/layout/shared.ts
|
|
14829
|
-
function chromeToInput(chrome) {
|
|
14830
|
-
return {
|
|
14831
|
-
eyebrow: chrome.eyebrow,
|
|
14832
|
-
title: chrome.title,
|
|
14833
|
-
subtitle: chrome.subtitle,
|
|
14834
|
-
source: chrome.source,
|
|
14835
|
-
byline: chrome.byline,
|
|
14836
|
-
footer: chrome.footer,
|
|
14837
|
-
brand: chrome.brand
|
|
14838
|
-
};
|
|
14839
|
-
}
|
|
14840
|
-
function scalePadding(basePadding, width, height) {
|
|
14841
|
-
const minDim = Math.min(width, height);
|
|
14842
|
-
if (minDim >= 500) return basePadding;
|
|
14843
|
-
if (minDim <= 200) return Math.max(Math.round(basePadding * 0.5), 4);
|
|
14844
|
-
const t = (minDim - 200) / 300;
|
|
14845
|
-
return Math.max(Math.round(basePadding * (0.5 + t * 0.5)), 4);
|
|
14846
|
-
}
|
|
14847
|
-
function bottomMargin(bottomHeight, padding, xAxisHeight) {
|
|
14848
|
-
return padding + bottomHeight + xAxisHeight;
|
|
14849
|
-
}
|
|
14850
|
-
var INLINE_TICK_OVERHANG_PAD = 6;
|
|
14851
|
-
|
|
14852
15032
|
// src/layout/plan.ts
|
|
14853
15033
|
function createMeasureFn(measureText) {
|
|
14854
15034
|
if (measureText) {
|
|
@@ -15070,7 +15250,9 @@ function resolveLayoutPlan(chartSpec, renderSpec, options, theme, strategy, wate
|
|
|
15070
15250
|
if (hasTopLegend) topMargin += TOP_LEGEND_GAP_ABOVE + legendContent.height + gap;
|
|
15071
15251
|
topMargin += effectiveTopAxisGap;
|
|
15072
15252
|
const bMargin = bottomMargin(chrome.bottomHeight, padding, xAxisExtent);
|
|
15073
|
-
const
|
|
15253
|
+
const chromeLayout = resolveChromeLayout(renderSpec, options);
|
|
15254
|
+
const effectiveHeight = chromeLayout === "grow" ? height + chrome.topHeight + chrome.bottomHeight : height;
|
|
15255
|
+
const chartHeight = Math.max(0, effectiveHeight - topMargin - bMargin);
|
|
15074
15256
|
const rightMargin = hPad + (isRadial ? hPad : axisMargin);
|
|
15075
15257
|
const rightAxisReserve = options.rightAxisReserve ?? 0;
|
|
15076
15258
|
const provisionalArea = {
|
|
@@ -15222,11 +15404,12 @@ function compileLayer(spec, options, compileChart2) {
|
|
|
15222
15404
|
const singleSpec = buildPrimarySpec(leaves, spec);
|
|
15223
15405
|
return compileChart2(singleSpec, options);
|
|
15224
15406
|
}
|
|
15407
|
+
const layerOptions = { ...options, layered: true };
|
|
15225
15408
|
if (spec.resolve?.scale?.y === "independent") {
|
|
15226
|
-
return compileLayerIndependent(leaves, spec,
|
|
15409
|
+
return compileLayerIndependent(leaves, spec, layerOptions, compileChart2);
|
|
15227
15410
|
}
|
|
15228
15411
|
const primarySpec = buildPrimarySpec(leaves, spec);
|
|
15229
|
-
const primaryLayout = compileChart2(primarySpec,
|
|
15412
|
+
const primaryLayout = compileChart2(primarySpec, layerOptions);
|
|
15230
15413
|
const allMarks = [];
|
|
15231
15414
|
const seenLabels = /* @__PURE__ */ new Set();
|
|
15232
15415
|
const pLegend = primaryLayout.legend;
|
|
@@ -15239,7 +15422,7 @@ function compileLayer(spec, options, compileChart2) {
|
|
|
15239
15422
|
zIndex: leaf.zIndex ?? i
|
|
15240
15423
|
}));
|
|
15241
15424
|
indexedLeaves.sort((a, b) => a.zIndex - b.zIndex);
|
|
15242
|
-
const leafOptions = { ...
|
|
15425
|
+
const leafOptions = { ...layerOptions, frozenChartArea: primaryLayout.area };
|
|
15243
15426
|
const sharedDomains = computeSharedDomains(leaves);
|
|
15244
15427
|
for (const { leaf } of indexedLeaves) {
|
|
15245
15428
|
const themedLeaf = {
|
|
@@ -15348,11 +15531,9 @@ function compileLayerIndependent(leaves, layerSpec, options, compileChart2) {
|
|
|
15348
15531
|
};
|
|
15349
15532
|
const xField0 = leaf0.encoding?.x?.field;
|
|
15350
15533
|
const xField1 = leaf1.encoding?.x?.field;
|
|
15351
|
-
const
|
|
15352
|
-
|
|
15353
|
-
|
|
15354
|
-
let leaf0WithUnionX = ensureXDomainCoverage(leaf0, xField0, unionXValues);
|
|
15355
|
-
let leaf1WithUnionX = ensureXDomainCoverage(leaf1, xField1, unionXValues);
|
|
15534
|
+
const union = withUnionXDomain(leaf0, leaf1);
|
|
15535
|
+
let leaf0WithUnionX = union.leaf0;
|
|
15536
|
+
let leaf1WithUnionX = union.leaf1;
|
|
15356
15537
|
const aligned = alignYDomains(leaf0WithUnionX, leaf1WithUnionX);
|
|
15357
15538
|
if (aligned) {
|
|
15358
15539
|
leaf0WithUnionX = withYDomain(leaf0WithUnionX, aligned.domain0);
|
|
@@ -15499,20 +15680,75 @@ function compileLayerIndependent(leaves, layerSpec, options, compileChart2) {
|
|
|
15499
15680
|
tooltipDescriptors: mergedTooltips
|
|
15500
15681
|
};
|
|
15501
15682
|
}
|
|
15502
|
-
function
|
|
15503
|
-
if (!
|
|
15504
|
-
|
|
15505
|
-
|
|
15506
|
-
|
|
15507
|
-
|
|
15508
|
-
|
|
15509
|
-
|
|
15683
|
+
function withXDomain(leaf, domain) {
|
|
15684
|
+
if (!leaf.encoding?.x) return leaf;
|
|
15685
|
+
return {
|
|
15686
|
+
...leaf,
|
|
15687
|
+
encoding: {
|
|
15688
|
+
...leaf.encoding,
|
|
15689
|
+
x: {
|
|
15690
|
+
...leaf.encoding.x,
|
|
15691
|
+
scale: {
|
|
15692
|
+
...leaf.encoding.x.scale,
|
|
15693
|
+
domain
|
|
15694
|
+
}
|
|
15695
|
+
}
|
|
15696
|
+
}
|
|
15697
|
+
};
|
|
15698
|
+
}
|
|
15699
|
+
function withUnionXDomain(leaf0, leaf1) {
|
|
15700
|
+
const xEnc0 = leaf0.encoding?.x;
|
|
15701
|
+
const xEnc1 = leaf1.encoding?.x;
|
|
15702
|
+
const xField0 = xEnc0?.field;
|
|
15703
|
+
const xField1 = xEnc1?.field;
|
|
15704
|
+
if (!xField0 || !xField1) return { leaf0, leaf1 };
|
|
15705
|
+
const xType = xEnc0?.type ?? xEnc1?.type;
|
|
15706
|
+
const pinned0 = xEnc0?.scale?.domain !== void 0;
|
|
15707
|
+
const pinned1 = xEnc1?.scale?.domain !== void 0;
|
|
15708
|
+
if (pinned0 && pinned1) return { leaf0, leaf1 };
|
|
15709
|
+
const values0 = leaf0.data.map((row) => row[xField0]);
|
|
15710
|
+
const values1 = leaf1.data.map((row) => row[xField1]);
|
|
15711
|
+
const allValues = [...values0, ...values1].filter((v) => v != null);
|
|
15712
|
+
if (allValues.length === 0) return { leaf0, leaf1 };
|
|
15713
|
+
let domain;
|
|
15714
|
+
if (xType === "temporal") {
|
|
15715
|
+
let minMs = Number.POSITIVE_INFINITY;
|
|
15716
|
+
let maxMs = Number.NEGATIVE_INFINITY;
|
|
15717
|
+
for (const v of allValues) {
|
|
15718
|
+
const ms = (v instanceof Date ? v : new Date(String(v))).getTime();
|
|
15719
|
+
if (Number.isNaN(ms)) continue;
|
|
15720
|
+
if (ms < minMs) minMs = ms;
|
|
15721
|
+
if (ms > maxMs) maxMs = ms;
|
|
15722
|
+
}
|
|
15723
|
+
if (minMs <= maxMs) {
|
|
15724
|
+
domain = [new Date(minMs).toISOString(), new Date(maxMs).toISOString()];
|
|
15725
|
+
}
|
|
15726
|
+
} else if (xType === "quantitative") {
|
|
15727
|
+
let min4 = Number.POSITIVE_INFINITY;
|
|
15728
|
+
let max4 = Number.NEGATIVE_INFINITY;
|
|
15729
|
+
for (const v of allValues) {
|
|
15730
|
+
const n = typeof v === "number" ? v : Number(v);
|
|
15731
|
+
if (!Number.isFinite(n)) continue;
|
|
15732
|
+
if (n < min4) min4 = n;
|
|
15733
|
+
if (n > max4) max4 = n;
|
|
15734
|
+
}
|
|
15735
|
+
if (min4 <= max4) domain = [min4, max4];
|
|
15736
|
+
} else {
|
|
15737
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15738
|
+
const categories = [];
|
|
15739
|
+
for (const v of allValues) {
|
|
15740
|
+
const s = String(v);
|
|
15741
|
+
if (!seen.has(s)) {
|
|
15742
|
+
seen.add(s);
|
|
15743
|
+
categories.push(s);
|
|
15744
|
+
}
|
|
15510
15745
|
}
|
|
15746
|
+
if (categories.length > 0) domain = categories;
|
|
15511
15747
|
}
|
|
15512
|
-
if (
|
|
15748
|
+
if (domain === void 0) return { leaf0, leaf1 };
|
|
15513
15749
|
return {
|
|
15514
|
-
|
|
15515
|
-
|
|
15750
|
+
leaf0: pinned0 ? leaf0 : withXDomain(leaf0, domain),
|
|
15751
|
+
leaf1: pinned1 ? leaf1 : withXDomain(leaf1, domain)
|
|
15516
15752
|
};
|
|
15517
15753
|
}
|
|
15518
15754
|
function alignYDomains(leaf0, leaf1) {
|
|
@@ -15631,6 +15867,10 @@ function buildPrimarySpec(leaves, layerSpec) {
|
|
|
15631
15867
|
...leaves[0],
|
|
15632
15868
|
data: allData,
|
|
15633
15869
|
chrome: layerSpec.chrome ?? leaves[0].chrome,
|
|
15870
|
+
// Annotations come from the parent LayerSpec when present, otherwise
|
|
15871
|
+
// the first flattened leaf's. Later leaves' annotations are silently
|
|
15872
|
+
// dropped. The dual-axis path (compileLayerIndependent) explicitly
|
|
15873
|
+
// clears the secondary axis spec's annotations.
|
|
15634
15874
|
annotations: layerSpec.annotations ?? leaves[0].annotations,
|
|
15635
15875
|
labels: layerSpec.labels ?? leaves[0].labels,
|
|
15636
15876
|
legend: layerSpec.legend ?? leaves[0].legend,
|
|
@@ -15731,7 +15971,7 @@ function resolveYouDrawIt(config, marks, scales, chartArea, xField) {
|
|
|
15731
15971
|
}
|
|
15732
15972
|
|
|
15733
15973
|
// src/compiler/a11y-warnings.ts
|
|
15734
|
-
import { contrastRatio, findAccessibleColor, isOpaqueColor } from "@opendata-ai/openchart-core";
|
|
15974
|
+
import { contrastRatio, findAccessibleColor, isOpaqueColor as isOpaqueColor2 } from "@opendata-ai/openchart-core";
|
|
15735
15975
|
var GRAPHIC_MIN = 3;
|
|
15736
15976
|
var TEXT_MIN = 4.5;
|
|
15737
15977
|
var ADJACENT_FILL_MARKS = /* @__PURE__ */ new Set(["bar", "area", "arc", "waffle"]);
|
|
@@ -15739,7 +15979,7 @@ var fmt = (ratio) => `${ratio.toFixed(2)}:1`;
|
|
|
15739
15979
|
function collectContrastWarnings(scales, markType, theme) {
|
|
15740
15980
|
const warnings = [];
|
|
15741
15981
|
const bg = theme.colors.background;
|
|
15742
|
-
const bgIsCheckable =
|
|
15982
|
+
const bgIsCheckable = isOpaqueColor2(bg);
|
|
15743
15983
|
const series = [];
|
|
15744
15984
|
if (scales.color && scales.color.type !== "sequential") {
|
|
15745
15985
|
const ordinal2 = scales.color.scale;
|
|
@@ -15787,6 +16027,37 @@ function collectContrastWarnings(scales, markType, theme) {
|
|
|
15787
16027
|
return warnings;
|
|
15788
16028
|
}
|
|
15789
16029
|
|
|
16030
|
+
// src/compiler/mark-render-mode.ts
|
|
16031
|
+
var AUTO_CANVAS_THRESHOLD = 1e3;
|
|
16032
|
+
var AUTO_CANVAS_REFUSAL_WARN_THRESHOLD = 5e3;
|
|
16033
|
+
function resolveMarkRenderMode(args, warnings = []) {
|
|
16034
|
+
const { markType, pointCount, display, faceted, layered } = args;
|
|
16035
|
+
const requested = args.requested ?? "auto";
|
|
16036
|
+
if (requested === "svg") return "svg";
|
|
16037
|
+
const refusal = describeRefusal(markType, display, faceted, layered);
|
|
16038
|
+
if (refusal) {
|
|
16039
|
+
if (requested === "canvas") {
|
|
16040
|
+
warnings.push(
|
|
16041
|
+
`Chart warning: renderer "canvas" is not supported ${refusal}; rendering marks as SVG instead.`
|
|
16042
|
+
);
|
|
16043
|
+
} else if (pointCount > AUTO_CANVAS_REFUSAL_WARN_THRESHOLD) {
|
|
16044
|
+
warnings.push(
|
|
16045
|
+
`[openchart] Rendering ${pointCount} point marks as SVG: the canvas mark layer is not supported ${refusal}. Expect slow paint and interaction. Reduce the point count, or restructure so the dense marks compile as a single unlayered, unfaceted point chart.`
|
|
16046
|
+
);
|
|
16047
|
+
}
|
|
16048
|
+
return "svg";
|
|
16049
|
+
}
|
|
16050
|
+
if (requested === "canvas") return "canvas";
|
|
16051
|
+
return pointCount > AUTO_CANVAS_THRESHOLD ? "canvas" : "svg";
|
|
16052
|
+
}
|
|
16053
|
+
function describeRefusal(markType, display, faceted, layered) {
|
|
16054
|
+
if (markType !== "point") return `for ${markType} marks (point marks only)`;
|
|
16055
|
+
if (faceted) return "on faceted charts";
|
|
16056
|
+
if (layered) return "on layered charts";
|
|
16057
|
+
if (display === "sparkline") return "on sparklines";
|
|
16058
|
+
return void 0;
|
|
16059
|
+
}
|
|
16060
|
+
|
|
15790
16061
|
// src/compiler/sparkline-defaults.ts
|
|
15791
16062
|
var TREND_DEADBAND = 5e-4;
|
|
15792
16063
|
function computeTrend(values) {
|
|
@@ -15853,7 +16124,7 @@ function buildSparklineAreaGradient(baseColor) {
|
|
|
15853
16124
|
};
|
|
15854
16125
|
}
|
|
15855
16126
|
|
|
15856
|
-
// src/geo/compile-map.ts
|
|
16127
|
+
// src/geo/compile-geo-map.ts
|
|
15857
16128
|
import {
|
|
15858
16129
|
adaptTheme as adaptTheme2,
|
|
15859
16130
|
buildD3Formatter as buildD3Formatter2,
|
|
@@ -17754,7 +18025,7 @@ function identity_default4() {
|
|
|
17754
18025
|
return projection2;
|
|
17755
18026
|
}
|
|
17756
18027
|
|
|
17757
|
-
// src/geo/compile-map.ts
|
|
18028
|
+
// src/geo/compile-geo-map.ts
|
|
17758
18029
|
import { feature as topoFeature, mesh as topoMesh } from "topojson-client";
|
|
17759
18030
|
|
|
17760
18031
|
// src/geo/join.ts
|
|
@@ -17843,13 +18114,32 @@ function joinDataToFeatures(features, data, dataKeyField, featureIdField) {
|
|
|
17843
18114
|
|
|
17844
18115
|
// src/geo/projections.ts
|
|
17845
18116
|
var MERCATOR_FIT_MIN_LAT = -60;
|
|
17846
|
-
function createProjection(type, width, height, geojson) {
|
|
18117
|
+
function createProjection(type, width, height, geojson, inset = 0) {
|
|
17847
18118
|
if (type === "identity") {
|
|
18119
|
+
if (inset > 0) {
|
|
18120
|
+
return identity_default4().fitExtent(
|
|
18121
|
+
[
|
|
18122
|
+
[inset, inset],
|
|
18123
|
+
[width - inset, height - inset]
|
|
18124
|
+
],
|
|
18125
|
+
geojson
|
|
18126
|
+
);
|
|
18127
|
+
}
|
|
17848
18128
|
return identity_default4().fitSize([width, height], geojson);
|
|
17849
18129
|
}
|
|
17850
18130
|
const projection2 = type === "albersUsa" ? albersUsa_default() : type === "equalEarth" ? equalEarth_default() : mercator_default();
|
|
17851
18131
|
const fitGeometry = type === "mercator" ? excludePolarFeatures(geojson) : geojson;
|
|
17852
|
-
|
|
18132
|
+
if (inset > 0) {
|
|
18133
|
+
projection2.fitExtent(
|
|
18134
|
+
[
|
|
18135
|
+
[inset, inset],
|
|
18136
|
+
[width - inset, height - inset]
|
|
18137
|
+
],
|
|
18138
|
+
fitGeometry
|
|
18139
|
+
);
|
|
18140
|
+
} else {
|
|
18141
|
+
projection2.fitSize([width, height], fitGeometry);
|
|
18142
|
+
}
|
|
17853
18143
|
return projection2;
|
|
17854
18144
|
}
|
|
17855
18145
|
function excludePolarFeatures(geojson) {
|
|
@@ -17868,7 +18158,8 @@ function excludePolarFeatures(geojson) {
|
|
|
17868
18158
|
return { type: "FeatureCollection", features: filtered };
|
|
17869
18159
|
}
|
|
17870
18160
|
|
|
17871
|
-
// src/geo/compile-map.ts
|
|
18161
|
+
// src/geo/compile-geo-map.ts
|
|
18162
|
+
var OVERLAY_LEGEND_INSET = 18;
|
|
17872
18163
|
function validateGeoFeatures(geo) {
|
|
17873
18164
|
if (!geo.features) {
|
|
17874
18165
|
throw new Error(
|
|
@@ -17889,14 +18180,14 @@ function validateGeoFeatures(geo) {
|
|
|
17889
18180
|
}
|
|
17890
18181
|
return topo;
|
|
17891
18182
|
}
|
|
17892
|
-
function
|
|
18183
|
+
function compileGeoMap(spec, options) {
|
|
17893
18184
|
const sugarWarnings = [];
|
|
17894
18185
|
const expandedSpec = spec && typeof spec === "object" && !Array.isArray(spec) ? expandSpecSugar(spec, sugarWarnings) : spec;
|
|
17895
18186
|
const { spec: normalized, warnings } = compile(expandedSpec);
|
|
17896
18187
|
emitSpecWarnings([...sugarWarnings, ...warnings], options.onWarn);
|
|
17897
18188
|
if (!("type" in normalized) || normalized.type !== "map") {
|
|
17898
18189
|
throw new Error(
|
|
17899
|
-
"
|
|
18190
|
+
"compileGeoMap received a non-map spec. Use compileChart, compileTileMap, compileSankey, or compileBarList instead."
|
|
17900
18191
|
);
|
|
17901
18192
|
}
|
|
17902
18193
|
const mapSpec = normalized;
|
|
@@ -17926,11 +18217,15 @@ function compileMap(spec, options) {
|
|
|
17926
18217
|
watermark
|
|
17927
18218
|
);
|
|
17928
18219
|
const padding = getBreakpoint(options.width) === "compact" ? Math.max(HPAD_COMPACT_MIN2, Math.round(theme.spacing.padding * HPAD_COMPACT_FRACTION2)) : theme.spacing.padding;
|
|
18220
|
+
const chromeLayout = resolveChromeLayout(
|
|
18221
|
+
spec,
|
|
18222
|
+
options
|
|
18223
|
+
);
|
|
17929
18224
|
const fullArea = {
|
|
17930
18225
|
x: padding,
|
|
17931
18226
|
y: padding + chrome.topHeight,
|
|
17932
18227
|
width: options.width - padding * 2,
|
|
17933
|
-
height: options.height - chrome.topHeight - chrome.bottomHeight - padding * 2
|
|
18228
|
+
height: chromeLayout === "grow" ? options.height - padding * 2 : options.height - chrome.topHeight - chrome.bottomHeight - padding * 2
|
|
17934
18229
|
};
|
|
17935
18230
|
if (fullArea.width <= 0 || fullArea.height <= 0) {
|
|
17936
18231
|
return emptyLayout3(chrome, theme, options, watermark);
|
|
@@ -17941,11 +18236,13 @@ function compileMap(spec, options) {
|
|
|
17941
18236
|
const compileWarnings = [];
|
|
17942
18237
|
const showLegend = mapSpec.legend?.show !== false;
|
|
17943
18238
|
const colorEncoding = mapSpec.encoding.color;
|
|
18239
|
+
const showChoroplethLegend = showLegend && colorEncoding?.legend !== null;
|
|
17944
18240
|
const isQuantitative = colorEncoding?.type === "quantitative";
|
|
17945
18241
|
const legendPosition = mapSpec.legend?.position === "bottom" ? "bottom" : "top";
|
|
18242
|
+
const pointLegendOverlay = mapSpec.legend?.position === "top-left";
|
|
17946
18243
|
let legendBlockHeight = 0;
|
|
17947
18244
|
let continuousContent = null;
|
|
17948
|
-
if (
|
|
18245
|
+
if (showChoroplethLegend && colorEncoding && isQuantitative) {
|
|
17949
18246
|
const colorValues = [];
|
|
17950
18247
|
for (const row of mapSpec.data) {
|
|
17951
18248
|
const v = row[colorEncoding.field];
|
|
@@ -17968,11 +18265,11 @@ function compileMap(spec, options) {
|
|
|
17968
18265
|
const labelRowHeight = Math.ceil(theme.fonts.sizes.small * 1.3);
|
|
17969
18266
|
legendBlockHeight = continuousContent.barHeight + CONTINUOUS_LABEL_GAP + labelRowHeight;
|
|
17970
18267
|
}
|
|
17971
|
-
} else if (
|
|
18268
|
+
} else if (showChoroplethLegend && colorEncoding) {
|
|
17972
18269
|
const labelHeight = Math.ceil(theme.fonts.sizes.small * 1.3);
|
|
17973
18270
|
legendBlockHeight = Math.max(10, labelHeight) + 6;
|
|
17974
18271
|
}
|
|
17975
|
-
if (showLegend && mapSpec.points?.color) {
|
|
18272
|
+
if (showLegend && !pointLegendOverlay && mapSpec.points?.color) {
|
|
17976
18273
|
if (mapSpec.points.color.type === "quantitative") {
|
|
17977
18274
|
const labelRowHeight = Math.ceil(theme.fonts.sizes.small * 1.3);
|
|
17978
18275
|
legendBlockHeight += CONTINUOUS_BAR_HEIGHT + CONTINUOUS_LABEL_GAP + labelRowHeight + 8;
|
|
@@ -17987,7 +18284,18 @@ function compileMap(spec, options) {
|
|
|
17987
18284
|
return emptyLayout3(chrome, theme, options, watermark);
|
|
17988
18285
|
}
|
|
17989
18286
|
const projectionType = mapSpec.geo.projection;
|
|
17990
|
-
|
|
18287
|
+
let pointInset = 0;
|
|
18288
|
+
if (mapSpec.points) {
|
|
18289
|
+
const sizeRange = mapSpec.points.size?.scale?.range;
|
|
18290
|
+
pointInset = sizeRange ? sizeRange[1] : SIZE_SCALE_DEFAULTS.mapPoint.range[1];
|
|
18291
|
+
}
|
|
18292
|
+
const projection2 = createProjection(
|
|
18293
|
+
projectionType,
|
|
18294
|
+
fullArea.width,
|
|
18295
|
+
mapAreaHeight,
|
|
18296
|
+
geoCollection,
|
|
18297
|
+
pointInset
|
|
18298
|
+
);
|
|
17991
18299
|
const pathGen = path_default(projection2);
|
|
17992
18300
|
if (projectionType !== "identity") {
|
|
17993
18301
|
for (const feat of geoFeatures) {
|
|
@@ -18019,7 +18327,7 @@ function compileMap(spec, options) {
|
|
|
18019
18327
|
compileWarnings.push(...filteredJoinWarnings);
|
|
18020
18328
|
}
|
|
18021
18329
|
const droppedFeatures = [];
|
|
18022
|
-
const formatter = buildD3Formatter2(mapSpec.valueFormat) ?? formatNumber3;
|
|
18330
|
+
const formatter = buildD3Formatter2(mapSpec.encoding?.color?.format ?? mapSpec.valueFormat) ?? formatNumber3;
|
|
18023
18331
|
const neutralFill = isDarkMode ? "#2a2a2a" : "#e8e8e8";
|
|
18024
18332
|
const neutralStroke = isDarkMode ? "rgba(255,255,255,0.08)" : "rgba(0,0,0,0.06)";
|
|
18025
18333
|
let featureMarks;
|
|
@@ -18047,7 +18355,7 @@ function compileMap(spec, options) {
|
|
|
18047
18355
|
droppedFeatures
|
|
18048
18356
|
});
|
|
18049
18357
|
featureMarks = result.marks;
|
|
18050
|
-
if (
|
|
18358
|
+
if (showChoroplethLegend && continuousContent) {
|
|
18051
18359
|
const labelStyle = {
|
|
18052
18360
|
fontFamily: theme.fonts.family,
|
|
18053
18361
|
fontSize: theme.fonts.sizes.small,
|
|
@@ -18098,7 +18406,7 @@ function compileMap(spec, options) {
|
|
|
18098
18406
|
mapAreaHeight,
|
|
18099
18407
|
legendReserveGap,
|
|
18100
18408
|
legendPosition,
|
|
18101
|
-
showLegend,
|
|
18409
|
+
showLegend: showChoroplethLegend,
|
|
18102
18410
|
droppedFeatures
|
|
18103
18411
|
});
|
|
18104
18412
|
featureMarks = result.marks;
|
|
@@ -18242,15 +18550,15 @@ function compileMap(spec, options) {
|
|
|
18242
18550
|
}));
|
|
18243
18551
|
const bottomChoroplethHeight = legendPosition === "bottom" ? continuousLegend?.bounds.height ?? categoricalLegend?.bounds.height ?? 0 : 0;
|
|
18244
18552
|
const choroplethLegendGap = bottomChoroplethHeight > 0 ? 8 : 0;
|
|
18245
|
-
const legendX = fullArea.x;
|
|
18246
|
-
const legendY = fullArea.y + mapAreaHeight + legendReserveGap + bottomChoroplethHeight + choroplethLegendGap;
|
|
18247
|
-
const legendWidth = fullArea.width;
|
|
18553
|
+
const legendX = pointLegendOverlay ? fullArea.x + OVERLAY_LEGEND_INSET : fullArea.x;
|
|
18554
|
+
const legendY = pointLegendOverlay ? fullArea.y + OVERLAY_LEGEND_INSET : fullArea.y + mapAreaHeight + legendReserveGap + bottomChoroplethHeight + choroplethLegendGap;
|
|
18555
|
+
const legendWidth = pointLegendOverlay ? fullArea.width - OVERLAY_LEGEND_INSET * 2 : fullArea.width;
|
|
18248
18556
|
const swatchSize = 10;
|
|
18249
18557
|
const swatchGap = 6;
|
|
18250
18558
|
const entryGap = 16;
|
|
18251
18559
|
pointCategoricalLegend = {
|
|
18252
18560
|
type: "categorical",
|
|
18253
|
-
position: "bottom",
|
|
18561
|
+
position: pointLegendOverlay ? "top-left" : "bottom",
|
|
18254
18562
|
bounds: { x: legendX, y: legendY, width: legendWidth, height: swatchSize + 6 },
|
|
18255
18563
|
labelStyle,
|
|
18256
18564
|
entries,
|
|
@@ -18290,8 +18598,8 @@ function compileMap(spec, options) {
|
|
|
18290
18598
|
};
|
|
18291
18599
|
const bottomChoroplethH = legendPosition === "bottom" ? continuousLegend?.bounds.height ?? categoricalLegend?.bounds.height ?? 0 : 0;
|
|
18292
18600
|
const choroplethLegendGap = bottomChoroplethH > 0 ? 8 : 0;
|
|
18293
|
-
const legendX = fullArea.x;
|
|
18294
|
-
const legendY = fullArea.y + mapAreaHeight + legendReserveGap + bottomChoroplethH + choroplethLegendGap;
|
|
18601
|
+
const legendX = pointLegendOverlay ? fullArea.x + OVERLAY_LEGEND_INSET : fullArea.x;
|
|
18602
|
+
const legendY = pointLegendOverlay ? fullArea.y + OVERLAY_LEGEND_INSET : fullArea.y + mapAreaHeight + legendReserveGap + bottomChoroplethH + choroplethLegendGap;
|
|
18295
18603
|
const ptLabelRowHeight = Math.ceil(theme.fonts.sizes.small * 1.3);
|
|
18296
18604
|
const ptLegendHeight = ptContinuousContent.barHeight + CONTINUOUS_LABEL_GAP + ptLabelRowHeight;
|
|
18297
18605
|
const bounds = {
|
|
@@ -18309,7 +18617,7 @@ function compileMap(spec, options) {
|
|
|
18309
18617
|
pointContinuousLegend = {
|
|
18310
18618
|
type: "continuous",
|
|
18311
18619
|
mode: ptContinuousContent.mode,
|
|
18312
|
-
position: "bottom",
|
|
18620
|
+
position: pointLegendOverlay ? "top-left" : "bottom",
|
|
18313
18621
|
bounds,
|
|
18314
18622
|
labelStyle,
|
|
18315
18623
|
bar,
|
|
@@ -18814,6 +19122,65 @@ import {
|
|
|
18814
19122
|
resolveTheme as resolveTheme4
|
|
18815
19123
|
} from "@opendata-ai/openchart-core";
|
|
18816
19124
|
|
|
19125
|
+
// src/graphs/animation.ts
|
|
19126
|
+
var ENTER_DEFAULT = {
|
|
19127
|
+
duration: 500,
|
|
19128
|
+
ease: "smooth",
|
|
19129
|
+
stagger: true,
|
|
19130
|
+
cameraFit: true
|
|
19131
|
+
};
|
|
19132
|
+
var UPDATE_DEFAULT = { duration: 300, ease: "smooth" };
|
|
19133
|
+
var EXIT_DEFAULT = { duration: 300, ease: "smooth" };
|
|
19134
|
+
var CAMERA_DEFAULT = { duration: "auto", ease: "smooth" };
|
|
19135
|
+
var HOVER_DEFAULT = { duration: 150, ease: "smooth" };
|
|
19136
|
+
function fullDefaults() {
|
|
19137
|
+
return {
|
|
19138
|
+
enter: { ...ENTER_DEFAULT },
|
|
19139
|
+
update: { ...UPDATE_DEFAULT },
|
|
19140
|
+
exit: { ...EXIT_DEFAULT },
|
|
19141
|
+
camera: { ...CAMERA_DEFAULT },
|
|
19142
|
+
hover: { ...HOVER_DEFAULT }
|
|
19143
|
+
};
|
|
19144
|
+
}
|
|
19145
|
+
function resolveGraphAnimation(spec) {
|
|
19146
|
+
if (spec === void 0 || spec === true) return fullDefaults();
|
|
19147
|
+
if (spec === false) return void 0;
|
|
19148
|
+
return {
|
|
19149
|
+
enter: resolveEnter(spec.enter),
|
|
19150
|
+
update: resolveDurationPhase(spec.update, UPDATE_DEFAULT),
|
|
19151
|
+
exit: resolveDurationPhase(spec.exit, EXIT_DEFAULT),
|
|
19152
|
+
camera: resolveCamera(spec.camera),
|
|
19153
|
+
hover: resolveDurationPhase(spec.hover, HOVER_DEFAULT)
|
|
19154
|
+
};
|
|
19155
|
+
}
|
|
19156
|
+
function resolveEnter(phase) {
|
|
19157
|
+
if (phase === false) return null;
|
|
19158
|
+
if (phase === void 0 || phase === true) return { ...ENTER_DEFAULT };
|
|
19159
|
+
return {
|
|
19160
|
+
duration: phase.duration ?? ENTER_DEFAULT.duration,
|
|
19161
|
+
ease: phase.ease ?? ENTER_DEFAULT.ease,
|
|
19162
|
+
stagger: phase.stagger !== false,
|
|
19163
|
+
cameraFit: ENTER_DEFAULT.cameraFit
|
|
19164
|
+
};
|
|
19165
|
+
}
|
|
19166
|
+
function resolveDurationPhase(phase, defaults) {
|
|
19167
|
+
if (phase === false) return null;
|
|
19168
|
+
if (phase === void 0 || phase === true)
|
|
19169
|
+
return { duration: defaults.duration, ease: defaults.ease };
|
|
19170
|
+
return {
|
|
19171
|
+
duration: phase.duration ?? defaults.duration,
|
|
19172
|
+
ease: phase.ease ?? defaults.ease
|
|
19173
|
+
};
|
|
19174
|
+
}
|
|
19175
|
+
function resolveCamera(phase) {
|
|
19176
|
+
if (phase === false) return null;
|
|
19177
|
+
if (phase === void 0 || phase === true) return { ...CAMERA_DEFAULT };
|
|
19178
|
+
return {
|
|
19179
|
+
duration: phase.duration ?? CAMERA_DEFAULT.duration,
|
|
19180
|
+
ease: phase.ease ?? CAMERA_DEFAULT.ease
|
|
19181
|
+
};
|
|
19182
|
+
}
|
|
19183
|
+
|
|
18817
19184
|
// src/graphs/encoding.ts
|
|
18818
19185
|
var DEFAULT_NODE_RADIUS = 5;
|
|
18819
19186
|
var MIN_NODE_RADIUS = 3;
|
|
@@ -18853,16 +19220,42 @@ function computeDegrees(nodes, edges) {
|
|
|
18853
19220
|
}
|
|
18854
19221
|
return degrees2;
|
|
18855
19222
|
}
|
|
19223
|
+
function resolveCategoricalDomain(values, sort, scaleDomain) {
|
|
19224
|
+
if (Array.isArray(scaleDomain) && scaleDomain.length > 0) {
|
|
19225
|
+
return scaleDomain.map((v) => String(v));
|
|
19226
|
+
}
|
|
19227
|
+
const seen = [];
|
|
19228
|
+
const set = /* @__PURE__ */ new Set();
|
|
19229
|
+
for (const v of values) {
|
|
19230
|
+
if (!set.has(v)) {
|
|
19231
|
+
set.add(v);
|
|
19232
|
+
seen.push(v);
|
|
19233
|
+
}
|
|
19234
|
+
}
|
|
19235
|
+
if (sort === null) return seen;
|
|
19236
|
+
if (Array.isArray(sort)) {
|
|
19237
|
+
const pinned = sort.filter((v) => set.has(v));
|
|
19238
|
+
const pinnedSet = new Set(pinned);
|
|
19239
|
+
const rest = seen.filter((v) => !pinnedSet.has(v));
|
|
19240
|
+
return [...pinned, ...rest];
|
|
19241
|
+
}
|
|
19242
|
+
const sorted = [...seen].sort((a, b) => a.localeCompare(b));
|
|
19243
|
+
return sort === "descending" ? sorted.reverse() : sorted;
|
|
19244
|
+
}
|
|
18856
19245
|
function resolveNodeVisuals(nodes, encoding, edges, theme, nodeOverrides) {
|
|
18857
19246
|
const degrees2 = computeDegrees(nodes, edges);
|
|
18858
19247
|
const maxDegree = Math.max(1, ...degrees2.values());
|
|
18859
19248
|
let sizeScale;
|
|
18860
19249
|
if (encoding.nodeSize?.field) {
|
|
18861
19250
|
const field = encoding.nodeSize.field;
|
|
19251
|
+
const scaleConfig = encoding.nodeSize.scale;
|
|
18862
19252
|
const values = nodes.map((n) => Number(n[field])).filter((v) => Number.isFinite(v));
|
|
18863
19253
|
const sizeMin = min(values) ?? 0;
|
|
18864
19254
|
const sizeMax = max(values) ?? 1;
|
|
18865
|
-
|
|
19255
|
+
const domain = scaleConfig?.domain && scaleConfig.domain.length === 2 ? scaleConfig.domain : [sizeMin, sizeMax];
|
|
19256
|
+
const range3 = scaleConfig?.range && scaleConfig.range.length >= 2 ? [Number(scaleConfig.range[0]), Number(scaleConfig.range[1])] : [MIN_NODE_RADIUS, MAX_NODE_RADIUS];
|
|
19257
|
+
const ctor = scaleConfig?.type === "linear" ? linear2 : sqrt;
|
|
19258
|
+
sizeScale = ctor().domain(domain).range(range3);
|
|
18866
19259
|
}
|
|
18867
19260
|
let colorFn;
|
|
18868
19261
|
if (encoding.nodeColor?.field) {
|
|
@@ -18883,13 +19276,39 @@ function resolveNodeVisuals(nodes, encoding, edges, theme, nodeOverrides) {
|
|
|
18883
19276
|
return Number.isFinite(val) ? colorScale(val) : theme.colors.categorical[0];
|
|
18884
19277
|
};
|
|
18885
19278
|
} else {
|
|
18886
|
-
const domain =
|
|
19279
|
+
const domain = resolveCategoricalDomain(
|
|
19280
|
+
nodes.map((n) => String(n[field] ?? "")),
|
|
19281
|
+
encoding.nodeColor.sort,
|
|
19282
|
+
scaleConfig?.domain
|
|
19283
|
+
);
|
|
18887
19284
|
const range3 = scaleConfig?.range && scaleConfig.range.length > 0 ? scaleConfig.range : theme.colors.categorical;
|
|
18888
19285
|
const ordinalScale = ordinal().domain(domain).range(range3);
|
|
18889
19286
|
colorFn = (node) => ordinalScale(String(node[field] ?? ""));
|
|
18890
19287
|
}
|
|
18891
19288
|
}
|
|
18892
19289
|
const defaultColor = theme.colors.categorical[0];
|
|
19290
|
+
let opacityScale;
|
|
19291
|
+
if (encoding.nodeOpacity?.field) {
|
|
19292
|
+
const field = encoding.nodeOpacity.field;
|
|
19293
|
+
const scaleConfig = encoding.nodeOpacity.scale;
|
|
19294
|
+
const values = nodes.map((n) => Number(n[field])).filter((v) => Number.isFinite(v));
|
|
19295
|
+
const opMin = min(values) ?? 0;
|
|
19296
|
+
const opMax = max(values) ?? 1;
|
|
19297
|
+
const domain = scaleConfig?.domain && scaleConfig.domain.length === 2 ? scaleConfig.domain : [opMin, opMax];
|
|
19298
|
+
const range3 = scaleConfig?.range && scaleConfig.range.length >= 2 ? [Number(scaleConfig.range[0]), Number(scaleConfig.range[1])] : [0.25, 1];
|
|
19299
|
+
opacityScale = linear2().domain(domain).range(range3);
|
|
19300
|
+
}
|
|
19301
|
+
let labelPriorityScale;
|
|
19302
|
+
if (encoding.nodeLabelPriority?.field) {
|
|
19303
|
+
const field = encoding.nodeLabelPriority.field;
|
|
19304
|
+
const scaleConfig = encoding.nodeLabelPriority.scale;
|
|
19305
|
+
const values = nodes.map((n) => Number(n[field])).filter((v) => Number.isFinite(v));
|
|
19306
|
+
const lpMin = min(values) ?? 0;
|
|
19307
|
+
const lpMax = max(values) ?? 1;
|
|
19308
|
+
const domain = scaleConfig?.domain && scaleConfig.domain.length === 2 ? scaleConfig.domain : [lpMin, lpMax];
|
|
19309
|
+
const range3 = scaleConfig?.range && scaleConfig.range.length >= 2 ? [Number(scaleConfig.range[0]), Number(scaleConfig.range[1])] : [0, 1];
|
|
19310
|
+
labelPriorityScale = linear2().domain(domain).range(range3);
|
|
19311
|
+
}
|
|
18893
19312
|
return nodes.map((node) => {
|
|
18894
19313
|
let radius = DEFAULT_NODE_RADIUS;
|
|
18895
19314
|
if (sizeScale && encoding.nodeSize?.field) {
|
|
@@ -18898,6 +19317,13 @@ function resolveNodeVisuals(nodes, encoding, edges, theme, nodeOverrides) {
|
|
|
18898
19317
|
radius = sizeScale(val);
|
|
18899
19318
|
}
|
|
18900
19319
|
}
|
|
19320
|
+
let opacity = 1;
|
|
19321
|
+
if (opacityScale && encoding.nodeOpacity?.field) {
|
|
19322
|
+
const val = Number(node[encoding.nodeOpacity.field]);
|
|
19323
|
+
if (Number.isFinite(val)) {
|
|
19324
|
+
opacity = opacityScale(val);
|
|
19325
|
+
}
|
|
19326
|
+
}
|
|
18901
19327
|
const fill = colorFn ? colorFn(node) : defaultColor;
|
|
18902
19328
|
const stroke = darkenColor(fill);
|
|
18903
19329
|
let label;
|
|
@@ -18907,8 +19333,14 @@ function resolveNodeVisuals(nodes, encoding, edges, theme, nodeOverrides) {
|
|
|
18907
19333
|
} else {
|
|
18908
19334
|
label = node.id;
|
|
18909
19335
|
}
|
|
18910
|
-
|
|
18911
|
-
|
|
19336
|
+
let labelPriority;
|
|
19337
|
+
if (labelPriorityScale && encoding.nodeLabelPriority?.field) {
|
|
19338
|
+
const val = Number(node[encoding.nodeLabelPriority.field]);
|
|
19339
|
+
labelPriority = Number.isFinite(val) ? labelPriorityScale(val) : 0;
|
|
19340
|
+
} else {
|
|
19341
|
+
const degree = degrees2.get(node.id) ?? 0;
|
|
19342
|
+
labelPriority = maxDegree > 0 ? degree / maxDegree : 0;
|
|
19343
|
+
}
|
|
18912
19344
|
const { id: _id, ...rest } = node;
|
|
18913
19345
|
const data = { id: node.id, ...rest };
|
|
18914
19346
|
const override = nodeOverrides?.[node.id];
|
|
@@ -18926,6 +19358,7 @@ function resolveNodeVisuals(nodes, encoding, edges, theme, nodeOverrides) {
|
|
|
18926
19358
|
label,
|
|
18927
19359
|
labelPriority: finalLabelPriority,
|
|
18928
19360
|
community: void 0,
|
|
19361
|
+
opacity,
|
|
18929
19362
|
data
|
|
18930
19363
|
};
|
|
18931
19364
|
});
|
|
@@ -18958,7 +19391,11 @@ function resolveEdgeVisuals(edges, encoding, theme) {
|
|
|
18958
19391
|
return Number.isFinite(val) ? colorScale(val) : hexWithOpacity(theme.colors.axis, 0.4);
|
|
18959
19392
|
};
|
|
18960
19393
|
} else {
|
|
18961
|
-
const domain =
|
|
19394
|
+
const domain = resolveCategoricalDomain(
|
|
19395
|
+
edges.map((e) => String(e[field] ?? "")),
|
|
19396
|
+
encoding.edgeColor.sort,
|
|
19397
|
+
scaleConfig?.domain
|
|
19398
|
+
);
|
|
18962
19399
|
const range3 = scaleConfig?.range && scaleConfig.range.length > 0 ? scaleConfig.range : theme.colors.categorical;
|
|
18963
19400
|
const ordinalScale = ordinal().domain(domain).range(range3);
|
|
18964
19401
|
edgeColorFn = (edge) => ordinalScale(String(edge[field] ?? ""));
|
|
@@ -18969,10 +19406,14 @@ function resolveEdgeVisuals(edges, encoding, theme) {
|
|
|
18969
19406
|
let styleFn;
|
|
18970
19407
|
if (encoding.edgeStyle?.field) {
|
|
18971
19408
|
const field = encoding.edgeStyle.field;
|
|
18972
|
-
const
|
|
19409
|
+
const domain = resolveCategoricalDomain(
|
|
19410
|
+
edges.map((e) => String(e[field] ?? "")),
|
|
19411
|
+
encoding.edgeStyle.sort,
|
|
19412
|
+
encoding.edgeStyle.scale?.domain
|
|
19413
|
+
);
|
|
18973
19414
|
const styleMap = /* @__PURE__ */ new Map();
|
|
18974
|
-
for (let i = 0; i <
|
|
18975
|
-
styleMap.set(
|
|
19415
|
+
for (let i = 0; i < domain.length; i++) {
|
|
19416
|
+
styleMap.set(domain[i], EDGE_STYLES[i % EDGE_STYLES.length]);
|
|
18976
19417
|
}
|
|
18977
19418
|
styleFn = (edge) => styleMap.get(String(edge[field] ?? "")) ?? "solid";
|
|
18978
19419
|
}
|
|
@@ -19030,12 +19471,49 @@ function applyCommunityColors(nodes, colorMap) {
|
|
|
19030
19471
|
}
|
|
19031
19472
|
}
|
|
19032
19473
|
|
|
19474
|
+
// src/graphs/interaction.ts
|
|
19475
|
+
var DEFAULT_DIM_OPACITY = 0.15;
|
|
19476
|
+
var DEFAULT_CURSOR_RADIUS = 80;
|
|
19477
|
+
var DEFAULT_CURSOR_STRENGTH = 30;
|
|
19478
|
+
function resolveGraphInteraction(cfg) {
|
|
19479
|
+
const hover = cfg?.hover;
|
|
19480
|
+
const cursor = cfg?.cursorRepulsion;
|
|
19481
|
+
let cursorRepulsion = null;
|
|
19482
|
+
if (cursor === true) {
|
|
19483
|
+
cursorRepulsion = { radius: DEFAULT_CURSOR_RADIUS, strength: DEFAULT_CURSOR_STRENGTH };
|
|
19484
|
+
} else if (cursor && typeof cursor === "object") {
|
|
19485
|
+
cursorRepulsion = {
|
|
19486
|
+
radius: cursor.radius ?? DEFAULT_CURSOR_RADIUS,
|
|
19487
|
+
strength: cursor.strength ?? DEFAULT_CURSOR_STRENGTH
|
|
19488
|
+
};
|
|
19489
|
+
}
|
|
19490
|
+
return {
|
|
19491
|
+
hoverMode: hover?.mode ?? "neighbors",
|
|
19492
|
+
dimOpacity: hover?.dimOpacity ?? DEFAULT_DIM_OPACITY,
|
|
19493
|
+
selectFlyTo: cfg?.select?.flyTo ?? false,
|
|
19494
|
+
cursorRepulsion,
|
|
19495
|
+
springyDrag: cfg?.springyDrag ?? false
|
|
19496
|
+
};
|
|
19497
|
+
}
|
|
19498
|
+
|
|
19033
19499
|
// src/graphs/compile-graph.ts
|
|
19034
19500
|
var graphNumberFormatter = defaultNumberFormatter8({ allIntegers: false, surface: "chart" });
|
|
19035
19501
|
var SWATCH_SIZE2 = 12;
|
|
19036
19502
|
var SWATCH_GAP2 = 6;
|
|
19037
19503
|
var ENTRY_GAP2 = 16;
|
|
19038
|
-
|
|
19504
|
+
var ENERGY_PRESETS = {
|
|
19505
|
+
gentle: { chargeStrength: -150, velocityDecay: 0.5 },
|
|
19506
|
+
balanced: { chargeStrength: -300, velocityDecay: 0.4 },
|
|
19507
|
+
energetic: { chargeStrength: -600, velocityDecay: 0.3 }
|
|
19508
|
+
};
|
|
19509
|
+
var SETTLE_PRESETS = {
|
|
19510
|
+
quick: 0.05,
|
|
19511
|
+
balanced: 0.0228,
|
|
19512
|
+
thorough: 0.01
|
|
19513
|
+
};
|
|
19514
|
+
var DEFAULT_WARMUP_TICKS = 100;
|
|
19515
|
+
var DEFAULT_WARMUP_BUDGET_MS = 250;
|
|
19516
|
+
function buildGraphLegend(nodes, communityColorMap, hasCommunities, theme, nodeColorField, legendOrder) {
|
|
19039
19517
|
const labelStyle = {
|
|
19040
19518
|
fontFamily: theme.fonts.family,
|
|
19041
19519
|
fontSize: theme.fonts.sizes.small,
|
|
@@ -19045,25 +19523,35 @@ function buildGraphLegend(nodes, communityColorMap, hasCommunities, theme, nodeC
|
|
|
19045
19523
|
};
|
|
19046
19524
|
let entries;
|
|
19047
19525
|
if (hasCommunities && communityColorMap.size > 0) {
|
|
19526
|
+
const counts = /* @__PURE__ */ new Map();
|
|
19527
|
+
for (const node of nodes) {
|
|
19528
|
+
if (node.community != null) {
|
|
19529
|
+
counts.set(node.community, (counts.get(node.community) ?? 0) + 1);
|
|
19530
|
+
}
|
|
19531
|
+
}
|
|
19048
19532
|
entries = [...communityColorMap.entries()].map(([label, color2]) => ({
|
|
19049
19533
|
label,
|
|
19050
19534
|
color: color2,
|
|
19051
19535
|
shape: "circle",
|
|
19052
|
-
active: true
|
|
19536
|
+
active: true,
|
|
19537
|
+
count: counts.get(label) ?? 0
|
|
19053
19538
|
}));
|
|
19054
19539
|
} else if (nodeColorField) {
|
|
19055
19540
|
const categoryColors = /* @__PURE__ */ new Map();
|
|
19541
|
+
const categoryCounts = /* @__PURE__ */ new Map();
|
|
19056
19542
|
for (const node of nodes) {
|
|
19057
19543
|
const category = String(node.data[nodeColorField] ?? node.label ?? node.id);
|
|
19058
19544
|
if (!categoryColors.has(category)) {
|
|
19059
19545
|
categoryColors.set(category, node.fill);
|
|
19060
19546
|
}
|
|
19547
|
+
categoryCounts.set(category, (categoryCounts.get(category) ?? 0) + 1);
|
|
19061
19548
|
}
|
|
19062
|
-
entries = categoryColors.size <= 1 ? [] : [...categoryColors.
|
|
19549
|
+
entries = categoryColors.size <= 1 ? [] : (legendOrder ?? [...categoryColors.keys()]).filter((label) => categoryColors.has(label)).map((label) => ({
|
|
19063
19550
|
label,
|
|
19064
|
-
color:
|
|
19551
|
+
color: categoryColors.get(label),
|
|
19065
19552
|
shape: "circle",
|
|
19066
|
-
active: true
|
|
19553
|
+
active: true,
|
|
19554
|
+
count: categoryCounts.get(label) ?? 0
|
|
19067
19555
|
}));
|
|
19068
19556
|
} else {
|
|
19069
19557
|
entries = [];
|
|
@@ -19079,6 +19567,30 @@ function buildGraphLegend(nodes, communityColorMap, hasCommunities, theme, nodeC
|
|
|
19079
19567
|
swatchChipFill: theme.colors.annotationFill
|
|
19080
19568
|
};
|
|
19081
19569
|
}
|
|
19570
|
+
function buildEdgeLegend(edges, encoding) {
|
|
19571
|
+
const field = encoding.edgeColor?.field;
|
|
19572
|
+
if (!field || (encoding.edgeColor?.type ?? "nominal") === "quantitative") return void 0;
|
|
19573
|
+
const categoryColors = /* @__PURE__ */ new Map();
|
|
19574
|
+
const categoryCounts = /* @__PURE__ */ new Map();
|
|
19575
|
+
for (const edge of edges) {
|
|
19576
|
+
const category = String(edge.data[field] ?? "");
|
|
19577
|
+
if (!categoryColors.has(category)) categoryColors.set(category, edge.stroke);
|
|
19578
|
+
categoryCounts.set(category, (categoryCounts.get(category) ?? 0) + 1);
|
|
19579
|
+
}
|
|
19580
|
+
if (categoryColors.size <= 1) return void 0;
|
|
19581
|
+
const order = resolveCategoricalDomain(
|
|
19582
|
+
edges.map((e) => String(e.data[field] ?? "")),
|
|
19583
|
+
encoding.edgeColor?.sort,
|
|
19584
|
+
encoding.edgeColor?.scale?.domain
|
|
19585
|
+
);
|
|
19586
|
+
return order.filter((label) => categoryColors.has(label)).map((label) => ({
|
|
19587
|
+
label,
|
|
19588
|
+
color: categoryColors.get(label),
|
|
19589
|
+
shape: "line",
|
|
19590
|
+
active: true,
|
|
19591
|
+
count: categoryCounts.get(label) ?? 0
|
|
19592
|
+
}));
|
|
19593
|
+
}
|
|
19082
19594
|
function buildGraphTooltips(nodes) {
|
|
19083
19595
|
const descriptors = /* @__PURE__ */ new Map();
|
|
19084
19596
|
for (const node of nodes) {
|
|
@@ -19105,6 +19617,21 @@ function buildGraphTooltips(nodes) {
|
|
|
19105
19617
|
}
|
|
19106
19618
|
return descriptors;
|
|
19107
19619
|
}
|
|
19620
|
+
function buildEdgeTooltip(edge) {
|
|
19621
|
+
const fields = [];
|
|
19622
|
+
for (const [key, value2] of Object.entries(edge.data)) {
|
|
19623
|
+
if (key === "source" || key === "target") continue;
|
|
19624
|
+
if (value2 == null) continue;
|
|
19625
|
+
fields.push({
|
|
19626
|
+
label: key,
|
|
19627
|
+
value: typeof value2 === "number" ? graphNumberFormatter(value2) : String(value2)
|
|
19628
|
+
});
|
|
19629
|
+
}
|
|
19630
|
+
return {
|
|
19631
|
+
title: `${edge.source} \u2192 ${edge.target}`,
|
|
19632
|
+
fields
|
|
19633
|
+
};
|
|
19634
|
+
}
|
|
19108
19635
|
function compileGraph(spec, options) {
|
|
19109
19636
|
const { spec: normalized, warnings } = compile(spec);
|
|
19110
19637
|
emitSpecWarnings(warnings, options.onWarn);
|
|
@@ -19114,6 +19641,16 @@ function compileGraph(spec, options) {
|
|
|
19114
19641
|
);
|
|
19115
19642
|
}
|
|
19116
19643
|
const graphSpec = normalized;
|
|
19644
|
+
for (const [name, ch] of [
|
|
19645
|
+
["nodeColor", graphSpec.encoding.nodeColor],
|
|
19646
|
+
["edgeColor", graphSpec.encoding.edgeColor]
|
|
19647
|
+
]) {
|
|
19648
|
+
if (ch?.sort != null && ch.type === "quantitative") {
|
|
19649
|
+
options.onWarn?.(
|
|
19650
|
+
`encoding.${name}.sort is ignored for a quantitative field (sort only orders categorical domains).`
|
|
19651
|
+
);
|
|
19652
|
+
}
|
|
19653
|
+
}
|
|
19117
19654
|
const rawWatermark = spec.watermark;
|
|
19118
19655
|
const watermark = rawWatermark !== void 0 ? graphSpec.watermark : options.watermark ?? true;
|
|
19119
19656
|
const mergedThemeConfig = options.theme ? { ...graphSpec.theme, ...options.theme } : graphSpec.theme;
|
|
@@ -19139,13 +19676,30 @@ function compileGraph(spec, options) {
|
|
|
19139
19676
|
}
|
|
19140
19677
|
const compiledEdges = resolveEdgeVisuals(graphSpec.edges, graphSpec.encoding, theme);
|
|
19141
19678
|
const useCommunitiesForLegend = hasCommunities && !hasNodeColorEncoding;
|
|
19679
|
+
const nodeColorField = graphSpec.encoding.nodeColor?.field;
|
|
19680
|
+
const legendOrder = nodeColorField ? resolveCategoricalDomain(
|
|
19681
|
+
compiledNodes.map((n) => String(n.data[nodeColorField] ?? n.label ?? n.id)),
|
|
19682
|
+
graphSpec.encoding.nodeColor?.sort,
|
|
19683
|
+
graphSpec.encoding.nodeColor?.scale?.domain
|
|
19684
|
+
) : void 0;
|
|
19142
19685
|
const legend = buildGraphLegend(
|
|
19143
19686
|
compiledNodes,
|
|
19144
19687
|
communityColorMap,
|
|
19145
19688
|
useCommunitiesForLegend,
|
|
19146
19689
|
theme,
|
|
19147
|
-
|
|
19690
|
+
nodeColorField,
|
|
19691
|
+
legendOrder
|
|
19148
19692
|
);
|
|
19693
|
+
const edgeLegend = buildEdgeLegend(compiledEdges, graphSpec.encoding);
|
|
19694
|
+
const legendField = nodeColorField ?? (useCommunitiesForLegend ? clusteringField ?? null : null);
|
|
19695
|
+
let initialHighlight;
|
|
19696
|
+
if (nodeColorField && graphSpec.encoding.nodeColor?.highlight != null) {
|
|
19697
|
+
const raw = graphSpec.encoding.nodeColor.highlight;
|
|
19698
|
+
const requested = Array.isArray(raw) ? raw : [raw];
|
|
19699
|
+
const available = new Set(legendOrder ?? []);
|
|
19700
|
+
const values = requested.filter((v) => available.has(v));
|
|
19701
|
+
if (values.length > 0) initialHighlight = { field: nodeColorField, values };
|
|
19702
|
+
}
|
|
19149
19703
|
const tooltipDescriptors = buildGraphTooltips(compiledNodes);
|
|
19150
19704
|
const communityCount = communityColorMap.size;
|
|
19151
19705
|
const altParts = [
|
|
@@ -19162,17 +19716,26 @@ function compileGraph(spec, options) {
|
|
|
19162
19716
|
};
|
|
19163
19717
|
const collisionPadding = graphSpec.layout.collisionPadding ?? 2;
|
|
19164
19718
|
const maxRadius = compiledNodes.length > 0 ? Math.max(...compiledNodes.map((n) => n.radius)) : DEFAULT_COLLISION_PADDING;
|
|
19719
|
+
const energyPreset = graphSpec.layout.energy ? ENERGY_PRESETS[graphSpec.layout.energy] : ENERGY_PRESETS.balanced;
|
|
19720
|
+
const settlePreset = graphSpec.layout.settle ? SETTLE_PRESETS[graphSpec.layout.settle] : SETTLE_PRESETS.balanced;
|
|
19721
|
+
const warmupRaw = graphSpec.layout.warmup;
|
|
19722
|
+
const warmupTicks = warmupRaw === false ? 0 : typeof warmupRaw === "number" ? Math.max(0, Math.floor(warmupRaw)) : DEFAULT_WARMUP_TICKS;
|
|
19165
19723
|
const simulationConfig = {
|
|
19166
|
-
chargeStrength: graphSpec.layout.chargeStrength ??
|
|
19724
|
+
chargeStrength: graphSpec.layout.chargeStrength ?? energyPreset.chargeStrength,
|
|
19167
19725
|
linkDistance: graphSpec.layout.linkDistance ?? 30,
|
|
19168
19726
|
clustering: clusteringField ? { field: clusteringField, strength: 0.5 } : null,
|
|
19169
|
-
alphaDecay:
|
|
19170
|
-
velocityDecay:
|
|
19727
|
+
alphaDecay: settlePreset,
|
|
19728
|
+
velocityDecay: energyPreset.velocityDecay,
|
|
19171
19729
|
collisionRadius: maxRadius + collisionPadding,
|
|
19172
19730
|
collisionPadding,
|
|
19173
19731
|
linkStrength: graphSpec.layout.linkStrength,
|
|
19174
|
-
centerForce: graphSpec.layout.centerForce
|
|
19732
|
+
centerForce: graphSpec.layout.centerForce,
|
|
19733
|
+
seed: graphSpec.layout.seed,
|
|
19734
|
+
warmupTicks,
|
|
19735
|
+
warmupBudgetMs: DEFAULT_WARMUP_BUDGET_MS
|
|
19175
19736
|
};
|
|
19737
|
+
const animation = resolveGraphAnimation(graphSpec.animation);
|
|
19738
|
+
const interaction = resolveGraphInteraction(graphSpec.interaction);
|
|
19176
19739
|
const chrome = computeChrome4(
|
|
19177
19740
|
{
|
|
19178
19741
|
title: graphSpec.chrome.title,
|
|
@@ -19201,7 +19764,12 @@ function compileGraph(spec, options) {
|
|
|
19201
19764
|
height: options.height
|
|
19202
19765
|
},
|
|
19203
19766
|
simulationConfig,
|
|
19204
|
-
watermark
|
|
19767
|
+
watermark,
|
|
19768
|
+
animation,
|
|
19769
|
+
interaction,
|
|
19770
|
+
legendField,
|
|
19771
|
+
initialHighlight,
|
|
19772
|
+
edgeLegend
|
|
19205
19773
|
};
|
|
19206
19774
|
}
|
|
19207
19775
|
var DEFAULT_COLLISION_PADDING = 5;
|
|
@@ -19294,6 +19862,7 @@ function legendLayoutHasContent(legendLayout) {
|
|
|
19294
19862
|
}
|
|
19295
19863
|
var MIN_CHART_WIDTH = 60;
|
|
19296
19864
|
var MIN_CHART_HEIGHT2 = 40;
|
|
19865
|
+
var PLOT_SHARE_MAX = 0.4;
|
|
19297
19866
|
var SERIES_SEARCH_INPUT_HEIGHT = 32;
|
|
19298
19867
|
var SERIES_SEARCH_GAP = 12;
|
|
19299
19868
|
function getMinChartDims(display) {
|
|
@@ -19336,8 +19905,10 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
|
|
|
19336
19905
|
watermark,
|
|
19337
19906
|
bottomLegendReservation
|
|
19338
19907
|
);
|
|
19908
|
+
const chromeLayout = resolveChromeLayout(spec, options);
|
|
19909
|
+
const effectiveHeight = chromeLayout === "grow" ? height + chrome.topHeight + chrome.bottomHeight : height;
|
|
19339
19910
|
if (isSparkline) {
|
|
19340
|
-
const total2 = { x: 0, y: 0, width, height };
|
|
19911
|
+
const total2 = { x: 0, y: 0, width, height: effectiveHeight };
|
|
19341
19912
|
const sparkPad = getSparklinePad(spec);
|
|
19342
19913
|
const xAxisSpace = userExplicit.xAxis ? 26 : 0;
|
|
19343
19914
|
const yAxisSpace = userExplicit.yAxis ? 30 : 0;
|
|
@@ -19361,7 +19932,7 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
|
|
|
19361
19932
|
x: margins2.left,
|
|
19362
19933
|
y: margins2.top,
|
|
19363
19934
|
width: Math.max(0, width - margins2.left - margins2.right),
|
|
19364
|
-
height: Math.max(0,
|
|
19935
|
+
height: Math.max(0, effectiveHeight - margins2.top - margins2.bottom)
|
|
19365
19936
|
};
|
|
19366
19937
|
return {
|
|
19367
19938
|
total: total2,
|
|
@@ -19373,7 +19944,7 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
|
|
|
19373
19944
|
effectiveAxisGap: 0
|
|
19374
19945
|
};
|
|
19375
19946
|
}
|
|
19376
|
-
const total = { x: 0, y: 0, width, height };
|
|
19947
|
+
const total = { x: 0, y: 0, width, height: effectiveHeight };
|
|
19377
19948
|
const isRadial = isAxislessMark2(spec.markType);
|
|
19378
19949
|
const encoding = spec.encoding;
|
|
19379
19950
|
const xAxisSuppressed = encoding.x?.axis === false;
|
|
@@ -19603,10 +20174,11 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
|
|
|
19603
20174
|
x: margins.left,
|
|
19604
20175
|
y: margins.top,
|
|
19605
20176
|
width: Math.max(0, width - margins.left - margins.right),
|
|
19606
|
-
height: Math.max(0,
|
|
20177
|
+
height: Math.max(0, effectiveHeight - margins.top - margins.bottom)
|
|
19607
20178
|
};
|
|
19608
20179
|
const minDims = getMinChartDims(spec.display);
|
|
19609
|
-
|
|
20180
|
+
const chromeEatsPlot = chromeLayout !== "grow" && chrome.topHeight > height * PLOT_SHARE_MAX;
|
|
20181
|
+
if ((chartArea.width < minDims.width || chartArea.height < minDims.height || chromeEatsPlot) && chromeMode !== "hidden") {
|
|
19610
20182
|
const fallbackMode = chromeMode === "full" ? "compact" : "hidden";
|
|
19611
20183
|
const fallbackChrome = computeChrome5(
|
|
19612
20184
|
chromeToInput(spec.chrome),
|
|
@@ -19632,7 +20204,7 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
|
|
|
19632
20204
|
x: margins.left,
|
|
19633
20205
|
y: margins.top,
|
|
19634
20206
|
width: Math.max(0, width - margins.left - margins.right),
|
|
19635
|
-
height: Math.max(0,
|
|
20207
|
+
height: Math.max(0, effectiveHeight - margins.top - margins.bottom)
|
|
19636
20208
|
};
|
|
19637
20209
|
const fallbackMetricsTopY = topPad + fallbackChrome.topHeight;
|
|
19638
20210
|
const fallbackMetricsArea = { x: hPad, width: Math.max(0, width - hPad * 2) };
|
|
@@ -19649,7 +20221,7 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
|
|
|
19649
20221
|
chartArea = {
|
|
19650
20222
|
...chartArea,
|
|
19651
20223
|
y: margins.top,
|
|
19652
|
-
height: Math.max(0,
|
|
20224
|
+
height: Math.max(0, effectiveHeight - margins.top - margins.bottom)
|
|
19653
20225
|
};
|
|
19654
20226
|
}
|
|
19655
20227
|
return {
|
|
@@ -19665,7 +20237,8 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
|
|
|
19665
20237
|
fallbackMetricsArea
|
|
19666
20238
|
) : void 0,
|
|
19667
20239
|
xAxisHeight,
|
|
19668
|
-
effectiveAxisGap: fallbackEffectiveAxisGap
|
|
20240
|
+
effectiveAxisGap: fallbackEffectiveAxisGap,
|
|
20241
|
+
chromeStripped: true
|
|
19669
20242
|
};
|
|
19670
20243
|
}
|
|
19671
20244
|
}
|
|
@@ -19677,7 +20250,7 @@ function computeDimensions(spec, options, legendLayout, theme, strategy, waterma
|
|
|
19677
20250
|
chartArea = {
|
|
19678
20251
|
...chartArea,
|
|
19679
20252
|
y: margins.top,
|
|
19680
|
-
height: Math.max(0,
|
|
20253
|
+
height: Math.max(0, effectiveHeight - margins.top - margins.bottom)
|
|
19681
20254
|
};
|
|
19682
20255
|
}
|
|
19683
20256
|
return {
|
|
@@ -20429,14 +21002,19 @@ function compileSankey(spec, options) {
|
|
|
20429
21002
|
watermark
|
|
20430
21003
|
);
|
|
20431
21004
|
const padding = theme.spacing.padding;
|
|
21005
|
+
const chromeLayout = resolveChromeLayout(
|
|
21006
|
+
spec,
|
|
21007
|
+
options
|
|
21008
|
+
);
|
|
21009
|
+
const grownHeight = chromeLayout === "grow" ? options.height + chrome.topHeight + chrome.bottomHeight : options.height;
|
|
20432
21010
|
const fullArea = {
|
|
20433
21011
|
x: padding,
|
|
20434
21012
|
y: padding + chrome.topHeight,
|
|
20435
21013
|
width: options.width - padding * 2,
|
|
20436
|
-
height: options.height - chrome.topHeight - chrome.bottomHeight - padding * 2
|
|
21014
|
+
height: chromeLayout === "grow" ? options.height - padding * 2 : options.height - chrome.topHeight - chrome.bottomHeight - padding * 2
|
|
20437
21015
|
};
|
|
20438
21016
|
if (fullArea.width <= 0 || fullArea.height <= 0) {
|
|
20439
|
-
return emptyLayout4(fullArea, chrome, theme, options, watermark);
|
|
21017
|
+
return emptyLayout4(fullArea, chrome, theme, { ...options, height: grownHeight }, watermark);
|
|
20440
21018
|
}
|
|
20441
21019
|
const sourceField = sankeySpec.encoding.source.field;
|
|
20442
21020
|
const targetField = sankeySpec.encoding.target.field;
|
|
@@ -20476,7 +21054,7 @@ function compileSankey(spec, options) {
|
|
|
20476
21054
|
height: fullArea.height - legend.bounds.height - legendGap2
|
|
20477
21055
|
};
|
|
20478
21056
|
if (area.height <= 0) {
|
|
20479
|
-
return emptyLayout4(area, chrome, theme, options, watermark);
|
|
21057
|
+
return emptyLayout4(area, chrome, theme, { ...options, height: grownHeight }, watermark);
|
|
20480
21058
|
}
|
|
20481
21059
|
const labelFontSize = theme.fonts.sizes.small;
|
|
20482
21060
|
const labelFontWeight = theme.fonts.weights.normal;
|
|
@@ -20628,7 +21206,7 @@ function compileSankey(spec, options) {
|
|
|
20628
21206
|
theme,
|
|
20629
21207
|
dimensions: {
|
|
20630
21208
|
width: options.width,
|
|
20631
|
-
height:
|
|
21209
|
+
height: grownHeight
|
|
20632
21210
|
},
|
|
20633
21211
|
animation: resolvedAnimation,
|
|
20634
21212
|
watermark,
|
|
@@ -21447,6 +22025,10 @@ var LEGEND_ENTRY_GAP = 16;
|
|
|
21447
22025
|
function clamp(value2, min4, max4) {
|
|
21448
22026
|
return Math.min(max4, Math.max(min4, value2));
|
|
21449
22027
|
}
|
|
22028
|
+
function growContentHeight(contentHeight, chromeLayout, budgetHeight, chrome) {
|
|
22029
|
+
if (chromeLayout !== "grow") return contentHeight;
|
|
22030
|
+
return Math.max(contentHeight, budgetHeight + chrome.topHeight + chrome.bottomHeight);
|
|
22031
|
+
}
|
|
21450
22032
|
function compileTileMap(spec, options) {
|
|
21451
22033
|
const sugarWarnings = [];
|
|
21452
22034
|
const expandedSpec = spec && typeof spec === "object" && !Array.isArray(spec) ? expandSpecSugar(spec, sugarWarnings) : spec;
|
|
@@ -21483,22 +22065,44 @@ function compileTileMap(spec, options) {
|
|
|
21483
22065
|
watermark
|
|
21484
22066
|
);
|
|
21485
22067
|
const padding = getBreakpoint2(options.width) === "compact" ? Math.max(HPAD_COMPACT_MIN4, Math.round(theme.spacing.padding * HPAD_COMPACT_FRACTION4)) : theme.spacing.padding;
|
|
22068
|
+
const chromeLayout = resolveChromeLayout(
|
|
22069
|
+
spec,
|
|
22070
|
+
options
|
|
22071
|
+
);
|
|
21486
22072
|
const fullArea = {
|
|
21487
22073
|
x: padding,
|
|
21488
22074
|
y: padding + chrome.topHeight,
|
|
21489
22075
|
width: options.width - padding * 2,
|
|
21490
|
-
height: options.height - chrome.topHeight - chrome.bottomHeight - padding * 2
|
|
22076
|
+
height: chromeLayout === "grow" ? options.height - padding * 2 : options.height - chrome.topHeight - chrome.bottomHeight - padding * 2
|
|
21491
22077
|
};
|
|
21492
22078
|
if (fullArea.width <= 0 || fullArea.height <= 0) {
|
|
21493
22079
|
return emptyLayout5(chrome, theme, options, watermark);
|
|
21494
22080
|
}
|
|
21495
22081
|
const isCategorical = tilemapSpec.encoding.color !== void 0 || tilemapSpec.colors !== void 0;
|
|
21496
22082
|
if (isCategorical) {
|
|
21497
|
-
return compileCategorical(
|
|
22083
|
+
return compileCategorical(
|
|
22084
|
+
tilemapSpec,
|
|
22085
|
+
options,
|
|
22086
|
+
theme,
|
|
22087
|
+
chrome,
|
|
22088
|
+
fullArea,
|
|
22089
|
+
isDarkMode,
|
|
22090
|
+
watermark,
|
|
22091
|
+
chromeLayout
|
|
22092
|
+
);
|
|
21498
22093
|
}
|
|
21499
|
-
return compileQuantitative(
|
|
22094
|
+
return compileQuantitative(
|
|
22095
|
+
tilemapSpec,
|
|
22096
|
+
options,
|
|
22097
|
+
theme,
|
|
22098
|
+
chrome,
|
|
22099
|
+
fullArea,
|
|
22100
|
+
isDarkMode,
|
|
22101
|
+
watermark,
|
|
22102
|
+
chromeLayout
|
|
22103
|
+
);
|
|
21500
22104
|
}
|
|
21501
|
-
function compileQuantitative(tilemapSpec, options, theme, chrome, fullArea, isDarkMode, watermark) {
|
|
22105
|
+
function compileQuantitative(tilemapSpec, options, theme, chrome, fullArea, isDarkMode, watermark, chromeLayout) {
|
|
21502
22106
|
const stateField = tilemapSpec.encoding.state.field;
|
|
21503
22107
|
const valueField = tilemapSpec.encoding.value.field;
|
|
21504
22108
|
const stateValueMap = /* @__PURE__ */ new Map();
|
|
@@ -21599,7 +22203,12 @@ function compileQuantitative(tilemapSpec, options, theme, chrome, fullArea, isDa
|
|
|
21599
22203
|
};
|
|
21600
22204
|
const resolvedAnimation = resolveAnimation(tilemapSpec.animation);
|
|
21601
22205
|
const padding = fullArea.x;
|
|
21602
|
-
const contentHeight =
|
|
22206
|
+
const contentHeight = growContentHeight(
|
|
22207
|
+
tileGridOffsetY + tilePositions.gridHeight + legendGap2 + legendTotalHeight + chrome.bottomHeight + padding,
|
|
22208
|
+
chromeLayout,
|
|
22209
|
+
options.height,
|
|
22210
|
+
chrome
|
|
22211
|
+
);
|
|
21603
22212
|
return {
|
|
21604
22213
|
area: fullArea,
|
|
21605
22214
|
chrome,
|
|
@@ -21616,7 +22225,7 @@ function compileQuantitative(tilemapSpec, options, theme, chrome, fullArea, isDa
|
|
|
21616
22225
|
measureText: options.measureText ?? ((text, fontSize) => ({ width: estimateTextWidth23(text, fontSize), height: fontSize }))
|
|
21617
22226
|
};
|
|
21618
22227
|
}
|
|
21619
|
-
function compileCategorical(tilemapSpec, options, theme, chrome, fullArea, isDarkMode, watermark) {
|
|
22228
|
+
function compileCategorical(tilemapSpec, options, theme, chrome, fullArea, isDarkMode, watermark, chromeLayout) {
|
|
21620
22229
|
const stateField = tilemapSpec.encoding.state.field;
|
|
21621
22230
|
const colorField = tilemapSpec.encoding.color?.field ?? tilemapSpec.encoding.value.field;
|
|
21622
22231
|
const stateCategoryMap = /* @__PURE__ */ new Map();
|
|
@@ -21735,7 +22344,12 @@ function compileCategorical(tilemapSpec, options, theme, chrome, fullArea, isDar
|
|
|
21735
22344
|
};
|
|
21736
22345
|
const resolvedAnimation = resolveAnimation(tilemapSpec.animation);
|
|
21737
22346
|
const padding = fullArea.x;
|
|
21738
|
-
const contentHeight =
|
|
22347
|
+
const contentHeight = growContentHeight(
|
|
22348
|
+
tileGridOffsetY + tilePositions.gridHeight + legendGap2 + legendTotalHeight + chrome.bottomHeight + padding,
|
|
22349
|
+
chromeLayout,
|
|
22350
|
+
options.height,
|
|
22351
|
+
chrome
|
|
22352
|
+
);
|
|
21739
22353
|
return {
|
|
21740
22354
|
area: fullArea,
|
|
21741
22355
|
chrome,
|
|
@@ -22795,6 +23409,38 @@ function applySparklineDefaults(spec, theme) {
|
|
|
22795
23409
|
}
|
|
22796
23410
|
return { ...spec, markDef: newMarkDef };
|
|
22797
23411
|
}
|
|
23412
|
+
function resolveScaleInvert(resolved) {
|
|
23413
|
+
if (!resolved) return void 0;
|
|
23414
|
+
const { scale, type } = resolved;
|
|
23415
|
+
if (type === "band" || type === "point") {
|
|
23416
|
+
const domain = scale.domain();
|
|
23417
|
+
const positions = domain.map((v) => {
|
|
23418
|
+
const pos = scale(v) ?? 0;
|
|
23419
|
+
return type === "band" ? pos + scale.bandwidth() / 2 : pos;
|
|
23420
|
+
});
|
|
23421
|
+
const range4 = scale.range();
|
|
23422
|
+
return {
|
|
23423
|
+
topPixel: range4[0],
|
|
23424
|
+
bottomPixel: range4[range4.length - 1],
|
|
23425
|
+
topData: 0,
|
|
23426
|
+
bottomData: 0,
|
|
23427
|
+
domain,
|
|
23428
|
+
positions
|
|
23429
|
+
};
|
|
23430
|
+
}
|
|
23431
|
+
const invert = scale.invert;
|
|
23432
|
+
if (typeof invert !== "function") return void 0;
|
|
23433
|
+
const range3 = scale.range();
|
|
23434
|
+
const topPx = range3[0];
|
|
23435
|
+
const bottomPx = range3[range3.length - 1];
|
|
23436
|
+
const topVal = invert.call(scale, topPx);
|
|
23437
|
+
const bottomVal = invert.call(scale, bottomPx);
|
|
23438
|
+
const topData = topVal instanceof Date ? +topVal : Number(topVal);
|
|
23439
|
+
const bottomData = bottomVal instanceof Date ? +bottomVal : Number(bottomVal);
|
|
23440
|
+
if (!Number.isFinite(topData) || !Number.isFinite(bottomData)) return void 0;
|
|
23441
|
+
const scaleType = type;
|
|
23442
|
+
return { topPixel: topPx, bottomPixel: bottomPx, topData, bottomData, scaleType };
|
|
23443
|
+
}
|
|
22798
23444
|
function compileChart(spec, optionsInput) {
|
|
22799
23445
|
const sugarWarnings = [];
|
|
22800
23446
|
const expandedSpec = spec && typeof spec === "object" && !Array.isArray(spec) ? expandSpecSugar(spec, sugarWarnings) : spec;
|
|
@@ -22811,7 +23457,7 @@ function compileChart(spec, optionsInput) {
|
|
|
22811
23457
|
throw new Error("compileChart received a sankey spec. Use compileSankey instead.");
|
|
22812
23458
|
}
|
|
22813
23459
|
if ("type" in normalized && normalized.type === "map") {
|
|
22814
|
-
throw new Error("compileChart received a map spec. Use
|
|
23460
|
+
throw new Error("compileChart received a map spec. Use compileGeoMap instead.");
|
|
22815
23461
|
}
|
|
22816
23462
|
let chartSpec = normalized;
|
|
22817
23463
|
const rawWatermark = expandedSpec.watermark;
|
|
@@ -22995,12 +23641,35 @@ function compileChart(spec, optionsInput) {
|
|
|
22995
23641
|
}
|
|
22996
23642
|
};
|
|
22997
23643
|
}
|
|
23644
|
+
let facetDirection = "wrap";
|
|
23645
|
+
const rowChannel = renderSpec.encoding.row;
|
|
23646
|
+
const colChannel = renderSpec.encoding.column;
|
|
23647
|
+
if (rowChannel?.field || colChannel?.field) {
|
|
23648
|
+
const channel = rowChannel?.field ? rowChannel : colChannel;
|
|
23649
|
+
facetDirection = rowChannel?.field ? "row" : "column";
|
|
23650
|
+
const desugared = { ...renderSpec.encoding };
|
|
23651
|
+
delete desugared.row;
|
|
23652
|
+
delete desugared.column;
|
|
23653
|
+
desugared.facet = {
|
|
23654
|
+
field: channel.field,
|
|
23655
|
+
type: channel.type,
|
|
23656
|
+
sort: channel.sort,
|
|
23657
|
+
...facetDirection === "row" ? { columns: 1 } : {}
|
|
23658
|
+
};
|
|
23659
|
+
renderSpec = { ...renderSpec, encoding: desugared };
|
|
23660
|
+
const chartDesugared = { ...chartSpec.encoding };
|
|
23661
|
+
delete chartDesugared.row;
|
|
23662
|
+
delete chartDesugared.column;
|
|
23663
|
+
chartDesugared.facet = desugared.facet;
|
|
23664
|
+
chartSpec = { ...chartSpec, encoding: chartDesugared };
|
|
23665
|
+
}
|
|
22998
23666
|
const facetChannel = renderSpec.encoding.facet;
|
|
22999
23667
|
if (facetChannel?.field) {
|
|
23000
23668
|
return compileFaceted(
|
|
23001
23669
|
chartSpec,
|
|
23002
23670
|
renderSpec,
|
|
23003
23671
|
facetChannel,
|
|
23672
|
+
facetDirection,
|
|
23004
23673
|
options,
|
|
23005
23674
|
theme,
|
|
23006
23675
|
strategy,
|
|
@@ -23065,7 +23734,10 @@ function compileChart(spec, optionsInput) {
|
|
|
23065
23734
|
skipY,
|
|
23066
23735
|
markType: chartSpec.markType,
|
|
23067
23736
|
totalWidth: options.width,
|
|
23068
|
-
|
|
23737
|
+
// If the guardrail stripped chrome, the plan's y-ticks were sized
|
|
23738
|
+
// against the pre-strip (shorter) plot. Drop them so computeAxes
|
|
23739
|
+
// regenerates against the final (taller) chartArea.
|
|
23740
|
+
precomputedYTicks: !dims.chromeStripped && plan.yTickValues.length > 0 ? plan.yTickValues : void 0
|
|
23069
23741
|
});
|
|
23070
23742
|
const xAxisExtent = axes.x?.extent ?? 0;
|
|
23071
23743
|
dims.chrome.bottomAnchorY = chartArea.y + chartArea.height + xAxisExtent;
|
|
@@ -23080,6 +23752,19 @@ function compileChart(spec, optionsInput) {
|
|
|
23080
23752
|
const renderer = getChartRenderer(rendererKey);
|
|
23081
23753
|
const marks = renderer ? renderer(renderSpec, scales, chartArea, strategy, theme, options.width) : [];
|
|
23082
23754
|
applyFillPatterns(marks, chartSpec.markDef, theme);
|
|
23755
|
+
const markRenderModeWarnings = [];
|
|
23756
|
+
const markRenderMode = resolveMarkRenderMode(
|
|
23757
|
+
{
|
|
23758
|
+
requested: options.renderer,
|
|
23759
|
+
markType: chartSpec.markType,
|
|
23760
|
+
pointCount: marks.reduce((n, m) => m.type === "point" ? n + 1 : n, 0),
|
|
23761
|
+
display: chartSpec.display,
|
|
23762
|
+
faceted: false,
|
|
23763
|
+
layered: options.layered ?? false
|
|
23764
|
+
},
|
|
23765
|
+
markRenderModeWarnings
|
|
23766
|
+
);
|
|
23767
|
+
emitSpecWarnings(markRenderModeWarnings, options.onWarn);
|
|
23083
23768
|
const xFieldForYdi = chartSpec.encoding.x && "field" in chartSpec.encoding.x ? chartSpec.encoding.x.field : void 0;
|
|
23084
23769
|
const youDrawIt = resolveYouDrawIt(chartSpec.youDrawIt, marks, scales, chartArea, xFieldForYdi);
|
|
23085
23770
|
const endpointLabels = computeEndpointLabels(
|
|
@@ -23160,6 +23845,8 @@ function compileChart(spec, optionsInput) {
|
|
|
23160
23845
|
);
|
|
23161
23846
|
assignAnimationIndices(marks, resolvedAnimation);
|
|
23162
23847
|
const chrome = footnotes ? { ...dims.chrome, footnotes } : dims.chrome;
|
|
23848
|
+
const xInvert = resolveScaleInvert(scales.x);
|
|
23849
|
+
const yInvert = resolveScaleInvert(scales.y);
|
|
23163
23850
|
return {
|
|
23164
23851
|
area: chartArea,
|
|
23165
23852
|
chrome,
|
|
@@ -23179,6 +23866,7 @@ function compileChart(spec, optionsInput) {
|
|
|
23179
23866
|
a11y: {
|
|
23180
23867
|
altText,
|
|
23181
23868
|
dataTableFallback,
|
|
23869
|
+
...chartSpec.data.length > MAX_SR_TABLE_ROWS ? { totalRows: chartSpec.data.length } : {},
|
|
23182
23870
|
role: "img",
|
|
23183
23871
|
keyboardNavigable: marks.length > 0,
|
|
23184
23872
|
...chartSpec.a11y?.hidden ? { hidden: true } : {}
|
|
@@ -23186,16 +23874,22 @@ function compileChart(spec, optionsInput) {
|
|
|
23186
23874
|
theme,
|
|
23187
23875
|
dimensions: {
|
|
23188
23876
|
width: options.width,
|
|
23189
|
-
|
|
23877
|
+
// In chromeLayout 'grow' mode, computeDimensions grows total.height by the
|
|
23878
|
+
// chrome height so the plot keeps its full budget. In the default
|
|
23879
|
+
// 'subtract' mode total.height === options.height, so this is a no-op.
|
|
23880
|
+
height: dims.total.height
|
|
23190
23881
|
},
|
|
23191
23882
|
animation: resolvedAnimation,
|
|
23192
23883
|
watermark,
|
|
23193
23884
|
display: chartSpec.display,
|
|
23194
23885
|
crosshair,
|
|
23195
|
-
measureText: options.measureText
|
|
23886
|
+
measureText: options.measureText,
|
|
23887
|
+
...xInvert ? { xInvert } : {},
|
|
23888
|
+
...yInvert ? { yInvert } : {},
|
|
23889
|
+
...markRenderMode === "canvas" ? { markRenderMode } : {}
|
|
23196
23890
|
};
|
|
23197
23891
|
}
|
|
23198
|
-
function compileFaceted(chartSpec, renderSpec, facetChannel, options, theme, strategy, watermark, resolvedAnimation, crosshair, rawSpec, optionsInput) {
|
|
23892
|
+
function compileFaceted(chartSpec, renderSpec, facetChannel, facetDirection, options, theme, strategy, watermark, resolvedAnimation, crosshair, rawSpec, optionsInput) {
|
|
23199
23893
|
const measure = createMeasureFn(options.measureText);
|
|
23200
23894
|
const panelEncoding = { ...renderSpec.encoding };
|
|
23201
23895
|
delete panelEncoding.facet;
|
|
@@ -23241,10 +23935,10 @@ function compileFaceted(chartSpec, renderSpec, facetChannel, options, theme, str
|
|
|
23241
23935
|
plan.xAxisExtent,
|
|
23242
23936
|
dims.effectiveAxisGap
|
|
23243
23937
|
);
|
|
23244
|
-
const leftReservation = plan.leftGutter;
|
|
23245
23938
|
const bottomReservation = plan.xAxisExtent;
|
|
23246
|
-
const
|
|
23247
|
-
|
|
23939
|
+
const effectiveColumns = facetDirection === "column" ? facetValues.length : facetChannel.columns;
|
|
23940
|
+
const grid = computeFacetGrid(facetValues, effectiveColumns, chartArea, {
|
|
23941
|
+
left: 0,
|
|
23248
23942
|
bottom: bottomReservation
|
|
23249
23943
|
});
|
|
23250
23944
|
if (!optionsInput.facetHeightGrown && grid.panels.length > 0 && grid.panels[0].area.height < MIN_PANEL_HEIGHT) {
|
|
@@ -23259,8 +23953,10 @@ function compileFaceted(chartSpec, renderSpec, facetChannel, options, theme, str
|
|
|
23259
23953
|
}
|
|
23260
23954
|
}
|
|
23261
23955
|
const resolveConfig = chartSpec.resolve;
|
|
23262
|
-
const
|
|
23263
|
-
const
|
|
23956
|
+
const xDefault = facetDirection === "column" ? "independent" : "shared";
|
|
23957
|
+
const yDefault = facetDirection === "row" ? "independent" : "shared";
|
|
23958
|
+
const yResolve = resolveConfig?.scale?.y ?? yDefault;
|
|
23959
|
+
const xResolve = resolveConfig?.scale?.x ?? xDefault;
|
|
23264
23960
|
const fullScales = computeScales(panelSpec, chartArea, renderSpec.data);
|
|
23265
23961
|
const sharedXDomain = xResolve === "shared" && fullScales.x ? fullScales.x.scale.domain() : void 0;
|
|
23266
23962
|
const sharedYDomain = yResolve === "shared" && fullScales.y ? fullScales.y.scale.domain() : void 0;
|
|
@@ -23325,6 +24021,16 @@ function compileFaceted(chartSpec, renderSpec, facetChannel, options, theme, str
|
|
|
23325
24021
|
tickMarks: false
|
|
23326
24022
|
};
|
|
23327
24023
|
}
|
|
24024
|
+
const isBottomRow = gridPanel.row === grid.rows - 1;
|
|
24025
|
+
if (xResolve === "shared" && facetDirection === "row" && !isBottomRow && panelAxes.x) {
|
|
24026
|
+
panelAxes.x = {
|
|
24027
|
+
...panelAxes.x,
|
|
24028
|
+
ticks: [],
|
|
24029
|
+
label: void 0,
|
|
24030
|
+
domainLine: false,
|
|
24031
|
+
tickMarks: false
|
|
24032
|
+
};
|
|
24033
|
+
}
|
|
23328
24034
|
const panelMarks = renderer ? renderer(
|
|
23329
24035
|
panelSpecWithDomains,
|
|
23330
24036
|
panelScales,
|
|
@@ -23378,10 +24084,11 @@ function compileFaceted(chartSpec, renderSpec, facetChannel, options, theme, str
|
|
|
23378
24084
|
annotations: panelAnnotations,
|
|
23379
24085
|
header: {
|
|
23380
24086
|
text: gridPanel.key,
|
|
23381
|
-
x: gridPanel.headerPos.x,
|
|
24087
|
+
x: facetDirection === "row" ? gridPanel.area.x : gridPanel.headerPos.x,
|
|
23382
24088
|
y: gridPanel.headerPos.y,
|
|
23383
24089
|
fontSize: theme.fonts.sizes.body,
|
|
23384
|
-
fontWeight: theme.fonts.weights.medium
|
|
24090
|
+
fontWeight: theme.fonts.weights.medium,
|
|
24091
|
+
...facetDirection === "row" ? { textAnchor: "start" } : {}
|
|
23385
24092
|
}
|
|
23386
24093
|
});
|
|
23387
24094
|
}
|
|
@@ -23418,6 +24125,19 @@ function compileFaceted(chartSpec, renderSpec, facetChannel, options, theme, str
|
|
|
23418
24125
|
chartSpec.data
|
|
23419
24126
|
);
|
|
23420
24127
|
assignAnimationIndices(allMarks, resolvedAnimation);
|
|
24128
|
+
const facetRenderModeWarnings = [];
|
|
24129
|
+
resolveMarkRenderMode(
|
|
24130
|
+
{
|
|
24131
|
+
requested: options.renderer,
|
|
24132
|
+
markType: chartSpec.markType,
|
|
24133
|
+
pointCount: allMarks.reduce((n, m) => m.type === "point" ? n + 1 : n, 0),
|
|
24134
|
+
display: chartSpec.display,
|
|
24135
|
+
faceted: true,
|
|
24136
|
+
layered: options.layered ?? false
|
|
24137
|
+
},
|
|
24138
|
+
facetRenderModeWarnings
|
|
24139
|
+
);
|
|
24140
|
+
emitSpecWarnings(facetRenderModeWarnings, options.onWarn);
|
|
23421
24141
|
return {
|
|
23422
24142
|
area: chartArea,
|
|
23423
24143
|
chrome: allFootnotes.length > 0 ? { ...dims.chrome, footnotes: allFootnotes } : dims.chrome,
|
|
@@ -23434,6 +24154,7 @@ function compileFaceted(chartSpec, renderSpec, facetChannel, options, theme, str
|
|
|
23434
24154
|
a11y: {
|
|
23435
24155
|
altText,
|
|
23436
24156
|
dataTableFallback,
|
|
24157
|
+
...chartSpec.data.length > MAX_SR_TABLE_ROWS ? { totalRows: chartSpec.data.length } : {},
|
|
23437
24158
|
role: "img",
|
|
23438
24159
|
keyboardNavigable: allMarks.length > 0,
|
|
23439
24160
|
...chartSpec.a11y?.hidden ? { hidden: true } : {}
|
|
@@ -23449,7 +24170,8 @@ function compileFaceted(chartSpec, renderSpec, facetChannel, options, theme, str
|
|
|
23449
24170
|
panels: panelLayouts,
|
|
23450
24171
|
facetField: facetChannel.field,
|
|
23451
24172
|
columns: grid.columns,
|
|
23452
|
-
sharedScales: yResolve === "shared" && xResolve === "shared"
|
|
24173
|
+
sharedScales: yResolve === "shared" && xResolve === "shared",
|
|
24174
|
+
direction: facetDirection
|
|
23453
24175
|
}
|
|
23454
24176
|
};
|
|
23455
24177
|
}
|
|
@@ -23488,8 +24210,8 @@ function compileSankey2(spec, options) {
|
|
|
23488
24210
|
function compileTileMap2(spec, options) {
|
|
23489
24211
|
return compileTileMap(spec, options);
|
|
23490
24212
|
}
|
|
23491
|
-
function
|
|
23492
|
-
return
|
|
24213
|
+
function compileGeoMap2(spec, options) {
|
|
24214
|
+
return compileGeoMap(spec, options);
|
|
23493
24215
|
}
|
|
23494
24216
|
function compileBarList2(spec, options) {
|
|
23495
24217
|
return compileBarList(spec, options);
|
|
@@ -23503,15 +24225,16 @@ export {
|
|
|
23503
24225
|
EXIT_DEFAULTS,
|
|
23504
24226
|
UPDATE_DEFAULTS,
|
|
23505
24227
|
buildAreaPath,
|
|
24228
|
+
buildEdgeTooltip,
|
|
23506
24229
|
buildLinePath,
|
|
23507
24230
|
clampStaggerDelay,
|
|
23508
24231
|
clearRenderers,
|
|
23509
24232
|
compile,
|
|
23510
24233
|
compileBarList2 as compileBarList,
|
|
23511
24234
|
compileChart,
|
|
24235
|
+
compileGeoMap2 as compileGeoMap,
|
|
23512
24236
|
compileGraph2 as compileGraph,
|
|
23513
24237
|
compileLayer2 as compileLayer,
|
|
23514
|
-
compileMap2 as compileMap,
|
|
23515
24238
|
compileSankey2 as compileSankey,
|
|
23516
24239
|
compileTable,
|
|
23517
24240
|
compileTileMap2 as compileTileMap,
|