graphein 0.13.0 → 0.14.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 +9 -1
- package/dist/index.js +493 -264
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6073,6 +6073,7 @@ function resolveSketch(spec) {
|
|
|
6073
6073
|
|
|
6074
6074
|
// src/layout/frame.ts
|
|
6075
6075
|
var TICK_SIZE = 6;
|
|
6076
|
+
var NO_PADDING = { top: 0, right: 0, bottom: 0, left: 0 };
|
|
6076
6077
|
var AXIS_LABEL_GAP = 6;
|
|
6077
6078
|
var AXIS_TITLE_GAP = 4;
|
|
6078
6079
|
var LEGEND_SWATCH = 11;
|
|
@@ -6691,6 +6692,155 @@ function drawLegend(surface, items, model) {
|
|
|
6691
6692
|
}
|
|
6692
6693
|
}
|
|
6693
6694
|
|
|
6695
|
+
// src/charts/emphasis.ts
|
|
6696
|
+
function rowAlpha(emphasis, row) {
|
|
6697
|
+
if (!emphasis) return 1;
|
|
6698
|
+
return emphasis.match(row) ? 1 : emphasis.dim;
|
|
6699
|
+
}
|
|
6700
|
+
function seriesEmphasisMode(emphasis, series) {
|
|
6701
|
+
if (!emphasis) return "all";
|
|
6702
|
+
let matched = 0;
|
|
6703
|
+
for (const row of series.rows) if (emphasis.match(row)) matched++;
|
|
6704
|
+
if (matched === 0) return "none";
|
|
6705
|
+
if (matched === series.rows.length) return "all";
|
|
6706
|
+
return "partial";
|
|
6707
|
+
}
|
|
6708
|
+
|
|
6709
|
+
// src/charts/scatter.ts
|
|
6710
|
+
var QUANTIZE_MIN_POINTS = 4e3;
|
|
6711
|
+
var QUANTIZE_AREA_DIVISOR = 4;
|
|
6712
|
+
var FIXED_RADIUS = 3.75;
|
|
6713
|
+
var MIN_SIZED_RADIUS = 3;
|
|
6714
|
+
function maxSizedRadius(plotSize) {
|
|
6715
|
+
return clamp(plotSize * 0.05, 10, 26);
|
|
6716
|
+
}
|
|
6717
|
+
function maxScatterRadius(spec, plotW, plotH) {
|
|
6718
|
+
return spec.encoding.size?.field ? maxSizedRadius(Math.min(plotW, plotH)) : FIXED_RADIUS;
|
|
6719
|
+
}
|
|
6720
|
+
function isMissing(value) {
|
|
6721
|
+
return value == null || value === "";
|
|
6722
|
+
}
|
|
6723
|
+
function isInvalidPositionValue(value) {
|
|
6724
|
+
return isMissing(value) || typeof value === "number" && Number.isNaN(value) || value instanceof Date && Number.isNaN(value.getTime());
|
|
6725
|
+
}
|
|
6726
|
+
function fixedRadius() {
|
|
6727
|
+
return FIXED_RADIUS;
|
|
6728
|
+
}
|
|
6729
|
+
function shouldQuantize(count, plot, hasSize) {
|
|
6730
|
+
return !hasSize && count > QUANTIZE_MIN_POINTS && count > plot.width * plot.height / QUANTIZE_AREA_DIVISOR;
|
|
6731
|
+
}
|
|
6732
|
+
function quantizePoints(points) {
|
|
6733
|
+
if (points.length === 0) return [];
|
|
6734
|
+
let minX = Infinity;
|
|
6735
|
+
let maxX = -Infinity;
|
|
6736
|
+
let minY = Infinity;
|
|
6737
|
+
let maxY = -Infinity;
|
|
6738
|
+
for (const p of points) {
|
|
6739
|
+
if (p.x < minX) minX = p.x;
|
|
6740
|
+
if (p.x > maxX) maxX = p.x;
|
|
6741
|
+
if (p.y < minY) minY = p.y;
|
|
6742
|
+
if (p.y > maxY) maxY = p.y;
|
|
6743
|
+
}
|
|
6744
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6745
|
+
const keep = [];
|
|
6746
|
+
for (const p of points) {
|
|
6747
|
+
const extentPoint = p.x === minX || p.x === maxX || p.y === minY || p.y === maxY;
|
|
6748
|
+
const ix = Math.round(p.x);
|
|
6749
|
+
const iy = Math.round(p.y);
|
|
6750
|
+
const key = `${p.seriesKey}|${ix}|${iy}`;
|
|
6751
|
+
if (extentPoint || !seen.has(key)) {
|
|
6752
|
+
keep.push(p);
|
|
6753
|
+
seen.add(key);
|
|
6754
|
+
}
|
|
6755
|
+
}
|
|
6756
|
+
return keep;
|
|
6757
|
+
}
|
|
6758
|
+
function radiusScale(rows, field, plotSize) {
|
|
6759
|
+
const rMin = MIN_SIZED_RADIUS;
|
|
6760
|
+
const rMax = maxSizedRadius(plotSize);
|
|
6761
|
+
const mid = (rMin + rMax) / 2;
|
|
6762
|
+
const domain = extent(rows, field);
|
|
6763
|
+
if (!domain) return () => mid;
|
|
6764
|
+
const [min, max] = domain;
|
|
6765
|
+
if (min === max) return () => mid;
|
|
6766
|
+
return (value) => {
|
|
6767
|
+
const n = toNumber(value);
|
|
6768
|
+
if (Number.isNaN(n)) return rMin;
|
|
6769
|
+
const norm = clamp((n - min) / (max - min), 0, 1);
|
|
6770
|
+
return rMin + (rMax - rMin) * Math.sqrt(norm);
|
|
6771
|
+
};
|
|
6772
|
+
}
|
|
6773
|
+
function drawScatter(surface, model) {
|
|
6774
|
+
const ctx = surface.marks.ctx;
|
|
6775
|
+
const spec = model.spec;
|
|
6776
|
+
const { plot, tokens } = model;
|
|
6777
|
+
const readX = accessor(model.x.field);
|
|
6778
|
+
const readY = accessor(model.y.field ?? "");
|
|
6779
|
+
const sizeField = spec.encoding.size?.field;
|
|
6780
|
+
const allRows = model.series.flatMap((series) => series.rows);
|
|
6781
|
+
const readSize = sizeField ? accessor(sizeField) : null;
|
|
6782
|
+
const radius = sizeField ? radiusScale(allRows, sizeField, Math.min(plot.width, plot.height)) : fixedRadius;
|
|
6783
|
+
const points = [];
|
|
6784
|
+
for (const series of model.series) {
|
|
6785
|
+
for (const row of series.rows) {
|
|
6786
|
+
const xValue = readX(row);
|
|
6787
|
+
const yValue = readY(row);
|
|
6788
|
+
const yNumber = toNumber(yValue);
|
|
6789
|
+
const px = model.x.pixel(xValue);
|
|
6790
|
+
if (px == null || isInvalidPositionValue(xValue) || isMissing(yValue) || Number.isNaN(yNumber)) {
|
|
6791
|
+
continue;
|
|
6792
|
+
}
|
|
6793
|
+
const py = model.y.pixel(yValue);
|
|
6794
|
+
if (!Number.isFinite(px) || !Number.isFinite(py)) continue;
|
|
6795
|
+
points.push({
|
|
6796
|
+
x: px,
|
|
6797
|
+
y: py,
|
|
6798
|
+
r: readSize ? radius(readSize(row)) : radius(),
|
|
6799
|
+
color: series.color,
|
|
6800
|
+
alpha: rowAlpha(model.emphasis, row),
|
|
6801
|
+
seriesKey: series.key
|
|
6802
|
+
});
|
|
6803
|
+
}
|
|
6804
|
+
}
|
|
6805
|
+
const originalCount = points.length;
|
|
6806
|
+
const drawPoints = shouldQuantize(originalCount, plot, !!sizeField) ? quantizePoints(points) : points;
|
|
6807
|
+
model.markStats = { drawn: drawPoints.length, original: originalCount };
|
|
6808
|
+
if (sizeField) drawPoints.sort((a, b) => b.r - a.r);
|
|
6809
|
+
ctx.save();
|
|
6810
|
+
ctx.beginPath();
|
|
6811
|
+
ctx.rect(plot.x, plot.y, plot.width, plot.height);
|
|
6812
|
+
ctx.clip();
|
|
6813
|
+
if (model.sketch) {
|
|
6814
|
+
const pen = new RoughPen(ctx, model.sketch);
|
|
6815
|
+
for (const point of drawPoints) {
|
|
6816
|
+
const prev = ctx.globalAlpha;
|
|
6817
|
+
if (point.alpha !== 1) ctx.globalAlpha = point.alpha;
|
|
6818
|
+
pen.circle(point.x, point.y, point.r, {
|
|
6819
|
+
fill: point.color,
|
|
6820
|
+
fillAlpha: 0.7,
|
|
6821
|
+
stroke: tokens.color.background,
|
|
6822
|
+
strokeWidth: 1
|
|
6823
|
+
});
|
|
6824
|
+
if (point.alpha !== 1) ctx.globalAlpha = prev;
|
|
6825
|
+
}
|
|
6826
|
+
ctx.restore();
|
|
6827
|
+
return;
|
|
6828
|
+
}
|
|
6829
|
+
ctx.lineWidth = 1;
|
|
6830
|
+
ctx.strokeStyle = tokens.color.background;
|
|
6831
|
+
for (const point of drawPoints) {
|
|
6832
|
+
ctx.beginPath();
|
|
6833
|
+
ctx.arc(point.x, point.y, point.r, 0, Math.PI * 2);
|
|
6834
|
+
ctx.fillStyle = point.color;
|
|
6835
|
+
ctx.globalAlpha = 0.7 * point.alpha;
|
|
6836
|
+
ctx.fill();
|
|
6837
|
+
ctx.globalAlpha = point.alpha;
|
|
6838
|
+
ctx.stroke();
|
|
6839
|
+
}
|
|
6840
|
+
ctx.globalAlpha = 1;
|
|
6841
|
+
ctx.restore();
|
|
6842
|
+
}
|
|
6843
|
+
|
|
6694
6844
|
// src/runtime/cartesian.ts
|
|
6695
6845
|
var CURVES = {
|
|
6696
6846
|
linear: curveLinear,
|
|
@@ -6781,8 +6931,43 @@ function formatNumericTick(value, userFormat) {
|
|
|
6781
6931
|
if (userFormat) return formatValue(value, userFormat);
|
|
6782
6932
|
return formatNumber2(value, ",");
|
|
6783
6933
|
}
|
|
6784
|
-
var DEFAULT_PADDING = { top: 12, right: 16, bottom: 12, left: 12 };
|
|
6785
6934
|
var LEGEND_SWATCH2 = 11;
|
|
6935
|
+
var SCATTER_EDGE_MARGIN = 2;
|
|
6936
|
+
var ZERO_INSETS = { top: 0, right: 0, bottom: 0, left: 0 };
|
|
6937
|
+
function annotationEdgeInsets(spec, yDomain, fontFamily, fontSize, fontWeight) {
|
|
6938
|
+
const explicit = spec.annotations;
|
|
6939
|
+
const points = Array.isArray(explicit) ? explicit.filter((a) => a.type === "point") : [];
|
|
6940
|
+
for (const a of autoInsightAnnotations(spec)) points.push(a);
|
|
6941
|
+
if (points.length === 0) return ZERO_INSETS;
|
|
6942
|
+
const span = yDomain[1] - yDomain[0] || 1;
|
|
6943
|
+
const font = fontString(fontSize, fontFamily, fontWeight);
|
|
6944
|
+
let maxR = 0;
|
|
6945
|
+
let maxLabelHalf = 0;
|
|
6946
|
+
let anyLabel = false;
|
|
6947
|
+
let maxFy = -Infinity;
|
|
6948
|
+
let minFy = Infinity;
|
|
6949
|
+
for (const ann of points) {
|
|
6950
|
+
const r = ann.markerRadius ?? 3.5;
|
|
6951
|
+
if (r > maxR) maxR = r;
|
|
6952
|
+
if (ann.label) {
|
|
6953
|
+
anyLabel = true;
|
|
6954
|
+
const half = (measureText(ann.label, font).width + 6) / 2;
|
|
6955
|
+
if (half > maxLabelHalf) maxLabelHalf = half;
|
|
6956
|
+
}
|
|
6957
|
+
const yv = toNumber(ann.y);
|
|
6958
|
+
if (!Number.isNaN(yv)) {
|
|
6959
|
+
const fy = (yv - yDomain[0]) / span;
|
|
6960
|
+
if (fy > maxFy) maxFy = fy;
|
|
6961
|
+
if (fy < minFy) minFy = fy;
|
|
6962
|
+
}
|
|
6963
|
+
}
|
|
6964
|
+
const halo = maxR + 1.6;
|
|
6965
|
+
const gap = maxR + 4;
|
|
6966
|
+
const hReserve = Math.ceil(Math.max(maxLabelHalf, halo)) + 2;
|
|
6967
|
+
const top = maxFy >= 0.5 ? Math.ceil(anyLabel ? gap + fontSize : halo) + 2 : 0;
|
|
6968
|
+
const bottom = minFy <= 0.5 ? Math.ceil(halo) + 2 : 0;
|
|
6969
|
+
return { top, right: hReserve, bottom, left: hReserve };
|
|
6970
|
+
}
|
|
6786
6971
|
function legendInteractive(spec) {
|
|
6787
6972
|
return typeof spec.legend === "object" && spec.legend.interactive === true;
|
|
6788
6973
|
}
|
|
@@ -6947,7 +7132,7 @@ function buildCartesianModel(spec, tokens, opts) {
|
|
|
6947
7132
|
color: s.color,
|
|
6948
7133
|
symbol: spec.type === "scatter" ? "circle" : spec.type === "line" ? "line" : "square"
|
|
6949
7134
|
}));
|
|
6950
|
-
const padding = { ...
|
|
7135
|
+
const padding = { ...NO_PADDING, ...spec.padding };
|
|
6951
7136
|
const titleInput4 = resolveTitle(spec);
|
|
6952
7137
|
const categoryAxisInput = {
|
|
6953
7138
|
show: xShow,
|
|
@@ -6990,7 +7175,18 @@ function buildCartesianModel(spec, tokens, opts) {
|
|
|
6990
7175
|
};
|
|
6991
7176
|
}) : void 0;
|
|
6992
7177
|
const plot = frame.plot;
|
|
6993
|
-
const
|
|
7178
|
+
const scatterInset = spec.type === "scatter" ? Math.min(
|
|
7179
|
+
maxScatterRadius(spec, plot.width, plot.height) + SCATTER_EDGE_MARGIN,
|
|
7180
|
+
Math.min(plot.width, plot.height) * 0.4
|
|
7181
|
+
) : 0;
|
|
7182
|
+
const annIns = horizontal ? ZERO_INSETS : annotationEdgeInsets(spec, yDomain, tokens.font.family, tokens.font.size.small, tokens.font.weight.medium);
|
|
7183
|
+
const capV = plot.height * 0.4;
|
|
7184
|
+
const capH = plot.width * 0.4;
|
|
7185
|
+
const insTop = Math.min(Math.max(scatterInset, annIns.top), capV);
|
|
7186
|
+
const insBottom = Math.min(Math.max(scatterInset, annIns.bottom), capV);
|
|
7187
|
+
const insLeft = Math.min(Math.max(scatterInset, annIns.left), capH);
|
|
7188
|
+
const insRight = Math.min(Math.max(scatterInset, annIns.right), capH);
|
|
7189
|
+
const valueRange = horizontal ? [plot.x + insLeft, plot.x + plot.width - insRight] : [plot.y + plot.height - insBottom, plot.y + insTop];
|
|
6994
7190
|
const yScale = yIsLog ? logScale({ domain: yDomain, range: valueRange, base: yBase, clamp: yClamp }) : linearScale({ domain: yDomain, range: valueRange, clamp: yClamp });
|
|
6995
7191
|
const yPixel = (value) => yScale.map(toNumber(value));
|
|
6996
7192
|
const valueMin = horizontal ? plot.x : plot.y;
|
|
@@ -7001,7 +7197,7 @@ function buildCartesianModel(spec, tokens, opts) {
|
|
|
7001
7197
|
type: xType,
|
|
7002
7198
|
categories,
|
|
7003
7199
|
domainNum: xDomainNum,
|
|
7004
|
-
range: horizontal ? [plot.y, plot.y + plot.height] : [plot.x, plot.x + plot.width],
|
|
7200
|
+
range: horizontal ? [plot.y + insTop, plot.y + plot.height - insBottom] : [plot.x + insLeft, plot.x + plot.width - insRight],
|
|
7005
7201
|
paddingInner: spec.type === "bar" ? 0.2 : spec.type === "box" ? 0.32 : 0.5,
|
|
7006
7202
|
scaleCfg: enc.x.scale
|
|
7007
7203
|
});
|
|
@@ -7128,21 +7324,32 @@ function maxFinite(values, fallback) {
|
|
|
7128
7324
|
return max === -Infinity ? fallback : max;
|
|
7129
7325
|
}
|
|
7130
7326
|
|
|
7131
|
-
// src/
|
|
7132
|
-
function
|
|
7133
|
-
|
|
7134
|
-
return emphasis.match(row) ? 1 : emphasis.dim;
|
|
7327
|
+
// src/render/metrics.ts
|
|
7328
|
+
function diagonal(plot) {
|
|
7329
|
+
return Math.hypot(plot.width, plot.height);
|
|
7135
7330
|
}
|
|
7136
|
-
function
|
|
7137
|
-
|
|
7138
|
-
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
|
|
7142
|
-
|
|
7331
|
+
function lineStrokeWidth(plot, base = 2) {
|
|
7332
|
+
return clamp(diagonal(plot) / 260, base, 4.5);
|
|
7333
|
+
}
|
|
7334
|
+
function markerRadius(plot, count, base = 3) {
|
|
7335
|
+
const bySize = diagonal(plot) / 150;
|
|
7336
|
+
const spacing = plot.width / Math.max(2, count);
|
|
7337
|
+
const bySpace = spacing * 0.34;
|
|
7338
|
+
return clamp(Math.min(bySize, bySpace), Math.min(base, 2.5), 8);
|
|
7339
|
+
}
|
|
7340
|
+
function markerStroke(radius) {
|
|
7341
|
+
return clamp(radius * 0.32, 1, 2.5);
|
|
7143
7342
|
}
|
|
7144
7343
|
|
|
7145
7344
|
// src/charts/line.ts
|
|
7345
|
+
function maxSeriesLength(allSeries) {
|
|
7346
|
+
let n = 0;
|
|
7347
|
+
for (const s of allSeries) {
|
|
7348
|
+
const finite4 = s.points.filter((p) => !Number.isNaN(p.x) && !Number.isNaN(p.y)).length;
|
|
7349
|
+
if (finite4 > n) n = finite4;
|
|
7350
|
+
}
|
|
7351
|
+
return n;
|
|
7352
|
+
}
|
|
7146
7353
|
function buildSeriesPoints(model, s) {
|
|
7147
7354
|
const readX = accessor(model.x.field);
|
|
7148
7355
|
const readY = accessor(model.y.field ?? "");
|
|
@@ -7199,7 +7406,7 @@ function finiteRuns(points) {
|
|
|
7199
7406
|
if (run.length) runs.push(run);
|
|
7200
7407
|
return runs;
|
|
7201
7408
|
}
|
|
7202
|
-
function drawLineSketch(ctx, model, allSeries, pen, filled, showPoints) {
|
|
7409
|
+
function drawLineSketch(ctx, model, allSeries, pen, filled, showPoints, strokeWidth, markerR, markerSW) {
|
|
7203
7410
|
if (filled) {
|
|
7204
7411
|
for (const { series, points, alpha } of allSeries) {
|
|
7205
7412
|
const prev = ctx.globalAlpha;
|
|
@@ -7218,7 +7425,7 @@ function drawLineSketch(ctx, model, allSeries, pen, filled, showPoints) {
|
|
|
7218
7425
|
for (const { series, points, alpha } of allSeries) {
|
|
7219
7426
|
const prev = ctx.globalAlpha;
|
|
7220
7427
|
if (alpha !== 1) ctx.globalAlpha = alpha;
|
|
7221
|
-
pen.trendStroke(points, { stroke: series.color });
|
|
7428
|
+
pen.trendStroke(points, { stroke: series.color, strokeWidth });
|
|
7222
7429
|
if (alpha !== 1) ctx.globalAlpha = prev;
|
|
7223
7430
|
}
|
|
7224
7431
|
if (showPoints) {
|
|
@@ -7227,10 +7434,10 @@ function drawLineSketch(ctx, model, allSeries, pen, filled, showPoints) {
|
|
|
7227
7434
|
if (alpha !== 1) ctx.globalAlpha = alpha;
|
|
7228
7435
|
for (const p of points) {
|
|
7229
7436
|
if (Number.isNaN(p.x) || Number.isNaN(p.y)) continue;
|
|
7230
|
-
pen.circle(p.x, p.y,
|
|
7437
|
+
pen.circle(p.x, p.y, markerR, {
|
|
7231
7438
|
fill: series.color,
|
|
7232
7439
|
stroke: model.tokens.color.background,
|
|
7233
|
-
strokeWidth:
|
|
7440
|
+
strokeWidth: markerSW
|
|
7234
7441
|
});
|
|
7235
7442
|
}
|
|
7236
7443
|
if (alpha !== 1) ctx.globalAlpha = prev;
|
|
@@ -7240,10 +7447,10 @@ function drawLineSketch(ctx, model, allSeries, pen, filled, showPoints) {
|
|
|
7240
7447
|
if (mode !== "partial") continue;
|
|
7241
7448
|
ctx.globalAlpha = 1;
|
|
7242
7449
|
for (const p of matchPoints) {
|
|
7243
|
-
pen.circle(p.x, p.y,
|
|
7450
|
+
pen.circle(p.x, p.y, markerR, {
|
|
7244
7451
|
fill: series.color,
|
|
7245
7452
|
stroke: model.tokens.color.background,
|
|
7246
|
-
strokeWidth:
|
|
7453
|
+
strokeWidth: markerSW
|
|
7247
7454
|
});
|
|
7248
7455
|
}
|
|
7249
7456
|
}
|
|
@@ -7267,12 +7474,15 @@ function drawLine(surface, model) {
|
|
|
7267
7474
|
};
|
|
7268
7475
|
});
|
|
7269
7476
|
const showPoints = spec.points || allSeries.some((s) => s.points.filter((p) => !Number.isNaN(p.x)).length === 1);
|
|
7477
|
+
const strokeWidth = lineStrokeWidth(plot, Math.max(1.75, tokens.stroke.thick));
|
|
7478
|
+
const markerR = markerRadius(plot, maxSeriesLength(allSeries));
|
|
7479
|
+
const markerSW = markerStroke(markerR);
|
|
7270
7480
|
ctx.save();
|
|
7271
7481
|
ctx.beginPath();
|
|
7272
7482
|
ctx.rect(plot.x, plot.y, plot.width, plot.height);
|
|
7273
7483
|
ctx.clip();
|
|
7274
7484
|
if (model.sketch) {
|
|
7275
|
-
drawLineSketch(ctx, model, allSeries, new RoughPen(ctx, model.sketch), Boolean(areaGen), showPoints);
|
|
7485
|
+
drawLineSketch(ctx, model, allSeries, new RoughPen(ctx, model.sketch), Boolean(areaGen), showPoints, strokeWidth, markerR, markerSW);
|
|
7276
7486
|
ctx.restore();
|
|
7277
7487
|
return;
|
|
7278
7488
|
}
|
|
@@ -7295,7 +7505,7 @@ function drawLine(surface, model) {
|
|
|
7295
7505
|
}
|
|
7296
7506
|
ctx.lineJoin = "round";
|
|
7297
7507
|
ctx.lineCap = "round";
|
|
7298
|
-
ctx.lineWidth =
|
|
7508
|
+
ctx.lineWidth = strokeWidth;
|
|
7299
7509
|
for (const { series, points, alpha } of allSeries) {
|
|
7300
7510
|
ctx.beginPath();
|
|
7301
7511
|
lineGen(points, ctx);
|
|
@@ -7308,12 +7518,12 @@ function drawLine(surface, model) {
|
|
|
7308
7518
|
for (const { series, points, alpha } of allSeries) {
|
|
7309
7519
|
ctx.fillStyle = series.color;
|
|
7310
7520
|
ctx.strokeStyle = tokens.color.background;
|
|
7311
|
-
ctx.lineWidth =
|
|
7521
|
+
ctx.lineWidth = markerSW;
|
|
7312
7522
|
ctx.globalAlpha = alpha;
|
|
7313
7523
|
for (const p of points) {
|
|
7314
7524
|
if (Number.isNaN(p.x) || Number.isNaN(p.y)) continue;
|
|
7315
7525
|
ctx.beginPath();
|
|
7316
|
-
ctx.arc(p.x, p.y,
|
|
7526
|
+
ctx.arc(p.x, p.y, markerR, 0, Math.PI * 2);
|
|
7317
7527
|
ctx.fill();
|
|
7318
7528
|
ctx.stroke();
|
|
7319
7529
|
}
|
|
@@ -7324,11 +7534,11 @@ function drawLine(surface, model) {
|
|
|
7324
7534
|
if (mode !== "partial") continue;
|
|
7325
7535
|
ctx.fillStyle = series.color;
|
|
7326
7536
|
ctx.strokeStyle = tokens.color.background;
|
|
7327
|
-
ctx.lineWidth =
|
|
7537
|
+
ctx.lineWidth = markerSW;
|
|
7328
7538
|
ctx.globalAlpha = 1;
|
|
7329
7539
|
for (const p of matchPoints) {
|
|
7330
7540
|
ctx.beginPath();
|
|
7331
|
-
ctx.arc(p.x, p.y,
|
|
7541
|
+
ctx.arc(p.x, p.y, markerR, 0, Math.PI * 2);
|
|
7332
7542
|
ctx.fill();
|
|
7333
7543
|
ctx.stroke();
|
|
7334
7544
|
}
|
|
@@ -7338,6 +7548,14 @@ function drawLine(surface, model) {
|
|
|
7338
7548
|
}
|
|
7339
7549
|
|
|
7340
7550
|
// src/charts/area.ts
|
|
7551
|
+
function maxBandLength(bands) {
|
|
7552
|
+
let n = 0;
|
|
7553
|
+
for (const b of bands) {
|
|
7554
|
+
const finite4 = b.points.filter((p) => !Number.isNaN(p.x) && !Number.isNaN(p.y1)).length;
|
|
7555
|
+
if (finite4 > n) n = finite4;
|
|
7556
|
+
}
|
|
7557
|
+
return n;
|
|
7558
|
+
}
|
|
7341
7559
|
function buildBands(model, stacked) {
|
|
7342
7560
|
const readX = accessor(model.x.field);
|
|
7343
7561
|
const readY = accessor(model.y.field ?? "");
|
|
@@ -7387,7 +7605,7 @@ function buildBands(model, stacked) {
|
|
|
7387
7605
|
return { series, points: reduced, alpha: mode === "all" ? 1 : model.emphasis?.dim ?? 1, mode, matchPoints };
|
|
7388
7606
|
});
|
|
7389
7607
|
}
|
|
7390
|
-
function drawAreaSketch(ctx, model, bands, pen, stacked) {
|
|
7608
|
+
function drawAreaSketch(ctx, model, bands, pen, stacked, strokeWidth, markerR, markerSW) {
|
|
7391
7609
|
for (const { series, points, alpha } of bands) {
|
|
7392
7610
|
const prev = ctx.globalAlpha;
|
|
7393
7611
|
if (alpha !== 1) ctx.globalAlpha = alpha;
|
|
@@ -7415,7 +7633,7 @@ function drawAreaSketch(ctx, model, bands, pen, stacked) {
|
|
|
7415
7633
|
if (alpha !== 1) ctx.globalAlpha = alpha;
|
|
7416
7634
|
pen.trendStroke(
|
|
7417
7635
|
points.map((p) => ({ x: p.x, y: p.y1 })),
|
|
7418
|
-
{ stroke: series.color }
|
|
7636
|
+
{ stroke: series.color, strokeWidth }
|
|
7419
7637
|
);
|
|
7420
7638
|
if (alpha !== 1) ctx.globalAlpha = prev;
|
|
7421
7639
|
}
|
|
@@ -7423,10 +7641,10 @@ function drawAreaSketch(ctx, model, bands, pen, stacked) {
|
|
|
7423
7641
|
if (mode !== "partial") continue;
|
|
7424
7642
|
ctx.globalAlpha = 1;
|
|
7425
7643
|
for (const p of matchPoints) {
|
|
7426
|
-
pen.circle(p.x, p.y,
|
|
7644
|
+
pen.circle(p.x, p.y, markerR, {
|
|
7427
7645
|
fill: series.color,
|
|
7428
7646
|
stroke: model.tokens.color.background,
|
|
7429
|
-
strokeWidth:
|
|
7647
|
+
strokeWidth: markerSW
|
|
7430
7648
|
});
|
|
7431
7649
|
}
|
|
7432
7650
|
}
|
|
@@ -7441,12 +7659,15 @@ function drawArea(surface, model) {
|
|
|
7441
7659
|
const lineGen = line({ curve });
|
|
7442
7660
|
const stacked = model.stacked;
|
|
7443
7661
|
const bands = buildBands(model, stacked);
|
|
7662
|
+
const strokeWidth = lineStrokeWidth(plot, Math.max(1.5, tokens.stroke.base));
|
|
7663
|
+
const markerR = markerRadius(plot, maxBandLength(bands));
|
|
7664
|
+
const markerSW = markerStroke(markerR);
|
|
7444
7665
|
ctx.save();
|
|
7445
7666
|
ctx.beginPath();
|
|
7446
7667
|
ctx.rect(plot.x, plot.y, plot.width, plot.height);
|
|
7447
7668
|
ctx.clip();
|
|
7448
7669
|
if (model.sketch) {
|
|
7449
|
-
drawAreaSketch(ctx, model, bands, new RoughPen(ctx, model.sketch), stacked);
|
|
7670
|
+
drawAreaSketch(ctx, model, bands, new RoughPen(ctx, model.sketch), stacked, strokeWidth, markerR, markerSW);
|
|
7450
7671
|
ctx.restore();
|
|
7451
7672
|
return;
|
|
7452
7673
|
}
|
|
@@ -7468,7 +7689,7 @@ function drawArea(surface, model) {
|
|
|
7468
7689
|
}
|
|
7469
7690
|
ctx.lineJoin = "round";
|
|
7470
7691
|
ctx.lineCap = "round";
|
|
7471
|
-
ctx.lineWidth =
|
|
7692
|
+
ctx.lineWidth = strokeWidth;
|
|
7472
7693
|
for (const { series, points, alpha } of bands) {
|
|
7473
7694
|
ctx.beginPath();
|
|
7474
7695
|
lineGen(
|
|
@@ -7484,11 +7705,11 @@ function drawArea(surface, model) {
|
|
|
7484
7705
|
if (mode !== "partial") continue;
|
|
7485
7706
|
ctx.fillStyle = series.color;
|
|
7486
7707
|
ctx.strokeStyle = tokens.color.background;
|
|
7487
|
-
ctx.lineWidth =
|
|
7708
|
+
ctx.lineWidth = markerSW;
|
|
7488
7709
|
ctx.globalAlpha = 1;
|
|
7489
7710
|
for (const p of matchPoints) {
|
|
7490
7711
|
ctx.beginPath();
|
|
7491
|
-
ctx.arc(p.x, p.y,
|
|
7712
|
+
ctx.arc(p.x, p.y, markerR, 0, Math.PI * 2);
|
|
7492
7713
|
ctx.fill();
|
|
7493
7714
|
ctx.stroke();
|
|
7494
7715
|
}
|
|
@@ -7632,133 +7853,6 @@ function drawBar(surface, model) {
|
|
|
7632
7853
|
ctx.restore();
|
|
7633
7854
|
}
|
|
7634
7855
|
|
|
7635
|
-
// src/charts/scatter.ts
|
|
7636
|
-
var QUANTIZE_MIN_POINTS = 4e3;
|
|
7637
|
-
var QUANTIZE_AREA_DIVISOR = 4;
|
|
7638
|
-
function isMissing(value) {
|
|
7639
|
-
return value == null || value === "";
|
|
7640
|
-
}
|
|
7641
|
-
function isInvalidPositionValue(value) {
|
|
7642
|
-
return isMissing(value) || typeof value === "number" && Number.isNaN(value) || value instanceof Date && Number.isNaN(value.getTime());
|
|
7643
|
-
}
|
|
7644
|
-
function fixedRadius() {
|
|
7645
|
-
return 3.75;
|
|
7646
|
-
}
|
|
7647
|
-
function shouldQuantize(count, plot, hasSize) {
|
|
7648
|
-
return !hasSize && count > QUANTIZE_MIN_POINTS && count > plot.width * plot.height / QUANTIZE_AREA_DIVISOR;
|
|
7649
|
-
}
|
|
7650
|
-
function quantizePoints(points) {
|
|
7651
|
-
if (points.length === 0) return [];
|
|
7652
|
-
let minX = Infinity;
|
|
7653
|
-
let maxX = -Infinity;
|
|
7654
|
-
let minY = Infinity;
|
|
7655
|
-
let maxY = -Infinity;
|
|
7656
|
-
for (const p of points) {
|
|
7657
|
-
if (p.x < minX) minX = p.x;
|
|
7658
|
-
if (p.x > maxX) maxX = p.x;
|
|
7659
|
-
if (p.y < minY) minY = p.y;
|
|
7660
|
-
if (p.y > maxY) maxY = p.y;
|
|
7661
|
-
}
|
|
7662
|
-
const seen = /* @__PURE__ */ new Set();
|
|
7663
|
-
const keep = [];
|
|
7664
|
-
for (const p of points) {
|
|
7665
|
-
const extentPoint = p.x === minX || p.x === maxX || p.y === minY || p.y === maxY;
|
|
7666
|
-
const ix = Math.round(p.x);
|
|
7667
|
-
const iy = Math.round(p.y);
|
|
7668
|
-
const key = `${p.seriesKey}|${ix}|${iy}`;
|
|
7669
|
-
if (extentPoint || !seen.has(key)) {
|
|
7670
|
-
keep.push(p);
|
|
7671
|
-
seen.add(key);
|
|
7672
|
-
}
|
|
7673
|
-
}
|
|
7674
|
-
return keep;
|
|
7675
|
-
}
|
|
7676
|
-
function radiusScale(rows, field, plotSize) {
|
|
7677
|
-
const rMin = 3;
|
|
7678
|
-
const rMax = clamp(plotSize * 0.05, 10, 26);
|
|
7679
|
-
const mid = (rMin + rMax) / 2;
|
|
7680
|
-
const domain = extent(rows, field);
|
|
7681
|
-
if (!domain) return () => mid;
|
|
7682
|
-
const [min, max] = domain;
|
|
7683
|
-
if (min === max) return () => mid;
|
|
7684
|
-
return (value) => {
|
|
7685
|
-
const n = toNumber(value);
|
|
7686
|
-
if (Number.isNaN(n)) return rMin;
|
|
7687
|
-
const norm = clamp((n - min) / (max - min), 0, 1);
|
|
7688
|
-
return rMin + (rMax - rMin) * Math.sqrt(norm);
|
|
7689
|
-
};
|
|
7690
|
-
}
|
|
7691
|
-
function drawScatter(surface, model) {
|
|
7692
|
-
const ctx = surface.marks.ctx;
|
|
7693
|
-
const spec = model.spec;
|
|
7694
|
-
const { plot, tokens } = model;
|
|
7695
|
-
const readX = accessor(model.x.field);
|
|
7696
|
-
const readY = accessor(model.y.field ?? "");
|
|
7697
|
-
const sizeField = spec.encoding.size?.field;
|
|
7698
|
-
const allRows = model.series.flatMap((series) => series.rows);
|
|
7699
|
-
const readSize = sizeField ? accessor(sizeField) : null;
|
|
7700
|
-
const radius = sizeField ? radiusScale(allRows, sizeField, Math.min(plot.width, plot.height)) : fixedRadius;
|
|
7701
|
-
const points = [];
|
|
7702
|
-
for (const series of model.series) {
|
|
7703
|
-
for (const row of series.rows) {
|
|
7704
|
-
const xValue = readX(row);
|
|
7705
|
-
const yValue = readY(row);
|
|
7706
|
-
const yNumber = toNumber(yValue);
|
|
7707
|
-
const px = model.x.pixel(xValue);
|
|
7708
|
-
if (px == null || isInvalidPositionValue(xValue) || isMissing(yValue) || Number.isNaN(yNumber)) {
|
|
7709
|
-
continue;
|
|
7710
|
-
}
|
|
7711
|
-
const py = model.y.pixel(yValue);
|
|
7712
|
-
if (!Number.isFinite(px) || !Number.isFinite(py)) continue;
|
|
7713
|
-
points.push({
|
|
7714
|
-
x: px,
|
|
7715
|
-
y: py,
|
|
7716
|
-
r: readSize ? radius(readSize(row)) : radius(),
|
|
7717
|
-
color: series.color,
|
|
7718
|
-
alpha: rowAlpha(model.emphasis, row),
|
|
7719
|
-
seriesKey: series.key
|
|
7720
|
-
});
|
|
7721
|
-
}
|
|
7722
|
-
}
|
|
7723
|
-
const originalCount = points.length;
|
|
7724
|
-
const drawPoints = shouldQuantize(originalCount, plot, !!sizeField) ? quantizePoints(points) : points;
|
|
7725
|
-
model.markStats = { drawn: drawPoints.length, original: originalCount };
|
|
7726
|
-
if (sizeField) drawPoints.sort((a, b) => b.r - a.r);
|
|
7727
|
-
ctx.save();
|
|
7728
|
-
ctx.beginPath();
|
|
7729
|
-
ctx.rect(plot.x, plot.y, plot.width, plot.height);
|
|
7730
|
-
ctx.clip();
|
|
7731
|
-
if (model.sketch) {
|
|
7732
|
-
const pen = new RoughPen(ctx, model.sketch);
|
|
7733
|
-
for (const point of drawPoints) {
|
|
7734
|
-
const prev = ctx.globalAlpha;
|
|
7735
|
-
if (point.alpha !== 1) ctx.globalAlpha = point.alpha;
|
|
7736
|
-
pen.circle(point.x, point.y, point.r, {
|
|
7737
|
-
fill: point.color,
|
|
7738
|
-
fillAlpha: 0.7,
|
|
7739
|
-
stroke: tokens.color.background,
|
|
7740
|
-
strokeWidth: 1
|
|
7741
|
-
});
|
|
7742
|
-
if (point.alpha !== 1) ctx.globalAlpha = prev;
|
|
7743
|
-
}
|
|
7744
|
-
ctx.restore();
|
|
7745
|
-
return;
|
|
7746
|
-
}
|
|
7747
|
-
ctx.lineWidth = 1;
|
|
7748
|
-
ctx.strokeStyle = tokens.color.background;
|
|
7749
|
-
for (const point of drawPoints) {
|
|
7750
|
-
ctx.beginPath();
|
|
7751
|
-
ctx.arc(point.x, point.y, point.r, 0, Math.PI * 2);
|
|
7752
|
-
ctx.fillStyle = point.color;
|
|
7753
|
-
ctx.globalAlpha = 0.7 * point.alpha;
|
|
7754
|
-
ctx.fill();
|
|
7755
|
-
ctx.globalAlpha = point.alpha;
|
|
7756
|
-
ctx.stroke();
|
|
7757
|
-
}
|
|
7758
|
-
ctx.globalAlpha = 1;
|
|
7759
|
-
ctx.restore();
|
|
7760
|
-
}
|
|
7761
|
-
|
|
7762
7856
|
// src/charts/box.ts
|
|
7763
7857
|
function quantileSorted(sorted, p) {
|
|
7764
7858
|
const n = sorted.length;
|
|
@@ -8003,7 +8097,7 @@ function buildBoxInteraction(model) {
|
|
|
8003
8097
|
}
|
|
8004
8098
|
|
|
8005
8099
|
// src/charts/chrome.ts
|
|
8006
|
-
var CHROME_PAD = { top:
|
|
8100
|
+
var CHROME_PAD = { top: 0, right: 0, bottom: 0, left: 0 };
|
|
8007
8101
|
function resolveTitle2(title2) {
|
|
8008
8102
|
if (typeof title2 === "string") return { text: title2, align: "left" };
|
|
8009
8103
|
if (title2 && typeof title2 === "object") {
|
|
@@ -9905,7 +9999,7 @@ function layout(graph, area2, nodeWidth, pad3) {
|
|
|
9905
9999
|
const kx = maxLayer > 0 ? (area2.width - nodeWidth) / maxLayer : 0;
|
|
9906
10000
|
const maxColumnSize = columns.reduce((m, col) => Math.max(m, col.length), 0);
|
|
9907
10001
|
const desiredPad = Math.max(0, pad3);
|
|
9908
|
-
const effectivePad = maxColumnSize > 1
|
|
10002
|
+
const effectivePad = maxColumnSize > 1 ? Math.min(desiredPad, area2.height * 0.35 / (maxColumnSize - 1)) : desiredPad;
|
|
9909
10003
|
for (const col of columns) {
|
|
9910
10004
|
for (const n of col) {
|
|
9911
10005
|
n.x0 = area2.x + n.layer * kx;
|
|
@@ -10027,15 +10121,24 @@ function drawSankey(surface, spec, tokens, size) {
|
|
|
10027
10121
|
const graph = buildGraph(sankey, tokens.color.palette);
|
|
10028
10122
|
if (graph.nodes.length === 0 || content.width <= 0 || content.height <= 0) return;
|
|
10029
10123
|
const labelFont = fontString(f.size.small, f.family, f.weight.medium);
|
|
10030
|
-
|
|
10031
|
-
|
|
10032
|
-
const
|
|
10124
|
+
const valueFont = fontString(f.size.tiny, f.family, f.weight.normal);
|
|
10125
|
+
const showValues = sankey.nodeValues !== false;
|
|
10126
|
+
const labelExtent = (n) => {
|
|
10127
|
+
const nameW = measureText(n.name, labelFont).width;
|
|
10128
|
+
const valW = showValues ? measureText(formatValue(n.value, sankey.encoding.value.format), valueFont).width : 0;
|
|
10129
|
+
return Math.max(nameW, valW);
|
|
10130
|
+
};
|
|
10131
|
+
const colExtent = (col) => col.reduce((m, n) => Math.max(m, labelExtent(n)), 0);
|
|
10132
|
+
const LABEL_GAP = 6;
|
|
10133
|
+
const capGutter = content.width * 0.3;
|
|
10134
|
+
const leftGutter = Math.min(colExtent(graph.columns[0] ?? []) + LABEL_GAP + 4, capGutter);
|
|
10135
|
+
const rightGutter = graph.maxLayer > 0 ? Math.min(colExtent(graph.columns[graph.maxLayer] ?? []) + LABEL_GAP + 4, capGutter) : 0;
|
|
10033
10136
|
const nodeWidth = sankey.nodeWidth ?? 16;
|
|
10034
10137
|
const pad3 = sankey.nodePadding ?? 14;
|
|
10035
10138
|
const area2 = {
|
|
10036
|
-
x: content.x +
|
|
10139
|
+
x: content.x + leftGutter,
|
|
10037
10140
|
y: content.y + 4,
|
|
10038
|
-
width: Math.max(10, content.width -
|
|
10141
|
+
width: Math.max(10, content.width - leftGutter - rightGutter),
|
|
10039
10142
|
height: Math.max(10, content.height - 8)
|
|
10040
10143
|
};
|
|
10041
10144
|
layout(graph, area2, nodeWidth, pad3);
|
|
@@ -10059,12 +10162,13 @@ function drawSankey(surface, spec, tokens, size) {
|
|
|
10059
10162
|
}
|
|
10060
10163
|
}
|
|
10061
10164
|
ctx.restore();
|
|
10062
|
-
const showValues = sankey.nodeValues !== false;
|
|
10063
10165
|
const mid = area2.x + area2.width / 2;
|
|
10064
10166
|
for (const n of graph.nodes) {
|
|
10065
|
-
const
|
|
10167
|
+
const outerLeft = n.layer === 0;
|
|
10168
|
+
const outerRight = n.layer === graph.maxLayer && graph.maxLayer > 0;
|
|
10169
|
+
const labelRight = outerRight ? true : outerLeft ? false : n.x0 < mid;
|
|
10066
10170
|
const cy = center(n);
|
|
10067
|
-
const left = labelRight ? n.x1 +
|
|
10171
|
+
const left = labelRight ? n.x1 + LABEL_GAP : n.x0 - LABEL_GAP;
|
|
10068
10172
|
const transform2 = labelRight ? "translateY(-50%)" : "translate(-100%,-50%)";
|
|
10069
10173
|
addOverlayText(surface, tokens, {
|
|
10070
10174
|
left,
|
|
@@ -13422,7 +13526,6 @@ function scatterInteraction(model) {
|
|
|
13422
13526
|
}
|
|
13423
13527
|
|
|
13424
13528
|
// src/runtime/combo.ts
|
|
13425
|
-
var DEFAULT_PADDING2 = { top: 12, right: 16, bottom: 12, left: 12 };
|
|
13426
13529
|
function fmtTick(v, f) {
|
|
13427
13530
|
return f ? formatValue(v, f) : formatNumber2(v, ",");
|
|
13428
13531
|
}
|
|
@@ -13608,7 +13711,7 @@ function buildComboModel(spec, tokens, opts) {
|
|
|
13608
13711
|
const legendPosition = typeof spec.legend === "object" && spec.legend.position || (legendItems.length > 8 ? "right" : "top");
|
|
13609
13712
|
const xShow = xAxisCfg.show !== false;
|
|
13610
13713
|
const yShow = spec.axes?.y?.show !== false;
|
|
13611
|
-
const padding = { ...
|
|
13714
|
+
const padding = { ...NO_PADDING, ...spec.padding };
|
|
13612
13715
|
const titleInput4 = typeof spec.title === "string" ? { text: spec.title } : spec.title ? { text: spec.title.text, subtitle: spec.title.subtitle } : void 0;
|
|
13613
13716
|
const frame = computeFrame({
|
|
13614
13717
|
width: opts.width,
|
|
@@ -13830,7 +13933,6 @@ function renderLayer(surface, lm) {
|
|
|
13830
13933
|
}
|
|
13831
13934
|
|
|
13832
13935
|
// src/runtime/histogram.ts
|
|
13833
|
-
var DEFAULT_PADDING3 = { top: 12, right: 16, bottom: 12, left: 12 };
|
|
13834
13936
|
function firstPaletteColor(tokens) {
|
|
13835
13937
|
return rgbaToCss(ordinalColorScale({ domain: ["0"], palette: tokens.color.palette }).map("0"));
|
|
13836
13938
|
}
|
|
@@ -13882,7 +13984,7 @@ function buildHistogramModel(spec, tokens, opts) {
|
|
|
13882
13984
|
const xLabels = xTickValues.map((v) => xFmt ? formatValue(v, xFmt) : formatNumber2(v, ","));
|
|
13883
13985
|
const yFmt = spec.axes?.y?.format ?? (spec.density ? ".3~f" : void 0);
|
|
13884
13986
|
const yLabels = yTickValues.map((v) => yFmt ? formatValue(v, yFmt) : formatNumber2(v, ","));
|
|
13885
|
-
const padding = { ...
|
|
13987
|
+
const padding = { ...NO_PADDING, ...spec.padding };
|
|
13886
13988
|
const titleInput4 = typeof spec.title === "string" ? { text: spec.title } : spec.title ? { text: spec.title.text, subtitle: spec.title.subtitle } : void 0;
|
|
13887
13989
|
const xShow = spec.axes?.x?.show !== false;
|
|
13888
13990
|
const yShow = spec.axes?.y?.show !== false;
|
|
@@ -14088,6 +14190,12 @@ function labelFor(value) {
|
|
|
14088
14190
|
const key = toKey(value);
|
|
14089
14191
|
return key === "" ? "(blank)" : key;
|
|
14090
14192
|
}
|
|
14193
|
+
function textureShade(fill) {
|
|
14194
|
+
const lum = (0.299 * fill.r + 0.587 * fill.g + 0.114 * fill.b) / 255;
|
|
14195
|
+
const k = lum > 0.5 ? 0.68 : 1.4;
|
|
14196
|
+
const c = (n) => Math.max(0, Math.min(255, Math.round(n * k)));
|
|
14197
|
+
return rgbaToCss({ r: c(fill.r), g: c(fill.g), b: c(fill.b), a: 1 });
|
|
14198
|
+
}
|
|
14091
14199
|
function buildLeaves(treemap) {
|
|
14092
14200
|
const readCategory = accessor(treemap.encoding.category.field);
|
|
14093
14201
|
const readValue = accessor(treemap.encoding.value.field);
|
|
@@ -14171,13 +14279,20 @@ function tileProbe(treemap, tile) {
|
|
|
14171
14279
|
if (groupField) probe[groupField] = tile.group;
|
|
14172
14280
|
return probe;
|
|
14173
14281
|
}
|
|
14174
|
-
function drawRect2(ctx, pen, rect, fill, stroke) {
|
|
14282
|
+
function drawRect2(ctx, pen, rect, fill, fillCss, stroke) {
|
|
14175
14283
|
if (rect.width <= 0 || rect.height <= 0) return;
|
|
14176
14284
|
if (pen) {
|
|
14177
|
-
pen.rect(rect.x, rect.y, rect.width, rect.height, { fill
|
|
14285
|
+
pen.rect(rect.x, rect.y, rect.width, rect.height, { fill: fillCss, fillStyle: "solid" });
|
|
14286
|
+
pen.rect(rect.x, rect.y, rect.width, rect.height, {
|
|
14287
|
+
fill: textureShade(fill),
|
|
14288
|
+
fillStyle: "hachure",
|
|
14289
|
+
fillAlpha: 0.4,
|
|
14290
|
+
hachureGap: 7,
|
|
14291
|
+
stroke
|
|
14292
|
+
});
|
|
14178
14293
|
return;
|
|
14179
14294
|
}
|
|
14180
|
-
ctx.fillStyle =
|
|
14295
|
+
ctx.fillStyle = fillCss;
|
|
14181
14296
|
ctx.fillRect(rect.x, rect.y, rect.width, rect.height);
|
|
14182
14297
|
ctx.strokeStyle = stroke;
|
|
14183
14298
|
ctx.lineWidth = 1;
|
|
@@ -14247,7 +14362,7 @@ function drawTreemap(surface, spec, tokens, size, context) {
|
|
|
14247
14362
|
const drawTile = (tile) => {
|
|
14248
14363
|
const alpha = emphasis ? emphasis.match(tileProbe(treemap, tile)) ? 1 : emphasis.dim : 1;
|
|
14249
14364
|
if (alpha !== 1) ctx.globalAlpha = alpha;
|
|
14250
|
-
drawRect2(ctx, pen, tile.rect, tile.fillCss, stroke);
|
|
14365
|
+
drawRect2(ctx, pen, tile.rect, tile.fill, tile.fillCss, stroke);
|
|
14251
14366
|
if (alpha !== 1) ctx.globalAlpha = 1;
|
|
14252
14367
|
};
|
|
14253
14368
|
ctx.save();
|
|
@@ -14284,11 +14399,13 @@ function drawTreemap(surface, spec, tokens, size, context) {
|
|
|
14284
14399
|
ctx.strokeRect(rect.x + 0.5, rect.y + 0.5, Math.max(0, rect.width - 1), Math.max(0, rect.height - 1));
|
|
14285
14400
|
}
|
|
14286
14401
|
if (headerH > 0) {
|
|
14402
|
+
const headerFont = fontString(tokens.font.size.tiny, tokens.font.family, tokens.font.weight.bold);
|
|
14403
|
+
const headerW = Math.max(0, rect.width - 10);
|
|
14287
14404
|
addOverlayText(surface, tokens, {
|
|
14288
14405
|
left: rect.x + 5,
|
|
14289
14406
|
top: rect.y + 4,
|
|
14290
|
-
width:
|
|
14291
|
-
text: group.label,
|
|
14407
|
+
width: headerW,
|
|
14408
|
+
text: ellipsize(group.label, headerW, headerFont),
|
|
14292
14409
|
color: tokens.color.text,
|
|
14293
14410
|
size: tokens.font.size.tiny,
|
|
14294
14411
|
weight: tokens.font.weight.bold,
|
|
@@ -14497,12 +14614,11 @@ function drawGauge(surface, spec, tokens, size, context) {
|
|
|
14497
14614
|
const legendFont = fontString(tokens.font.size.small, tokens.font.family, tokens.font.weight.normal);
|
|
14498
14615
|
const legendW = legendEntries.length ? measureLegendWidth(legendEntries, legendFont) + 12 : 0;
|
|
14499
14616
|
const dialW = Math.max(40, content.width - legendW);
|
|
14500
|
-
const
|
|
14501
|
-
|
|
14502
|
-
|
|
14503
|
-
|
|
14504
|
-
);
|
|
14505
|
-
const trackWidth = clamp8(radius * 0.17, 14, 54);
|
|
14617
|
+
const availH = Math.max(0, content.height - captionReserve);
|
|
14618
|
+
const provR = Math.max(18, Math.min(dialW / 2, availH));
|
|
14619
|
+
const trackWidth = clamp8(provR * 0.17, 14, 54);
|
|
14620
|
+
const edgeGuard = trackWidth / 2 + clamp8(trackWidth * 0.3, 4, 10) + 1;
|
|
14621
|
+
const radius = Math.max(18, Math.min(provR, dialW / 2 - edgeGuard, availH - edgeGuard));
|
|
14506
14622
|
const cx = content.x + dialW / 2;
|
|
14507
14623
|
const blockH = radius + trackWidth / 2 + captionReserve;
|
|
14508
14624
|
const topMargin = Math.max(0, (content.height - blockH) / 2);
|
|
@@ -14645,10 +14761,7 @@ function drawBullet(surface, spec, tokens, size, context) {
|
|
|
14645
14761
|
}
|
|
14646
14762
|
const labelFont = fontString(tokens.font.size.small, tokens.font.family, tokens.font.weight.bold);
|
|
14647
14763
|
const valueFont = fontString(tokens.font.size.small, tokens.font.family, tokens.font.weight.normal);
|
|
14648
|
-
const labelW = Math.
|
|
14649
|
-
Math.max(72, content.width * 0.18, measureText(caption, labelFont).width + 18),
|
|
14650
|
-
Math.max(72, content.width * 0.38)
|
|
14651
|
-
);
|
|
14764
|
+
const labelW = clamp9(measureText(caption, labelFont).width + 14, 44, Math.max(72, content.width * 0.4));
|
|
14652
14765
|
const axisReserve = Math.max(24, tokens.font.size.tiny * 2);
|
|
14653
14766
|
const availableTrackW = Math.max(0, content.width - labelW);
|
|
14654
14767
|
const trackW = Math.max(0, availableTrackW - 4);
|
|
@@ -14766,7 +14879,6 @@ function drawBullet(surface, spec, tokens, size, context) {
|
|
|
14766
14879
|
// src/charts/calendarHeatmap.ts
|
|
14767
14880
|
var DAY_MS2 = 864e5;
|
|
14768
14881
|
var GAP2 = 2;
|
|
14769
|
-
var MAX_CELL = 16;
|
|
14770
14882
|
var WEEKDAY_LABELS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
14771
14883
|
var MONTH_LABELS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
14772
14884
|
function pad22(n) {
|
|
@@ -14789,9 +14901,9 @@ function addDays(date, days) {
|
|
|
14789
14901
|
d.setDate(d.getDate() + days);
|
|
14790
14902
|
return d;
|
|
14791
14903
|
}
|
|
14792
|
-
function drawRoundedCell2(ctx, x, y,
|
|
14904
|
+
function drawRoundedCell2(ctx, x, y, w, h, radius) {
|
|
14793
14905
|
ctx.beginPath();
|
|
14794
|
-
roundedRect(ctx, x, y,
|
|
14906
|
+
roundedRect(ctx, x, y, w, h, radius);
|
|
14795
14907
|
ctx.fill();
|
|
14796
14908
|
}
|
|
14797
14909
|
function noData(surface, tokens, content) {
|
|
@@ -14902,16 +15014,26 @@ function drawCalendarHeatmap(surface, spec, tokens, size, context) {
|
|
|
14902
15014
|
const labelHeight = Math.ceil(labelSize * 1.7) + 2;
|
|
14903
15015
|
const availableW = Math.max(0, content.width - leftGutter);
|
|
14904
15016
|
const availableH = Math.max(0, content.height - labelHeight);
|
|
14905
|
-
const
|
|
14906
|
-
|
|
15017
|
+
const MAX_ASPECT = 1.75;
|
|
15018
|
+
const rawW = (availableW - GAP2 * Math.max(0, grid.weeks - 1)) / grid.weeks;
|
|
15019
|
+
const rawH = (availableH - GAP2 * 6) / 7;
|
|
15020
|
+
const cellW = Math.floor(Math.max(1, Math.min(rawW, rawH * MAX_ASPECT)));
|
|
15021
|
+
const cellH = Math.floor(Math.max(1, Math.min(rawH, rawW * MAX_ASPECT)));
|
|
15022
|
+
if (!Number.isFinite(cellW) || !Number.isFinite(cellH) || cellW <= 0 || cellH <= 0) {
|
|
14907
15023
|
noData(surface, tokens, content);
|
|
14908
15024
|
return;
|
|
14909
15025
|
}
|
|
15026
|
+
const stepX = cellW + GAP2;
|
|
15027
|
+
const stepY = cellH + GAP2;
|
|
15028
|
+
const gridW = grid.weeks * cellW + Math.max(0, grid.weeks - 1) * GAP2;
|
|
15029
|
+
const gridH = 7 * cellH + 6 * GAP2;
|
|
15030
|
+
const vpad = Math.max(0, (availableH - gridH) / 2);
|
|
15031
|
+
const hpad = Math.max(0, (availableW - gridW) / 2);
|
|
14910
15032
|
const gridRect = {
|
|
14911
|
-
x: content.x + leftGutter,
|
|
14912
|
-
y: content.y + labelHeight,
|
|
14913
|
-
width:
|
|
14914
|
-
height:
|
|
15033
|
+
x: content.x + leftGutter + hpad,
|
|
15034
|
+
y: content.y + labelHeight + vpad,
|
|
15035
|
+
width: gridW,
|
|
15036
|
+
height: gridH
|
|
14915
15037
|
};
|
|
14916
15038
|
const values = days.map((d) => d.value);
|
|
14917
15039
|
const min = Math.min(...values);
|
|
@@ -14920,35 +15042,35 @@ function drawCalendarHeatmap(surface, spec, tokens, size, context) {
|
|
|
14920
15042
|
const cscale = sequentialColorScale({ domain: [min, max], interpolator: interp });
|
|
14921
15043
|
const sketch = resolveSketch(spec);
|
|
14922
15044
|
const pen = sketch ? new RoughPen(ctx, sketch) : null;
|
|
14923
|
-
const radius = Math.min(3, tokens.radius.sm,
|
|
15045
|
+
const radius = Math.min(3, tokens.radius.sm, Math.min(cellW, cellH) / 3);
|
|
14924
15046
|
const laidOut = /* @__PURE__ */ new Map();
|
|
14925
15047
|
ctx.save();
|
|
14926
15048
|
for (const c of grid.cells) {
|
|
14927
|
-
const x = gridRect.x + c.week *
|
|
14928
|
-
const y = gridRect.y + c.weekday *
|
|
15049
|
+
const x = gridRect.x + c.week * stepX;
|
|
15050
|
+
const y = gridRect.y + c.weekday * stepY;
|
|
14929
15051
|
const fill = c.present && c.value !== void 0 ? rgbaToCss(cscale.map(c.value)) : tokens.color.surface;
|
|
14930
|
-
laidOut.set(c.isoDate, { ...c, x, y,
|
|
15052
|
+
laidOut.set(c.isoDate, { ...c, x, y, w: cellW, h: cellH, fill });
|
|
14931
15053
|
ctx.globalAlpha = c.present ? rowAlpha(emphasis, c.row ?? { [dateField]: c.isoDate }) : 1;
|
|
14932
15054
|
if (pen) {
|
|
14933
|
-
pen.rect(x, y,
|
|
15055
|
+
pen.rect(x, y, cellW, cellH, {
|
|
14934
15056
|
fill,
|
|
14935
15057
|
fillStyle: "solid",
|
|
14936
15058
|
stroke: c.present ? fill : tokens.color.border
|
|
14937
15059
|
});
|
|
14938
15060
|
} else {
|
|
14939
15061
|
ctx.fillStyle = fill;
|
|
14940
|
-
drawRoundedCell2(ctx, x, y,
|
|
15062
|
+
drawRoundedCell2(ctx, x, y, cellW, cellH, radius);
|
|
14941
15063
|
ctx.strokeStyle = tokens.color.border;
|
|
14942
15064
|
ctx.lineWidth = 1;
|
|
14943
|
-
ctx.strokeRect(x + 0.5, y + 0.5, Math.max(0,
|
|
15065
|
+
ctx.strokeRect(x + 0.5, y + 0.5, Math.max(0, cellW - 1), Math.max(0, cellH - 1));
|
|
14944
15066
|
}
|
|
14945
15067
|
ctx.globalAlpha = 1;
|
|
14946
15068
|
}
|
|
14947
15069
|
ctx.restore();
|
|
14948
15070
|
for (const m of monthAnchors(grid)) {
|
|
14949
15071
|
addOverlayText(surface, tokens, {
|
|
14950
|
-
left: gridRect.x + m.week *
|
|
14951
|
-
top:
|
|
15072
|
+
left: gridRect.x + m.week * stepX,
|
|
15073
|
+
top: gridRect.y - labelHeight,
|
|
14952
15074
|
text: m.label,
|
|
14953
15075
|
color: tokens.color.textMuted,
|
|
14954
15076
|
size: labelSize
|
|
@@ -14957,7 +15079,7 @@ function drawCalendarHeatmap(surface, spec, tokens, size, context) {
|
|
|
14957
15079
|
for (const weekday of [1, 3, 5]) {
|
|
14958
15080
|
addOverlayText(surface, tokens, {
|
|
14959
15081
|
left: content.x,
|
|
14960
|
-
top: gridRect.y + weekday *
|
|
15082
|
+
top: gridRect.y + weekday * stepY + cellH / 2,
|
|
14961
15083
|
width: Math.max(0, leftGutter - tokens.spacing.xs),
|
|
14962
15084
|
text: WEEKDAY_LABELS[weekday],
|
|
14963
15085
|
color: tokens.color.textMuted,
|
|
@@ -14969,11 +15091,11 @@ function drawCalendarHeatmap(surface, spec, tokens, size, context) {
|
|
|
14969
15091
|
const colorLabel = cal.encoding.color.title ?? cal.encoding.color.field;
|
|
14970
15092
|
const hitCell = (px, py) => {
|
|
14971
15093
|
if (px < gridRect.x || py < gridRect.y || px > gridRect.x + gridRect.width || py > gridRect.y + gridRect.height) return null;
|
|
14972
|
-
const week = Math.floor((px - gridRect.x) /
|
|
14973
|
-
const weekday = Math.floor((py - gridRect.y) /
|
|
14974
|
-
const x = gridRect.x + week *
|
|
14975
|
-
const y = gridRect.y + weekday *
|
|
14976
|
-
if (week < 0 || week >= grid.weeks || weekday < 0 || weekday > 6 || px > x +
|
|
15094
|
+
const week = Math.floor((px - gridRect.x) / stepX);
|
|
15095
|
+
const weekday = Math.floor((py - gridRect.y) / stepY);
|
|
15096
|
+
const x = gridRect.x + week * stepX;
|
|
15097
|
+
const y = gridRect.y + weekday * stepY;
|
|
15098
|
+
if (week < 0 || week >= grid.weeks || weekday < 0 || weekday > 6 || px > x + cellW || py > y + cellH) return null;
|
|
14977
15099
|
const match = grid.cells.find((c) => c.week === week && c.weekday === weekday);
|
|
14978
15100
|
if (!match || !match.present) return null;
|
|
14979
15101
|
return laidOut.get(match.isoDate) ?? null;
|
|
@@ -15002,7 +15124,6 @@ function drawCalendarHeatmap(surface, spec, tokens, size, context) {
|
|
|
15002
15124
|
}
|
|
15003
15125
|
|
|
15004
15126
|
// src/runtime/waterfall.ts
|
|
15005
|
-
var DEFAULT_PADDING4 = { top: 12, right: 16, bottom: 12, left: 12 };
|
|
15006
15127
|
function labelFor2(value) {
|
|
15007
15128
|
if (value == null) return "";
|
|
15008
15129
|
if (value instanceof Date) return value.toISOString().slice(0, 10);
|
|
@@ -15110,7 +15231,7 @@ function buildWaterfallModel(spec, tokens, opts) {
|
|
|
15110
15231
|
const fmt = spec.encoding.value.format ?? spec.axes?.y?.format;
|
|
15111
15232
|
const yLabels = yTickValues.map((v) => fmt ? formatValue(v, fmt) : formatNumber2(v, ","));
|
|
15112
15233
|
const categories = bars.map((b) => b.label);
|
|
15113
|
-
const padding = { ...
|
|
15234
|
+
const padding = { ...NO_PADDING, ...spec.padding };
|
|
15114
15235
|
const xShow = spec.axes?.x?.show !== false;
|
|
15115
15236
|
const yShow = spec.axes?.y?.show !== false;
|
|
15116
15237
|
const xTitle = spec.axes?.x?.title ?? spec.encoding.stage.title;
|
|
@@ -15351,7 +15472,6 @@ function drawWaterfall(surface, spec, tokens, size, context) {
|
|
|
15351
15472
|
}
|
|
15352
15473
|
|
|
15353
15474
|
// src/runtime/slope.ts
|
|
15354
|
-
var DEFAULT_PADDING5 = { top: 16, right: 76, bottom: 26, left: 76 };
|
|
15355
15475
|
function labelFor3(value) {
|
|
15356
15476
|
if (value == null) return "";
|
|
15357
15477
|
if (value instanceof Date) return value.toISOString().slice(0, 10);
|
|
@@ -15387,7 +15507,44 @@ function buildSlopeModel(spec, tokens, opts) {
|
|
|
15387
15507
|
];
|
|
15388
15508
|
const fmt = spec.format ?? spec.encoding.y.format ?? spec.axes?.y?.format;
|
|
15389
15509
|
const yLabels = yTickValues.map((v) => fmtTick2(v, fmt));
|
|
15390
|
-
const
|
|
15510
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
15511
|
+
for (const row of data) {
|
|
15512
|
+
const rawSeries = readSeries(row);
|
|
15513
|
+
const key = toKey(rawSeries);
|
|
15514
|
+
let group = grouped.get(key);
|
|
15515
|
+
if (!group) {
|
|
15516
|
+
group = { key, label: labelFor3(rawSeries), value: rawSeries, values: /* @__PURE__ */ new Map() };
|
|
15517
|
+
grouped.set(key, group);
|
|
15518
|
+
}
|
|
15519
|
+
const rawX = readX(row);
|
|
15520
|
+
const catKey = labelFor3(rawX);
|
|
15521
|
+
const value = toNumber(readY(row));
|
|
15522
|
+
if (!Number.isNaN(value) && !group.values.has(catKey)) group.values.set(catKey, value);
|
|
15523
|
+
}
|
|
15524
|
+
const showLabels = spec.labels !== false;
|
|
15525
|
+
let leftLabelW = 0;
|
|
15526
|
+
let rightLabelW = 0;
|
|
15527
|
+
if (showLabels) {
|
|
15528
|
+
const boldTiny = fontString(tokens.font.size.tiny, tokens.font.family, tokens.font.weight.bold);
|
|
15529
|
+
const normTiny = fontString(tokens.font.size.tiny, tokens.font.family, tokens.font.weight.normal);
|
|
15530
|
+
for (const group of grouped.values()) {
|
|
15531
|
+
const present = categories.filter((c) => group.values.has(c));
|
|
15532
|
+
if (present.length === 0) continue;
|
|
15533
|
+
const firstV = group.values.get(present[0]);
|
|
15534
|
+
const lastV = group.values.get(present[present.length - 1]);
|
|
15535
|
+
leftLabelW = Math.max(
|
|
15536
|
+
leftLabelW,
|
|
15537
|
+
measureText(group.label, boldTiny).width,
|
|
15538
|
+
measureText(fmtTick2(firstV, fmt), normTiny).width
|
|
15539
|
+
);
|
|
15540
|
+
rightLabelW = Math.max(rightLabelW, measureText(fmtTick2(lastV, fmt), normTiny).width);
|
|
15541
|
+
}
|
|
15542
|
+
leftLabelW = Math.ceil(leftLabelW);
|
|
15543
|
+
rightLabelW = Math.ceil(rightLabelW);
|
|
15544
|
+
}
|
|
15545
|
+
const labelBand = tokens.font.size.tiny + 4;
|
|
15546
|
+
const basePadding = showLabels ? { top: labelBand, right: rightLabelW + 8, bottom: labelBand, left: leftLabelW + 8 } : { top: 0, right: 0, bottom: 0, left: 0 };
|
|
15547
|
+
const padding = { ...basePadding, ...spec.padding };
|
|
15391
15548
|
const xShow = spec.axes?.x?.show !== false;
|
|
15392
15549
|
const yShow = spec.axes?.y?.show === true;
|
|
15393
15550
|
const xTitle = spec.axes?.x?.title ?? spec.encoding.x.title;
|
|
@@ -15404,20 +15561,6 @@ function buildSlopeModel(spec, tokens, opts) {
|
|
|
15404
15561
|
const plot = frame.plot;
|
|
15405
15562
|
const point = pointScale({ domain: categories, range: [plot.x, plot.x + plot.width], padding: 0.5 });
|
|
15406
15563
|
const yScale = linearScale({ domain: yDomain, range: [plot.y + plot.height, plot.y] });
|
|
15407
|
-
const grouped = /* @__PURE__ */ new Map();
|
|
15408
|
-
for (const row of data) {
|
|
15409
|
-
const rawSeries = readSeries(row);
|
|
15410
|
-
const key = toKey(rawSeries);
|
|
15411
|
-
let group = grouped.get(key);
|
|
15412
|
-
if (!group) {
|
|
15413
|
-
group = { key, label: labelFor3(rawSeries), value: rawSeries, values: /* @__PURE__ */ new Map() };
|
|
15414
|
-
grouped.set(key, group);
|
|
15415
|
-
}
|
|
15416
|
-
const rawX = readX(row);
|
|
15417
|
-
const catKey = labelFor3(rawX);
|
|
15418
|
-
const value = toNumber(readY(row));
|
|
15419
|
-
if (!Number.isNaN(value) && !group.values.has(catKey)) group.values.set(catKey, value);
|
|
15420
|
-
}
|
|
15421
15564
|
const palette = ordinalColorScale({ domain: [...grouped.keys()], palette: tokens.color.palette });
|
|
15422
15565
|
const series = [...grouped.values()].map((group) => {
|
|
15423
15566
|
const points = categories.map((catKey) => {
|
|
@@ -15486,7 +15629,9 @@ function buildSlopeModel(spec, tokens, opts) {
|
|
|
15486
15629
|
series,
|
|
15487
15630
|
categories,
|
|
15488
15631
|
format: fmt,
|
|
15489
|
-
showLabels
|
|
15632
|
+
showLabels,
|
|
15633
|
+
leftLabelW,
|
|
15634
|
+
rightLabelW,
|
|
15490
15635
|
base,
|
|
15491
15636
|
sketch
|
|
15492
15637
|
};
|
|
@@ -15494,13 +15639,15 @@ function buildSlopeModel(spec, tokens, opts) {
|
|
|
15494
15639
|
|
|
15495
15640
|
// src/charts/slope.ts
|
|
15496
15641
|
var HIT_RADIUS2 = 8;
|
|
15497
|
-
var LABEL_WIDTH = 68;
|
|
15498
15642
|
function fmtValue(v, format) {
|
|
15499
15643
|
return format ? formatValue(v, format) : formatNumber2(v, ",");
|
|
15500
15644
|
}
|
|
15501
15645
|
function drawLines(surface, model, alphaOf) {
|
|
15502
15646
|
const ctx = surface.marks.ctx;
|
|
15503
15647
|
const pen = model.sketch ? new RoughPen(ctx, model.sketch) : null;
|
|
15648
|
+
const strokeW = lineStrokeWidth(model.plot);
|
|
15649
|
+
const dotR = Math.min(6, markerRadius(model.plot, 2));
|
|
15650
|
+
const dotSW = markerStroke(dotR);
|
|
15504
15651
|
ctx.save();
|
|
15505
15652
|
ctx.beginPath();
|
|
15506
15653
|
ctx.rect(model.plot.x, model.plot.y, model.plot.width, model.plot.height);
|
|
@@ -15510,11 +15657,11 @@ function drawLines(surface, model, alphaOf) {
|
|
|
15510
15657
|
if (points.length === 0) continue;
|
|
15511
15658
|
ctx.globalAlpha = alphaOf(series);
|
|
15512
15659
|
if (pen && points.length >= 2) {
|
|
15513
|
-
pen.polyline(points, { stroke: series.color });
|
|
15660
|
+
pen.polyline(points, { stroke: series.color, strokeWidth: strokeW });
|
|
15514
15661
|
} else if (points.length >= 2) {
|
|
15515
15662
|
ctx.beginPath();
|
|
15516
15663
|
ctx.strokeStyle = series.color;
|
|
15517
|
-
ctx.lineWidth =
|
|
15664
|
+
ctx.lineWidth = strokeW;
|
|
15518
15665
|
ctx.lineJoin = "round";
|
|
15519
15666
|
ctx.lineCap = "round";
|
|
15520
15667
|
ctx.moveTo(points[0].x, points[0].y);
|
|
@@ -15523,13 +15670,13 @@ function drawLines(surface, model, alphaOf) {
|
|
|
15523
15670
|
}
|
|
15524
15671
|
for (const p of points) {
|
|
15525
15672
|
if (pen) {
|
|
15526
|
-
pen.circle(p.x, p.y,
|
|
15673
|
+
pen.circle(p.x, p.y, dotR, { fill: series.color, stroke: series.color });
|
|
15527
15674
|
} else {
|
|
15528
15675
|
ctx.beginPath();
|
|
15529
15676
|
ctx.fillStyle = series.color;
|
|
15530
15677
|
ctx.strokeStyle = model.tokens.color.background;
|
|
15531
|
-
ctx.lineWidth =
|
|
15532
|
-
ctx.arc(p.x, p.y,
|
|
15678
|
+
ctx.lineWidth = dotSW;
|
|
15679
|
+
ctx.arc(p.x, p.y, dotR, 0, Math.PI * 2);
|
|
15533
15680
|
ctx.fill();
|
|
15534
15681
|
ctx.stroke();
|
|
15535
15682
|
}
|
|
@@ -15543,15 +15690,17 @@ function drawEndLabels(surface, model, alphaOf) {
|
|
|
15543
15690
|
const { tokens } = model;
|
|
15544
15691
|
const labelSize = tokens.font.size.tiny;
|
|
15545
15692
|
const valueSize = tokens.font.size.tiny;
|
|
15693
|
+
const leftW = model.leftLabelW;
|
|
15694
|
+
const rightW = model.rightLabelW;
|
|
15546
15695
|
for (const series of model.series) {
|
|
15547
15696
|
if (series.points.length === 0) continue;
|
|
15548
15697
|
const opacity = alphaOf(series) === 1 ? 1 : 0.5;
|
|
15549
15698
|
const first = series.points[0];
|
|
15550
15699
|
const last = series.points[series.points.length - 1];
|
|
15551
15700
|
addOverlayText(surface, tokens, {
|
|
15552
|
-
left: first.x - 8 -
|
|
15701
|
+
left: first.x - 8 - leftW,
|
|
15553
15702
|
top: first.y - labelSize - 2,
|
|
15554
|
-
width:
|
|
15703
|
+
width: leftW,
|
|
15555
15704
|
text: series.label,
|
|
15556
15705
|
color: series.color,
|
|
15557
15706
|
size: labelSize,
|
|
@@ -15560,9 +15709,9 @@ function drawEndLabels(surface, model, alphaOf) {
|
|
|
15560
15709
|
opacity
|
|
15561
15710
|
});
|
|
15562
15711
|
addOverlayText(surface, tokens, {
|
|
15563
|
-
left: first.x - 8 -
|
|
15712
|
+
left: first.x - 8 - leftW,
|
|
15564
15713
|
top: first.y + 1,
|
|
15565
|
-
width:
|
|
15714
|
+
width: leftW,
|
|
15566
15715
|
text: fmtValue(first.value, model.format),
|
|
15567
15716
|
color: tokens.color.textMuted,
|
|
15568
15717
|
size: valueSize,
|
|
@@ -15573,7 +15722,7 @@ function drawEndLabels(surface, model, alphaOf) {
|
|
|
15573
15722
|
addOverlayText(surface, tokens, {
|
|
15574
15723
|
left: last.x + 8,
|
|
15575
15724
|
top: last.y - valueSize / 2,
|
|
15576
|
-
width:
|
|
15725
|
+
width: rightW,
|
|
15577
15726
|
text: fmtValue(last.value, model.format),
|
|
15578
15727
|
color: series.color,
|
|
15579
15728
|
size: valueSize,
|
|
@@ -15747,7 +15896,7 @@ function measureMax2(labels, font) {
|
|
|
15747
15896
|
function valueLabel(value, format) {
|
|
15748
15897
|
return format ? formatValue(value, format) : formatNumber2(value, ",");
|
|
15749
15898
|
}
|
|
15750
|
-
function drawConnector(ctx, pen, x1, x2, y, tokens) {
|
|
15899
|
+
function drawConnector(ctx, pen, x1, x2, y, width, tokens) {
|
|
15751
15900
|
if (pen) {
|
|
15752
15901
|
pen.polyline(
|
|
15753
15902
|
[
|
|
@@ -15763,13 +15912,12 @@ function drawConnector(ctx, pen, x1, x2, y, tokens) {
|
|
|
15763
15912
|
ctx.moveTo(x1, y);
|
|
15764
15913
|
ctx.lineTo(x2, y);
|
|
15765
15914
|
ctx.strokeStyle = tokens.color.axis;
|
|
15766
|
-
ctx.lineWidth =
|
|
15915
|
+
ctx.lineWidth = width;
|
|
15767
15916
|
ctx.lineCap = "round";
|
|
15768
15917
|
ctx.stroke();
|
|
15769
15918
|
ctx.restore();
|
|
15770
15919
|
}
|
|
15771
|
-
function drawDot(ctx, pen, x, y, color, tokens) {
|
|
15772
|
-
const r = 5;
|
|
15920
|
+
function drawDot(ctx, pen, x, y, r, color, tokens) {
|
|
15773
15921
|
if (pen) {
|
|
15774
15922
|
pen.circle(x, y, r + 1.5, { fill: tokens.color.background, stroke: tokens.color.background });
|
|
15775
15923
|
pen.circle(x, y, r, { fill: color, stroke: tokens.color.background });
|
|
@@ -15780,16 +15928,16 @@ function drawDot(ctx, pen, x, y, color, tokens) {
|
|
|
15780
15928
|
ctx.arc(x, y, r, 0, Math.PI * 2);
|
|
15781
15929
|
ctx.fillStyle = color;
|
|
15782
15930
|
ctx.fill();
|
|
15783
|
-
ctx.lineWidth = 1.5;
|
|
15931
|
+
ctx.lineWidth = Math.max(1.5, r * 0.3);
|
|
15784
15932
|
ctx.strokeStyle = tokens.color.background;
|
|
15785
15933
|
ctx.stroke();
|
|
15786
15934
|
ctx.restore();
|
|
15787
15935
|
}
|
|
15788
|
-
function layoutPlot(content, labelWidth, tokens) {
|
|
15936
|
+
function layoutPlot(content, labelWidth, rightReserve, tokens) {
|
|
15789
15937
|
const leftGutter = Math.ceil(Math.min(content.width * 0.3, Math.max(42, labelWidth + tokens.spacing.sm)));
|
|
15790
15938
|
const axisHeight = 28;
|
|
15791
15939
|
const topPad = Math.min(6, CHROME_PAD.top / 2);
|
|
15792
|
-
const rightPad = 8;
|
|
15940
|
+
const rightPad = Math.max(8, Math.ceil(rightReserve));
|
|
15793
15941
|
return {
|
|
15794
15942
|
leftGutter,
|
|
15795
15943
|
axisHeight,
|
|
@@ -15824,7 +15972,16 @@ function drawDumbbell(surface, spec, tokens, size, context) {
|
|
|
15824
15972
|
}
|
|
15825
15973
|
const labelFont = fontString(tokens.font.size.small, tokens.font.family, tokens.font.weight.normal);
|
|
15826
15974
|
const widestCategory = measureMax2(model.rows.map((row) => row.catLabel), labelFont);
|
|
15827
|
-
|
|
15975
|
+
let valueReserve = 0;
|
|
15976
|
+
if (dumbbell.labels) {
|
|
15977
|
+
const valueFont = fontString(tokens.font.size.tiny, tokens.font.family, tokens.font.weight.normal);
|
|
15978
|
+
const widestValue = measureMax2(
|
|
15979
|
+
model.rows.flatMap((row) => row.dots.map((dot) => formatDumbbellValue(dot.value, model.format))),
|
|
15980
|
+
valueFont
|
|
15981
|
+
);
|
|
15982
|
+
valueReserve = Math.min(content.width * 0.2, widestValue + 9);
|
|
15983
|
+
}
|
|
15984
|
+
const { plot, leftGutter } = layoutPlot(content, widestCategory, valueReserve, tokens);
|
|
15828
15985
|
if (plot.width <= 8 || plot.height <= 8) return;
|
|
15829
15986
|
const xScale = linearScale({ domain: model.valueDomain, range: [plot.x, plot.x + plot.width] });
|
|
15830
15987
|
const yBand = bandScale({ domain: model.categories, range: [plot.y, plot.y + plot.height], paddingInner: 0.45, paddingOuter: 0.25 });
|
|
@@ -15851,6 +16008,9 @@ function drawDumbbell(surface, spec, tokens, size, context) {
|
|
|
15851
16008
|
}
|
|
15852
16009
|
ctx.restore();
|
|
15853
16010
|
const pixelRows = [];
|
|
16011
|
+
const dotR = Math.max(4, Math.min(13, yBand.bandwidth * 0.16));
|
|
16012
|
+
const connectorW = Math.max(3, Math.min(9, dotR * 0.7));
|
|
16013
|
+
const labelGap = Math.round(dotR + 4);
|
|
15854
16014
|
for (const row of model.rows) {
|
|
15855
16015
|
const bandTop = yBand.map(row.catKey);
|
|
15856
16016
|
if (bandTop === void 0) continue;
|
|
@@ -15868,8 +16028,8 @@ function drawDumbbell(surface, spec, tokens, size, context) {
|
|
|
15868
16028
|
if (pixelDots.length === 0) continue;
|
|
15869
16029
|
pixelRows.push({ ...row, y: cy, pixelDots });
|
|
15870
16030
|
ctx.globalAlpha = rowAlpha(emphasis, { [categoryField]: row.catRawValue });
|
|
15871
|
-
drawConnector(ctx, pen, pixelDots[0].x, pixelDots[pixelDots.length - 1].x, cy, tokens);
|
|
15872
|
-
for (const dot of pixelDots) drawDot(ctx, pen, dot.x, cy, dot.color, tokens);
|
|
16031
|
+
drawConnector(ctx, pen, pixelDots[0].x, pixelDots[pixelDots.length - 1].x, cy, connectorW, tokens);
|
|
16032
|
+
for (const dot of pixelDots) drawDot(ctx, pen, dot.x, cy, dotR, dot.color, tokens);
|
|
15873
16033
|
ctx.globalAlpha = 1;
|
|
15874
16034
|
addOverlayText(surface, tokens, {
|
|
15875
16035
|
left: content.x,
|
|
@@ -15886,7 +16046,7 @@ function drawDumbbell(surface, spec, tokens, size, context) {
|
|
|
15886
16046
|
const dot = pixelDots[i];
|
|
15887
16047
|
const atLeft = i === 0 && pixelDots.length > 1;
|
|
15888
16048
|
addOverlayText(surface, tokens, {
|
|
15889
|
-
left: atLeft ? dot.x -
|
|
16049
|
+
left: atLeft ? dot.x - labelGap : dot.x + labelGap,
|
|
15890
16050
|
top: cy,
|
|
15891
16051
|
width: 54,
|
|
15892
16052
|
text: formatDumbbellValue(dot.value, model.format),
|
|
@@ -16074,10 +16234,13 @@ function labelBox(model, horizontalRule, pos, p) {
|
|
|
16074
16234
|
const inset = 6;
|
|
16075
16235
|
if (horizontalRule) {
|
|
16076
16236
|
const top = p - 3;
|
|
16077
|
-
|
|
16078
|
-
|
|
16079
|
-
|
|
16080
|
-
|
|
16237
|
+
if (pos === "start") {
|
|
16238
|
+
return { left: plot.x + inset, top, align: "left", transform: "translateY(-100%)" };
|
|
16239
|
+
}
|
|
16240
|
+
if (pos === "middle") {
|
|
16241
|
+
return { left: plot.x + plot.width / 2, top, align: "center", transform: "translateX(-50%) translateY(-100%)" };
|
|
16242
|
+
}
|
|
16243
|
+
return { left: plot.x + plot.width - inset, top, align: "right", transform: "translateX(-100%) translateY(-100%)" };
|
|
16081
16244
|
}
|
|
16082
16245
|
const left = p;
|
|
16083
16246
|
const transform2 = "translateX(-50%)";
|
|
@@ -16252,7 +16415,8 @@ function drawTrendlineLabels(surface, model) {
|
|
|
16252
16415
|
const y1 = model.y.pixel(g.fit.predict(g.xMax));
|
|
16253
16416
|
if (x1 == null || !Number.isFinite(x1) || !Number.isFinite(y1)) continue;
|
|
16254
16417
|
const text = `R\xB2=${g.fit.r2.toFixed(2)}`;
|
|
16255
|
-
const
|
|
16418
|
+
const labelW = measureText(text, font).width;
|
|
16419
|
+
const nearRight = x1 + 6 + labelW > plot.x + plot.width;
|
|
16256
16420
|
const left = nearRight ? x1 - 6 : x1 + 6;
|
|
16257
16421
|
const align = nearRight ? "right" : "left";
|
|
16258
16422
|
const transform2 = nearRight ? "translateX(-100%) translateY(-50%)" : "translateY(-50%)";
|
|
@@ -16767,6 +16931,7 @@ function dependentParams(highlight, filter, ownParams = []) {
|
|
|
16767
16931
|
var MARK_CONTRAST_MIN = 1.5;
|
|
16768
16932
|
var TEXT_CONTRAST_MIN = 4.5;
|
|
16769
16933
|
var MAX_DISTINGUISHABLE_SERIES = 8;
|
|
16934
|
+
var DEFAULT_POINT_MARKER_RADIUS = 3.5;
|
|
16770
16935
|
var SEVERITY_RANK = { error: 0, warning: 1, info: 2 };
|
|
16771
16936
|
var VALUE_CHART_TYPES = /* @__PURE__ */ new Set(["kpi", "gauge", "bullet"]);
|
|
16772
16937
|
var CONTINUOUS_COLOR_TYPES = /* @__PURE__ */ new Set([
|
|
@@ -16824,6 +16989,7 @@ function buildRenderReport(input) {
|
|
|
16824
16989
|
if (model) {
|
|
16825
16990
|
checkDegenerateAxis(model, add);
|
|
16826
16991
|
checkClippedMarks(model, spec, add);
|
|
16992
|
+
checkAnnotationOverflow(model, spec, tokens, add);
|
|
16827
16993
|
checkAxisLabelOverlap(model, spec, tokens, add);
|
|
16828
16994
|
checkLegendOverflow(model, spec, add);
|
|
16829
16995
|
}
|
|
@@ -16943,6 +17109,69 @@ function checkClippedMarks(model, spec, add) {
|
|
|
16943
17109
|
});
|
|
16944
17110
|
}
|
|
16945
17111
|
}
|
|
17112
|
+
function checkAnnotationOverflow(model, spec, tokens, add) {
|
|
17113
|
+
if (model.orientation === "horizontal") return;
|
|
17114
|
+
const explicit = spec.annotations;
|
|
17115
|
+
const points = Array.isArray(explicit) ? explicit.filter((a) => a.type === "point") : [];
|
|
17116
|
+
for (const a of autoInsightAnnotations(spec)) points.push(a);
|
|
17117
|
+
if (points.length === 0) return;
|
|
17118
|
+
const { plot } = model;
|
|
17119
|
+
const fontSize = tokens.font.size.small;
|
|
17120
|
+
const font = fontString(fontSize, tokens.font.family, tokens.font.weight.medium);
|
|
17121
|
+
const EPS = 0.75;
|
|
17122
|
+
const sides = /* @__PURE__ */ new Set();
|
|
17123
|
+
const artifacts = /* @__PURE__ */ new Set();
|
|
17124
|
+
let clippedAnnotations = 0;
|
|
17125
|
+
let clippedArtifacts = 0;
|
|
17126
|
+
for (const ann of points) {
|
|
17127
|
+
const cat = model.x.pixel(ann.x);
|
|
17128
|
+
const val = model.y.pixel(ann.y);
|
|
17129
|
+
if (cat == null || val == null || !Number.isFinite(cat) || !Number.isFinite(val)) continue;
|
|
17130
|
+
const { x: px, y: py } = model.project(cat, val);
|
|
17131
|
+
const r = ann.markerRadius ?? DEFAULT_POINT_MARKER_RADIUS;
|
|
17132
|
+
const halo = r + 1.6;
|
|
17133
|
+
const markerSides = overflowSides(px - halo, py - halo, px + halo, py + halo, plot, EPS);
|
|
17134
|
+
let annClipped = false;
|
|
17135
|
+
if (markerSides.length) {
|
|
17136
|
+
clippedArtifacts++;
|
|
17137
|
+
annClipped = true;
|
|
17138
|
+
artifacts.add("marker");
|
|
17139
|
+
markerSides.forEach((s) => sides.add(s));
|
|
17140
|
+
}
|
|
17141
|
+
if (!ann.label) continue;
|
|
17142
|
+
const gap = r + 4;
|
|
17143
|
+
const width = measureText(ann.label, font).width + 6;
|
|
17144
|
+
const aboveTop = py - gap - fontSize;
|
|
17145
|
+
const top = aboveTop < plot.y ? py + gap : aboveTop;
|
|
17146
|
+
const labelSides = overflowSides(px - width / 2, top, px + width / 2, top + fontSize, plot, EPS);
|
|
17147
|
+
if (labelSides.length) {
|
|
17148
|
+
clippedArtifacts++;
|
|
17149
|
+
annClipped = true;
|
|
17150
|
+
artifacts.add("label");
|
|
17151
|
+
labelSides.forEach((s) => sides.add(s));
|
|
17152
|
+
}
|
|
17153
|
+
if (annClipped) clippedAnnotations++;
|
|
17154
|
+
}
|
|
17155
|
+
if (clippedAnnotations > 0) {
|
|
17156
|
+
const artifactList = [...artifacts].join(" and ");
|
|
17157
|
+
const sideList = [...sides].join(", ");
|
|
17158
|
+
add({
|
|
17159
|
+
code: "annotation-clipped",
|
|
17160
|
+
severity: "warning",
|
|
17161
|
+
message: `${clippedAnnotations} point annotation ${artifactList} overflow${clippedAnnotations === 1 ? "s" : ""} the plot (${sideList}); the chart is too small to fit its annotation labels.`,
|
|
17162
|
+
details: { clipped: clippedAnnotations, clippedArtifacts, artifacts: [...artifacts], sides: [...sides] },
|
|
17163
|
+
hint: "Enlarge the chart, shorten annotation labels, or remove labels/insights that cannot fit."
|
|
17164
|
+
});
|
|
17165
|
+
}
|
|
17166
|
+
}
|
|
17167
|
+
function overflowSides(left, top, right, bottom, plot, eps) {
|
|
17168
|
+
const sides = [];
|
|
17169
|
+
if (left < plot.x - eps) sides.push("left");
|
|
17170
|
+
if (right > plot.x + plot.width + eps) sides.push("right");
|
|
17171
|
+
if (top < plot.y - eps) sides.push("top");
|
|
17172
|
+
if (bottom > plot.y + plot.height + eps) sides.push("bottom");
|
|
17173
|
+
return sides;
|
|
17174
|
+
}
|
|
16946
17175
|
function checkAxisLabelOverlap(model, spec, tokens, add) {
|
|
16947
17176
|
const ticks2 = model.xTicks;
|
|
16948
17177
|
if (ticks2.length < 2) return;
|
|
@@ -17030,7 +17259,7 @@ function manualYDomainFix(spec) {
|
|
|
17030
17259
|
// src/runtime/facet.ts
|
|
17031
17260
|
var FACETABLE_TYPES2 = /* @__PURE__ */ new Set(["line", "area", "bar", "scatter"]);
|
|
17032
17261
|
var FACET_GAP = 16;
|
|
17033
|
-
var FACET_PADDING = { top:
|
|
17262
|
+
var FACET_PADDING = { top: 0, right: 0, bottom: 0, left: 0 };
|
|
17034
17263
|
var SEVERITY_RANK2 = { error: 0, warning: 1, info: 2 };
|
|
17035
17264
|
function isFaceted(spec) {
|
|
17036
17265
|
const facet = spec.facet;
|
|
@@ -18719,6 +18948,6 @@ function renderToContext(target, spec) {
|
|
|
18719
18948
|
// src/index.ts
|
|
18720
18949
|
var VERSION = "0.1.0";
|
|
18721
18950
|
|
|
18722
|
-
export { CARTESIAN_TYPES, CHART_TYPES, CanvasLayer, DEFAULT_ENTRANCE_DURATION, DEFAULT_ROUGH_STYLE, DEFAULT_UPDATE_DURATION, DIM_ALPHA, ExpressionError, FACETABLE_TYPES2 as FACETABLE_TYPES, FUNCTION_NAMES, InteractionController, RoughPen, SKETCH_FONT_FAMILY, SKETCH_FONT_NAME, SLICER_TYPES, SR_ONLY_STYLE, Surface, TICK_SIZE, TIME_UNITS, TRANSFORM_KINDS, Tooltip, VERSION, aggregateValues, analyzeChart, animate, applyA11y, applyAggregate, applyBin, applyCalculate, applyFilter, applyFold, applyPatch, applyPick, applyTimeUnit, applyTransform, applyTransforms, arc, area, assertValidSpec, autoInsightAnnotations, backOut, bandScale, bounceOut, buildCartesianInteraction, buildCartesianModel, buildComboModel, buildDataTableFallback, buildFacetModels, buildHistogramModel, buildRenderReport, cartesianInteractionBuilders, cartesianRenderers, categorical, categoricalSchemes, chartTitleText, chartTypeLabel, checkExpression, clamp012 as clamp01, clamp255, compileExpression, compilePredicate, computeBackingSize, computeBins, computeFrame, computeSeriesInsights, contrastRatio, createDiv, createRoughPen, createSelectionStore, cubicIn, cubicInOut, cubicOut, curveCatmullRom, curveLinear, curveMonotoneX, curveStep, curveStepAfter, curveStepBefore, customRenderers, darkTheme, decimate, defaultSpan, dependentParams, diverging, divergingColorScale, divergingSchemes, drawAnnotationLabels, drawAnnotations, drawAxesUnderlay, drawFacet, drawLegend, drawOverlay, drawTitle, drawTrendlineLabels, drawTrendlines, easings, elasticOut, ellipsize, ensureSketchFont, expoInOut, expoOut, facetReport, fillParentStyle, filterRows, fontString, formatDate, formatNumber2 as formatNumber, formatValue, getDevicePixelRatio, groupBy, hashString, inferFieldType, inferFieldTypes, inferValueType, inheritInto, interpolateArray, interpolateNumber, interpolateNumberArray, interpolateObject, interpolateOklab, interpolateRgb, isBrowser, isEmptyValue, isFaceted, isParamClause, isSlicerType, keyFields, legendSwatchWidth, lightTheme, line, linear, linearRegression, linearScale, linearToSrgb, lintSpec, literalToValue, logScale, lttbRun, makeMatcher, matchesValue, measureText, monotoneXTangents, mulberry32, niceDomain, oklabToOklch, oklabToRgb, oklchToOklab, ordinalColorScale, overlayTextToCanvasCmd, paintCanvasText, paintLegendSwatch, parseColor, parseNumberFormat, pivot, placeViews, pointScale, polygonHachureLines, prefersReducedMotion, prettyDate, profileColumns, quadIn, quadInOut, quadOut, rampFromStops, readableTextColor, recommendChart, relativeLuminance, render, renderDashboard, renderToContext, repairReport, repairSpec, resolveCurve, resolveDashboardLayout, resolveDashboardSections, resolveEmphasis, resolveEntrance, resolveFilterValues, resolveInsightOptions, resolveSketch, resolveTheme, resolveUpdate, resolveValueRef, rgbToOklab, rgbaToCss, rotatePoint, roundedRect, sampleArc, sequential, sequentialColorScale, sequentialSchemes, setMeasureContext, setStyle, sinInOut, slicerParamName, smartDate, specFields, srgbToLinear, summarize, summarizeChart, themes, tickIncrement, tickStep, ticks, timeScale, timeTickFormat, timeTicks, toHex, toPointer, tooltipEnabled, truncateTo, validateDashboard, validateSpec, wireViews, withAlpha, withSketchFont };
|
|
18951
|
+
export { CARTESIAN_TYPES, CHART_TYPES, CanvasLayer, DEFAULT_ENTRANCE_DURATION, DEFAULT_ROUGH_STYLE, DEFAULT_UPDATE_DURATION, DIM_ALPHA, ExpressionError, FACETABLE_TYPES2 as FACETABLE_TYPES, FUNCTION_NAMES, InteractionController, NO_PADDING, RoughPen, SKETCH_FONT_FAMILY, SKETCH_FONT_NAME, SLICER_TYPES, SR_ONLY_STYLE, Surface, TICK_SIZE, TIME_UNITS, TRANSFORM_KINDS, Tooltip, VERSION, aggregateValues, analyzeChart, animate, applyA11y, applyAggregate, applyBin, applyCalculate, applyFilter, applyFold, applyPatch, applyPick, applyTimeUnit, applyTransform, applyTransforms, arc, area, assertValidSpec, autoInsightAnnotations, backOut, bandScale, bounceOut, buildCartesianInteraction, buildCartesianModel, buildComboModel, buildDataTableFallback, buildFacetModels, buildHistogramModel, buildRenderReport, cartesianInteractionBuilders, cartesianRenderers, categorical, categoricalSchemes, chartTitleText, chartTypeLabel, checkExpression, clamp012 as clamp01, clamp255, compileExpression, compilePredicate, computeBackingSize, computeBins, computeFrame, computeSeriesInsights, contrastRatio, createDiv, createRoughPen, createSelectionStore, cubicIn, cubicInOut, cubicOut, curveCatmullRom, curveLinear, curveMonotoneX, curveStep, curveStepAfter, curveStepBefore, customRenderers, darkTheme, decimate, defaultSpan, dependentParams, diverging, divergingColorScale, divergingSchemes, drawAnnotationLabels, drawAnnotations, drawAxesUnderlay, drawFacet, drawLegend, drawOverlay, drawTitle, drawTrendlineLabels, drawTrendlines, easings, elasticOut, ellipsize, ensureSketchFont, expoInOut, expoOut, facetReport, fillParentStyle, filterRows, fontString, formatDate, formatNumber2 as formatNumber, formatValue, getDevicePixelRatio, groupBy, hashString, inferFieldType, inferFieldTypes, inferValueType, inheritInto, interpolateArray, interpolateNumber, interpolateNumberArray, interpolateObject, interpolateOklab, interpolateRgb, isBrowser, isEmptyValue, isFaceted, isParamClause, isSlicerType, keyFields, legendSwatchWidth, lightTheme, line, linear, linearRegression, linearScale, linearToSrgb, lintSpec, literalToValue, logScale, lttbRun, makeMatcher, matchesValue, measureText, monotoneXTangents, mulberry32, niceDomain, oklabToOklch, oklabToRgb, oklchToOklab, ordinalColorScale, overlayTextToCanvasCmd, paintCanvasText, paintLegendSwatch, parseColor, parseNumberFormat, pivot, placeViews, pointScale, polygonHachureLines, prefersReducedMotion, prettyDate, profileColumns, quadIn, quadInOut, quadOut, rampFromStops, readableTextColor, recommendChart, relativeLuminance, render, renderDashboard, renderToContext, repairReport, repairSpec, resolveCurve, resolveDashboardLayout, resolveDashboardSections, resolveEmphasis, resolveEntrance, resolveFilterValues, resolveInsightOptions, resolveSketch, resolveTheme, resolveUpdate, resolveValueRef, rgbToOklab, rgbaToCss, rotatePoint, roundedRect, sampleArc, sequential, sequentialColorScale, sequentialSchemes, setMeasureContext, setStyle, sinInOut, slicerParamName, smartDate, specFields, srgbToLinear, summarize, summarizeChart, themes, tickIncrement, tickStep, ticks, timeScale, timeTickFormat, timeTicks, toHex, toPointer, tooltipEnabled, truncateTo, validateDashboard, validateSpec, wireViews, withAlpha, withSketchFont };
|
|
18723
18952
|
//# sourceMappingURL=index.js.map
|
|
18724
18953
|
//# sourceMappingURL=index.js.map
|