@lolmath/ui 9.4.0 → 9.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/dist/charts.d.mts +352 -0
- package/dist/charts.mjs +942 -0
- package/dist/charts.mjs.map +1 -0
- package/dist/index.css +813 -227
- package/dist/index.d.mts +133 -8
- package/dist/index.mjs +232 -27
- package/dist/index.mjs.map +1 -1
- package/package.json +17 -3
- package/readme.md +156 -0
package/dist/charts.mjs
ADDED
|
@@ -0,0 +1,942 @@
|
|
|
1
|
+
/* empty css */
|
|
2
|
+
import { cx } from "cva";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { useMemo } from "react";
|
|
5
|
+
import { areaY, areaY as areaY$1, barX, barX as barX$1, barY, barY as barY$1, crosshair, crosshair as crosshair$1, d3Curve, defineChart, dot, dot as dot$1, group, group as group$1, lineX, lineY, lineY as lineY$1, rect, ruleX, ruleY, stack, stack as stack$1, text, text as text$1, tickX, tickY } from "@tanstack/charts";
|
|
6
|
+
import { scaleBand, scaleBand as scaleBand$1 } from "@tanstack/charts/scales/band";
|
|
7
|
+
import { scaleLinear, scaleLinear as scaleLinear$1 } from "@tanstack/charts/scales/linear";
|
|
8
|
+
import { scaleOrdinal } from "@tanstack/charts/scales/ordinal";
|
|
9
|
+
import { scalePoint, scalePoint as scalePoint$1 } from "@tanstack/charts/scales/point";
|
|
10
|
+
import { tooltip, tooltip as tooltip$1 } from "@tanstack/charts/tooltip";
|
|
11
|
+
import { Chart } from "@tanstack/charts/react";
|
|
12
|
+
//#region src/charts/curves.ts
|
|
13
|
+
/** Straight segments, like d3's `curveLinear`. */
|
|
14
|
+
const linearCurve = makeCurve({ segments: linearSegments });
|
|
15
|
+
/**
|
|
16
|
+
* Monotone cubic interpolation over x — d3's `curveMonotoneX`, by way of
|
|
17
|
+
* Steffen's method. Smooth, but it never overshoots a reading, so a rounded
|
|
18
|
+
* corner cannot invent a value the data never had.
|
|
19
|
+
*/
|
|
20
|
+
const smoothCurve = makeCurve({
|
|
21
|
+
segments: monotoneSegments,
|
|
22
|
+
dedupe: true
|
|
23
|
+
});
|
|
24
|
+
/** Holds each value until the next one, like d3's `curveStepAfter`. */
|
|
25
|
+
const stepCurve = makeCurve({
|
|
26
|
+
segments: stepAfterSegments,
|
|
27
|
+
back: stepBeforeSegments
|
|
28
|
+
});
|
|
29
|
+
const CURVES = {
|
|
30
|
+
linear: linearCurve,
|
|
31
|
+
smooth: smoothCurve,
|
|
32
|
+
step: stepCurve
|
|
33
|
+
};
|
|
34
|
+
function resolveCurve(name) {
|
|
35
|
+
return CURVES[name];
|
|
36
|
+
}
|
|
37
|
+
function makeCurve(kernel) {
|
|
38
|
+
const back = kernel.back ?? kernel.segments;
|
|
39
|
+
const prepare = (points) => kernel.dedupe ? dedupe(points) : points;
|
|
40
|
+
return {
|
|
41
|
+
line: (points) => {
|
|
42
|
+
const run = prepare(points);
|
|
43
|
+
if (run.length === 0) return "";
|
|
44
|
+
const tail = run.length === 1 ? "Z" : kernel.segments(run);
|
|
45
|
+
return `M${pair(run[0])}${tail}`;
|
|
46
|
+
},
|
|
47
|
+
area: (top, bottom) => {
|
|
48
|
+
const upper = prepare(top);
|
|
49
|
+
const lower = prepare([...bottom].reverse());
|
|
50
|
+
if (upper.length === 0 || lower.length === 0) return "";
|
|
51
|
+
return `M${pair(upper[0])}${upper.length === 1 ? "" : kernel.segments(upper)}L${pair(lower[0])}${lower.length === 1 ? "" : back(lower)}Z`;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function dedupe(points) {
|
|
56
|
+
const run = [];
|
|
57
|
+
for (const point of points) {
|
|
58
|
+
const last = run[run.length - 1];
|
|
59
|
+
if (last && last[0] === point[0] && last[1] === point[1]) continue;
|
|
60
|
+
run.push(point);
|
|
61
|
+
}
|
|
62
|
+
return run;
|
|
63
|
+
}
|
|
64
|
+
function linearSegments(points) {
|
|
65
|
+
let path = "";
|
|
66
|
+
for (let index = 1; index < points.length; index += 1) path += `L${pair(points[index])}`;
|
|
67
|
+
return path;
|
|
68
|
+
}
|
|
69
|
+
/** Across at the height being held, then up to the new one. */
|
|
70
|
+
function stepAfterSegments(points) {
|
|
71
|
+
let path = "";
|
|
72
|
+
for (let index = 1; index < points.length; index += 1) {
|
|
73
|
+
const [x, y] = points[index];
|
|
74
|
+
path += `L${number(x)},${number(points[index - 1][1])}L${number(x)},${number(y)}`;
|
|
75
|
+
}
|
|
76
|
+
return path;
|
|
77
|
+
}
|
|
78
|
+
/** Up to the new height first, then across — the mirror of the above. */
|
|
79
|
+
function stepBeforeSegments(points) {
|
|
80
|
+
let path = "";
|
|
81
|
+
for (let index = 1; index < points.length; index += 1) {
|
|
82
|
+
const [x, y] = points[index];
|
|
83
|
+
path += `L${number(points[index - 1][0])},${number(y)}L${number(x)},${number(y)}`;
|
|
84
|
+
}
|
|
85
|
+
return path;
|
|
86
|
+
}
|
|
87
|
+
function monotoneSegments(points) {
|
|
88
|
+
if (points.length < 3) return linearSegments(points);
|
|
89
|
+
const tangents = monotoneTangents(points);
|
|
90
|
+
let path = "";
|
|
91
|
+
for (let index = 1; index < points.length; index += 1) {
|
|
92
|
+
const [x0, y0] = points[index - 1];
|
|
93
|
+
const [x1, y1] = points[index];
|
|
94
|
+
const third = (x1 - x0) / 3;
|
|
95
|
+
path += `C${number(x0 + third)},${number(y0 + third * tangents[index - 1])},${number(x1 - third)},${number(y1 - third * tangents[index])},${number(x1)},${number(y1)}`;
|
|
96
|
+
}
|
|
97
|
+
return path;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* The tangent at every point. Interior tangents come from Steffen's rule,
|
|
101
|
+
* which clamps each one to the smaller neighbouring slope and zeroes it at a
|
|
102
|
+
* turning point — that clamp is what keeps the curve monotone. The two ends
|
|
103
|
+
* take d3's one-sided estimate off their single neighbour.
|
|
104
|
+
*/
|
|
105
|
+
function monotoneTangents(points) {
|
|
106
|
+
const count = points.length;
|
|
107
|
+
const tangents = new Array(count);
|
|
108
|
+
for (let index = 1; index < count - 1; index += 1) tangents[index] = steffen(points[index - 1], points[index], points[index + 1]);
|
|
109
|
+
tangents[0] = oneSided(points[0], points[1], tangents[1]);
|
|
110
|
+
tangents[count - 1] = oneSided(points[count - 2], points[count - 1], tangents[count - 2]);
|
|
111
|
+
return tangents;
|
|
112
|
+
}
|
|
113
|
+
function steffen(before, at, after) {
|
|
114
|
+
const runBefore = at[0] - before[0];
|
|
115
|
+
const runAfter = after[0] - at[0];
|
|
116
|
+
const slopeBefore = (at[1] - before[1]) / (runBefore || (runAfter < 0 ? -0 : 0));
|
|
117
|
+
const slopeAfter = (after[1] - at[1]) / (runAfter || (runBefore < 0 ? -0 : 0));
|
|
118
|
+
const parabolic = (slopeBefore * runAfter + slopeAfter * runBefore) / (runBefore + runAfter);
|
|
119
|
+
return (sign(slopeBefore) + sign(slopeAfter)) * Math.min(Math.abs(slopeBefore), Math.abs(slopeAfter), .5 * Math.abs(parabolic)) || 0;
|
|
120
|
+
}
|
|
121
|
+
function oneSided(from, to, neighbour) {
|
|
122
|
+
const run = to[0] - from[0];
|
|
123
|
+
return run ? (3 * ((to[1] - from[1]) / run) - neighbour) / 2 : neighbour;
|
|
124
|
+
}
|
|
125
|
+
function sign(value) {
|
|
126
|
+
return value < 0 ? -1 : 1;
|
|
127
|
+
}
|
|
128
|
+
function pair(point) {
|
|
129
|
+
return `${number(point[0])},${number(point[1])}`;
|
|
130
|
+
}
|
|
131
|
+
/** Trims float noise, so an unchanged scene serialises to an unchanged path. */
|
|
132
|
+
function number(value) {
|
|
133
|
+
return Number.isFinite(value) ? String(Math.round(value * 1e6) / 1e6) : "0";
|
|
134
|
+
}
|
|
135
|
+
//#endregion
|
|
136
|
+
//#region src/charts/theme/theme.ts
|
|
137
|
+
/**
|
|
138
|
+
* The Hextech palette, in slot order. Every entry is a CSS custom property, so
|
|
139
|
+
* a host page retunes the whole library by redefining `--lol-chart-series-N`
|
|
140
|
+
* rather than by threading colours through props.
|
|
141
|
+
*
|
|
142
|
+
* Assign these in sequence and never cycle them: a seventh series is not a
|
|
143
|
+
* seventh colour, it is a sign that the chart should fold its tail into
|
|
144
|
+
* "Other" or split into small multiples.
|
|
145
|
+
*/
|
|
146
|
+
const hextechPalette = [
|
|
147
|
+
"var(--lol-chart-series-1)",
|
|
148
|
+
"var(--lol-chart-series-2)",
|
|
149
|
+
"var(--lol-chart-series-3)",
|
|
150
|
+
"var(--lol-chart-series-4)",
|
|
151
|
+
"var(--lol-chart-series-5)",
|
|
152
|
+
"var(--lol-chart-series-6)"
|
|
153
|
+
];
|
|
154
|
+
/** How many categorical series the palette can carry. */
|
|
155
|
+
const hextechPaletteSize = hextechPalette.length;
|
|
156
|
+
/**
|
|
157
|
+
* Dot, bubble and scatter forms are held to a harder test than bars and lines:
|
|
158
|
+
* any two marks can end up touching, not just neighbouring slots. The palette
|
|
159
|
+
* clears that test for its first three slots, so those forms cap at three
|
|
160
|
+
* series — past that, facet rather than reach for a fourth colour.
|
|
161
|
+
*/
|
|
162
|
+
const hextechScatterPaletteSize = 3;
|
|
163
|
+
/**
|
|
164
|
+
* Reserved status colours. A series that *means* good or bad — a win rate, a
|
|
165
|
+
* gold lead, a delta — wears these; a series that is merely "the third one"
|
|
166
|
+
* wears the categorical palette. Never both in one chart.
|
|
167
|
+
*/
|
|
168
|
+
const hextechStatusColors = {
|
|
169
|
+
positive: "var(--lol-chart-positive)",
|
|
170
|
+
negative: "var(--lol-chart-negative)"
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* The chart theme: gold ink and a near-black plot, matching the League client.
|
|
174
|
+
*
|
|
175
|
+
* `background` stays transparent so the frame behind the chart — or whatever
|
|
176
|
+
* the host puts there — shows through.
|
|
177
|
+
*/
|
|
178
|
+
const hextechChartTheme = {
|
|
179
|
+
foreground: "var(--lol-chart-foreground)",
|
|
180
|
+
muted: "var(--lol-chart-muted)",
|
|
181
|
+
grid: "var(--lol-chart-grid)",
|
|
182
|
+
background: "transparent",
|
|
183
|
+
palette: hextechPalette
|
|
184
|
+
};
|
|
185
|
+
/** The colour for a categorical slot, counted from zero and never wrapped. */
|
|
186
|
+
function hextechSeriesColor(index) {
|
|
187
|
+
return hextechPalette[index] ?? hextechPalette[hextechPalette.length - 1];
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Applies the Hextech theme to a chart definition you wrote by hand, keeping
|
|
191
|
+
* any theme fields the definition sets for itself.
|
|
192
|
+
*
|
|
193
|
+
* ```ts
|
|
194
|
+
* const chart = withHextechTheme(defineChart({ marks: [...], x, y }));
|
|
195
|
+
* ```
|
|
196
|
+
*/
|
|
197
|
+
function withHextechTheme(definition) {
|
|
198
|
+
return {
|
|
199
|
+
...definition,
|
|
200
|
+
theme: {
|
|
201
|
+
...hextechChartTheme,
|
|
202
|
+
...definition.theme
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
//#endregion
|
|
207
|
+
//#region src/charts/components/chart-common.ts
|
|
208
|
+
/** The colour a series is drawn in: its own, or its slot in the palette. */
|
|
209
|
+
function seriesColor(series, index) {
|
|
210
|
+
return series.color ?? hextechSeriesColor(index);
|
|
211
|
+
}
|
|
212
|
+
function seriesLabel(series) {
|
|
213
|
+
return series.label ?? series.key;
|
|
214
|
+
}
|
|
215
|
+
function legendItems(series) {
|
|
216
|
+
return series.map((entry, index) => ({
|
|
217
|
+
key: entry.key,
|
|
218
|
+
label: seriesLabel(entry),
|
|
219
|
+
color: seriesColor(entry, index)
|
|
220
|
+
}));
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Whether to draw the legend. One series does not get one: there is a single
|
|
224
|
+
* colour, and the title already says what it is.
|
|
225
|
+
*/
|
|
226
|
+
function showLegend(series, legend) {
|
|
227
|
+
return legend ?? series.length > 1;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* The chart needs a label whatever the caller passed. A string title is the
|
|
231
|
+
* obvious one; past that we fall back to naming the series, so the chart is
|
|
232
|
+
* never announced as an unlabelled graphic.
|
|
233
|
+
*/
|
|
234
|
+
function resolveAriaLabel(ariaLabel, title, series) {
|
|
235
|
+
if (ariaLabel) return ariaLabel;
|
|
236
|
+
if (typeof title === "string") return title;
|
|
237
|
+
if (typeof title === "number") return String(title);
|
|
238
|
+
const names = series.map(seriesLabel);
|
|
239
|
+
return names.length ? `Chart of ${names.join(", ")}` : "Chart";
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Folds wide rows into one row per (row, series) pair.
|
|
243
|
+
*
|
|
244
|
+
* Grouping and stacking are computed *within* a mark, off its series channel —
|
|
245
|
+
* so a grouped or stacked chart is a single mark over folded data, not one mark
|
|
246
|
+
* per series. Rows come out x-major, which keeps a stack in the order the
|
|
247
|
+
* `series` array declares.
|
|
248
|
+
*/
|
|
249
|
+
function foldSeries(data, series, x) {
|
|
250
|
+
const rows = [];
|
|
251
|
+
for (const datum of data) {
|
|
252
|
+
const xValue = x(datum);
|
|
253
|
+
for (const entry of series) rows.push({
|
|
254
|
+
datum,
|
|
255
|
+
seriesKey: entry.key,
|
|
256
|
+
x: xValue,
|
|
257
|
+
value: entry.value(datum)
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
return rows;
|
|
261
|
+
}
|
|
262
|
+
/** Looks up each series' colour by key, for a folded mark's `fill`. */
|
|
263
|
+
function seriesColorLookup(series) {
|
|
264
|
+
const colors = new Map(series.map((entry, index) => [entry.key, seriesColor(entry, index)]));
|
|
265
|
+
return (key) => colors.get(key) ?? seriesColor(series[0] ?? {
|
|
266
|
+
key,
|
|
267
|
+
value: () => 0
|
|
268
|
+
}, 0);
|
|
269
|
+
}
|
|
270
|
+
/** Every distinct x value, in the order the data first mentions it. */
|
|
271
|
+
function xDomain(data, x) {
|
|
272
|
+
const seen = /* @__PURE__ */ new Set();
|
|
273
|
+
const domain = [];
|
|
274
|
+
for (const datum of data) {
|
|
275
|
+
const value = x(datum);
|
|
276
|
+
if (seen.has(value)) continue;
|
|
277
|
+
seen.add(value);
|
|
278
|
+
domain.push(value);
|
|
279
|
+
}
|
|
280
|
+
return domain;
|
|
281
|
+
}
|
|
282
|
+
/** Categorical unless every x is a number. */
|
|
283
|
+
function isCategoricalX(data, x) {
|
|
284
|
+
return data.some((datum) => typeof x(datum) !== "number");
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* The x axis for a chart whose marks sit *between* positions — lines, areas,
|
|
288
|
+
* dots. Categorical data gets a point scale; numbers get a linear one.
|
|
289
|
+
*/
|
|
290
|
+
function pointXAxis(data, x, options) {
|
|
291
|
+
const categorical = isCategoricalX(data, x);
|
|
292
|
+
const domain = xDomain(data, x);
|
|
293
|
+
return {
|
|
294
|
+
scale: categorical ? () => scalePoint$1().domain(domain).padding(.2) : scaleLinear$1,
|
|
295
|
+
nice: !categorical,
|
|
296
|
+
axis: axisPresentation(options)
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
/** The x axis for marks that occupy a slot: bars and their labels. */
|
|
300
|
+
function bandXAxis(data, x, options) {
|
|
301
|
+
const domain = xDomain(data, x);
|
|
302
|
+
return {
|
|
303
|
+
scale: () => scaleBand$1().domain(domain).padding(options.padding ?? .24),
|
|
304
|
+
axis: axisPresentation(options)
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
/** A linear measure axis, niced and — usually — gridded. */
|
|
308
|
+
function valueAxis(options) {
|
|
309
|
+
return {
|
|
310
|
+
scale: scaleLinear$1,
|
|
311
|
+
nice: true,
|
|
312
|
+
grid: options.grid ?? true,
|
|
313
|
+
axis: axisPresentation(options)
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
function axisPresentation(options) {
|
|
317
|
+
return {
|
|
318
|
+
label: options.label,
|
|
319
|
+
ticks: options.format ? { format: options.format } : void 0
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* The tooltip, wired so it speaks the caller's labels and formats rather than
|
|
324
|
+
* the raw channel values. The `group` item is what turns "line-0" into
|
|
325
|
+
* "Blue side" on a shared-x tooltip.
|
|
326
|
+
*/
|
|
327
|
+
function hextechTooltip(args) {
|
|
328
|
+
const labels = new Map(args.series.map((entry) => [entry.key, seriesLabel(entry)]));
|
|
329
|
+
const items = [{
|
|
330
|
+
channel: "x",
|
|
331
|
+
label: args.xLabel,
|
|
332
|
+
text: (point) => formatChartValue(point.xValue, args.formatX)
|
|
333
|
+
}, {
|
|
334
|
+
channel: "y",
|
|
335
|
+
label: args.yLabel,
|
|
336
|
+
text: (point) => formatChartValue(point.yValue, args.formatY)
|
|
337
|
+
}];
|
|
338
|
+
if (args.series.length > 1) items.push({
|
|
339
|
+
channel: "group",
|
|
340
|
+
text: (point) => labels.get(String(point.group ?? point.markId)) ?? point.groupLabel
|
|
341
|
+
});
|
|
342
|
+
return {
|
|
343
|
+
use: tooltip$1,
|
|
344
|
+
items
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
/** Row-level accessor for a tooltip item, tolerant of the widened value type. */
|
|
348
|
+
function formatChartValue(value, format) {
|
|
349
|
+
if (format) return format(value);
|
|
350
|
+
if (typeof value === "number") return numberFormat.format(value);
|
|
351
|
+
return String(value);
|
|
352
|
+
}
|
|
353
|
+
const numberFormat = new Intl.NumberFormat();
|
|
354
|
+
//#endregion
|
|
355
|
+
//#region src/charts/components/chart-frame/chart-frame.module.css
|
|
356
|
+
var chart_frame_module_default = {
|
|
357
|
+
"frame": "_frame_7dkb0_8",
|
|
358
|
+
"bare": "_bare_7dkb0_26",
|
|
359
|
+
"corner": "_corner_7dkb0_38",
|
|
360
|
+
"cornerTopLeft": "_cornerTopLeft_7dkb0_51",
|
|
361
|
+
"cornerTopRight": "_cornerTopRight_7dkb0_56",
|
|
362
|
+
"cornerBottomLeft": "_cornerBottomLeft_7dkb0_61",
|
|
363
|
+
"cornerBottomRight": "_cornerBottomRight_7dkb0_66",
|
|
364
|
+
"header": "_header_7dkb0_71",
|
|
365
|
+
"headings": "_headings_7dkb0_78",
|
|
366
|
+
"title": "_title_7dkb0_87",
|
|
367
|
+
"subtitle": "_subtitle_7dkb0_98",
|
|
368
|
+
"actions": "_actions_7dkb0_106",
|
|
369
|
+
"rule": "_rule_7dkb0_115",
|
|
370
|
+
"ruleLine": "_ruleLine_7dkb0_121",
|
|
371
|
+
"ruleDiamond": "_ruleDiamond_7dkb0_135",
|
|
372
|
+
"body": "_body_7dkb0_143",
|
|
373
|
+
"footer": "_footer_7dkb0_149"
|
|
374
|
+
};
|
|
375
|
+
//#endregion
|
|
376
|
+
//#region src/charts/components/chart-frame/chart-frame.tsx
|
|
377
|
+
/**
|
|
378
|
+
* The panel a Hextech chart sits in: a gold hairline, diamond corners, a title
|
|
379
|
+
* in Beaufort and a rule under it.
|
|
380
|
+
*
|
|
381
|
+
* Every chart in this package renders one of these. Reach for it directly when
|
|
382
|
+
* you are building a chart of your own and want it to sit alongside them.
|
|
383
|
+
*/
|
|
384
|
+
function ChartFrame({ title, subtitle, actions, footer, preset = "framed", className, children, ...rest }) {
|
|
385
|
+
const hasHeader = title !== void 0 || subtitle !== void 0 || actions;
|
|
386
|
+
return /* @__PURE__ */ jsxs("figure", {
|
|
387
|
+
className: cx(chart_frame_module_default.frame, preset === "bare" && chart_frame_module_default.bare, className),
|
|
388
|
+
...rest,
|
|
389
|
+
children: [
|
|
390
|
+
hasHeader && /* @__PURE__ */ jsxs("figcaption", {
|
|
391
|
+
className: chart_frame_module_default.header,
|
|
392
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
393
|
+
className: chart_frame_module_default.headings,
|
|
394
|
+
children: [title !== void 0 && /* @__PURE__ */ jsx("p", {
|
|
395
|
+
className: chart_frame_module_default.title,
|
|
396
|
+
children: title
|
|
397
|
+
}), subtitle !== void 0 && /* @__PURE__ */ jsx("p", {
|
|
398
|
+
className: chart_frame_module_default.subtitle,
|
|
399
|
+
children: subtitle
|
|
400
|
+
})]
|
|
401
|
+
}), actions && /* @__PURE__ */ jsx("div", {
|
|
402
|
+
className: chart_frame_module_default.actions,
|
|
403
|
+
children: actions
|
|
404
|
+
})]
|
|
405
|
+
}),
|
|
406
|
+
hasHeader && /* @__PURE__ */ jsxs("div", {
|
|
407
|
+
"aria-hidden": true,
|
|
408
|
+
className: chart_frame_module_default.rule,
|
|
409
|
+
children: [
|
|
410
|
+
/* @__PURE__ */ jsx("span", { className: chart_frame_module_default.ruleDiamond }),
|
|
411
|
+
/* @__PURE__ */ jsx("hr", { className: chart_frame_module_default.ruleLine }),
|
|
412
|
+
/* @__PURE__ */ jsx("span", { className: chart_frame_module_default.ruleDiamond })
|
|
413
|
+
]
|
|
414
|
+
}),
|
|
415
|
+
/* @__PURE__ */ jsx("div", {
|
|
416
|
+
className: chart_frame_module_default.body,
|
|
417
|
+
children
|
|
418
|
+
}),
|
|
419
|
+
footer && /* @__PURE__ */ jsx("div", {
|
|
420
|
+
className: chart_frame_module_default.footer,
|
|
421
|
+
children: footer
|
|
422
|
+
}),
|
|
423
|
+
/* @__PURE__ */ jsx("span", {
|
|
424
|
+
"aria-hidden": true,
|
|
425
|
+
className: cx(chart_frame_module_default.corner, chart_frame_module_default.cornerTopLeft)
|
|
426
|
+
}),
|
|
427
|
+
/* @__PURE__ */ jsx("span", {
|
|
428
|
+
"aria-hidden": true,
|
|
429
|
+
className: cx(chart_frame_module_default.corner, chart_frame_module_default.cornerTopRight)
|
|
430
|
+
}),
|
|
431
|
+
/* @__PURE__ */ jsx("span", {
|
|
432
|
+
"aria-hidden": true,
|
|
433
|
+
className: cx(chart_frame_module_default.corner, chart_frame_module_default.cornerBottomLeft)
|
|
434
|
+
}),
|
|
435
|
+
/* @__PURE__ */ jsx("span", {
|
|
436
|
+
"aria-hidden": true,
|
|
437
|
+
className: cx(chart_frame_module_default.corner, chart_frame_module_default.cornerBottomRight)
|
|
438
|
+
})
|
|
439
|
+
]
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
//#endregion
|
|
443
|
+
//#region src/charts/components/chart-legend/chart-legend.module.css
|
|
444
|
+
var chart_legend_module_default = {
|
|
445
|
+
"legend": "_legend_1rk8r_2",
|
|
446
|
+
"item": "_item_1rk8r_13",
|
|
447
|
+
"swatch": "_swatch_1rk8r_26",
|
|
448
|
+
"square": "_square_1rk8r_35",
|
|
449
|
+
"line": "_line_1rk8r_39"
|
|
450
|
+
};
|
|
451
|
+
//#endregion
|
|
452
|
+
//#region src/charts/components/chart-legend/chart-legend.tsx
|
|
453
|
+
/**
|
|
454
|
+
* The legend every multi-series chart carries.
|
|
455
|
+
*
|
|
456
|
+
* Colour alone is never allowed to be the only way to tell two series apart,
|
|
457
|
+
* so this is not optional decoration — a chart with two or more series renders
|
|
458
|
+
* one. A single-series chart does not: its title already says what is plotted,
|
|
459
|
+
* and a lone swatch would only restate it.
|
|
460
|
+
*/
|
|
461
|
+
function ChartLegend({ items, swatch = "diamond", className, ...rest }) {
|
|
462
|
+
return /* @__PURE__ */ jsx("ul", {
|
|
463
|
+
className: cx(chart_legend_module_default.legend, className),
|
|
464
|
+
...rest,
|
|
465
|
+
children: items.map((item) => /* @__PURE__ */ jsxs("li", {
|
|
466
|
+
className: chart_legend_module_default.item,
|
|
467
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
468
|
+
"aria-hidden": true,
|
|
469
|
+
className: cx(chart_legend_module_default.swatch, swatch === "square" && chart_legend_module_default.square, swatch === "line" && chart_legend_module_default.line),
|
|
470
|
+
style: { "--lol-chart-legend-color": item.color }
|
|
471
|
+
}), item.label ?? item.key]
|
|
472
|
+
}, item.key))
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
//#endregion
|
|
476
|
+
//#region src/charts/components/hextech-chart/hextech-chart.module.css
|
|
477
|
+
var hextech_chart_module_default = { "chart": "_chart_1mnqy_2" };
|
|
478
|
+
//#endregion
|
|
479
|
+
//#region src/charts/components/hextech-chart/hextech-chart.tsx
|
|
480
|
+
/**
|
|
481
|
+
* A TanStack chart wearing the Hextech theme, with no frame around it.
|
|
482
|
+
*
|
|
483
|
+
* Use it when you have written a `defineChart` definition of your own and want
|
|
484
|
+
* it to look like the rest of the library. The theme is merged into the
|
|
485
|
+
* definition, so anything the definition sets for itself still wins.
|
|
486
|
+
*/
|
|
487
|
+
function HextechChart({ definition, glow = true, className, wrapperProps, ...rest }) {
|
|
488
|
+
const themed = useMemo(() => applyHextechTheme(definition), [definition]);
|
|
489
|
+
const { className: wrapperClassName, ...restWrapperProps } = wrapperProps ?? {};
|
|
490
|
+
return /* @__PURE__ */ jsx("div", {
|
|
491
|
+
"data-lol-chart": "",
|
|
492
|
+
"data-lol-chart-glow": glow,
|
|
493
|
+
className: cx(hextech_chart_module_default.chart, wrapperClassName),
|
|
494
|
+
...restWrapperProps,
|
|
495
|
+
children: /* @__PURE__ */ jsx(Chart, {
|
|
496
|
+
definition: themed,
|
|
497
|
+
className,
|
|
498
|
+
...rest
|
|
499
|
+
})
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Merges the theme in. A responsive definition builds its spec per size, so the
|
|
504
|
+
* theme has to go on what the builder returns rather than on the definition.
|
|
505
|
+
*/
|
|
506
|
+
function applyHextechTheme(definition) {
|
|
507
|
+
if ("chart" in definition) {
|
|
508
|
+
const build = definition.chart;
|
|
509
|
+
return {
|
|
510
|
+
...definition,
|
|
511
|
+
chart: (context) => withHextechTheme(build(context))
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
return {
|
|
515
|
+
...definition,
|
|
516
|
+
theme: {
|
|
517
|
+
...hextechChartTheme,
|
|
518
|
+
...definition.theme
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
//#endregion
|
|
523
|
+
//#region src/charts/components/area-chart/area-chart.tsx
|
|
524
|
+
/**
|
|
525
|
+
* Filled areas — a composition over time, or a single magnitude you want to
|
|
526
|
+
* read as volume rather than as a trace.
|
|
527
|
+
*
|
|
528
|
+
* Overlaid areas (the default) are only honest for two or three series; past
|
|
529
|
+
* that the ones behind disappear. Stack them, or split into small multiples.
|
|
530
|
+
*/
|
|
531
|
+
function AreaChart({ data, series, x, curve = "linear", stacked = false, normalize = false, stroke = true, crosshair: withCrosshair = true, height = 280, title, subtitle, actions, xLabel, yLabel, formatX, formatY, grid = true, legend, frame = true, glow = true, ariaLabel, ariaDescription, className, frameProps }) {
|
|
532
|
+
const definition = useMemo(() => {
|
|
533
|
+
const resolvedCurve = resolveCurve(curve);
|
|
534
|
+
const marks = [];
|
|
535
|
+
if (stacked) {
|
|
536
|
+
const rows = foldSeries(data, series, x);
|
|
537
|
+
const colorOf = seriesColorLookup(series);
|
|
538
|
+
marks.push(areaY$1(rows, {
|
|
539
|
+
id: "areas",
|
|
540
|
+
x: (row) => row.x,
|
|
541
|
+
y: (row) => row.value,
|
|
542
|
+
z: (row) => row.seriesKey,
|
|
543
|
+
fill: (row) => colorOf(row.seriesKey),
|
|
544
|
+
fillOpacity: .62,
|
|
545
|
+
curve: resolvedCurve,
|
|
546
|
+
layout: stack$1(normalize ? { offset: "normalize" } : void 0),
|
|
547
|
+
...stroke ? {
|
|
548
|
+
stroke: "var(--lol-chart-surface)",
|
|
549
|
+
strokeWidth: 1
|
|
550
|
+
} : {}
|
|
551
|
+
}));
|
|
552
|
+
} else for (const [index, entry] of series.entries()) {
|
|
553
|
+
const color = seriesColor(entry, index);
|
|
554
|
+
marks.push(areaY$1(data, {
|
|
555
|
+
id: entry.key,
|
|
556
|
+
x,
|
|
557
|
+
y: entry.value,
|
|
558
|
+
fill: color,
|
|
559
|
+
fillOpacity: .16,
|
|
560
|
+
curve: resolvedCurve
|
|
561
|
+
}));
|
|
562
|
+
if (stroke) marks.push(lineY$1(data, {
|
|
563
|
+
id: `${entry.key}-line`,
|
|
564
|
+
x,
|
|
565
|
+
y: entry.value,
|
|
566
|
+
stroke: color,
|
|
567
|
+
strokeWidth: 2,
|
|
568
|
+
curve: resolvedCurve
|
|
569
|
+
}));
|
|
570
|
+
}
|
|
571
|
+
if (withCrosshair) marks.push(crosshair$1({
|
|
572
|
+
x: true,
|
|
573
|
+
y: false,
|
|
574
|
+
stroke: "var(--lol-chart-frame-accent)",
|
|
575
|
+
strokeOpacity: .45
|
|
576
|
+
}));
|
|
577
|
+
return {
|
|
578
|
+
marks,
|
|
579
|
+
x: pointXAxis(data, x, {
|
|
580
|
+
label: xLabel,
|
|
581
|
+
format: formatX
|
|
582
|
+
}),
|
|
583
|
+
y: valueAxis({
|
|
584
|
+
label: yLabel,
|
|
585
|
+
format: formatY,
|
|
586
|
+
grid
|
|
587
|
+
}),
|
|
588
|
+
focus: "group-x",
|
|
589
|
+
tooltip: hextechTooltip({
|
|
590
|
+
series,
|
|
591
|
+
xLabel,
|
|
592
|
+
yLabel,
|
|
593
|
+
formatX,
|
|
594
|
+
formatY
|
|
595
|
+
})
|
|
596
|
+
};
|
|
597
|
+
}, [
|
|
598
|
+
curve,
|
|
599
|
+
data,
|
|
600
|
+
formatX,
|
|
601
|
+
formatY,
|
|
602
|
+
grid,
|
|
603
|
+
normalize,
|
|
604
|
+
series,
|
|
605
|
+
stacked,
|
|
606
|
+
stroke,
|
|
607
|
+
withCrosshair,
|
|
608
|
+
x,
|
|
609
|
+
xLabel,
|
|
610
|
+
yLabel
|
|
611
|
+
]);
|
|
612
|
+
return /* @__PURE__ */ jsx(ChartFrame, {
|
|
613
|
+
title,
|
|
614
|
+
subtitle,
|
|
615
|
+
actions,
|
|
616
|
+
preset: frame ? "framed" : "bare",
|
|
617
|
+
className,
|
|
618
|
+
footer: showLegend(series, legend) ? /* @__PURE__ */ jsx(ChartLegend, { items: legendItems(series) }) : void 0,
|
|
619
|
+
...frameProps,
|
|
620
|
+
children: /* @__PURE__ */ jsx(HextechChart, {
|
|
621
|
+
definition,
|
|
622
|
+
height,
|
|
623
|
+
glow,
|
|
624
|
+
ariaLabel: resolveAriaLabel(ariaLabel, title, series),
|
|
625
|
+
ariaDescription
|
|
626
|
+
})
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
//#endregion
|
|
630
|
+
//#region src/charts/components/bar-chart/bar-chart.tsx
|
|
631
|
+
/**
|
|
632
|
+
* Columns over categories — per-champion damage, per-role gold share, counts
|
|
633
|
+
* by patch.
|
|
634
|
+
*
|
|
635
|
+
* Bars are separated by a gap in the surface rather than by an outline: a
|
|
636
|
+
* stroke around a bar is ink that carries no data.
|
|
637
|
+
*/
|
|
638
|
+
function BarChart({ data, series, x, layout = "grouped", normalize = false, radius = 0, maxThickness = 24, height = 280, title, subtitle, actions, xLabel, yLabel, formatX, formatY, grid = true, legend, frame = true, glow = false, ariaLabel, ariaDescription, className, frameProps }) {
|
|
639
|
+
const definition = useMemo(() => {
|
|
640
|
+
const stacked = layout === "stacked";
|
|
641
|
+
const rows = foldSeries(data, series, x);
|
|
642
|
+
const colorOf = seriesColorLookup(series);
|
|
643
|
+
return {
|
|
644
|
+
marks: [barY$1(rows, {
|
|
645
|
+
id: "bars",
|
|
646
|
+
x: (row) => row.x,
|
|
647
|
+
y: (row) => row.value,
|
|
648
|
+
z: (row) => row.seriesKey,
|
|
649
|
+
fill: (row) => colorOf(row.seriesKey),
|
|
650
|
+
inset: 1,
|
|
651
|
+
maxThickness,
|
|
652
|
+
radius,
|
|
653
|
+
layout: stacked ? stack$1(normalize ? { offset: "normalize" } : void 0) : group$1({ padding: .16 })
|
|
654
|
+
})],
|
|
655
|
+
x: bandXAxis(data, x, {
|
|
656
|
+
label: xLabel,
|
|
657
|
+
format: formatX
|
|
658
|
+
}),
|
|
659
|
+
y: valueAxis({
|
|
660
|
+
label: yLabel,
|
|
661
|
+
format: formatY,
|
|
662
|
+
grid
|
|
663
|
+
}),
|
|
664
|
+
focus: series.length > 1 ? "group-x" : "nearest",
|
|
665
|
+
tooltip: hextechTooltip({
|
|
666
|
+
series,
|
|
667
|
+
xLabel,
|
|
668
|
+
yLabel,
|
|
669
|
+
formatX,
|
|
670
|
+
formatY
|
|
671
|
+
})
|
|
672
|
+
};
|
|
673
|
+
}, [
|
|
674
|
+
data,
|
|
675
|
+
formatX,
|
|
676
|
+
formatY,
|
|
677
|
+
grid,
|
|
678
|
+
layout,
|
|
679
|
+
maxThickness,
|
|
680
|
+
normalize,
|
|
681
|
+
radius,
|
|
682
|
+
series,
|
|
683
|
+
x,
|
|
684
|
+
xLabel,
|
|
685
|
+
yLabel
|
|
686
|
+
]);
|
|
687
|
+
return /* @__PURE__ */ jsx(ChartFrame, {
|
|
688
|
+
title,
|
|
689
|
+
subtitle,
|
|
690
|
+
actions,
|
|
691
|
+
preset: frame ? "framed" : "bare",
|
|
692
|
+
className,
|
|
693
|
+
footer: showLegend(series, legend) ? /* @__PURE__ */ jsx(ChartLegend, {
|
|
694
|
+
items: legendItems(series),
|
|
695
|
+
swatch: "square"
|
|
696
|
+
}) : void 0,
|
|
697
|
+
...frameProps,
|
|
698
|
+
children: /* @__PURE__ */ jsx(HextechChart, {
|
|
699
|
+
definition,
|
|
700
|
+
height,
|
|
701
|
+
glow,
|
|
702
|
+
ariaLabel: resolveAriaLabel(ariaLabel, title, series),
|
|
703
|
+
ariaDescription
|
|
704
|
+
})
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
//#endregion
|
|
708
|
+
//#region src/charts/components/line-chart/line-chart.tsx
|
|
709
|
+
/**
|
|
710
|
+
* Lines over time — gold curves, damage curves, anything that only makes sense
|
|
711
|
+
* read left to right.
|
|
712
|
+
*
|
|
713
|
+
* ```tsx
|
|
714
|
+
* <LineChart
|
|
715
|
+
* title="Team gold"
|
|
716
|
+
* data={timeline}
|
|
717
|
+
* x={(row) => row.minute}
|
|
718
|
+
* series={[
|
|
719
|
+
* { key: "blue", label: "Blue side", value: (row) => row.blueGold },
|
|
720
|
+
* { key: "red", label: "Red side", value: (row) => row.redGold },
|
|
721
|
+
* ]}
|
|
722
|
+
* xLabel="Minute"
|
|
723
|
+
* yLabel="Gold"
|
|
724
|
+
* />
|
|
725
|
+
* ```
|
|
726
|
+
*/
|
|
727
|
+
function LineChart({ data, series, x, curve = "linear", points = false, area = false, crosshair: withCrosshair = true, height = 280, title, subtitle, actions, xLabel, yLabel, formatX, formatY, grid = true, legend, frame = true, glow = true, ariaLabel, ariaDescription, className, frameProps }) {
|
|
728
|
+
const definition = useMemo(() => {
|
|
729
|
+
const resolvedCurve = resolveCurve(curve);
|
|
730
|
+
const marks = [];
|
|
731
|
+
for (const [index, entry] of series.entries()) {
|
|
732
|
+
const color = seriesColor(entry, index);
|
|
733
|
+
if (area) marks.push(areaY$1(data, {
|
|
734
|
+
id: `${entry.key}-area`,
|
|
735
|
+
x,
|
|
736
|
+
y: entry.value,
|
|
737
|
+
fill: color,
|
|
738
|
+
fillOpacity: .12,
|
|
739
|
+
curve: resolvedCurve
|
|
740
|
+
}));
|
|
741
|
+
marks.push(lineY$1(data, {
|
|
742
|
+
id: entry.key,
|
|
743
|
+
x,
|
|
744
|
+
y: entry.value,
|
|
745
|
+
stroke: color,
|
|
746
|
+
strokeWidth: 2,
|
|
747
|
+
curve: resolvedCurve
|
|
748
|
+
}));
|
|
749
|
+
if (points) marks.push(dot$1(data, {
|
|
750
|
+
id: `${entry.key}-points`,
|
|
751
|
+
x,
|
|
752
|
+
y: entry.value,
|
|
753
|
+
r: 4,
|
|
754
|
+
fill: color,
|
|
755
|
+
stroke: "var(--lol-chart-surface)",
|
|
756
|
+
strokeWidth: 2
|
|
757
|
+
}));
|
|
758
|
+
}
|
|
759
|
+
if (withCrosshair) marks.push(crosshair$1({
|
|
760
|
+
x: true,
|
|
761
|
+
y: false,
|
|
762
|
+
stroke: "var(--lol-chart-frame-accent)",
|
|
763
|
+
strokeOpacity: .45
|
|
764
|
+
}));
|
|
765
|
+
return {
|
|
766
|
+
marks,
|
|
767
|
+
x: pointXAxis(data, x, {
|
|
768
|
+
label: xLabel,
|
|
769
|
+
format: formatX
|
|
770
|
+
}),
|
|
771
|
+
y: valueAxis({
|
|
772
|
+
label: yLabel,
|
|
773
|
+
format: formatY,
|
|
774
|
+
grid
|
|
775
|
+
}),
|
|
776
|
+
focus: "group-x",
|
|
777
|
+
tooltip: hextechTooltip({
|
|
778
|
+
series,
|
|
779
|
+
xLabel,
|
|
780
|
+
yLabel,
|
|
781
|
+
formatX,
|
|
782
|
+
formatY
|
|
783
|
+
})
|
|
784
|
+
};
|
|
785
|
+
}, [
|
|
786
|
+
area,
|
|
787
|
+
curve,
|
|
788
|
+
data,
|
|
789
|
+
formatX,
|
|
790
|
+
formatY,
|
|
791
|
+
grid,
|
|
792
|
+
points,
|
|
793
|
+
series,
|
|
794
|
+
withCrosshair,
|
|
795
|
+
x,
|
|
796
|
+
xLabel,
|
|
797
|
+
yLabel
|
|
798
|
+
]);
|
|
799
|
+
return /* @__PURE__ */ jsx(ChartFrame, {
|
|
800
|
+
title,
|
|
801
|
+
subtitle,
|
|
802
|
+
actions,
|
|
803
|
+
preset: frame ? "framed" : "bare",
|
|
804
|
+
className,
|
|
805
|
+
footer: showLegend(series, legend) ? /* @__PURE__ */ jsx(ChartLegend, {
|
|
806
|
+
items: legendItems(series),
|
|
807
|
+
swatch: "line"
|
|
808
|
+
}) : void 0,
|
|
809
|
+
...frameProps,
|
|
810
|
+
children: /* @__PURE__ */ jsx(HextechChart, {
|
|
811
|
+
definition,
|
|
812
|
+
height,
|
|
813
|
+
glow,
|
|
814
|
+
ariaLabel: resolveAriaLabel(ariaLabel, title, series),
|
|
815
|
+
ariaDescription
|
|
816
|
+
})
|
|
817
|
+
});
|
|
818
|
+
}
|
|
819
|
+
//#endregion
|
|
820
|
+
//#region src/charts/components/ranking-chart/ranking-chart.tsx
|
|
821
|
+
const defaultFormat = new Intl.NumberFormat();
|
|
822
|
+
/**
|
|
823
|
+
* A ranked horizontal bar chart — the leaderboard shape. Longest bar on top,
|
|
824
|
+
* every value written at the tip.
|
|
825
|
+
*
|
|
826
|
+
* ```tsx
|
|
827
|
+
* <RankingChart
|
|
828
|
+
* title="Damage to champions"
|
|
829
|
+
* data={scoreboard}
|
|
830
|
+
* label={(row) => row.champion}
|
|
831
|
+
* value={(row) => row.damage}
|
|
832
|
+
* formatValue={(value) => `${Math.round(value / 1000)}k`}
|
|
833
|
+
* />
|
|
834
|
+
* ```
|
|
835
|
+
*/
|
|
836
|
+
function RankingChart({ data, label, value, color, order = "descending", limit, showValues = true, formatValue, valueLabel, axis = false, height, title, subtitle, actions, frame = true, glow = false, ariaLabel, ariaDescription, className, frameProps }) {
|
|
837
|
+
const rows = useMemo(() => {
|
|
838
|
+
const mapped = data.map((datum) => ({
|
|
839
|
+
datum,
|
|
840
|
+
label: label(datum),
|
|
841
|
+
value: value(datum)
|
|
842
|
+
}));
|
|
843
|
+
if (order === "descending") mapped.sort((a, b) => b.value - a.value);
|
|
844
|
+
if (order === "ascending") mapped.sort((a, b) => a.value - b.value);
|
|
845
|
+
return (limit === void 0 ? mapped : mapped.slice(0, limit)).map((row, rank) => ({
|
|
846
|
+
...row,
|
|
847
|
+
rank
|
|
848
|
+
}));
|
|
849
|
+
}, [
|
|
850
|
+
data,
|
|
851
|
+
label,
|
|
852
|
+
limit,
|
|
853
|
+
order,
|
|
854
|
+
value
|
|
855
|
+
]);
|
|
856
|
+
const format = formatValue ?? ((input) => defaultFormat.format(input));
|
|
857
|
+
const definition = useMemo(() => {
|
|
858
|
+
const fill = (row) => typeof color === "function" ? color(row.datum, row.rank) : color ?? hextechSeriesColor(0);
|
|
859
|
+
const domain = rows.map((row) => row.label);
|
|
860
|
+
const marks = [barX$1(rows, {
|
|
861
|
+
id: "value",
|
|
862
|
+
x: (row) => row.value,
|
|
863
|
+
y: (row) => row.label,
|
|
864
|
+
fill,
|
|
865
|
+
inset: 1,
|
|
866
|
+
maxThickness: 24
|
|
867
|
+
})];
|
|
868
|
+
if (showValues) marks.push(text$1(rows, {
|
|
869
|
+
id: "value-label",
|
|
870
|
+
x: (row) => row.value,
|
|
871
|
+
y: (row) => row.label,
|
|
872
|
+
text: (row) => format(row.value),
|
|
873
|
+
fill: "var(--lol-chart-foreground)",
|
|
874
|
+
anchor: "start",
|
|
875
|
+
dx: 8,
|
|
876
|
+
fontSize: 12
|
|
877
|
+
}));
|
|
878
|
+
return {
|
|
879
|
+
marks,
|
|
880
|
+
x: {
|
|
881
|
+
scale: scaleLinear$1,
|
|
882
|
+
nice: true,
|
|
883
|
+
grid: axis,
|
|
884
|
+
axis: axis ? {
|
|
885
|
+
label: valueLabel,
|
|
886
|
+
ticks: { format }
|
|
887
|
+
} : false
|
|
888
|
+
},
|
|
889
|
+
y: {
|
|
890
|
+
scale: () => scaleBand$1().domain(domain).padding(.28),
|
|
891
|
+
axis: {
|
|
892
|
+
line: false,
|
|
893
|
+
ticks: {
|
|
894
|
+
size: 0,
|
|
895
|
+
padding: 8
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
},
|
|
899
|
+
...showValues ? { margin: { right: 56 } } : {},
|
|
900
|
+
clip: false,
|
|
901
|
+
focus: "nearest",
|
|
902
|
+
tooltip: {
|
|
903
|
+
use: tooltip$1,
|
|
904
|
+
items: [{
|
|
905
|
+
channel: "y",
|
|
906
|
+
label: "Name",
|
|
907
|
+
text: (point) => point.datum.label
|
|
908
|
+
}, {
|
|
909
|
+
channel: "x",
|
|
910
|
+
label: valueLabel,
|
|
911
|
+
text: (point) => format(point.datum.value)
|
|
912
|
+
}]
|
|
913
|
+
}
|
|
914
|
+
};
|
|
915
|
+
}, [
|
|
916
|
+
axis,
|
|
917
|
+
color,
|
|
918
|
+
format,
|
|
919
|
+
rows,
|
|
920
|
+
showValues,
|
|
921
|
+
valueLabel
|
|
922
|
+
]);
|
|
923
|
+
return /* @__PURE__ */ jsx(ChartFrame, {
|
|
924
|
+
title,
|
|
925
|
+
subtitle,
|
|
926
|
+
actions,
|
|
927
|
+
preset: frame ? "framed" : "bare",
|
|
928
|
+
className,
|
|
929
|
+
...frameProps,
|
|
930
|
+
children: /* @__PURE__ */ jsx(HextechChart, {
|
|
931
|
+
definition,
|
|
932
|
+
height: height ?? Math.max(120, rows.length * 34 + 24),
|
|
933
|
+
glow,
|
|
934
|
+
ariaLabel: ariaLabel ?? (typeof title === "string" ? title : "Ranking"),
|
|
935
|
+
ariaDescription
|
|
936
|
+
})
|
|
937
|
+
});
|
|
938
|
+
}
|
|
939
|
+
//#endregion
|
|
940
|
+
export { AreaChart, BarChart, ChartFrame, ChartLegend, HextechChart, LineChart, RankingChart, areaY, barX, barY, crosshair, d3Curve, defineChart, dot, group, hextechChartTheme, hextechPalette, hextechPaletteSize, hextechScatterPaletteSize, hextechSeriesColor, hextechStatusColors, lineX, lineY, linearCurve, rect, ruleX, ruleY, scaleBand, scaleLinear, scaleOrdinal, scalePoint, smoothCurve, stack, stepCurve, text, tickX, tickY, tooltip, withHextechTheme };
|
|
941
|
+
|
|
942
|
+
//# sourceMappingURL=charts.mjs.map
|