bezel-charts 1.5.0 → 1.6.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/README.md +27 -7
- package/dist/bezel-charts.iife.js +18 -12
- package/dist/bezel-charts.js +153 -6
- package/dist/bezel-charts.min.js +18 -12
- package/dist/charts/area.js +2 -2
- package/dist/charts/bars.js +2 -2
- package/dist/charts/boxplot.js +8 -0
- package/dist/charts/donut.js +2 -2
- package/dist/charts/gauge.js +2 -2
- package/dist/charts/heatmap.js +2 -2
- package/dist/charts/histogram.js +2 -2
- package/dist/charts/line.js +2 -2
- package/dist/charts/progress.js +2 -2
- package/dist/charts/ring.js +2 -2
- package/dist/charts/scatter.js +2 -2
- package/dist/charts/{shared-I437GKHE.js → shared-56ZZ4O3F.js} +2 -2
- package/dist/charts/{shared-5J5X5F2N.js → shared-CYFOZG36.js} +2 -2
- package/dist/charts/shared-YIDF72XF.js +2 -0
- package/dist/charts/spark.js +2 -2
- package/package.json +5 -3
- package/src/charts/boxplot.js +134 -0
- package/src/element.js +1 -1
- package/src/entries/boxplot.js +10 -0
- package/src/index.js +2 -1
- package/src/render.js +1 -1
- package/dist/charts/shared-WQEE2V6C.js +0 -2
package/dist/bezel-charts.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! Bezel Charts v1.
|
|
1
|
+
/*! Bezel Charts v1.6.0 | MIT | github.com/ShazMoghaddam/bezel-charts */
|
|
2
2
|
|
|
3
3
|
// src/core/util.js
|
|
4
4
|
var SANS = "ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif";
|
|
@@ -268,7 +268,7 @@ var THEMES = {
|
|
|
268
268
|
};
|
|
269
269
|
|
|
270
270
|
// src/render.js
|
|
271
|
-
var NAMES = ["spark", "line", "area", "bars", "histogram", "scatter", "ring", "donut", "gauge", "progress", "heatmap"];
|
|
271
|
+
var NAMES = ["spark", "line", "area", "bars", "histogram", "boxplot", "scatter", "ring", "donut", "gauge", "progress", "heatmap"];
|
|
272
272
|
var TYPES = {};
|
|
273
273
|
function register(type, fn) {
|
|
274
274
|
TYPES[type] = fn;
|
|
@@ -350,7 +350,8 @@ var ATTRIBUTES = [
|
|
|
350
350
|
"bins",
|
|
351
351
|
"bin-width",
|
|
352
352
|
"mark",
|
|
353
|
-
"percent"
|
|
353
|
+
"percent",
|
|
354
|
+
"whiskers"
|
|
354
355
|
];
|
|
355
356
|
var HOST_CSS = `:host{display:block;position:relative;max-width:100%}:host([hidden]){display:none}svg{display:block;max-width:100%;height:auto;overflow:visible}.tip{position:absolute;left:0;top:0;pointer-events:none;background:#0b0b10;color:#f2f1f7;font:600 12px/1.5 ${MONO};padding:7px 10px;border-radius:10px;white-space:pre;opacity:0;transform:translate(-50%,calc(-100% - 12px));transition:opacity .12s;z-index:3;border:1px solid #2a2935;box-shadow:0 8px 24px rgba(0,0,0,.35)}.tip.on{opacity:1}.c{outline:none}.c:focus-visible{outline:2px solid #fff;outline-offset:3px;box-shadow:0 0 0 7px #000}.k{stroke:currentColor;stroke-width:2;stroke-opacity:1}.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}@media (forced-colors:active){.c:focus-visible{outline-color:Highlight}}`;
|
|
356
357
|
var STEPS = { ArrowLeft: -1, ArrowUp: -1, ArrowRight: 1, ArrowDown: 1 };
|
|
@@ -1362,8 +1363,154 @@ function median(v) {
|
|
|
1362
1363
|
register("histogram", histogram);
|
|
1363
1364
|
define("histogram");
|
|
1364
1365
|
|
|
1366
|
+
// src/charts/boxplot.js
|
|
1367
|
+
function boxplot(o, th) {
|
|
1368
|
+
var S = series(o.values), names = list(o.series), pal = palette(o, th), k = S.length;
|
|
1369
|
+
var horiz = bool(o.horizontal), many = list(o.color).length > 1, showMean = list(o.mark).indexOf("mean") >= 0;
|
|
1370
|
+
var stats = S.map(function(v) {
|
|
1371
|
+
return summary(v, o.whiskers === "range");
|
|
1372
|
+
});
|
|
1373
|
+
var nameOf = function(i) {
|
|
1374
|
+
return names[i] || "Group " + (i + 1);
|
|
1375
|
+
};
|
|
1376
|
+
var h = num(o.height, horiz ? Math.max(120, k * 36 + 24) : 200);
|
|
1377
|
+
var f = function(v) {
|
|
1378
|
+
return fmt(v, o);
|
|
1379
|
+
};
|
|
1380
|
+
var meds = stats.map(function(s) {
|
|
1381
|
+
return s.median;
|
|
1382
|
+
});
|
|
1383
|
+
var about = k === 1 ? "median " + f(stats[0].median) + ", middle half " + f(stats[0].q1) + " to " + f(stats[0].q3) : k + " groups, medians from " + f(Math.min.apply(null, meds)) + " to " + f(Math.max.apply(null, meds));
|
|
1384
|
+
return tile(o, th, h, function(x0, y0, w, h2) {
|
|
1385
|
+
if (!k) return emptyState(th, x0, y0, w, h2);
|
|
1386
|
+
var lo = Math.min.apply(null, stats.map(function(s2) {
|
|
1387
|
+
return s2.min;
|
|
1388
|
+
})), hi = Math.max.apply(null, stats.map(function(s2) {
|
|
1389
|
+
return s2.max;
|
|
1390
|
+
}));
|
|
1391
|
+
if (has(o.goal)) {
|
|
1392
|
+
lo = Math.min(lo, +o.goal);
|
|
1393
|
+
hi = Math.max(hi, +o.goal);
|
|
1394
|
+
}
|
|
1395
|
+
var sc = niceScale(lo, hi, 4), s = "";
|
|
1396
|
+
var tl = sc.ticks.map(function(t) {
|
|
1397
|
+
return fmt(t, o, true);
|
|
1398
|
+
});
|
|
1399
|
+
var nameW = horiz ? Math.min(w * 0.4, Math.max.apply(null, S.map(function(_, i) {
|
|
1400
|
+
return tw(nameOf(i), 11);
|
|
1401
|
+
})) + 12) : 0;
|
|
1402
|
+
var axisW = horiz ? 0 : Math.max.apply(null, tl.map(function(t) {
|
|
1403
|
+
return tw(t, 10, true);
|
|
1404
|
+
})) + 10;
|
|
1405
|
+
var px = x0 + (horiz ? nameW : axisW), pw = w - (horiz ? nameW : axisW), ph = h2 - 20;
|
|
1406
|
+
var V = horiz ? function(v) {
|
|
1407
|
+
return px + (v - sc.lo) / (sc.hi - sc.lo) * pw;
|
|
1408
|
+
} : function(v) {
|
|
1409
|
+
return y0 + ph - (v - sc.lo) / (sc.hi - sc.lo) * ph;
|
|
1410
|
+
};
|
|
1411
|
+
var band = (horiz ? ph : pw) / k, half = Math.min(28, band * 0.28);
|
|
1412
|
+
var C = function(i) {
|
|
1413
|
+
return (horiz ? y0 : px) + band * (i + 0.5);
|
|
1414
|
+
};
|
|
1415
|
+
var P = function(c, v) {
|
|
1416
|
+
return horiz ? [v, c] : [c, v];
|
|
1417
|
+
};
|
|
1418
|
+
var seg = function(c1, v1, c2, v2, attrs) {
|
|
1419
|
+
var a = P(c1, v1), b = P(c2, v2);
|
|
1420
|
+
return '<line x1="' + r2(a[0]) + '" y1="' + r2(a[1]) + '" x2="' + r2(b[0]) + '" y2="' + r2(b[1]) + '"' + attrs + "/>";
|
|
1421
|
+
};
|
|
1422
|
+
sc.ticks.forEach(function(t, i) {
|
|
1423
|
+
var v = V(t);
|
|
1424
|
+
s += seg(horiz ? y0 : px, v, horiz ? y0 + ph : px + pw, v, ' stroke="' + th.grid + '"' + (t === 0 ? "" : ' stroke-dasharray="2 4"')) + (horiz ? text(v, y0 + ph + 15, tl[i], small(th, 10, 'text-anchor="middle"')) : text(px - 8, v + 3.5, tl[i], small(th, 10, 'text-anchor="end"')));
|
|
1425
|
+
});
|
|
1426
|
+
stats.forEach(function(st, i) {
|
|
1427
|
+
var c = C(i), col = many ? pal[i % pal.length] : pal[0], line2 = ' stroke="' + col + '" stroke-width="1.5"';
|
|
1428
|
+
if (k > 1 || names.length) {
|
|
1429
|
+
var label = fit(nameOf(i), horiz ? nameW - 10 : band - 6, horiz ? 11 : 10, !horiz);
|
|
1430
|
+
s += horiz ? text(x0, c + 4, label, small(th, 11, "", th.fg)) : text(c, y0 + ph + 15, label, small(th, 10, 'text-anchor="middle"'));
|
|
1431
|
+
}
|
|
1432
|
+
if (!st.n) return;
|
|
1433
|
+
var a1 = P(c - half, V(st.q1)), a2 = P(c + half, V(st.q3));
|
|
1434
|
+
s += "<g" + anim(o, "bzc-a", Math.min(0.6, i * 0.06)) + ">" + seg(c, V(st.low), c, V(st.q1), line2) + seg(c, V(st.q3), c, V(st.high), line2) + seg(c - half / 2, V(st.low), c + half / 2, V(st.low), line2) + seg(c - half / 2, V(st.high), c + half / 2, V(st.high), line2) + '<rect x="' + r2(Math.min(a1[0], a2[0])) + '" y="' + r2(Math.min(a1[1], a2[1])) + '" width="' + r2(Math.abs(a2[0] - a1[0])) + '" height="' + r2(Math.max(1, Math.abs(a2[1] - a1[1]))) + '" rx="3" fill="' + col + '" fill-opacity=".22"' + line2 + "/>" + seg(c - half, V(st.median), c + half, V(st.median), ' stroke="' + col + '" stroke-width="2.5"');
|
|
1435
|
+
st.outliers.forEach(function(v) {
|
|
1436
|
+
var p = P(c, V(v));
|
|
1437
|
+
s += '<circle cx="' + r2(p[0]) + '" cy="' + r2(p[1]) + '" r="2.5" fill="none"' + line2 + "/>";
|
|
1438
|
+
});
|
|
1439
|
+
if (showMean) {
|
|
1440
|
+
var m = P(c, V(st.mean));
|
|
1441
|
+
s += marker("diamond", m[0], m[1], 4, ' fill="' + (o.background || th.tile) + '"' + line2);
|
|
1442
|
+
}
|
|
1443
|
+
s += "</g>";
|
|
1444
|
+
});
|
|
1445
|
+
if (has(o.goal)) {
|
|
1446
|
+
var g = V(+o.goal);
|
|
1447
|
+
s += horiz ? seg(g, y0, g, y0 + ph, ' stroke="' + th.fg + '" stroke-opacity=".55" stroke-dasharray="4 4"') : goalLine(o, th, px, px + pw, g);
|
|
1448
|
+
}
|
|
1449
|
+
stats.forEach(function(st, i) {
|
|
1450
|
+
if (!st.n) return;
|
|
1451
|
+
var tip = nameOf(i) + "\nMedian " + f(st.median) + "\nMiddle half " + f(st.q1) + " to " + f(st.q3) + "\n" + (st.outliers.length ? "Range without outliers " : "Range ") + f(st.low) + " to " + f(st.high) + (st.outliers.length ? "\n" + st.outliers.length + (st.outliers.length === 1 ? " outlier" : " outliers") : "") + (showMean ? "\nMean " + f(st.mean) : "") + "\nn = " + st.n;
|
|
1452
|
+
s += horiz ? hit(px, C(i) - band / 2, pw, band, tip) : hit(C(i) - band / 2, y0, band, ph, tip);
|
|
1453
|
+
});
|
|
1454
|
+
return s;
|
|
1455
|
+
}, { summary: k ? about : "no data" });
|
|
1456
|
+
}
|
|
1457
|
+
boxplot.table = function(o) {
|
|
1458
|
+
var S = series(o.values), names = list(o.series), showMean = list(o.mark).indexOf("mean") >= 0;
|
|
1459
|
+
var f = function(v) {
|
|
1460
|
+
return fmt(v, o);
|
|
1461
|
+
};
|
|
1462
|
+
return {
|
|
1463
|
+
head: ["Group", "Count", "Lowest", "Lower quartile", "Median", "Upper quartile", "Highest", "Outliers"].concat(showMean ? ["Mean"] : []),
|
|
1464
|
+
rows: S.map(function(v, i) {
|
|
1465
|
+
var st = summary(v, o.whiskers === "range");
|
|
1466
|
+
return [names[i] || "Group " + (i + 1), String(st.n), f(st.min), f(st.q1), f(st.median), f(st.q3), f(st.max), String(st.outliers.length)].concat(showMean ? [f(st.mean)] : []);
|
|
1467
|
+
})
|
|
1468
|
+
};
|
|
1469
|
+
};
|
|
1470
|
+
function fit(name, width, size, mono) {
|
|
1471
|
+
var t = String(name);
|
|
1472
|
+
while (t.length > 1 && tw(t, size, mono) > width) t = trunc(t, t.length - 1);
|
|
1473
|
+
return t;
|
|
1474
|
+
}
|
|
1475
|
+
function quantile(s, p) {
|
|
1476
|
+
var h = (s.length - 1) * p, i = Math.floor(h);
|
|
1477
|
+
return i + 1 < s.length ? s[i] + (h - i) * (s[i + 1] - s[i]) : s[i];
|
|
1478
|
+
}
|
|
1479
|
+
function summary(v, range) {
|
|
1480
|
+
var s = v.slice().sort(function(a, b) {
|
|
1481
|
+
return a - b;
|
|
1482
|
+
}), n = s.length;
|
|
1483
|
+
if (!n) return { n: 0, outliers: [] };
|
|
1484
|
+
var q1 = quantile(s, 0.25), q3 = quantile(s, 0.75), iqr = q3 - q1, t = 0;
|
|
1485
|
+
var lowFence = range ? -Infinity : q1 - 1.5 * iqr, highFence = range ? Infinity : q3 + 1.5 * iqr;
|
|
1486
|
+
var inside = s.filter(function(x) {
|
|
1487
|
+
return x >= lowFence && x <= highFence;
|
|
1488
|
+
});
|
|
1489
|
+
s.forEach(function(x) {
|
|
1490
|
+
t += x;
|
|
1491
|
+
});
|
|
1492
|
+
return {
|
|
1493
|
+
n,
|
|
1494
|
+
min: s[0],
|
|
1495
|
+
max: s[n - 1],
|
|
1496
|
+
q1,
|
|
1497
|
+
median: quantile(s, 0.5),
|
|
1498
|
+
q3,
|
|
1499
|
+
mean: t / n,
|
|
1500
|
+
low: inside[0],
|
|
1501
|
+
high: inside[inside.length - 1],
|
|
1502
|
+
outliers: s.filter(function(x) {
|
|
1503
|
+
return x < lowFence || x > highFence;
|
|
1504
|
+
})
|
|
1505
|
+
};
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
// src/entries/boxplot.js
|
|
1509
|
+
register("boxplot", boxplot);
|
|
1510
|
+
define("boxplot");
|
|
1511
|
+
|
|
1365
1512
|
// src/charts/scatter.js
|
|
1366
|
-
function
|
|
1513
|
+
function fit2(xs, ys) {
|
|
1367
1514
|
var n = Math.min(xs.length, ys.length);
|
|
1368
1515
|
if (n < 2) return null;
|
|
1369
1516
|
var mx = 0, my = 0, i;
|
|
@@ -1468,7 +1615,7 @@ function scatter(o, th) {
|
|
|
1468
1615
|
if (has(o.goal)) s += goalLine(o, th, px, px + pw, PY(+o.goal));
|
|
1469
1616
|
if (trend) {
|
|
1470
1617
|
groups.forEach(function(gr, j) {
|
|
1471
|
-
var f =
|
|
1618
|
+
var f = fit2(gr.xs, gr.ys);
|
|
1472
1619
|
if (!f) return;
|
|
1473
1620
|
var xa = Math.min.apply(null, gr.xs), xb = Math.max.apply(null, gr.xs);
|
|
1474
1621
|
var ya = f.slope * xa + f.intercept, yb = f.slope * xb + f.intercept;
|
|
@@ -1845,7 +1992,7 @@ register("heatmap", heatmap);
|
|
|
1845
1992
|
define("heatmap");
|
|
1846
1993
|
|
|
1847
1994
|
// src/index.js
|
|
1848
|
-
var version = "1.
|
|
1995
|
+
var version = "1.6.0";
|
|
1849
1996
|
var types = NAMES.slice();
|
|
1850
1997
|
export {
|
|
1851
1998
|
BezelChart,
|