bezel-charts 1.7.0 → 1.8.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 +16 -7
- package/dist/bezel-charts.iife.js +21 -21
- package/dist/bezel-charts.js +222 -30
- package/dist/bezel-charts.min.js +21 -21
- package/dist/charts/area.js +4 -4
- package/dist/charts/bars.js +2 -2
- package/dist/charts/boxplot.js +2 -2
- package/dist/charts/combo.js +2 -2
- 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 +3 -3
- 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-62V33ZP5.js +2 -0
- package/dist/charts/shared-7G7LN4HE.js +2 -0
- package/dist/charts/{shared-Y6MBWBOE.js → shared-TBF2ZMMV.js} +2 -2
- package/dist/charts/shared-ZKK7S7JV.js +2 -0
- package/dist/charts/spark.js +2 -2
- package/package.json +1 -1
- package/src/charts/area.js +15 -7
- package/src/charts/combo.js +1 -1
- package/src/charts/line.js +26 -11
- package/src/core/lines.js +30 -0
- package/src/core/time.js +101 -0
- package/src/core/xy.js +73 -38
- package/src/element.js +1 -1
- package/src/index.js +1 -1
- package/dist/charts/shared-6SF4EQMI.js +0 -2
- package/dist/charts/shared-D5IXRVKV.js +0 -2
package/src/charts/line.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { newId, r2, num, list, series, bool, fmt, pathOf, text, small, anim, palette, emptyState, parseNotes, statOf } from '../core/util.js';
|
|
1
|
+
import { newId, r2, num, has, list, series, bool, fmt, pathOf, text, small, anim, palette, emptyState, parseNotes, statOf } from '../core/util.js';
|
|
2
2
|
import { seriesTable, styleOf, DASHES, SHAPES } from '../core/series.js';
|
|
3
|
-
import { xyFrame, xyFinish
|
|
3
|
+
import { xyFrame, xyFinish } from '../core/xy.js';
|
|
4
|
+
import { lineKey, seriesLine, pointMarks } from '../core/lines.js';
|
|
5
|
+
import { parseDates, hasTimes, pointName, datedTable } from '../core/time.js';
|
|
4
6
|
import { tile } from '../core/tile.js';
|
|
5
7
|
|
|
6
8
|
export default function line(o, th) {
|
|
@@ -13,21 +15,34 @@ export default function line(o, th) {
|
|
|
13
15
|
// With dashes or markers, the legend shows a short sample of each line instead of a dot.
|
|
14
16
|
var key = (dashOf || markOf) && lineKey(pal, dashOf, markOf, bg);
|
|
15
17
|
var nameOf = function (k) { return names[k] || 'Series ' + (k + 1); };
|
|
18
|
+
var T = parseDates(o, n), timed = T && hasTimes(T), lang = o.lang || 'en-GB';
|
|
19
|
+
// A log scale needs positive values; zero and negative ones leave gaps. With none at all, the axis stays linear.
|
|
20
|
+
var all = [].concat.apply([], S), pos = all.filter(function (v) { return v > 0; });
|
|
21
|
+
if (has(o.goal) && +o.goal > 0) pos.push(+o.goal);
|
|
22
|
+
var log = bool(o.log) && pos.length > 0;
|
|
16
23
|
return tile(o, th, h, function (x0, y0, w, h) {
|
|
17
24
|
if (!n) return emptyState(th, x0, y0, w, h);
|
|
18
|
-
var all = [].concat.apply([], S);
|
|
19
25
|
var f = xyFrame(o, th, {
|
|
20
26
|
n: n, names: multi ? S.map(function (_, k) { return nameOf(k); }) : null, pal: pal, key: key, kw: key && 24,
|
|
21
27
|
lo: Math.min.apply(null, all), hi: Math.max.apply(null, all), zero: bool(o.zero), labels: labels, notes: notes,
|
|
22
|
-
tick: function (t) { return fmt(t, o, true); },
|
|
28
|
+
tick: function (t) { return fmt(t, o, true); }, dates: T, min: has(o.min) ? +o.min : NaN, max: has(o.max) ? +o.max : NaN,
|
|
29
|
+
log: log, posLo: log ? Math.min.apply(null, pos) : 0, posHi: log ? Math.max.apply(null, pos) : 0,
|
|
23
30
|
}, x0, y0, w, h);
|
|
24
|
-
var s = f.svg, X = f.X, Y = f.Y, px = f.px, pw = f.pw, top = f.top, ph = f.ph;
|
|
31
|
+
var s = f.svg + (f.clip ? '<g' + f.clip + '>' : ''), X = f.X, Y = f.Y, px = f.px, pw = f.pw, top = f.top, ph = f.ph;
|
|
25
32
|
S.forEach(function (v, k) {
|
|
26
33
|
var c = pal[k % pal.length];
|
|
27
34
|
var P = v.map(function (y, i) { return [X(i), Y(y)]; });
|
|
28
35
|
if (P.length === 1) P = [[px, P[0][1]], [px + pw, P[0][1]]];
|
|
29
|
-
|
|
30
|
-
|
|
36
|
+
// On a log scale the line breaks around points it can't place.
|
|
37
|
+
var runs = log ? P.reduce(function (r, p) {
|
|
38
|
+
if (isFinite(p[1])) r[r.length - 1].push(p); else if (r[r.length - 1].length) r.push([]);
|
|
39
|
+
return r;
|
|
40
|
+
}, [[]]).filter(function (r) { return r.length; }) : [P];
|
|
41
|
+
if (!runs.length) return;
|
|
42
|
+
var d = runs.map(function (r) { return pathOf(r, bool(o.straight)); }).join('');
|
|
43
|
+
P = [].concat.apply([], runs);
|
|
44
|
+
// The soft fill under the first line has no floor to reach on a log scale, so it's left out there.
|
|
45
|
+
if (k === 0 && !log) {
|
|
31
46
|
var g = newId('g'), last = P[P.length - 1];
|
|
32
47
|
s += '<defs><linearGradient id="' + g + '" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="' + c + '" stop-opacity=".26"/><stop offset="1" stop-color="' + c + '" stop-opacity="0"/></linearGradient></defs>' +
|
|
33
48
|
'<path d="' + d + 'L' + r2(last[0]) + ',' + r2(top + ph) + 'L' + r2(P[0][0]) + ',' + r2(top + ph) + 'Z" fill="url(#' + g + ')"' + anim(o, 'bzc-a') + '/>';
|
|
@@ -40,14 +55,14 @@ export default function line(o, th) {
|
|
|
40
55
|
var e = P[P.length - 1];
|
|
41
56
|
s += '<circle cx="' + r2(e[0]) + '" cy="' + r2(e[1]) + '" r="4" fill="' + c + '" stroke="' + bg + '" stroke-width="2"/>';
|
|
42
57
|
}
|
|
43
|
-
if (bool(o.showValues)) v.forEach(function (y, i) { s += text(X(i), Y(y) - 8, fmt(y, o, true), small(th, 9, 'text-anchor="middle"')); });
|
|
58
|
+
if (bool(o.showValues)) v.forEach(function (y, i) { if (isFinite(Y(y))) s += text(X(i), Y(y) - 8, fmt(y, o, true), small(th, 9, 'text-anchor="middle"')); });
|
|
44
59
|
});
|
|
45
|
-
return s + xyFinish(o, th, f, n, function (j) {
|
|
46
|
-
var tip = labels
|
|
60
|
+
return s + (f.clip ? '</g>' : '') + xyFinish(o, th, f, n, function (j) {
|
|
61
|
+
var tip = pointName(labels, T, j, lang, timed);
|
|
47
62
|
S.forEach(function (v, k) { if (j < v.length) tip += '\n' + (multi ? nameOf(k) + ': ' : '') + fmt(v[j], o); });
|
|
48
63
|
return tip;
|
|
49
64
|
});
|
|
50
65
|
}, { stat: st, summary: S.length + ' series over ' + n + ' points' });
|
|
51
66
|
}
|
|
52
67
|
|
|
53
|
-
line.table = function (o) {
|
|
68
|
+
line.table = function (o) { var t = seriesTable(o); return datedTable(t, o, t.rows.length); };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** Series lines, their markers and legend samples, shared by line, area and combo charts. */
|
|
2
|
+
import { r2, anim } from './util.js';
|
|
3
|
+
import { marker, DASHES } from './series.js';
|
|
4
|
+
|
|
5
|
+
/** A legend swatch for a line: a short sample with its dash and marker. */
|
|
6
|
+
export function lineKey(pal, dashOf, markOf, bg) {
|
|
7
|
+
return function (k, x, y) {
|
|
8
|
+
var c = pal[k % pal.length], dk = dashOf ? DASHES[dashOf(k)] : '', mk = markOf ? markOf(k) : 'none';
|
|
9
|
+
return '<line x1="' + r2(x) + '" x2="' + r2(x + 18) + '" y1="' + r2(y + 6) + '" y2="' + r2(y + 6) + '" stroke="' + c + '" stroke-width="2.5" stroke-linecap="round"' +
|
|
10
|
+
(dk ? ' stroke-dasharray="' + dk + '"' : '') + '/>' + (mk !== 'none' ? marker(mk, x + 9, y + 6, 3.5, ' fill="' + c + '" stroke="' + bg + '" stroke-width="1.5"') : '');
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** A series line along path d. The draw-in animation is itself a dash, so dashed lines fade in instead. */
|
|
15
|
+
export function seriesLine(o, d, c, k, dk) {
|
|
16
|
+
return dk
|
|
17
|
+
? '<path d="' + d + '" fill="none" stroke="' + c + '" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="' + dk + '"' + anim(o, 'bzc-a', k * 0.15) + '/>'
|
|
18
|
+
: '<path d="' + d + '" fill="none" stroke="' + c + '" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" pathLength="1" style="stroke-dasharray:1' + (o.animate ? ';animation-delay:' + k * 0.15 + 's' : '') + '"' + (o.animate ? ' class="bzc-d"' : '') + '/>';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Markers on a series' points. Long series get one on every few points, and always on the last. */
|
|
22
|
+
export function pointMarks(o, mk, ys, X, Y, c, bg, k) {
|
|
23
|
+
var s = '', every = Math.ceil(ys.length / 40);
|
|
24
|
+
ys.forEach(function (y, i) {
|
|
25
|
+
// On a log scale, zero and negative values have no position, so they get no marker.
|
|
26
|
+
if (!isFinite(Y(y))) return;
|
|
27
|
+
if (i % every === 0 || i === ys.length - 1) s += marker(mk, X(i), Y(y), 3.5, ' fill="' + c + '" stroke="' + bg + '" stroke-width="1.5"' + anim(o, 'bzc-a', 0.6 + k * 0.15));
|
|
28
|
+
});
|
|
29
|
+
return s;
|
|
30
|
+
}
|
package/src/core/time.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/** Real dates along the bottom of line and area charts: parsing, tick steps and labels. Only those charts load this. */
|
|
2
|
+
import { list } from './util.js';
|
|
3
|
+
|
|
4
|
+
var HOUR = 36e5, DAY = 864e5;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The dates option as UTC times, one per point: "2026-01-05", or with a time, "2026-01-05T14:30". Returns null, so
|
|
8
|
+
* points stay evenly spaced, unless there is a valid date for every point.
|
|
9
|
+
*/
|
|
10
|
+
export function parseDates(o, n) {
|
|
11
|
+
var d = list(o.dates);
|
|
12
|
+
if (!n || d.length < n) return null;
|
|
13
|
+
var out = [];
|
|
14
|
+
for (var i = 0; i < n; i++) {
|
|
15
|
+
var m = /^(\d{4})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2})(?::(\d{2}))?)?$/.exec(String(d[i]).trim());
|
|
16
|
+
if (!m) return null;
|
|
17
|
+
out.push(Date.UTC(+m[1], +m[2] - 1, +m[3], +(m[4] || 0), +(m[5] || 0), +(m[6] || 0)));
|
|
18
|
+
}
|
|
19
|
+
return out;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function fmt(lang, opt) {
|
|
23
|
+
try { return new Intl.DateTimeFormat(lang, Object.assign({ timeZone: 'UTC' }, opt)); } catch (e) { return new Intl.DateTimeFormat('en-GB', Object.assign({ timeZone: 'UTC' }, opt)); }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
var pad = function (n) { return (n < 10 ? '0' : '') + n; };
|
|
27
|
+
var clock = function (t) { var d = new Date(t); return pad(d.getUTCHours()) + ':' + pad(d.getUTCMinutes()); };
|
|
28
|
+
|
|
29
|
+
/** A date for tooltips and the data table: "5 Jan 2026", with the time too when the dates have times. */
|
|
30
|
+
export function dateText(t, lang, withTime) {
|
|
31
|
+
return fmt(lang, { day: 'numeric', month: 'short', year: 'numeric' }).format(new Date(t)) + (withTime ? ' ' + clock(t) : '');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Whether any of the dates has a time of day. */
|
|
35
|
+
export function hasTimes(T) {
|
|
36
|
+
return T.some(function (t) { return t % DAY !== 0; });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Tick steps from an hour to a century, smallest first. Each is a unit and how many of it.
|
|
40
|
+
var STEPS = [['h', 1], ['h', 3], ['h', 6], ['h', 12], ['d', 1], ['d', 2], ['w', 1], ['w', 2], ['m', 1], ['m', 2], ['m', 3], ['m', 6],
|
|
41
|
+
['y', 1], ['y', 2], ['y', 5], ['y', 10], ['y', 20], ['y', 50], ['y', 100]];
|
|
42
|
+
var ROUGH = { h: HOUR, d: DAY, w: 7 * DAY, m: 30.44 * DAY, y: 365.25 * DAY };
|
|
43
|
+
|
|
44
|
+
/** Every tick of one step between t0 and t1: whole hours, midnights, Mondays, firsts of the month or new years. */
|
|
45
|
+
function ticksFor(t0, t1, unit, k) {
|
|
46
|
+
var out = [], t;
|
|
47
|
+
if (unit === 'h' || unit === 'd' || unit === 'w') {
|
|
48
|
+
var size = unit === 'h' ? HOUR * k : DAY * (unit === 'w' ? 7 * k : k);
|
|
49
|
+
// Weeks start on Mondays: 5 January 1970 was the first Monday after the epoch.
|
|
50
|
+
var from = unit === 'w' ? 4 * DAY : 0;
|
|
51
|
+
for (t = Math.ceil((t0 - from) / size) * size + from; t <= t1; t += size) out.push(t);
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
var d = new Date(t0), y = d.getUTCFullYear(), mo = unit === 'm' ? d.getUTCMonth() : 0;
|
|
55
|
+
for (;;) {
|
|
56
|
+
t = Date.UTC(y, mo, 1);
|
|
57
|
+
if (t > t1) return out;
|
|
58
|
+
if (t >= t0 && (unit === 'm' ? mo % k === 0 : y % k === 0)) out.push(t);
|
|
59
|
+
if (unit === 'm') { mo++; if (mo === 12) { mo = 0; y++; } } else y++;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Ticks and labels for the dates t0 to t1 across room pixels: the smallest step that leaves about 64 px per label.
|
|
65
|
+
* Hours read 14:00 (midnight shows the day), days and weeks 5 Jan, months Jan with the year on January and the first
|
|
66
|
+
* tick, and years 2026.
|
|
67
|
+
*/
|
|
68
|
+
export function dateTicks(t0, t1, room, lang) {
|
|
69
|
+
var most = Math.max(2, Math.floor(room / 64)), span = t1 - t0;
|
|
70
|
+
for (var i = 0; i < STEPS.length; i++) {
|
|
71
|
+
var unit = STEPS[i][0], k = STEPS[i][1];
|
|
72
|
+
if (span / (ROUGH[unit] * k) > most + 2) continue;
|
|
73
|
+
var ticks = ticksFor(t0, t1, unit, k);
|
|
74
|
+
if (ticks.length > most) continue;
|
|
75
|
+
var dm = fmt(lang, { day: 'numeric', month: 'short' }), my = fmt(lang, { month: 'short', year: 'numeric' }), mm = fmt(lang, { month: 'short' });
|
|
76
|
+
return ticks.map(function (t, j) {
|
|
77
|
+
var d = new Date(t), text;
|
|
78
|
+
if (unit === 'h') text = t % DAY === 0 ? dm.format(d) : clock(t);
|
|
79
|
+
else if (unit === 'd' || unit === 'w') text = dm.format(d);
|
|
80
|
+
else if (unit === 'm') text = d.getUTCMonth() === 0 || j === 0 ? my.format(d) : mm.format(d);
|
|
81
|
+
else text = String(d.getUTCFullYear());
|
|
82
|
+
return { t: t, text: text };
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** A point's name: its label, else its date, else its number. */
|
|
89
|
+
export function pointName(labels, T, i, lang, timed) {
|
|
90
|
+
return labels[i] || (T ? dateText(T[i], lang, timed) : '#' + (i + 1));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Puts dates in a data table's first column, for the rows without a label. */
|
|
94
|
+
export function datedTable(t, o, n) {
|
|
95
|
+
var T = parseDates(o, n), labels = list(o.labels);
|
|
96
|
+
if (!T) return t;
|
|
97
|
+
var timed = hasTimes(T);
|
|
98
|
+
t.head[0] = 'Date';
|
|
99
|
+
t.rows.forEach(function (r, i) { if (!labels[i]) r[0] = dateText(T[i], o.lang || 'en-GB', timed); });
|
|
100
|
+
return t;
|
|
101
|
+
}
|
package/src/core/xy.js
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
/** The axis frame
|
|
2
|
-
import { r2, clamp, has, tw, text, small, hit,
|
|
3
|
-
import { niceScale, legend
|
|
1
|
+
/** The axis frame line and area charts share: dates, fixed ranges and log scales included. Other charts don't load it. */
|
|
2
|
+
import { newId, r2, clamp, has, tw, text, small, hit, goalLine } from './util.js';
|
|
3
|
+
import { niceScale, legend } from './series.js';
|
|
4
|
+
import { dateTicks } from './time.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* The frame line and area charts share: the legend, the value axis with its gridlines, labels along the bottom and notes.
|
|
7
8
|
* c holds n (points), names (legend names, or null for no legend), pal, key and kw (legend swatches), lo and hi (the data
|
|
8
|
-
* range), zero (keep zero on the axis), labels, notes and tick (formats an axis number).
|
|
9
|
-
*
|
|
9
|
+
* range), zero (keep zero on the axis), labels, notes and tick (formats an axis number). Optionally, dates (a UTC time
|
|
10
|
+
* per point, spacing points in time), min and max (fixing the value axis, NaN when not set) and log (with posLo and
|
|
11
|
+
* posHi, the data's smallest and largest positive values).
|
|
12
|
+
* Returns the SVG so far, the scales X(i) and Y(v), the plot box (px, pw, top, ph), and clip: an attribute that keeps
|
|
13
|
+
* series inside the plot when min or max is set, or ''.
|
|
10
14
|
*/
|
|
11
15
|
export function xyFrame(o, th, c, x0, y0, w, h) {
|
|
12
|
-
var s = '', top = y0, n = c.n, labels = c.labels;
|
|
16
|
+
var s = '', top = y0, n = c.n, labels = c.labels, T = c.dates;
|
|
13
17
|
if (c.names) {
|
|
14
18
|
var lg = legend(c.names, c.pal, th, x0, top, w, c.key, c.kw);
|
|
15
19
|
s += lg.svg;
|
|
@@ -18,19 +22,42 @@ export function xyFrame(o, th, c, x0, y0, w, h) {
|
|
|
18
22
|
var mn = c.lo, mx = c.hi;
|
|
19
23
|
if (has(o.goal)) { mn = Math.min(mn, +o.goal); mx = Math.max(mx, +o.goal); }
|
|
20
24
|
if (c.zero) { mn = Math.min(0, mn); mx = Math.max(0, mx); }
|
|
21
|
-
|
|
25
|
+
// A min or max you set wins over the data, the goal and zero. Both together must leave some room between them.
|
|
26
|
+
var hasMin = isFinite(c.min), hasMax = isFinite(c.max);
|
|
27
|
+
if (hasMin && hasMax && c.min >= c.max) hasMin = hasMax = false;
|
|
28
|
+
var sc = c.log ? logScale(hasMin && c.min > 0 ? c.min : c.posLo, hasMax && c.max > 0 ? c.max : c.posHi)
|
|
29
|
+
: hasMin || hasMax ? fixedScale(hasMin ? c.min : mn, hasMax ? c.max : mx, hasMin, hasMax)
|
|
30
|
+
: niceScale(mn, mx, 4);
|
|
22
31
|
var tl = sc.ticks.map(c.tick);
|
|
23
32
|
var axisW = Math.max.apply(null, tl.map(function (t) { return tw(t, 10, true); })) + 10;
|
|
24
|
-
var bottom = labels.length ? 20 : 4;
|
|
33
|
+
var bottom = labels.length || T ? 20 : 4;
|
|
25
34
|
var px = x0 + axisW, pw = w - axisW, ph = h - (top - y0) - bottom;
|
|
26
|
-
var
|
|
27
|
-
|
|
35
|
+
var t0 = T ? Math.min.apply(null, T) : 0, span = T ? Math.max.apply(null, T) - t0 : 0;
|
|
36
|
+
// With dates, points sit where they fall in time; otherwise they are evenly spaced.
|
|
37
|
+
var X = T
|
|
38
|
+
? function (i) { return span ? px + (T[i] - t0) / span * pw : px + pw / 2; }
|
|
39
|
+
: function (i) { return n === 1 ? px + pw / 2 : px + i * pw / (n - 1); };
|
|
40
|
+
var Y = sc.log
|
|
41
|
+
? function (v) { return top + ph - (Math.log10(v) - sc.a) / (sc.b - sc.a) * ph; }
|
|
42
|
+
: function (v) { return top + ph - (v - sc.lo) / (sc.hi - sc.lo) * ph; };
|
|
43
|
+
var clip = '';
|
|
44
|
+
if (hasMin || hasMax) {
|
|
45
|
+
var cid = newId('c');
|
|
46
|
+
s += '<defs><clipPath id="' + cid + '"><rect x="' + r2(px - 4) + '" y="' + r2(top - 4) + '" width="' + r2(pw + 8) + '" height="' + r2(ph + 8) + '"/></clipPath></defs>';
|
|
47
|
+
clip = ' clip-path="url(#' + cid + ')"';
|
|
48
|
+
}
|
|
28
49
|
sc.ticks.forEach(function (t, i) {
|
|
29
50
|
var y = Y(t);
|
|
30
51
|
s += '<line x1="' + r2(px) + '" x2="' + r2(px + pw) + '" y1="' + r2(y) + '" y2="' + r2(y) + '" stroke="' + th.grid + '"' + (t === 0 ? '' : ' stroke-dasharray="2 4"') + '/>' +
|
|
31
52
|
text(px - 8, y + 3.5, tl[i], small(th, 10, 'text-anchor="end"'));
|
|
32
53
|
});
|
|
33
|
-
if (
|
|
54
|
+
if (T) {
|
|
55
|
+
// Date ticks pick their own step, and labels near the ends are nudged in so they stay inside the plot.
|
|
56
|
+
dateTicks(t0, t0 + span, pw, o.lang || 'en-GB').forEach(function (d) {
|
|
57
|
+
var half = tw(d.text, 10, true) / 2, x = span ? px + (d.t - t0) / span * pw : px + pw / 2;
|
|
58
|
+
s += text(clamp(x, px + half, px + pw - half), top + ph + 15, d.text, small(th, 10, 'text-anchor="middle"'));
|
|
59
|
+
});
|
|
60
|
+
} else if (labels.length) {
|
|
34
61
|
var every = Math.max(1, Math.ceil(n * (Math.max.apply(null, labels.map(function (l) { return tw(l, 10, true); })) + 10) / pw));
|
|
35
62
|
for (var i = 0; i < n; i += every) {
|
|
36
63
|
if (labels[i] == null) continue;
|
|
@@ -44,38 +71,46 @@ export function xyFrame(o, th, c, x0, y0, w, h) {
|
|
|
44
71
|
s += '<line x1="' + r2(x) + '" x2="' + r2(x) + '" y1="' + r2(top + 12) + '" y2="' + r2(top + ph) + '" stroke="' + th.fg + '" stroke-opacity=".4" stroke-dasharray="3 3"/>' +
|
|
45
72
|
text(clamp(x, px + 30, px + pw - 30), top + 8, nt.text, small(th, 10, 'text-anchor="middle"', th.fg));
|
|
46
73
|
});
|
|
47
|
-
return { svg: s, X: X, Y: Y, px: px, pw: pw, top: top, ph: ph };
|
|
74
|
+
return { svg: s, X: X, Y: Y, px: px, pw: pw, top: top, ph: ph, clip: clip, uneven: !!T };
|
|
48
75
|
}
|
|
49
76
|
|
|
50
|
-
/**
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return function (k, x, y) {
|
|
61
|
-
var c = pal[k % pal.length], dk = dashOf ? DASHES[dashOf(k)] : '', mk = markOf ? markOf(k) : 'none';
|
|
62
|
-
return '<line x1="' + r2(x) + '" x2="' + r2(x + 18) + '" y1="' + r2(y + 6) + '" y2="' + r2(y + 6) + '" stroke="' + c + '" stroke-width="2.5" stroke-linecap="round"' +
|
|
63
|
-
(dk ? ' stroke-dasharray="' + dk + '"' : '') + '/>' + (mk !== 'none' ? marker(mk, x + 9, y + 6, 3.5, ' fill="' + c + '" stroke="' + bg + '" stroke-width="1.5"') : '');
|
|
64
|
-
};
|
|
77
|
+
/**
|
|
78
|
+
* A scale from lo to hi where min, max or both are fixed. Gridlines fall on the round steps inside the range, and a
|
|
79
|
+
* fixed end gets its own line too unless a round one sits close by.
|
|
80
|
+
*/
|
|
81
|
+
function fixedScale(lo, hi, hasMin, hasMax) {
|
|
82
|
+
var nice = niceScale(lo, hi, 4), a = hasMin ? lo : nice.lo, b = hasMax ? hi : nice.hi, step = nice.ticks[1] - nice.ticks[0];
|
|
83
|
+
var ticks = nice.ticks.filter(function (t) { return t >= a - step * 1e-9 && t <= b + step * 1e-9; });
|
|
84
|
+
if (hasMin && (!ticks.length || ticks[0] - a > step * 0.4)) ticks.unshift(a);
|
|
85
|
+
if (hasMax && (!ticks.length || b - ticks[ticks.length - 1] > step * 0.4)) ticks.push(b);
|
|
86
|
+
return { lo: a, hi: b, ticks: ticks };
|
|
65
87
|
}
|
|
66
88
|
|
|
67
|
-
/** A
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
89
|
+
/** A log scale over whole powers of ten from lo to hi, with 2 and 5 between them when it spans two powers or fewer. */
|
|
90
|
+
function logScale(lo, hi) {
|
|
91
|
+
var a = Math.floor(Math.log10(lo)), b = Math.ceil(Math.log10(hi)), ticks = [];
|
|
92
|
+
if (b === a) b++;
|
|
93
|
+
for (var e = a; e <= b; e++) {
|
|
94
|
+
var p = Number('1e' + e);
|
|
95
|
+
ticks.push(p);
|
|
96
|
+
if (b - a <= 2 && e < b) ticks.push(2 * p, 5 * p);
|
|
97
|
+
}
|
|
98
|
+
return { log: true, a: a, b: b, lo: ticks[0], hi: ticks[ticks.length - 1], ticks: ticks };
|
|
72
99
|
}
|
|
73
100
|
|
|
74
|
-
/**
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
101
|
+
/**
|
|
102
|
+
* The goal line, then one hover column per point. Evenly spaced points get equal columns centred on them; dated points
|
|
103
|
+
* get columns that reach halfway to each neighbour. tip(j) gives each column's tooltip.
|
|
104
|
+
*/
|
|
105
|
+
export function xyFinish(o, th, f, n, tip) {
|
|
106
|
+
var g = has(o.goal) ? f.Y(+o.goal) : NaN;
|
|
107
|
+
var s = isFinite(g) ? goalLine(o, th, f.px, f.px + f.pw, g) : '';
|
|
108
|
+
var step = n > 1 ? f.pw / (n - 1) : f.pw, X = f.X;
|
|
109
|
+
for (var j = 0; j < n; j++) {
|
|
110
|
+
if (!f.uneven) { s += hit(X(j) - step / 2, f.top, step, f.ph, tip(j)); continue; }
|
|
111
|
+
var l = j ? (X(j - 1) + X(j)) / 2 : X(0) - (n > 1 ? (X(1) - X(0)) / 2 : f.pw / 2);
|
|
112
|
+
var r = j < n - 1 ? (X(j) + X(j + 1)) / 2 : X(j) + (n > 1 ? (X(j) - X(j - 1)) / 2 : f.pw / 2);
|
|
113
|
+
s += hit(l, f.top, Math.max(1, r - l), f.ph, tip(j));
|
|
114
|
+
}
|
|
80
115
|
return s;
|
|
81
116
|
}
|
package/src/element.js
CHANGED
|
@@ -7,7 +7,7 @@ export const ATTRIBUTES = [
|
|
|
7
7
|
'type', 'values', 'labels', 'series', 'heading', 'prefix', 'suffix', 'decimals', 'compact', 'color', 'theme', 'frame',
|
|
8
8
|
'width', 'height', 'goal', 'goal-label', 'notes', 'show-values', 'stat', 'delta', 'delta-label', 'max', 'min', 'value',
|
|
9
9
|
'zones', 'horizontal', 'straight', 'zero', 'start', 'lang', 'corners', 'background', 'center-label', 'highlight',
|
|
10
|
-
'x', 'y', 'x-label', 'y-label', 'trend', 'static', 'no-tooltips', 'stacked', 'angle-labels', 'dash', 'markers', 'patterns', 'bins', 'bin-width', 'mark', 'percent', 'whiskers', 'line', 'line-series', 'line-prefix', 'line-suffix', 'line-decimals', 'line-label', 'line-zero',
|
|
10
|
+
'x', 'y', 'x-label', 'y-label', 'trend', 'static', 'no-tooltips', 'stacked', 'angle-labels', 'dash', 'markers', 'patterns', 'bins', 'bin-width', 'mark', 'percent', 'whiskers', 'line', 'line-series', 'line-prefix', 'line-suffix', 'line-decimals', 'line-label', 'line-zero', 'dates', 'log',
|
|
11
11
|
];
|
|
12
12
|
|
|
13
13
|
const HOST_CSS =
|
package/src/index.js
CHANGED
|
@@ -21,6 +21,6 @@ import { NAMES, render, toSVG } from './render.js';
|
|
|
21
21
|
import { THEMES } from './core/themes.js';
|
|
22
22
|
import { BezelChart } from './element.js';
|
|
23
23
|
|
|
24
|
-
export const version = '1.
|
|
24
|
+
export const version = '1.8.0';
|
|
25
25
|
export const types = NAMES.slice();
|
|
26
26
|
export { render, toSVG, BezelChart, THEMES as themes };
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
/*! Bezel Charts v1.7.0 | MIT | github.com/ShazMoghaddam/bezel-charts */
|
|
2
|
-
var g={dark:{tile:"#15151d",bezel:"#000000",fg:"#f2f1f7",muted:"#8c8aa0",grid:"#2a2935",up:"#5EE6C8",down:"#F675A8",palette:["#9FA1FF","#F675A8","#5EE6C8","#FFC857","#7CC4FF","#FF8A5B"]},light:{tile:"#ffffff",bezel:"#000000",fg:"#17161f",muted:"#6b6980",grid:"#e8e6ef",up:"#12a383",down:"#d63f7c",palette:["#6E70F0","#E2508C","#16A884","#D99A0E","#2F8FE0","#EE6431"]}};var x="ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif",w="ui-monospace,SFMono-Regular,Menlo,Consolas,monospace",W=0;function nt(t){return"bzc"+t+(++W).toString(36)+Math.random().toString(36).slice(2,6)}function h(t){return String(t??"").replace(/[&<>"']/g,function(e){return{"&":"&","<":"<",">":">",'"':""","'":"'"}[e]})}function s(t){return Math.round(t*100)/100}function u(t,e,r){return Math.max(e,Math.min(r,t))}function v(t,e){var r=parseFloat(t);return isFinite(r)?r:e}function c(t){return t!=null&&t!==""}function T(t){return Array.isArray(t)?t.map(function(e){var r=+e;return isFinite(r)?r:0}):c(t)?String(t).split(/[\s,;]+/).filter(Boolean).map(function(e){var r=+e;return isFinite(r)?r:0}):[]}function V(t){return Array.isArray(t)?t.map(String):c(t)?String(t).split(",").map(function(e){return e.trim()}):[]}function at(t){return Array.isArray(t)?Array.isArray(t[0])?t.map(T):[T(t)]:c(t)?String(t).split("|").map(T).filter(function(e){return e.length}):[]}function Y(t){return t.reduce(function(e,r){return e+r},0)}function ot(t,e,r){return String(t).length*e*(r?.6:.56)}function st(t,e){return t=String(t),t.length>e?t.slice(0,Math.max(1,e-1))+"\u2026":t}function C(t){return t===!0||t===""||t==="true"||t==="1"}function k(t,e,r){if(!isFinite(t))return"\u2013";var i=Math.abs(t),n;c(e.decimals)?n=u(parseInt(e.decimals,10)||0,0,6):n=t%1===0?0:i<10?2:i<100?1:0;var a={maximumFractionDigits:n,minimumFractionDigits:c(e.decimals)?n:0};(C(e.compact)||r)&&i>=1e4&&(a={notation:"compact",maximumFractionDigits:1});var o;try{o=new Intl.NumberFormat(e.lang||"en-GB",a).format(i)}catch{o=String(s(i))}return(t<0?"\u2212":"")+(e.prefix||"")+o+(e.suffix||"")}function lt(t,e){if(!t.length)return"";for(var r="M"+s(t[0][0])+","+s(t[0][1]),i=1;i<t.length;i++){var n=t[i-1],a=t[i];if(e)r+="L"+s(a[0])+","+s(a[1]);else{var o=(n[0]+a[0])/2;r+="C"+s(o)+","+s(n[1])+" "+s(o)+","+s(a[1])+" "+s(a[0])+","+s(a[1])}}return r}function p(t,e,r,i){return'<text x="'+s(t)+'" y="'+s(e)+'" '+(i||"")+">"+h(r)+"</text>"}function F(t,e,r,i){return'fill="'+(i||t.muted)+'" font-family="'+w+'" font-size="'+(e||10)+'"'+(r?" "+r:"")}function ct(t,e,r,i,n){return'<rect class="bzc-hit" x="'+s(t)+'" y="'+s(e)+'" width="'+s(Math.max(1,r))+'" height="'+s(Math.max(1,i))+'" fill="#000" fill-opacity="0" data-tip="'+h(n)+'"/>'}function ht(t,e,r){return t.animate?' class="'+e+'"'+(r?' style="animation-delay:'+s(r)+'s"':""):""}function ut(t,e){var r=V(t.color).filter(Boolean);return r.length?r:e.palette}function dt(t,e,r,i,n){return p(e+i/2,r+n/2+4,"No data yet",'text-anchor="middle" fill="'+t.muted+'" font-family="'+x+'" font-size="13"')}function ft(t,e){return c(t.notes)?String(t.notes).split(";").map(function(r){var i=r.indexOf(":");if(i<0)return null;var n=r.slice(0,i).trim(),a=r.slice(i+1).trim(),o=e.map(String).indexOf(n);return o<0&&String(parseInt(n,10))===n&&(o=parseInt(n,10)),o>=0&&a?{i:o,text:a}:null}).filter(Boolean):[]}function mt(t,e,r,i,n){var a=(c(t.goalLabel)?t.goalLabel:"Goal")+" "+k(v(t.goal,0),t);return'<line x1="'+s(r)+'" x2="'+s(i)+'" y1="'+s(n)+'" y2="'+s(n)+'" stroke="'+e.fg+'" stroke-opacity=".55" stroke-width="1.25" stroke-dasharray="4 4"/>'+p(i,n-5,a,F(e,10,'text-anchor="end"'))}function pt(t,e,r){var i=String(c(e.stat)?e.stat:r||"").toLowerCase();if(!i||i==="none"||!t.length)return null;var n=Y(t),a={last:t[t.length-1],total:n,sum:n,average:n/t.length,avg:n/t.length,max:Math.max.apply(null,t),min:Math.min.apply(null,t)};if(!(i in a))return null;var o=null;return i==="last"&&t.length>1&&e.delta!=="none"&&(o=t[t.length-1]-t[0]),{val:a[i],delta:o}}var N=["spark","line","area","bars","combo","histogram","boxplot","scatter","ring","donut","gauge","progress","heatmap"],z={};function wt(t,e){z[t]=e}var X=t=>t.replace(/-([a-z])/g,(e,r)=>r.toUpperCase());function U(t,e){if(!z[t])throw new Error(N.includes(t)?`Bezel Charts: the ${t} chart isn't loaded. Add import 'bezel-charts/${t}', or load dist/charts/${t}.js.`:`Bezel Charts: unknown chart type "${t}". Choose one of: ${N.join(", ")}.`);let r={};for(let[i,n]of Object.entries(e))r[X(i)]=n;return r}function A(t,e={}){let r=U(t,e);r.animate=C(r.animate),r.frame=r.frame==="none"?"none":"bezel";let i=r.theme==="light"||r.theme==="dark"?r.theme:r.autoTheme||"dark";return z[t](r,g[i])}function j(t,e={}){return z[t].table(U(t,e))}function $(t){return t.replace(/<rect class="bzc-hit"[^>]*\/>/g,"").replace(/<circle[^>]* class="bzc-hit"[^>]*\/>/g,"").replace(/ data-tip="[^"]*"/g,"")}function yt(t,e={}){return $(A(t,{...e,animate:!1}))}var q=["type","values","labels","series","heading","prefix","suffix","decimals","compact","color","theme","frame","width","height","goal","goal-label","notes","show-values","stat","delta","delta-label","max","min","value","zones","horizontal","straight","zero","start","lang","corners","background","center-label","highlight","x","y","x-label","y-label","trend","static","no-tooltips","stacked","angle-labels","dash","markers","patterns","bins","bin-width","mark","percent","whiskers","line","line-series","line-prefix","line-suffix","line-decimals","line-label","line-zero"],_=`: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 ${w};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}}`,Q={ArrowLeft:-1,ArrowUp:-1,ArrowRight:1,ArrowDown:1},J=()=>typeof matchMedia=="function"?matchMedia("(prefers-color-scheme: dark)"):null,K=()=>{let t=typeof document<"u"&&document.documentElement?.getAttribute?.("data-theme");return t==="light"||t==="dark"?t:null},R=new Set;typeof MutationObserver=="function"&&typeof document<"u"&&document.documentElement&&new MutationObserver(()=>R.forEach(t=>t.refresh())).observe(document.documentElement,{attributes:!0,attributeFilter:["data-theme"]});var Z=typeof HTMLElement>"u"?class{}:HTMLElement,S=class extends Z{static get observedAttributes(){return q}static get themes(){return g}get resolvedTheme(){let e=this.getAttribute("theme");return e==="light"||e==="dark"?e:this.options.autoTheme}get chartType(){return this.getAttribute("type")||"spark"}connectedCallback(){this.shadowRoot||(this.attachShadow({mode:"open"}).innerHTML=`<style>${_}</style><div class="c" role="group" aria-roledescription="chart"></div><p class="sr" id="h">Use the arrow keys to step through the values.</p><div class="tip" aria-hidden="true"></div><div class="sr" aria-live="polite"></div><div class="sr"></div>`,[,this.#t,,this.#r,this.#s,this.#h]=this.shadowRoot.children,this.shadowRoot.addEventListener("pointermove",e=>this.#d(e)),this.shadowRoot.addEventListener("pointerdown",e=>this.#d(e)),this.addEventListener("pointerleave",()=>this.#r.classList.remove("on")),this.#t.addEventListener("keydown",e=>this.#g(e)),this.#t.addEventListener("blur",()=>this.#b())),R.add(this),this.#i=J(),this.#i?.addEventListener?.("change",this.#u),typeof ResizeObserver=="function"?(this.#o=new ResizeObserver(([e])=>{let r=Math.round(e.contentRect.width);(!this.#n||!this.hasAttribute("width")&&r>0&&Math.abs(r-this.#l)>1)&&this.#a()}),this.#o.observe(this)):this.#a()}disconnectedCallback(){R.delete(this),this.#o?.disconnect(),this.#i?.removeEventListener?.("change",this.#u)}attributeChangedCallback(){!this.#n||this.#c||(this.#c=!0,queueMicrotask(()=>{this.#c=!1,this.#a()}))}get options(){let e={};for(let r of q)this.hasAttribute(r)&&(e[r]=this.getAttribute(r));return e.width||(e.width=this.#l||360),e.autoTheme=K()||(this.#i?this.#i.matches?"dark":"light":"dark"),e}refresh(){this.#n&&this.#a()}toSVG(e={}){return $(A(this.chartType,{...this.options,...e,animate:!1}))}download(e){let r=URL.createObjectURL(new Blob([this.toSVG()],{type:"image/svg+xml"})),i=Object.assign(document.createElement("a"),{href:r,download:`${(e||this.getAttribute("heading")||this.chartType).replace(/[^\w-]+/g,"-").toLowerCase()}.svg`});document.body.append(i),i.click(),i.remove(),setTimeout(()=>URL.revokeObjectURL(r),1e3)}#o=null;#t=null;#r=null;#s=null;#h=null;#e=-1;#i=null;#l=0;#n=!1;#c=!1;#u=()=>{let e=this.getAttribute("theme");(!e||e==="auto")&&this.refresh()};#a(){if(!this.shadowRoot)return;let e=Math.round(this.getBoundingClientRect?.().width||0);this.#l=e>0?e:360;let r=this.options;r.animate=!this.#n&&!this.hasAttribute("static");let i,n=null;try{i=A(this.chartType,r),n=j(this.chartType,r)}catch(d){i=`<p style="font:13px ${x};color:#d63f7c">${h(d.message)}</p>`}let a=this.#t;a.innerHTML=i.replace(/<title>[\s\S]*?<\/title>/,"");let o=a.querySelector("svg");o?(a.setAttribute("aria-label",o.getAttribute("aria-label")),o.removeAttribute("role"),o.removeAttribute("aria-label"),o.setAttribute("aria-hidden","true")):a.removeAttribute("aria-label");let l=!!o&&!this.hasAttribute("no-tooltips");l?(a.setAttribute("tabindex","0"),a.setAttribute("aria-describedby","h")):(a.removeAttribute("tabindex"),a.removeAttribute("aria-describedby")),a.style.color=g[r.theme==="light"||r.theme==="dark"?r.theme:r.autoTheme].fg,a.style.borderRadius=`${r.frame==="none"?4:u(+r.corners||22,0,60)}px`,this.#h.innerHTML=n&&n.rows.length?tt(r.heading,n):"",this.#e>=0&&l&&this.shadowRoot.activeElement===a?this.#p(this.#e):this.#e=-1,this.#n=!0,this.dispatchEvent(new CustomEvent("bezel-render",{bubbles:!0}))}#d(e){if(this.hasAttribute("no-tooltips"))return;let r=e.target?.closest?.("[data-tip]");if(!r){this.#r.classList.remove("on");return}this.#f(r,e.clientX,e.clientY)}#f(e,r,i){let n=this.#r;n.textContent=e.getAttribute("data-tip");let a=this.getBoundingClientRect?.()||{left:0,top:0,width:0},o=n.offsetWidth/2;n.style.left=`${u(r-a.left,o,Math.max(o,a.width-o))}px`,n.style.top=`${i-a.top}px`,n.classList.add("on")}#m(){return[...this.#t.querySelectorAll("[data-tip]:not([data-skip])")]}#g(e){let r=this.#m(),i=r.length;if(!i)return;let n=this.#e,a=Q[e.key];if(a)this.chartType==="heatmap"&&/Left|Right/.test(e.key)&&(a*=7),n=n<0?a>0?0:i-1:u(n+a,0,i-1);else if(e.key==="Home"||e.key==="End")n=e.key==="Home"?0:i-1;else{e.key==="Escape"&&this.#b();return}e.preventDefault(),this.#p(n,!0)}#p(e,r){let i=this.#m();if(!i.length)return;e=u(e,0,i.length-1),this.#t.querySelector(".k")?.classList.remove("k");let n=i[e],a=n.getBoundingClientRect?.()||{left:0,top:0,width:0};n.classList.add("k"),this.#e=e,this.#f(n,a.left+a.width/2,a.top),r&&(this.#s.textContent=`${n.getAttribute("data-tip").replace(/\n/g,", ")}. ${e+1} of ${i.length}`)}#b(){this.#t.querySelector(".k")?.classList.remove("k"),this.#r.classList.remove("on"),this.#s.textContent="",this.#e=-1}};function tt(t,{head:e,rows:r}){let i=n=>n.map((a,o)=>o?`<td>${h(a)}</td>`:`<th scope="row">${h(a)}</th>`).join("");return`<table><caption>${h(t||"Chart data")}</caption><thead><tr>${e.map(n=>`<th scope="col">${h(n)}</th>`).join("")}</tr></thead><tbody>${r.map(n=>`<tr>${i(n)}</tr>`).join("")}</tbody></table>`}function St(t){typeof customElements>"u"||typeof HTMLElement>"u"||(customElements.get(`bezel-${t}`)||customElements.define(`bezel-${t}`,class extends S{get chartType(){return t}}),customElements.get("bezel-chart")||customElements.define("bezel-chart",class extends S{}))}function et(t){var e=Math.round(u(v(t.width,360),160,2400)),r=t.frame==="none"?0:4,i=t.frame==="none"?8:20;return{W:e,b:r,P:i,w:e-2*(r+i)}}var rt=".bzc-a{animation:bzc-in .6s ease both}.bzc-d{animation:bzc-draw 1.1s cubic-bezier(.3,.7,.2,1) both}.bzc-g{transform-box:fill-box;transform-origin:50% 100%;animation:bzc-grow .7s cubic-bezier(.2,.8,.2,1) both}.bzc-gn{transform-box:fill-box;transform-origin:50% 0;animation:bzc-grow .7s cubic-bezier(.2,.8,.2,1) both}.bzc-gx{transform-box:fill-box;transform-origin:0 50%;animation:bzc-growx .8s cubic-bezier(.2,.8,.2,1) both}.bzc-s{animation:bzc-sweep 1.1s cubic-bezier(.2,.8,.2,1) both}@keyframes bzc-in{from{opacity:0}}@keyframes bzc-draw{from{stroke-dashoffset:1}}@keyframes bzc-grow{from{transform:scaleY(0)}}@keyframes bzc-growx{from{transform:scaleX(0)}}@keyframes bzc-sweep{from{stroke-dasharray:0 100}}@media (prefers-reduced-motion:reduce){[class^=bzc-]{animation:none!important}}";function Ft(t,e,r,i,n){var a=et(t),o=a.W,l=a.b,d=a.P,O=a.w,E=u(v(t.corners,22),0,60),f=l+d,y="";c(t.heading)&&(y+=p(l+d,f+10,String(t.heading).toUpperCase(),F(e,11,'font-weight="600" letter-spacing="1.3"')),f+=24);var m=n&&n.stat;if(m){if(y+=p(l+d,f+30,k(m.val,t),'fill="'+e.fg+'" font-family="'+x+'" font-size="32" font-weight="800" letter-spacing="-0.5"'),m.delta!=null){var M=m.delta>0,H=m.delta===0,I=t.delta==="inverse"?!M:M,D=H?e.muted:I?e.up:e.down,P=(H?"\u25CF ":M?"\u25B2 ":"\u25BC ")+k(Math.abs(m.delta),t)+" "+(c(t.deltaLabel)?t.deltaLabel:"since start");y+=p(l+d+O,f+28,P,'text-anchor="end" fill="'+D+'" font-family="'+w+'" font-size="11" font-weight="600"')}f+=44}var G=i(l+d,f,O,r),b=Math.round(f+r+d+l),L="";t.frame!=="none"?L='<rect width="'+o+'" height="'+b+'" rx="'+E+'" fill="'+e.bezel+'"/><rect x="'+l+'" y="'+l+'" width="'+(o-2*l)+'" height="'+(b-2*l)+'" rx="'+Math.max(0,E-l)+'" fill="'+(t.background||e.tile)+'"/>':c(t.background)&&(L='<rect width="'+o+'" height="'+b+'" rx="'+E+'" fill="'+t.background+'"/>');var B=(c(t.heading)?t.heading+": ":"")+(n&&n.summary||"chart");return'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 '+o+" "+b+'" width="'+o+'" height="'+b+'" role="img" aria-label="'+h(B)+'"><title>'+h(B)+"</title>"+(t.animate?"<style>"+rt+"</style>":"")+L+y+G+"</svg>"}export{x as a,w as b,nt as c,h as d,s as e,u as f,v as g,c as h,T as i,V as j,at as k,Y as l,ot as m,st as n,C as o,k as p,lt as q,p as r,F as s,ct as t,ht as u,ut as v,dt as w,ft as x,mt as y,pt as z,et as A,Ft as B,wt as C,A as D,yt as E,S as F,St as G};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
/*! Bezel Charts v1.7.0 | MIT | github.com/ShazMoghaddam/bezel-charts */
|
|
2
|
-
import{a as q,b as B,c as C,g as Y}from"./shared-Y6MBWBOE.js";import{e as p,f as H,h as L,m as S,r as M,s as b,t as K,u as X,y as W}from"./shared-6SF4EQMI.js";function Q(e,t,r,i,l,h,u){var a="",n=l,s=r.n,k=r.labels;if(r.names){var c=B(r.names,r.pal,t,i,n,h,r.key,r.kw);a+=c.svg,n+=c.height}var f=r.lo,v=r.hi;L(e.goal)&&(f=Math.min(f,+e.goal),v=Math.max(v,+e.goal)),r.zero&&(f=Math.min(0,f),v=Math.max(0,v));var g=q(f,v,4),F=g.ticks.map(r.tick),A=Math.max.apply(null,F.map(function(o){return S(o,10,!0)}))+10,G=k.length?20:4,m=i+A,d=h-A,y=u-(n-l)-G,z=function(o){return s===1?m+d/2:m+o*d/(s-1)},D=function(o){return n+y-(o-g.lo)/(g.hi-g.lo)*y};if(g.ticks.forEach(function(o,w){var E=D(o);a+='<line x1="'+p(m)+'" x2="'+p(m+d)+'" y1="'+p(E)+'" y2="'+p(E)+'" stroke="'+t.grid+'"'+(o===0?"":' stroke-dasharray="2 4"')+"/>"+M(m-8,E+3.5,F[w],b(t,10,'text-anchor="end"'))}),k.length){for(var I=Math.max(1,Math.ceil(s*(Math.max.apply(null,k.map(function(o){return S(o,10,!0)}))+10)/d)),x=0;x<s;x+=I)if(k[x]!=null){var J=s>1&&x===0?"start":s>1&&x===s-1?"end":"middle";a+=M(z(x),n+y+15,k[x],b(t,10,'text-anchor="'+J+'"'))}}return r.notes.forEach(function(o){if(!(o.i>=s)){var w=z(o.i);a+='<line x1="'+p(w)+'" x2="'+p(w)+'" y1="'+p(n+12)+'" y2="'+p(n+y)+'" stroke="'+t.fg+'" stroke-opacity=".4" stroke-dasharray="3 3"/>'+M(H(w,m+30,m+d-30),n+8,o.text,b(t,10,'text-anchor="middle"',t.fg))}}),{svg:a,X:z,Y:D,px:m,pw:d,top:n,ph:y}}function R(e,t,r,i,l){for(var h=L(e.goal)?W(e,t,r.px,r.px+r.pw,r.Y(+e.goal)):"",u=i>1?r.pw/(i-1):r.pw,a=0;a<i;a++)h+=K(r.X(a)-u/2,r.top,u,r.ph,l(a));return h}function T(e,t,r,i){return function(l,h,u){var a=e[l%e.length],n=t?C[t(l)]:"",s=r?r(l):"none";return'<line x1="'+p(h)+'" x2="'+p(h+18)+'" y1="'+p(u+6)+'" y2="'+p(u+6)+'" stroke="'+a+'" stroke-width="2.5" stroke-linecap="round"'+(n?' stroke-dasharray="'+n+'"':"")+"/>"+(s!=="none"?Y(s,h+9,u+6,3.5,' fill="'+a+'" stroke="'+i+'" stroke-width="1.5"'):"")}}function U(e,t,r,i,l){return l?'<path d="'+t+'" fill="none" stroke="'+r+'" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="'+l+'"'+X(e,"bzc-a",i*.15)+"/>":'<path d="'+t+'" fill="none" stroke="'+r+'" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" pathLength="1" style="stroke-dasharray:1'+(e.animate?";animation-delay:"+i*.15+"s":"")+'"'+(e.animate?' class="bzc-d"':"")+"/>"}function V(e,t,r,i,l,h,u,a){var n="",s=Math.ceil(r.length/40);return r.forEach(function(k,c){(c%s===0||c===r.length-1)&&(n+=Y(t,i(c),l(k),3.5,' fill="'+h+'" stroke="'+u+'" stroke-width="1.5"'+X(e,"bzc-a",.6+a*.15)))}),n}export{Q as a,R as b,T as c,U as d,V as e};
|