@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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lolmath/ui",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.6.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "lolmath.net UI",
|
|
6
6
|
"type": "module",
|
|
@@ -31,11 +31,14 @@
|
|
|
31
31
|
"url": "https://github.com/lolmath/lolmath/issues"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
+
"@tanstack/charts": "^0.14.0",
|
|
34
35
|
"@tsdown/css": "^0.22.14",
|
|
36
|
+
"@types/d3-shape": "^3.1.8",
|
|
35
37
|
"@types/node": "^26.1.1",
|
|
36
38
|
"@types/postcss-url": "^10.0.4",
|
|
37
39
|
"@types/react": "^19.2.17",
|
|
38
40
|
"@types/react-dom": "^19.2.3",
|
|
41
|
+
"d3-shape": "^3.2.0",
|
|
39
42
|
"lightningcss": "^1.33.0",
|
|
40
43
|
"postcss-url": "^10.1.4",
|
|
41
44
|
"publint": "^0.3.22",
|
|
@@ -49,11 +52,15 @@
|
|
|
49
52
|
"peerDependencies": {
|
|
50
53
|
"react": ">=19",
|
|
51
54
|
"react-dom": ">=19",
|
|
52
|
-
"tailwindcss": ">=3"
|
|
55
|
+
"tailwindcss": ">=3",
|
|
56
|
+
"@tanstack/charts": ">=0.14.0"
|
|
53
57
|
},
|
|
54
58
|
"peerDependenciesMeta": {
|
|
55
59
|
"tailwindcss": {
|
|
56
60
|
"optional": true
|
|
61
|
+
},
|
|
62
|
+
"@tanstack/charts": {
|
|
63
|
+
"optional": true
|
|
57
64
|
}
|
|
58
65
|
},
|
|
59
66
|
"exports": {
|
|
@@ -63,6 +70,12 @@
|
|
|
63
70
|
"default": "./dist/index.mjs"
|
|
64
71
|
}
|
|
65
72
|
},
|
|
73
|
+
"./charts": {
|
|
74
|
+
"import": {
|
|
75
|
+
"types": "./dist/charts.d.mts",
|
|
76
|
+
"default": "./dist/charts.mjs"
|
|
77
|
+
}
|
|
78
|
+
},
|
|
66
79
|
"./css": {
|
|
67
80
|
"types": "./dist/css.d.ts",
|
|
68
81
|
"default": "./dist/index.css"
|
|
@@ -86,6 +99,7 @@
|
|
|
86
99
|
"dev": "tsdown --watch",
|
|
87
100
|
"publint": "publint",
|
|
88
101
|
"typecheck": "tsc --noEmit",
|
|
89
|
-
"docs": "node ./docs.ts"
|
|
102
|
+
"docs": "node ./docs.ts",
|
|
103
|
+
"test": "vitest run"
|
|
90
104
|
}
|
|
91
105
|
}
|
package/readme.md
CHANGED
|
@@ -70,6 +70,162 @@ fonts.
|
|
|
70
70
|
@import "@lolmath/ui/tailwind";
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
+
## Charts
|
|
74
|
+
|
|
75
|
+
`@lolmath/ui/charts` draws [TanStack Charts](https://tanstack.com/charts) in the
|
|
76
|
+
same visual language as the rest of the library.
|
|
77
|
+
|
|
78
|
+
It is a separate entrypoint because `@tanstack/charts` is an **optional peer
|
|
79
|
+
dependency**: install it only if you import from `/charts`, and nothing changes
|
|
80
|
+
for anyone who does not.
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npm install @tanstack/charts
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
import { LineChart } from "@lolmath/ui/charts";
|
|
88
|
+
|
|
89
|
+
<LineChart
|
|
90
|
+
title="Team gold"
|
|
91
|
+
subtitle="Ranked solo queue · patch 14.7"
|
|
92
|
+
data={timeline}
|
|
93
|
+
x={(row) => row.minute}
|
|
94
|
+
series={[
|
|
95
|
+
{ key: "blue", label: "Blue side", value: (row) => row.blueGold },
|
|
96
|
+
{ key: "red", label: "Red side", value: (row) => row.redGold },
|
|
97
|
+
]}
|
|
98
|
+
xLabel="Minute"
|
|
99
|
+
yLabel="Gold"
|
|
100
|
+
formatY={(gold) => `${Math.round(gold / 1000)}k`}
|
|
101
|
+
/>;
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The chart styles ship inside `@lolmath/ui/css`, so there is no second
|
|
105
|
+
stylesheet to import. The fonts matter for more than looks here: the chart
|
|
106
|
+
engine measures text against the computed font of its own container, so axis
|
|
107
|
+
layout is only right once Beaufort and Spiegel have loaded.
|
|
108
|
+
|
|
109
|
+
| Component | For |
|
|
110
|
+
| --- | --- |
|
|
111
|
+
| `LineChart` | A measure read left to right. `curve`, `points`, `area`. |
|
|
112
|
+
| `AreaChart` | A composition over time. `stacked`, `normalize`. |
|
|
113
|
+
| `BarChart` | Columns over categories. `layout="grouped" \| "stacked"`. |
|
|
114
|
+
| `RankingChart` | The leaderboard shape: ranked horizontal bars, values at the tip. |
|
|
115
|
+
| `HextechChart` | Your own `defineChart` definition, themed. |
|
|
116
|
+
| `ChartFrame` | The panel: gold hairline, diamond corners, Beaufort title. |
|
|
117
|
+
| `ChartLegend` | Diamond swatches and text in ink. |
|
|
118
|
+
|
|
119
|
+
Every chart takes its data wide — one row per x position — plus a `series`
|
|
120
|
+
array that reads each measure out of a row, so nothing has to be reshaped
|
|
121
|
+
before it is plotted.
|
|
122
|
+
|
|
123
|
+
### What they do without being asked
|
|
124
|
+
|
|
125
|
+
- **A legend for two or more series, never for one.** Colour is never the only
|
|
126
|
+
way to tell two series apart; a lone swatch would only restate the title.
|
|
127
|
+
- **A tooltip, and a crosshair on line and area charts.** An HTML chart is
|
|
128
|
+
interactive, so the hover layer is not opt-in.
|
|
129
|
+
- **Formatters reach everywhere.** `formatY` lands on the axis, the crosshair
|
|
130
|
+
label and the tooltip from one place.
|
|
131
|
+
- **Gaps, not outlines.** Bars are separated by a two-pixel channel of surface
|
|
132
|
+
and dots carry a two-pixel surface ring — a stroke around a mark is ink that
|
|
133
|
+
carries no data.
|
|
134
|
+
|
|
135
|
+
### Writing your own
|
|
136
|
+
|
|
137
|
+
`defineChart`, the marks, the scales and the tooltip extension are re-exported
|
|
138
|
+
from `@lolmath/ui/charts`, so a chart shape the library does not ship still
|
|
139
|
+
needs only one import path. Wrap the result in `HextechChart` for the theme and
|
|
140
|
+
`ChartFrame` for the panel.
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
import {
|
|
144
|
+
barY,
|
|
145
|
+
ChartFrame,
|
|
146
|
+
defineChart,
|
|
147
|
+
HextechChart,
|
|
148
|
+
ruleY,
|
|
149
|
+
scaleBand,
|
|
150
|
+
scaleLinear,
|
|
151
|
+
tooltip,
|
|
152
|
+
} from "@lolmath/ui/charts";
|
|
153
|
+
|
|
154
|
+
const chart = defineChart({
|
|
155
|
+
marks: [
|
|
156
|
+
barY(rows, {
|
|
157
|
+
x: (row) => row.minute,
|
|
158
|
+
y: (row) => row.lead,
|
|
159
|
+
fill: (row) =>
|
|
160
|
+
row.lead >= 0
|
|
161
|
+
? "var(--lol-chart-positive)"
|
|
162
|
+
: "var(--lol-chart-negative)",
|
|
163
|
+
}),
|
|
164
|
+
ruleY([0]),
|
|
165
|
+
],
|
|
166
|
+
x: { scale: () => scaleBand<number>().domain(minutes) },
|
|
167
|
+
y: { scale: scaleLinear, nice: true, grid: true },
|
|
168
|
+
tooltip,
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
<ChartFrame title="Gold lead">
|
|
172
|
+
<HextechChart definition={chart} height={260} ariaLabel="Gold lead by minute" />
|
|
173
|
+
</ChartFrame>;
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
`withHextechTheme` does the same for a definition you render yourself.
|
|
177
|
+
|
|
178
|
+
### The Hextech mapping
|
|
179
|
+
|
|
180
|
+
The look follows the rules Riot set out in
|
|
181
|
+
[The Visual Language of Hextech](https://nexus.leagueoflegends.com/en-us/2016/12/the-visual-language-of-hextech/):
|
|
182
|
+
metal linework *frames* information and hextech magic *is* the information. So
|
|
183
|
+
gold carries the frame, the axes and the grid at low opacity, and the marks are
|
|
184
|
+
the only saturated thing on the panel. The square, the diamond and the circle
|
|
185
|
+
keep their stated jobs — square bar ends and a rectangular frame, diamonds at
|
|
186
|
+
the corners and in the legend, a circle for the focused reading. The storybook's
|
|
187
|
+
**Charts → The Hextech language** page walks through it in full.
|
|
188
|
+
|
|
189
|
+
### The palette
|
|
190
|
+
|
|
191
|
+
Six categorical slots, assigned in order and never cycled:
|
|
192
|
+
|
|
193
|
+
| Slot | Name | Value |
|
|
194
|
+
| --- | --- | --- |
|
|
195
|
+
| 1 | Hextech teal | `#0aa89b` |
|
|
196
|
+
| 2 | Piltover gold | `#ba8c2e` |
|
|
197
|
+
| 3 | Arcane violet | `#8e6be8` |
|
|
198
|
+
| 4 | Ruin red | `#e8574f` |
|
|
199
|
+
| 5 | Rift azure | `#1e8fd5` |
|
|
200
|
+
| 6 | Chemtech green | `#4fa83a` |
|
|
201
|
+
|
|
202
|
+
Slots 1 and 2 are the Hextech signature; the rest reach further into Runeterra,
|
|
203
|
+
because a palette that stayed inside gold and teal could not be told apart.
|
|
204
|
+
|
|
205
|
+
The set is checked against the hextech-black surface for the OKLCH lightness
|
|
206
|
+
band, the chroma floor, protanopia and deuteranopia separation between
|
|
207
|
+
neighbouring slots, and 3:1 contrast. It clears all four for bars, lines and
|
|
208
|
+
areas. Scatter and bubble forms are held to the harder all-pairs test and clear
|
|
209
|
+
it for the **first three slots only** — past three series there, facet rather
|
|
210
|
+
than reach for a fourth colour. Re-run those checks before changing a value.
|
|
211
|
+
|
|
212
|
+
`--lol-chart-positive` and `--lol-chart-negative` sit outside the categorical
|
|
213
|
+
set and stay reserved for series that *mean* good or bad.
|
|
214
|
+
|
|
215
|
+
Everything is a `--lol-chart-*` custom property alongside the rest of the
|
|
216
|
+
design tokens, and TanStack's own `--ts-chart-*` variables are bridged to them,
|
|
217
|
+
so a hand-written definition that never sets a theme still picks up the palette
|
|
218
|
+
and the tooltip styling.
|
|
219
|
+
|
|
220
|
+
### Limits worth knowing
|
|
221
|
+
|
|
222
|
+
- **No time scale.** TanStack Charts ships band, point, linear and ordinal
|
|
223
|
+
scales. Map a date to a number or to a pre-formatted label before it reaches
|
|
224
|
+
a chart; `ChartXValue` is `string | number` for that reason.
|
|
225
|
+
- **Never a dual axis.** Two measures of different scale are two charts, small
|
|
226
|
+
multiples, or one series indexed to a common base.
|
|
227
|
+
- **Overlaid areas stop being honest past three series.** Stack them, or facet.
|
|
228
|
+
|
|
73
229
|
## Client-side Routing
|
|
74
230
|
|
|
75
231
|
See [react-aria-components](https://react-spectrum.adobe.com/react-aria/routing.html#app-router)
|