Chart: an optional y axis title
The unit stays on the ticks; `yLabel` names the axis. It is part of the chart's rebuild identity, so editing the title takes effect at once. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HTsT1isxUjw5gtkJk8WhuA
This commit is contained in:
@@ -76,6 +76,7 @@ export function UplotChart({
|
|||||||
empty = "Nothing has come through yet.",
|
empty = "Nothing has come through yet.",
|
||||||
unit,
|
unit,
|
||||||
yRange,
|
yRange,
|
||||||
|
yLabel,
|
||||||
onCursor,
|
onCursor,
|
||||||
onSelect,
|
onSelect,
|
||||||
}: {
|
}: {
|
||||||
@@ -88,6 +89,8 @@ export function UplotChart({
|
|||||||
unit?: string
|
unit?: string
|
||||||
/** A y axis fixed to these bounds; unset lets it follow the data. */
|
/** A y axis fixed to these bounds; unset lets it follow the data. */
|
||||||
yRange?: [number, number]
|
yRange?: [number, number]
|
||||||
|
/** A named y axis; the unit stays on the ticks. */
|
||||||
|
yLabel?: string
|
||||||
/** The x value under the pointer, and null once it leaves the plot. */
|
/** The x value under the pointer, and null once it leaves the plot. */
|
||||||
onCursor?: (ts: number | null) => void
|
onCursor?: (ts: number | null) => void
|
||||||
/** The x value clicked, or null for a click that landed on no point. */
|
/** The x value clicked, or null for a click that landed on no point. */
|
||||||
@@ -107,9 +110,9 @@ export function UplotChart({
|
|||||||
|
|
||||||
const points = plots.reduce((total, plot) => total + plot.length, 0)
|
const points = plots.reduce((total, plot) => total + plot.length, 0)
|
||||||
// The identity of the series set: the chart is rebuilt when it changes,
|
// The identity of the series set: the chart is rebuilt when it changes,
|
||||||
// while a new reading only sets its data. The unit and the fixed range are
|
// while a new reading only sets its data. The unit, the fixed range and the
|
||||||
// part of it — both are baked into the axes when the chart is built.
|
// axis title are part of it — all are baked into the axes at build time.
|
||||||
const key = `${labels.join(" ")}|${unit ?? ""}|${yRange?.join(",") ?? ""}`
|
const key = `${labels.join(" ")}|${unit ?? ""}|${yRange?.join(",") ?? ""}|${yLabel ?? ""}`
|
||||||
// uPlot leaves its axes half-initialised while the scales have no range, and
|
// uPlot leaves its axes half-initialised while the scales have no range, and
|
||||||
// a resize in that window (a card still settling, say) draws them anyway and
|
// a resize in that window (a card still settling, say) draws them anyway and
|
||||||
// throws. Waiting for the first reading avoids the state altogether.
|
// throws. Waiting for the first reading avoids the state altogether.
|
||||||
@@ -170,6 +173,10 @@ export function UplotChart({
|
|||||||
{ ...axis, size: 28 },
|
{ ...axis, size: 28 },
|
||||||
{
|
{
|
||||||
...axis,
|
...axis,
|
||||||
|
label: yLabel,
|
||||||
|
// uPlot's default label font is a hardcoded bold sans-serif, which
|
||||||
|
// would ignore the app's face.
|
||||||
|
labelFont: axis.font,
|
||||||
// The unit is written after every tick, so the gutter widens to
|
// The unit is written after every tick, so the gutter widens to
|
||||||
// hold it rather than clipping the number in front of it.
|
// hold it rather than clipping the number in front of it.
|
||||||
size: unit ? 62 : 46,
|
size: unit ? 62 : 46,
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ function presentation(cfg: Record<string, unknown>) {
|
|||||||
const high = Number(cfg.y_max)
|
const high = Number(cfg.y_max)
|
||||||
return {
|
return {
|
||||||
unit: cfg.unit ? String(cfg.unit) : undefined,
|
unit: cfg.unit ? String(cfg.unit) : undefined,
|
||||||
|
yLabel: cfg.y_label ? String(cfg.y_label) : undefined,
|
||||||
yRange:
|
yRange:
|
||||||
Number.isFinite(low) && Number.isFinite(high) && low < high
|
Number.isFinite(low) && Number.isFinite(high) && low < high
|
||||||
? ([low, high] as [number, number])
|
? ([low, high] as [number, number])
|
||||||
|
|||||||
Reference in New Issue
Block a user