@umriss-ui/charts 0.16.0 → 0.35.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/docs/llms-full.md CHANGED
@@ -1,4 +1,4 @@
1
- # @umriss-ui/charts 0.16.0
1
+ # @umriss-ui/charts 0.35.0
2
2
 
3
3
  > React canvas chart library for data-dense dashboards - line, area, bar, box plot, scatter, control and Pareto charts. Few chart kinds, drawn well, fast.
4
4
 
@@ -1057,7 +1057,7 @@ npm install @umriss-ui/charts
1057
1057
 
1058
1058
  Demo page: https://romanhaendler.github.io/umriss-ui/charts/installation/
1059
1059
 
1060
- The command installs the package alone: React 18 or 19 is its only peer and stays the application's own, and the package depends on nothing else. The stylesheet comes with the JavaScript, so there is nothing to import - `@umriss-ui/charts/styles.css` is there for setups that link stylesheets by hand. Its colours, type and sizes are `--uc-` tokens that fall back onto core's; [core's Theming page](https://romanhaendler.github.io/umriss-ui/core/theming/#charts-tokens) lists them all.
1060
+ The command installs the package alone: React 19 or newer is its only peer and stays the application's own, and the package depends on nothing else. The stylesheet comes with the JavaScript, so there is nothing to import - `@umriss-ui/charts/styles.css` is there for setups that link stylesheets by hand. Its colours, type and sizes are `--uc-` tokens that fall back onto core's; [core's Theming page](https://romanhaendler.github.io/umriss-ui/core/theming/#charts-tokens) lists them all.
1061
1061
 
1062
1062
  A chart takes its container's width and follows it; give it a `height` (300 px without one). `useChart(rows)` hands out `Chart`, its axes and its series, typed at the row; each reads its value from a row through `value`, a field name or a function - a value that is `null`, `undefined` or not finite is a gap, never a zero.
1063
1063
 
@@ -1407,11 +1407,10 @@ export default function Empty() {
1407
1407
 
1408
1408
  ##### Read it by keyboard and screen reader
1409
1409
 
1410
- A chart with a `Tooltip` is one tab stop: the keys walk its values, and a screen reader hears them; `wording` gives the German words.
1410
+ A chart with a `Tooltip` is one tab stop: the keys walk its values, and a screen reader hears them; `wording` gives the German words, numbers and times.
1411
1411
 
1412
1412
  ```tsx
1413
- import { useState } from "react";
1414
- import { Tooltip, useChart, type ChartView } from "@umriss-ui/charts";
1413
+ import { Tooltip, useChart, type ChartParts } from "@umriss-ui/charts";
1415
1414
  import { GERMAN_CHARTS_WORDING } from "@umriss-ui/charts/wording/de";
1416
1415
 
1417
1416
  /* Data from the operations world, written out here so the example runs on its own. */
@@ -1513,10 +1512,9 @@ function week(serviceId: string, step: number): MetricPoint[] {
1513
1512
  const SEARCH_WEEK = week("search", 5 * 60_000);
1514
1513
 
1515
1514
  export default function KeyboardAndScreenReader() {
1516
- // The two charts zoom together: each hands the other what it reports.
1517
- const [view, setView] = useState<ChartView>({});
1518
- const english = useChart(SEARCH_WEEK, { initialView: view, onViewChange: setView });
1519
- const german = useChart(SEARCH_WEEK, { initialView: view, onViewChange: setView });
1515
+ // The two charts zoom together: each sends the other what the reader did to it.
1516
+ const english: ChartParts<MetricPoint> = useChart(SEARCH_WEEK, { onViewChange: (v) => german.setView(v) });
1517
+ const german: ChartParts<MetricPoint> = useChart(SEARCH_WEEK, { onViewChange: (v) => english.setView(v) });
1520
1518
  const { Chart, XAxis, YAxis, Line } = english;
1521
1519
  const { Chart: Diagramm } = german;
1522
1520
  return (
@@ -2184,9 +2182,9 @@ Under forced colours the chart draws in the system colours and tells its series
2184
2182
  | `padding` | `number \| Partial<`[`Padding`](#type-Padding)`>` | — | Outer spacing of the plot area in CSS pixels.<br>Shown in: [Fix the domain and name the ticks (Axis)](#/axis/configuration) |
2185
2183
  | `empty` | `ReactNode` | the wording's `empty` | Shown in the middle of the plot area when no visible series has a point to show - no data, only gaps, or every series hidden. Axes and frame stay. Not while `loading`.<br>Shown in: [Say there is nothing to show](#/chart/empty) |
2186
2184
  | `loading` | `boolean` | `false` | The rows are on their way, as the table's `loading` says ([ADR-0042](https://github.com/romanhaendler/umriss-ui/blob/main/docs/adr/0042-a-rows-height-never-follows-what-it-shows.md)). A course already drawn stays: it dims after a moment and takes no pointer until the answer is in. Where there is nothing to show, the empty message waits. The plot is `aria-busy` meanwhile.<br>Shown in: [Show that rows are on their way](#/chart/loading) |
2187
- | `wording` | `Partial<`[`ChartsWording`](#type-ChartsWording)`>` | `DEFAULT_CHARTS_WORDING` | The chart's words ([ADR-0031](https://github.com/romanhaendler/umriss-ui/blob/main/docs/adr/0031-the-charts-carry-their-own-wording.md)); entries left out fall back to English. German: `GERMAN_CHARTS_WORDING` from `@umriss-ui/charts/wording/de`.<br>Shown in: [Read it by keyboard and screen reader](#/chart/keyboard-and-screen-reader) |
2185
+ | `wording` | `Partial<`[`ChartsWording`](#type-ChartsWording)`>` | `DEFAULT_CHARTS_WORDING` | The chart's words ([ADR-0031](https://github.com/romanhaendler/umriss-ui/blob/main/docs/adr/0031-the-charts-carry-their-own-wording.md)); entries left out fall back to English. Its `locale` also formats every number and every date or time label the chart makes itself (`en-GB`, `de-DE`; the browser's language is not read) - a `tickFormat` or `format` of your own stays in charge of its axis or series. German: `GERMAN_CHARTS_WORDING` from `@umriss-ui/charts/wording/de`.<br>Shown in: [Read it by keyboard and screen reader](#/chart/keyboard-and-screen-reader) |
2188
2186
  | `encoding` | `"color" \| "marks"` | `"color"` | How series are told apart. `"color"`: by their colour. `"marks"`: by a dash and a marker shape as well - a line, an area and a scatter -, and by a hatch - a bar, a state, a matrix cell, a limit band -, chosen by the same palette place as the colour, so that a reader who does not see the colours still tells them apart; the legend's chips show the same. A caller's own `dash` wins over the place's.<br>Shown in: [Tell series apart without colour](#/chart/told-apart-without-colour), [Mark every kind](#/chart/marks-on-every-kind), [Mark bands, limits and cells](#/chart/bands-limits-and-cells) |
2189
- | `syncId` | `string` | — | Charts with the same id share the pointer's x position, in domain units: each draws its crosshair there, the tooltip stays with the chart under the pointer. Zoom is not shared this way: charts zoom together by handing each other their view (`useChart`'s `initialView` and `onViewChange`).<br>Shown in: [Keep charts in step (Zoom and pan)](#/zoom-and-pan/cursor-sync), [Watch latency against its objective (Scenarios)](#/scenarios/watch-latency-against-its-objective), [Hold the tile length in control (Scenarios)](#/scenarios/hold-the-tile-length-in-control) |
2187
+ | `syncId` | `string` | — | Charts with the same id share the pointer's x position, in domain units: each draws its crosshair there, the tooltip stays with the chart under the pointer. Zoom is not shared this way: charts zoom together by sending each other their view (`useChart`'s `onViewChange` and `setView`).<br>Shown in: [Keep charts in step (Zoom and pan)](#/zoom-and-pan/cursor-sync), [Watch latency against its objective (Scenarios)](#/scenarios/watch-latency-against-its-objective), [Hold the tile length in control (Scenarios)](#/scenarios/hold-the-tile-length-in-control) |
2190
2188
  | `children` | `ReactNode` | — | The axes, series and companions of this chart. They draw nothing themselves: each registers its configuration and the scene draws it, and the order in the JSX is the drawing order.<br>Shown in: [Mix series kinds](#/chart/mixed), [Say there is nothing to show](#/chart/empty), [Read it by keyboard and screen reader](#/chart/keyboard-and-screen-reader) and 74 more |
2191
2189
 
2192
2190
  ###### Events
@@ -2227,6 +2225,7 @@ Everything the charts put out as text.
2227
2225
 
2228
2226
  | Prop | Type | Default | Description |
2229
2227
  |---|---|---|---|
2228
+ | `locale` *required* | `string` | — | The BCP 47 tag every number and every date or time label of the chart is formatted in (`en-GB`, `de-DE`). The one input for the locale: the browser's language is not read. The clock stays 24-hour in both. |
2230
2229
  | `roleDescription` *required* | `string` | — | What a screen reader calls the plot area that takes the keys (`aria-roledescription`). |
2231
2230
  | `empty` *required* | `string` | — | Shown in the plot area when no visible series has a point to show. |
2232
2231
  | `seriesList` *required* | `(names: readonly string[]) => string` | — | The summary's visible series, by name. |
@@ -2234,15 +2233,15 @@ Everything the charts put out as text.
2234
2233
  | `seriesExtent` *required* | `(name: string, min: string, max: string) => string` | — | The summary's lowest and highest value of one series in that stretch. |
2235
2234
  | `limitList` *required* | `(limits: readonly { name: string; value: string }[]) => string` | — | The summary's labelled limits, each with its value in its axis' format (a band's two edges as one value). |
2236
2235
  | `readout` *required* | `(x: string, rows: readonly { name: string; value: string; x: string }[]) => string` | — | What is read after a key: the position, then each series with its value (and its own x where it stands on another x axis), the emphasised one first. |
2237
- | `stackTotal` *required* | `string` | — | The last row of a stack in the tooltip and the readout: the sum of its members at the point (charts-stacking K4). |
2238
- | `percent` *required* | `(value: string) => string` | — | A share in a normalised stack, its number already formatted (K5). |
2236
+ | `stackTotal` *required* | `string` | — | The last row of a stack in the tooltip and the readout: the sum of its members at the point. |
2237
+ | `percent` *required* | `(value: string) => string` | — | A share in a normalised stack, its number already formatted. |
2239
2238
  | `walkHelp` *required* | `string` | — | The keys that walk the chart. |
2240
2239
  | `selectHelp` *required* | `string` | — | The key that reports the Active point - only where `onSelect` is given. |
2241
2240
  | `zoomHelp` *required* | `string` | — | The keys that zoom and pan it - only where the chart can be zoomed. |
2242
2241
  | `legendHelp` *required* | `string` | — | The keys of the legend's entries - only where it has one to press. |
2243
2242
  | `allShown` *required* | `string` | — | Read out where hiding would leave nothing to see, and every series is shown instead. |
2244
2243
  | `showAll` *required* | `string` | — | The control over a zoomed plot that brings every zoomed axis back to its own domain (component-view 04). |
2245
- | `showData` *required* | `string` | — | The data table's disclosure key, closed and open (charts-alternatives C1). |
2244
+ | `showData` *required* | `string` | — | The data table's disclosure key, closed and open. |
2246
2245
  | `hideData` *required* | `string` | — | |
2247
2246
  | `positionColumn` *required* | `string` | — | The heading of the table's x column where its axis has no `label`, and of a matrix' row column where its y axis has none. |
2248
2247
  | `rowColumn` *required* | `string` | — | |
@@ -2257,7 +2256,7 @@ Everything the charts put out as text.
2257
2256
  | `notch` *required* | `string` | — | |
2258
2257
  | `count` *required* | `string` | — | |
2259
2258
  | `outlierList` *required* | `(values: readonly string[], more: number) => string` | — | |
2260
- | `downsampled` *required* | `(readings: number) => string` | — | Added to the caption where the table shows the downsampled course (C2): how many readings its rows stand for. |
2259
+ | `downsampled` *required* | `(readings: number) => string` | — | Added to the caption where the table shows the downsampled course: how many readings its rows stand for. |
2261
2260
 
2262
2261
  ###### `ChartPerf`
2263
2262
 
@@ -2949,11 +2948,11 @@ The keys of [Chart](#/chart/keyboard-chart) apply here.
2949
2948
  | Prop | Type | Default | Description |
2950
2949
  |---|---|---|---|
2951
2950
  | `value` *required* | [`AxisField`](#type-AxisField)`<T> \| ((d: T, index: number) => `[`AxisValue`](#type-AxisValue)`)` | — | Where a row lies on this axis: a field of the row, compared by its name, or a function of it, compared by its source text as a series' is (`ValueFunction`) - with the same closure limit. A number is a position, a `Date` an instant, a string a category: every distinct one gets a place of its own, in the order the rows bring them, a tick and its name as the label ([ADR-0052](https://github.com/romanhaendler/umriss-ui/blob/main/docs/adr/0052-a-chart-reads-its-rows-as-they-come.md)). The type decides, never the content - `"2024"` is a category, `2024` a number - and a row without a value has no place. The axis reads the rows of every series bound to it; where those bring their own `data`, name their row: `<XAxis<HourCount> value="hour" />`.<br>Shown in: [Fix the domain and name the ticks](#/axis/configuration), [Add axes for other magnitudes](#/axis/axes), [Leave out the hours nobody works](#/axis/working-time) and 74 more |
2952
- | `domain` | `"nice" \| "data" \| readonly [number, number] \| readonly [Date, Date]` | `"nice"` | `"nice"` widens the data's extent to ticks - to named `ticks` where there are any, on a time axis to whole units of a step of hours or longer -, `"data"` keeps it, a pair is fixed: numbers, on a time axis milliseconds or two `Date`s, on a category axis places. On a `zoomable` axis it is the start: what the axis shows while the chart's view names no span for it.<br>Shown in: [Bind every kind of series to a second axis](#/axis/every-kind-on-a-second-axis), [Read it by keyboard and screen reader (Chart)](#/chart/keyboard-and-screen-reader), [Gestures and keys (Zoom and pan)](#/zoom-and-pan/gestures-and-keys) and 10 more |
2951
+ | `domain` | `"nice" \| "data" \| readonly [number, number] \| readonly [Date, Date]` | `"nice"` | `"nice"` widens the data's extent to ticks - to named `ticks` where there are any, on a time axis to whole units of a step of hours or longer -, `"data"` keeps it, a pair is fixed: numbers, on a time axis milliseconds or two `Date`s, on a category axis places. On a `zoomable` axis it is the start: what the axis shows while the chart's view names no span for it.<br>Shown in: [Bind every kind of series to a second axis](#/axis/every-kind-on-a-second-axis), [Read it by keyboard and screen reader (Chart)](#/chart/keyboard-and-screen-reader), [Gestures and keys (Zoom and pan)](#/zoom-and-pan/gestures-and-keys) and 11 more |
2953
2952
  | `position` | `"bottom" \| "top"` | `"bottom"` | Which edge the axis stands at. A second x axis on the opposite edge is how a series counts in a unit of its own.<br>Shown in: [Add axes for other magnitudes](#/axis/axes), [Bind every kind of series to a second axis](#/axis/every-kind-on-a-second-axis) |
2954
2953
  | `time` | `boolean` | — | The values are instants: milliseconds since the epoch, or with `time` said ISO 8601 strings as an API sends them, read by the platform's rule - a date with a time and no offset is local time, a date alone is UTC; a string that is none is not drawn. Rows that hold a `Date` put the axis in time without `time`. Ticks on local boundaries from the minute to the month, labels by level in en-GB with a 24-hour clock - `15:00`, `17 Mar`, `Mar 2026` - and the date on the first tick and on the first of a new day (`17 Mar 00:00`); a day tick there carries the year. The tooltip's x value carries the seconds where the readings lie less than a minute apart. Another language is a `tickFormat`, which is handed the instant in milliseconds. `calendar` implies it.<br>Shown in: [Align a second axis to the grid](#/axis/aligned-ticks), [Draw a first chart (Installation)](#/installation/first-chart), [Size a chart by its container (Installation)](#/installation/in-its-container) and 36 more |
2955
2954
  | `calendar` | `readonly `[`WorkingInterval`](#type-WorkingInterval)`[]` | — | Working calendar: the intervals in which time counts. With it the axis stands in working time - nights and weekends are out, and every removed span gets a break mark. The scale stays affine; the mapping happens in materialisation ([ADR-0001](https://github.com/romanhaendler/umriss-ui/blob/main/docs/adr/0001-affine-scale-contract.md)).<br>Shown in: [Leave out the hours nobody works](#/axis/working-time) |
2956
- | `zoomable` | `boolean` | `false` | Zoom and pan: Ctrl or ⌘ with the wheel - and a pinch - zoom around the pointer, a drag, a horizontal wheel or Shift with the wheel pan, a double click goes back to `domain`; with the focus on the chart, + and − zoom, Shift with ← or → pans and 0 goes back. The span shown is part of the chart's view, by this axis' `id` (`useChart`'s `initialView`, `onViewChange`, `setDomain`). The plain wheel always scrolls the page.<br>Shown in: [Read it by keyboard and screen reader (Chart)](#/chart/keyboard-and-screen-reader), [Gestures and keys (Zoom and pan)](#/zoom-and-pan/gestures-and-keys), [Limit the zoom (Zoom and pan)](#/zoom-and-pan/zoom-limits) and 5 more |
2955
+ | `zoomable` | `boolean` | `false` | Zoom and pan: Ctrl or ⌘ with the wheel - and a pinch - zoom around the pointer, a drag, a horizontal wheel or Shift with the wheel pan, a double click goes back to `domain`; with the focus on the chart, + and − zoom, Shift with ← or → pans and 0 goes back. The span shown is part of the chart's view, by this axis' `id` (`useChart`'s `initialView`, `onViewChange`, `setView`, `setDomain`). The plain wheel always scrolls the page.<br>Shown in: [Read it by keyboard and screen reader (Chart)](#/chart/keyboard-and-screen-reader), [Gestures and keys (Zoom and pan)](#/zoom-and-pan/gestures-and-keys), [Limit the zoom (Zoom and pan)](#/zoom-and-pan/zoom-limits) and 6 more |
2957
2956
  | `zoomLimits` | [`ZoomLimits`](#type-ZoomLimits) | at most the data's extent or this axis' own `domain`, whichever is wider, at least three data steps | The narrowest and the widest span zoom may reach, in the axis' units - milliseconds on a time axis.<br>Shown in: [Limit the zoom (Zoom and pan)](#/zoom-and-pan/zoom-limits) |
2958
2957
  | `id` | `string` | `"x"` | Axis id, through which series bind themselves.<br>Shown in: [Add axes for other magnitudes](#/axis/axes), [Align a second axis to the grid](#/axis/aligned-ticks), [Bind every kind of series to a second axis](#/axis/every-kind-on-a-second-axis) and 7 more |
2959
2958
  | `label` | `string` | — | Axis title.<br>Shown in: [Fix the domain and name the ticks](#/axis/configuration), [Add axes for other magnitudes](#/axis/axes), [Leave out the hours nobody works](#/axis/working-time) and 66 more |
@@ -2968,7 +2967,7 @@ The keys of [Chart](#/chart/keyboard-chart) apply here.
2968
2967
 
2969
2968
  | Prop | Type | Default | Description |
2970
2969
  |---|---|---|---|
2971
- | `domain` | `"nice" \| "data" \| "visible" \| readonly [number, number]` | `"nice"` | As on the x axis, and `"visible"`: what the series show inside their x axis' domain - a zoomed hour gets the hour's range, not the week's -, widened to ticks as `"nice"` is. Where the x domain is not fixed that is every point.<br>Shown in: [Fix the domain and name the ticks](#/axis/configuration), [Bind every kind of series to a second axis](#/axis/every-kind-on-a-second-axis), [Mark bands, limits and cells (Chart)](#/chart/bands-limits-and-cells) and 10 more |
2970
+ | `domain` | `"nice" \| "data" \| "visible" \| readonly [number, number]` | `"nice"` | As on the x axis, and `"visible"`: what the series show inside their x axis' domain - a zoomed hour gets the hour's range, not the week's -, widened to ticks as `"nice"` is. Where the x domain is not fixed that is every point.<br>Shown in: [Fix the domain and name the ticks](#/axis/configuration), [Bind every kind of series to a second axis](#/axis/every-kind-on-a-second-axis), [Mark bands, limits and cells (Chart)](#/chart/bands-limits-and-cells) and 11 more |
2972
2971
  | `alignTicks` | `boolean` | — | On a further y axis: take the first y axis' tick count and widen this axis' domain until its ticks fall on that one's grid lines, the steps still 1-2-5 - one grid serves both. `tickCount` then does not apply; on the first y axis it changes nothing.<br>Shown in: [Align a second axis to the grid](#/axis/aligned-ticks) |
2973
2972
  | `position` | `"left" \| "right"` | `"left"` | Which edge the axis stands at. Several y axes per side are stacked outwards, so that extents of clearly different magnitude stay readable.<br>Shown in: [Add axes for other magnitudes](#/axis/axes), [Align a second axis to the grid](#/axis/aligned-ticks), [Bind every kind of series to a second axis](#/axis/every-kind-on-a-second-axis) and 7 more |
2974
2973
  | `id` | `string` | `"y"` | Axis id, through which series bind themselves.<br>Shown in: [Add axes for other magnitudes](#/axis/axes), [Align a second axis to the grid](#/axis/aligned-ticks), [Bind every kind of series to a second axis](#/axis/every-kind-on-a-second-axis) and 7 more |
@@ -3046,11 +3045,11 @@ import { useChart } from "@umriss-ui/charts";
3046
3045
 
3047
3046
  Demo page: https://romanhaendler.github.io/umriss-ui/charts/zoom-and-pan/
3048
3047
 
3049
- `zoomable` on an x axis turns the gestures and keys on; nothing else is needed. The span shown is part of the chart's view ([ADR-0047](https://github.com/romanhaendler/umriss-ui/blob/main/docs/adr/0047-a-component-holds-its-own-view.md)): `useChart(rows, { initialView, onViewChange })` takes a start and reports every change, whole, at most once per frame; `domains` and `setDomain(axisId, span | null)` stand on what the hook returns. A lone x axis is `"x"`.
3048
+ `zoomable` on an x axis turns the gestures and keys on; nothing else is needed. The span shown is part of the chart's view ([ADR-0047](https://github.com/romanhaendler/umriss-ui/blob/main/docs/adr/0047-a-component-holds-its-own-view.md)): `useChart(rows, { initialView, onViewChange })` takes a start and reports what the reader does, whole, at most once per frame; `setView(view)`, `domains` and `setDomain(axisId, span | null)` stand on what the hook returns. A lone x axis is `"x"`.
3050
3049
 
3051
3050
  Once an axis is zoomed, the chart offers 'Show all' over a corner of its plot - a button of its own, a tab stop beside the plot's, that brings every zoomed axis back and goes. Its words are the wording's `showAll`.
3052
3051
 
3053
- Charts stay in step by handing each other what they report: one `useState` for the view, its value as every chart's `initialView` and its setter as every `onViewChange`. A view equal to the one a chart reported itself changes nothing, so a pan does not jump back. `syncId` shares only the pointer.
3052
+ Charts stay in step by sending each other what the reader did: each chart's `onViewChange` calls the other's `setView`. `setView` is not reported, so two charts linked both ways do not answer each other, and a pan does not jump back. `syncId` shares only the pointer.
3054
3053
 
3055
3054
  A zoom stops at `zoomLimits`; without them at three readings and at the data's extent. A y axis with `domain="visible"` follows the stretch shown.
3056
3055
 
@@ -3419,10 +3418,10 @@ export default function VisibleDomain() {
3419
3418
 
3420
3419
  ##### Keep charts in step
3421
3420
 
3422
- Charts with one `syncId` share the pointer; hand them one view through `initialView` and `onViewChange`, and a zoom in any of them zooms all.
3421
+ Charts with one `syncId` share the pointer; send each one's `onViewChange` to the others' `setView`, and a zoom in any of them zooms all.
3423
3422
 
3424
3423
  ```tsx
3425
- import { useState } from "react";
3424
+ import { useEffect, useState } from "react";
3426
3425
  import { Tooltip, useChart, type ChartView } from "@umriss-ui/charts";
3427
3426
 
3428
3427
  /* Data from the operations world, written out here so the example runs on its own. */
@@ -3530,21 +3529,29 @@ const CHANNELS = [
3530
3529
  ] as const;
3531
3530
 
3532
3531
  export default function CursorSync() {
3533
- // The view the three share: each hands it what it reports.
3534
- const [view, setView] = useState<ChartView>({});
3532
+ // The three share a view: each sends the others what the reader did to it.
3533
+ const [peers] = useState(() => new Map<string, (view: ChartView) => void>());
3535
3534
  return (
3536
3535
  <div>
3537
3536
  {/* Each plot begins where its y axis ends: labels of one width - three
3538
3537
  figures here - keep the crosshairs in one column. */}
3539
3538
  {CHANNELS.map((c) => (
3540
- <Channel key={c.name} channel={c} view={view} onViewChange={setView} />
3539
+ <Channel key={c.name} channel={c} peers={peers} />
3541
3540
  ))}
3542
3541
  </div>
3543
3542
  );
3544
3543
  }
3545
3544
 
3546
- function Channel({ channel: c, view, onViewChange }: { channel: (typeof CHANNELS)[number]; view: ChartView; onViewChange: (view: ChartView) => void }) {
3547
- const { Chart, XAxis, YAxis, Line } = useChart(IMAGES_WEEK, { initialView: view, onViewChange });
3545
+ function Channel({ channel: c, peers }: { channel: (typeof CHANNELS)[number]; peers: Map<string, (view: ChartView) => void> }) {
3546
+ const { Chart, XAxis, YAxis, Line, setView } = useChart(IMAGES_WEEK, {
3547
+ onViewChange: (view) => {
3548
+ for (const [name, goTo] of peers) if (name !== c.name) goTo(view);
3549
+ },
3550
+ });
3551
+ useEffect(() => {
3552
+ peers.set(c.name, setView);
3553
+ return () => void peers.delete(c.name);
3554
+ }, [peers, c.name, setView]);
3548
3555
  return (
3549
3556
  <Chart height={140} syncId="images" ariaLabel={`Image service ${c.name} over last week`}>
3550
3557
  <XAxis value="t" time domain="data" zoomable />
@@ -3567,11 +3574,11 @@ The keys of [Chart](#/chart/keyboard-chart) apply here.
3567
3574
  | Prop | Type | Default | Description |
3568
3575
  |---|---|---|---|
3569
3576
  | `value` *required* | [`AxisField`](#type-AxisField)`<T> \| ((d: T, index: number) => `[`AxisValue`](#type-AxisValue)`)` | — | Where a row lies on this axis: a field of the row, compared by its name, or a function of it, compared by its source text as a series' is (`ValueFunction`) - with the same closure limit. A number is a position, a `Date` an instant, a string a category: every distinct one gets a place of its own, in the order the rows bring them, a tick and its name as the label ([ADR-0052](https://github.com/romanhaendler/umriss-ui/blob/main/docs/adr/0052-a-chart-reads-its-rows-as-they-come.md)). The type decides, never the content - `"2024"` is a category, `2024` a number - and a row without a value has no place. The axis reads the rows of every series bound to it; where those bring their own `data`, name their row: `<XAxis<HourCount> value="hour" />`.<br>Shown in: [Gestures and keys](#/zoom-and-pan/gestures-and-keys), [Limit the zoom](#/zoom-and-pan/zoom-limits), [Fit the y axis to what is visible](#/zoom-and-pan/visible-domain) and 74 more |
3570
- | `domain` | `"nice" \| "data" \| readonly [number, number] \| readonly [Date, Date]` | `"nice"` | `"nice"` widens the data's extent to ticks - to named `ticks` where there are any, on a time axis to whole units of a step of hours or longer -, `"data"` keeps it, a pair is fixed: numbers, on a time axis milliseconds or two `Date`s, on a category axis places. On a `zoomable` axis it is the start: what the axis shows while the chart's view names no span for it.<br>Shown in: [Gestures and keys](#/zoom-and-pan/gestures-and-keys), [Limit the zoom](#/zoom-and-pan/zoom-limits), [Fit the y axis to what is visible](#/zoom-and-pan/visible-domain) and 10 more |
3577
+ | `domain` | `"nice" \| "data" \| readonly [number, number] \| readonly [Date, Date]` | `"nice"` | `"nice"` widens the data's extent to ticks - to named `ticks` where there are any, on a time axis to whole units of a step of hours or longer -, `"data"` keeps it, a pair is fixed: numbers, on a time axis milliseconds or two `Date`s, on a category axis places. On a `zoomable` axis it is the start: what the axis shows while the chart's view names no span for it.<br>Shown in: [Gestures and keys](#/zoom-and-pan/gestures-and-keys), [Limit the zoom](#/zoom-and-pan/zoom-limits), [Fit the y axis to what is visible](#/zoom-and-pan/visible-domain) and 11 more |
3571
3578
  | `position` | `"bottom" \| "top"` | `"bottom"` | Which edge the axis stands at. A second x axis on the opposite edge is how a series counts in a unit of its own.<br>Shown in: [Add axes for other magnitudes (Axis)](#/axis/axes), [Bind every kind of series to a second axis (Axis)](#/axis/every-kind-on-a-second-axis) |
3572
3579
  | `time` | `boolean` | — | The values are instants: milliseconds since the epoch, or with `time` said ISO 8601 strings as an API sends them, read by the platform's rule - a date with a time and no offset is local time, a date alone is UTC; a string that is none is not drawn. Rows that hold a `Date` put the axis in time without `time`. Ticks on local boundaries from the minute to the month, labels by level in en-GB with a 24-hour clock - `15:00`, `17 Mar`, `Mar 2026` - and the date on the first tick and on the first of a new day (`17 Mar 00:00`); a day tick there carries the year. The tooltip's x value carries the seconds where the readings lie less than a minute apart. Another language is a `tickFormat`, which is handed the instant in milliseconds. `calendar` implies it.<br>Shown in: [Gestures and keys](#/zoom-and-pan/gestures-and-keys), [Limit the zoom](#/zoom-and-pan/zoom-limits), [Fit the y axis to what is visible](#/zoom-and-pan/visible-domain) and 36 more |
3573
3580
  | `calendar` | `readonly `[`WorkingInterval`](#type-WorkingInterval)`[]` | — | Working calendar: the intervals in which time counts. With it the axis stands in working time - nights and weekends are out, and every removed span gets a break mark. The scale stays affine; the mapping happens in materialisation ([ADR-0001](https://github.com/romanhaendler/umriss-ui/blob/main/docs/adr/0001-affine-scale-contract.md)).<br>Shown in: [Leave out the hours nobody works (Axis)](#/axis/working-time) |
3574
- | `zoomable` | `boolean` | `false` | Zoom and pan: Ctrl or ⌘ with the wheel - and a pinch - zoom around the pointer, a drag, a horizontal wheel or Shift with the wheel pan, a double click goes back to `domain`; with the focus on the chart, + and − zoom, Shift with ← or → pans and 0 goes back. The span shown is part of the chart's view, by this axis' `id` (`useChart`'s `initialView`, `onViewChange`, `setDomain`). The plain wheel always scrolls the page.<br>Shown in: [Gestures and keys](#/zoom-and-pan/gestures-and-keys), [Limit the zoom](#/zoom-and-pan/zoom-limits), [Fit the y axis to what is visible](#/zoom-and-pan/visible-domain) and 5 more |
3581
+ | `zoomable` | `boolean` | `false` | Zoom and pan: Ctrl or ⌘ with the wheel - and a pinch - zoom around the pointer, a drag, a horizontal wheel or Shift with the wheel pan, a double click goes back to `domain`; with the focus on the chart, + and − zoom, Shift with ← or → pans and 0 goes back. The span shown is part of the chart's view, by this axis' `id` (`useChart`'s `initialView`, `onViewChange`, `setView`, `setDomain`). The plain wheel always scrolls the page.<br>Shown in: [Gestures and keys](#/zoom-and-pan/gestures-and-keys), [Limit the zoom](#/zoom-and-pan/zoom-limits), [Fit the y axis to what is visible](#/zoom-and-pan/visible-domain) and 6 more |
3575
3582
  | `zoomLimits` | [`ZoomLimits`](#type-ZoomLimits) | at most the data's extent or this axis' own `domain`, whichever is wider, at least three data steps | The narrowest and the widest span zoom may reach, in the axis' units - milliseconds on a time axis.<br>Shown in: [Limit the zoom](#/zoom-and-pan/zoom-limits) |
3576
3583
  | `id` | `string` | `"x"` | Axis id, through which series bind themselves.<br>Shown in: [Add axes for other magnitudes (Axis)](#/axis/axes), [Align a second axis to the grid (Axis)](#/axis/aligned-ticks), [Bind every kind of series to a second axis (Axis)](#/axis/every-kind-on-a-second-axis) and 7 more |
3577
3584
  | `label` | `string` | — | Axis title.<br>Shown in: [Gestures and keys](#/zoom-and-pan/gestures-and-keys), [Limit the zoom](#/zoom-and-pan/zoom-limits), [Fit the y axis to what is visible](#/zoom-and-pan/visible-domain) and 66 more |
@@ -3586,13 +3593,13 @@ The keys of [Chart](#/chart/keyboard-chart) apply here.
3586
3593
 
3587
3594
  | Prop | Type | Default | Description |
3588
3595
  |---|---|---|---|
3589
- | `initialView` | [`ChartView`](#/view/type-ChartView) | — | The view to start from, and to go to whenever one differing in content from the last is handed in - the same view again changes nothing, and what it leaves out is reset; one the chart reported itself, handed back late, is its own state coming back and not gone to - two charts in step do not jump back mid-pan. The chart remembers none: where a view is kept is the application's decision.<br>Shown in: [Fit the y axis to what is visible](#/zoom-and-pan/visible-domain), [Keep charts in step](#/zoom-and-pan/cursor-sync), [Read it by keyboard and screen reader (Chart)](#/chart/keyboard-and-screen-reader) and 2 more |
3596
+ | `initialView` | [`ChartView`](#/view/type-ChartView) | — | The view to start from, read once when the hook first runs; a different value on a later render is ignored, as React ignores a changed `defaultValue`. To go to a view later, call `setView`. The chart remembers none: where a view is kept is the application's decision.<br>Shown in: [Fit the y axis to what is visible](#/zoom-and-pan/visible-domain), [Hide a series from the legend (Legend)](#/legend/hide-a-series) |
3590
3597
 
3591
3598
  ###### Events
3592
3599
 
3593
3600
  | Prop | Type | Default | Description |
3594
3601
  |---|---|---|---|
3595
- | `onViewChange` | `(view: `[`ChartView`](#/view/type-ChartView)`) => void` | — | Every change of the view, once, always the whole view - the one to keep, or to hand another chart as its `initialView`. A pan or zoom is reported at most once per frame. Not called for the view the chart starts with.<br>Shown in: [Keep charts in step](#/zoom-and-pan/cursor-sync), [Read it by keyboard and screen reader (Chart)](#/chart/keyboard-and-screen-reader), [Keep and restore a view (View)](#/view/keep-and-restore) |
3602
+ | `onViewChange` | `(view: `[`ChartView`](#/view/type-ChartView)`) => void` | — | Every change the reader makes, once, always the whole view - the one to keep, or to hand another chart's `setView`. A pan or zoom is reported at most once per frame. Not called for the view the chart starts with, nor for one `setView` applies.<br>Shown in: [Keep charts in step](#/zoom-and-pan/cursor-sync), [Read it by keyboard and screen reader (Chart)](#/chart/keyboard-and-screen-reader) |
3596
3603
  | `onSelect` | `(hit: `[`TooltipHit`](#type-TooltipHit)`<Z>) => void` | — | The reader chose a point: a click on a hit (a tap too), or Enter on the Active point - the same hit the tooltip's `render` receives. Once per click; the end of a drag does not report, and the second click of a double click does not either. The chart holds no selection and draws none: what is chosen is the application's state. Needs a `<Tooltip>`, which makes the hits; the hit does not travel over `syncId`.<br>Shown in: [Choose a hit (Tooltip)](#/tooltip/choose-a-hit) |
3597
3604
 
3598
3605
  ##### Types on this page
@@ -3685,7 +3692,7 @@ A box's further numbers beside its median, by name.
3685
3692
 
3686
3693
  ###### `BoxExtras<V = number>`
3687
3694
 
3688
- The optional numbers of a box (box-plot 04), by name.
3695
+ The optional numbers of a box by name.
3689
3696
 
3690
3697
  | Prop | Type | Default | Description |
3691
3698
  |---|---|---|---|
@@ -3702,7 +3709,7 @@ What umriss deliberately does not build, and why: [ADR-0032](https://romanhaendl
3702
3709
 
3703
3710
  ### View
3704
3711
 
3705
- How a reader is looking at a chart - the span in view and the hidden series - kept by the chart, reported whole, and handed back to restore it (saved state, a bookmark, a reload).
3712
+ How a reader is looking at a chart - the span in view and the hidden series - kept by the chart, reported whole, and gone back to with `setView` to restore it (saved state, a bookmark, a reload).
3706
3713
 
3707
3714
  ```ts
3708
3715
  import { useChart } from "@umriss-ui/charts";
@@ -3712,13 +3719,13 @@ Demo page: https://romanhaendler.github.io/umriss-ui/charts/view/
3712
3719
 
3713
3720
  A chart holds its own view ([ADR-0047](https://github.com/romanhaendler/umriss-ui/blob/main/docs/adr/0047-a-component-holds-its-own-view.md)): `{ domains, hidden }` - the span each zoomable x axis shows, by axis `id`, and the hidden series, by `name`. Whatever is at its default is absent, so a chart nobody touched reports `{}`.
3714
3721
 
3715
- `useChart(rows, { initialView, onViewChange })`: `onViewChange` hears every change once, always the whole view; `initialView` is the start, and a view handed in later is gone to whenever its content differs from the last one handed in. An axis id or a series name that no longer occurs falls out. Where a view is kept - state, storage, an address - is the application's decision; the chart remembers none.
3722
+ `useChart(rows, { initialView, onViewChange })`: `onViewChange` hears every change the reader makes once, always the whole view; `initialView` is the start, read once - a different value on a later render is ignored; `setView(view)` goes to a whole view later and is not reported. An axis id or a series name that no longer occurs falls out. Where a view is kept - state, storage, an address - is the application's decision; the chart remembers none.
3716
3723
 
3717
3724
  #### Examples
3718
3725
 
3719
3726
  ##### Keep and restore a view
3720
3727
 
3721
- `onViewChange` reports the span in view and the hidden series as one view; keep it - here in the browser's storage, so it outlives a reload - and hand it back through `initialView`. Zoom, hide a series, keep, reload, restore.
3728
+ `onViewChange` reports the span in view and the hidden series as one view; keep it - here in the browser's storage, so it outlives a reload - and go back to it with `setView`. Zoom, hide a series, keep, reload, restore.
3722
3729
 
3723
3730
  ```tsx
3724
3731
  import { useState } from "react";
@@ -3833,11 +3840,10 @@ function keep(view: ChartView): void {
3833
3840
  }
3834
3841
 
3835
3842
  export default function KeepAndRestore() {
3836
- /* The application holds the view the chart reports; handing it another one
3837
- is all it takes to restore. */
3838
- const [view, setView] = useState<ChartView>({});
3843
+ /* The chart holds its view; `view` is what it shows now, and `setView`
3844
+ restores a kept one. */
3839
3845
  const [kept, setKept] = useState<ChartView | null>(readKept);
3840
- const { Chart, XAxis, YAxis, Line } = useChart(SERIES[0]!.data, { initialView: view, onViewChange: setView });
3846
+ const { Chart, XAxis, YAxis, Line, view, setView } = useChart(SERIES[0]!.data);
3841
3847
  return (
3842
3848
  <>
3843
3849
  <Chart height={260} ariaLabel="Latency of three services today">
@@ -3890,13 +3896,13 @@ The keys of [Chart](#/chart/keyboard-chart) apply here.
3890
3896
 
3891
3897
  | Prop | Type | Default | Description |
3892
3898
  |---|---|---|---|
3893
- | `initialView` | [`ChartView`](#type-ChartView) | — | The view to start from, and to go to whenever one differing in content from the last is handed in - the same view again changes nothing, and what it leaves out is reset; one the chart reported itself, handed back late, is its own state coming back and not gone to - two charts in step do not jump back mid-pan. The chart remembers none: where a view is kept is the application's decision.<br>Shown in: [Keep and restore a view](#/view/keep-and-restore), [Fit the y axis to what is visible (Zoom and pan)](#/zoom-and-pan/visible-domain), [Keep charts in step (Zoom and pan)](#/zoom-and-pan/cursor-sync) and 2 more |
3899
+ | `initialView` | [`ChartView`](#type-ChartView) | — | The view to start from, read once when the hook first runs; a different value on a later render is ignored, as React ignores a changed `defaultValue`. To go to a view later, call `setView`. The chart remembers none: where a view is kept is the application's decision.<br>Shown in: [Fit the y axis to what is visible (Zoom and pan)](#/zoom-and-pan/visible-domain), [Hide a series from the legend (Legend)](#/legend/hide-a-series) |
3894
3900
 
3895
3901
  ###### Events
3896
3902
 
3897
3903
  | Prop | Type | Default | Description |
3898
3904
  |---|---|---|---|
3899
- | `onViewChange` | `(view: `[`ChartView`](#type-ChartView)`) => void` | — | Every change of the view, once, always the whole view - the one to keep, or to hand another chart as its `initialView`. A pan or zoom is reported at most once per frame. Not called for the view the chart starts with.<br>Shown in: [Keep and restore a view](#/view/keep-and-restore), [Keep charts in step (Zoom and pan)](#/zoom-and-pan/cursor-sync), [Read it by keyboard and screen reader (Chart)](#/chart/keyboard-and-screen-reader) |
3905
+ | `onViewChange` | `(view: `[`ChartView`](#type-ChartView)`) => void` | — | Every change the reader makes, once, always the whole view - the one to keep, or to hand another chart's `setView`. A pan or zoom is reported at most once per frame. Not called for the view the chart starts with, nor for one `setView` applies.<br>Shown in: [Keep charts in step (Zoom and pan)](#/zoom-and-pan/cursor-sync), [Read it by keyboard and screen reader (Chart)](#/chart/keyboard-and-screen-reader) |
3900
3906
  | `onSelect` | `(hit: `[`TooltipHit`](#type-TooltipHit)`<Z>) => void` | — | The reader chose a point: a click on a hit (a tap too), or Enter on the Active point - the same hit the tooltip's `render` receives. Once per click; the end of a drag does not report, and the second click of a double click does not either. The chart holds no selection and draws none: what is chosen is the application's state. Needs a `<Tooltip>`, which makes the hits; the hit does not travel over `syncId`.<br>Shown in: [Choose a hit (Tooltip)](#/tooltip/choose-a-hit) |
3901
3907
 
3902
3908
  ##### `ChartView`
@@ -3957,7 +3963,7 @@ A box's further numbers beside its median, by name.
3957
3963
 
3958
3964
  ###### `BoxExtras<V = number>`
3959
3965
 
3960
- The optional numbers of a box (box-plot 04), by name.
3966
+ The optional numbers of a box by name.
3961
3967
 
3962
3968
  | Prop | Type | Default | Description |
3963
3969
  |---|---|---|---|
@@ -5501,11 +5507,11 @@ The keys of [Chart](#/chart/keyboard-chart) apply here.
5501
5507
 
5502
5508
  | Prop | Type | Default | Description |
5503
5509
  |---|---|---|---|
5504
- | `value` *required* | [`Value`](#type-Value)`<T>` | — | Y value - a number field of the row or a function of it; null/undefined/NaN/±Infinity means a gap.<br>Shown in: [Plot single measurements](#/scatter/arrivals), [Mark samples that miss a target](#/scatter/against-a-target), [Mix series kinds (Chart)](#/chart/mixed) and 2 more |
5510
+ | `value` *required* | [`Value`](#type-Value)`<T>` | — | Y value - a number field of the row or a function of it; null/undefined/NaN/±Infinity means a gap.<br>Shown in: [Plot single measurements](#/scatter/arrivals), [Mark samples that miss a target](#/scatter/against-a-target), [Mix series kinds (Chart)](#/chart/mixed) and 3 more |
5505
5511
  | `xAxisId` | `string` | `"x"` | Binding to an x axis.<br>Shown in: [Bind every kind of series to a second axis (Axis)](#/axis/every-kind-on-a-second-axis) |
5506
5512
  | `yAxisId` | `string` | `"y"` | Binding to a y axis.<br>Shown in: [Bind every kind of series to a second axis (Axis)](#/axis/every-kind-on-a-second-axis) |
5507
5513
  | `data` | `readonly T[]` | — | Series-own data; overrides the container data.<br>Shown in: [Bind every kind of series to a second axis (Axis)](#/axis/every-kind-on-a-second-axis) |
5508
- | `name` | `string` | "Series n", after its place in the chart | The name in legend and tooltip. Without one a warning stands in DEV - an unnamed series is a colour nobody can look up.<br>Shown in: [Plot single measurements](#/scatter/arrivals), [Mark samples that miss a target](#/scatter/against-a-target), [Mix series kinds (Chart)](#/chart/mixed) and 2 more |
5514
+ | `name` | `string` | "Series n", after its place in the chart | The name in legend and tooltip. Without one a warning stands in DEV - an unnamed series is a colour nobody can look up.<br>Shown in: [Plot single measurements](#/scatter/arrivals), [Mark samples that miss a target](#/scatter/against-a-target), [Mix series kinds (Chart)](#/chart/mixed) and 3 more |
5509
5515
  | `format` | `(value: number) => string` | the y axis' `tickFormat`, else the built-in number format | The value as the tooltip writes it. |
5510
5516
  | `color` | `string` | the palette's `--uc-series-N` | Any CSS colour value. |
5511
5517
  | `tone` | `"ok" \| "warning" \| "alarm"` | — | A role instead of a colour value; the theme resolves it.<br>Shown in: [Mark samples that miss a target](#/scatter/against-a-target) |
@@ -6703,12 +6709,12 @@ The keys of [Chart](#/chart/keyboard-chart) apply here.
6703
6709
 
6704
6710
  | Prop | Type | Default | Description |
6705
6711
  |---|---|---|---|
6706
- | `value` *required* | [`Value`](#type-Value)`<T>` | — | Index of the state in `states` - a number field of the row or a function of it; null/undefined/NaN/±Infinity is a gap - and a gap stays a hole, it gets no colour for "unknown". A colour would be a claim about the interval.<br>Shown in: [One vehicle through the day](#/stateband/one-vehicle), [Lay a state under a course](#/stateband/under-a-course), [Give each one a lane](#/stateband/one-lane-each) and 3 more |
6707
- | `states` *required* | `readonly `[`StateEntry`](#type-StateEntry)`[]` | — | The closed set of states, in the order of their codes.<br>Shown in: [One vehicle through the day](#/stateband/one-vehicle), [Lay a state under a course](#/stateband/under-a-course), [Give each one a lane](#/stateband/one-lane-each) and 3 more |
6712
+ | `value` *required* | [`Value`](#type-Value)`<T>` | — | Index of the state in `states` - a number field of the row or a function of it; null/undefined/NaN/±Infinity is a gap - and a gap stays a hole, it gets no colour for "unknown". A colour would be a claim about the interval.<br>Shown in: [One vehicle through the day](#/stateband/one-vehicle), [Lay a state under a course](#/stateband/under-a-course), [Give each one a lane](#/stateband/one-lane-each) and 4 more |
6713
+ | `states` *required* | `readonly `[`StateEntry`](#type-StateEntry)`[]` | — | The closed set of states, in the order of their codes.<br>Shown in: [One vehicle through the day](#/stateband/one-vehicle), [Lay a state under a course](#/stateband/under-a-course), [Give each one a lane](#/stateband/one-lane-each) and 4 more |
6708
6714
  | `xAxisId` | `string` | — | Binding to an x axis. |
6709
6715
  | `yAxisId` | `string` | — | Binding to a y axis.<br>Shown in: [Lay a state under a course](#/stateband/under-a-course), [Mark bands, limits and cells (Chart)](#/chart/bands-limits-and-cells), [Read limits above the states (LimitLine)](#/limitline/limits-and-state) |
6710
6716
  | `data` | `readonly T[]` | — | Series-own data; overrides the container data.<br>Shown in: [Lay a state under a course](#/stateband/under-a-course), [Give each one a lane](#/stateband/one-lane-each), [Mark bands, limits and cells (Chart)](#/chart/bands-limits-and-cells) and 2 more |
6711
- | `name` | `string` | "Series n", after its place in the chart | The name in legend and tooltip. Without one a warning stands in DEV - an unnamed series is a colour nobody can look up.<br>Shown in: [One vehicle through the day](#/stateband/one-vehicle), [Lay a state under a course](#/stateband/under-a-course), [Give each one a lane](#/stateband/one-lane-each) and 3 more |
6717
+ | `name` | `string` | "Series n", after its place in the chart | The name in legend and tooltip. Without one a warning stands in DEV - an unnamed series is a colour nobody can look up.<br>Shown in: [One vehicle through the day](#/stateband/one-vehicle), [Lay a state under a course](#/stateband/under-a-course), [Give each one a lane](#/stateband/one-lane-each) and 4 more |
6712
6718
  | `lane` | `string` | — | The lane by its name: a category of the y axis, whose place the band takes, as wide as a bar is. The y axis then lists a lane per name, the first at the top, in the bands' order or its own `categories` ([ADR-0052](https://github.com/romanhaendler/umriss-ui/blob/main/docs/adr/0052-a-chart-reads-its-rows-as-they-come.md)). Not together with `laneFrom` or `laneTo`.<br>Shown in: [Give each one a lane](#/stateband/one-lane-each), [Mark bands, limits and cells (Chart)](#/chart/bands-limits-and-cells), [Read limits above the states (LimitLine)](#/limitline/limits-and-state) and 1 more |
6713
6719
  | `laneFrom` | `number` | the beginning of the axis' domain | Lower edge of the lane in domain units of a numeric y axis.<br>Shown in: [Lay a state under a course](#/stateband/under-a-course) |
6714
6720
  | `laneTo` | `number` | the end of the axis' domain | Upper edge of the lane in domain units of a numeric y axis.<br>Shown in: [Lay a state under a course](#/stateband/under-a-course) |
@@ -6953,13 +6959,13 @@ The keys of [Chart](#/chart/keyboard-chart) apply here.
6953
6959
 
6954
6960
  | Prop | Type | Default | Description |
6955
6961
  |---|---|---|---|
6956
- | `value` *required* | [`AxisField`](#type-AxisField)`<T, number \| string \| null \| undefined> \| ((d: T, index: number) => number \| string \| null \| undefined)` | — | The row on the y axis - a field of the data's row or a function of it. A number is a position, as every series' y is; a string is a category: the y axis then has a named row per distinct one, the first at the top, in the order the data bring them or the y axis' `categories` ([ADR-0052](https://github.com/romanhaendler/umriss-ui/blob/main/docs/adr/0052-a-chart-reads-its-rows-as-they-come.md)). Never an instant: a `Date` is refused.<br>Shown in: [Colour cells by their limits](#/matrix/by-limits), [Colour cells along a gradient](#/matrix/gradient), [Mark bands, limits and cells (Chart)](#/chart/bands-limits-and-cells) |
6957
- | `level` *required* | [`Value`](#type-Value)`<T>` | — | The level that decides the colour - a number field of the row or a function of it. A missing level is a hole, not a zero.<br>Shown in: [Colour cells by their limits](#/matrix/by-limits), [Colour cells along a gradient](#/matrix/gradient), [Mark bands, limits and cells (Chart)](#/chart/bands-limits-and-cells) |
6962
+ | `value` *required* | [`AxisField`](#type-AxisField)`<T, number \| string \| null \| undefined> \| ((d: T, index: number) => number \| string \| null \| undefined)` | — | The row on the y axis - a field of the data's row or a function of it. A number is a position, as every series' y is; a string is a category: the y axis then has a named row per distinct one, the first at the top, in the order the data bring them or the y axis' `categories` ([ADR-0052](https://github.com/romanhaendler/umriss-ui/blob/main/docs/adr/0052-a-chart-reads-its-rows-as-they-come.md)). Never an instant: a `Date` is refused.<br>Shown in: [Colour cells by their limits](#/matrix/by-limits), [Colour cells along a gradient](#/matrix/gradient), [Mark bands, limits and cells (Chart)](#/chart/bands-limits-and-cells) and 1 more |
6963
+ | `level` *required* | [`Value`](#type-Value)`<T>` | — | The level that decides the colour - a number field of the row or a function of it. A missing level is a hole, not a zero.<br>Shown in: [Colour cells by their limits](#/matrix/by-limits), [Colour cells along a gradient](#/matrix/gradient), [Mark bands, limits and cells (Chart)](#/chart/bands-limits-and-cells) and 1 more |
6958
6964
  | `coloring` | [`MatrixColoring`](#type-MatrixColoring) | `{ kind: "gradient", stops: DEFAULT_GRADIENT }` | How the level colours a cell: by assessment against limits, or across a gradient.<br>Shown in: [Colour cells by their limits](#/matrix/by-limits), [Mark bands, limits and cells (Chart)](#/chart/bands-limits-and-cells) |
6959
6965
  | `xAxisId` | `string` | `"x"` | Binding to an x axis. |
6960
6966
  | `yAxisId` | `string` | `"y"` | Binding to a y axis. |
6961
6967
  | `data` | `readonly T[]` | — | Series-own data; overrides the container data. |
6962
- | `name` | `string` | "Series n", after its place in the chart | The name in legend and tooltip. Without one a warning stands in DEV - an unnamed series is a colour nobody can look up.<br>Shown in: [Colour cells by their limits](#/matrix/by-limits), [Colour cells along a gradient](#/matrix/gradient), [Mark bands, limits and cells (Chart)](#/chart/bands-limits-and-cells) |
6968
+ | `name` | `string` | "Series n", after its place in the chart | The name in legend and tooltip. Without one a warning stands in DEV - an unnamed series is a colour nobody can look up.<br>Shown in: [Colour cells by their limits](#/matrix/by-limits), [Colour cells along a gradient](#/matrix/gradient), [Mark bands, limits and cells (Chart)](#/chart/bands-limits-and-cells) and 1 more |
6963
6969
  | `format` | `(value: number) => string` | the built-in number format | The level as the tooltip writes it. The y axis' `tickFormat` writes the row, not the level.<br>Shown in: [Colour cells by their limits](#/matrix/by-limits) |
6964
6970
 
6965
6971
  ##### Types on this page
@@ -9578,13 +9584,13 @@ The keys of [Chart](#/chart/keyboard-chart) apply here.
9578
9584
 
9579
9585
  | Prop | Type | Default | Description |
9580
9586
  |---|---|---|---|
9581
- | `initialView` | [`ChartView`](#/view/type-ChartView) | — | The view to start from, and to go to whenever one differing in content from the last is handed in - the same view again changes nothing, and what it leaves out is reset; one the chart reported itself, handed back late, is its own state coming back and not gone to - two charts in step do not jump back mid-pan. The chart remembers none: where a view is kept is the application's decision.<br>Shown in: [Fit the y axis to what is visible (Zoom and pan)](#/zoom-and-pan/visible-domain), [Keep charts in step (Zoom and pan)](#/zoom-and-pan/cursor-sync), [Read it by keyboard and screen reader (Chart)](#/chart/keyboard-and-screen-reader) and 2 more |
9587
+ | `initialView` | [`ChartView`](#/view/type-ChartView) | — | The view to start from, read once when the hook first runs; a different value on a later render is ignored, as React ignores a changed `defaultValue`. To go to a view later, call `setView`. The chart remembers none: where a view is kept is the application's decision.<br>Shown in: [Fit the y axis to what is visible (Zoom and pan)](#/zoom-and-pan/visible-domain), [Hide a series from the legend (Legend)](#/legend/hide-a-series) |
9582
9588
 
9583
9589
  ###### Events
9584
9590
 
9585
9591
  | Prop | Type | Default | Description |
9586
9592
  |---|---|---|---|
9587
- | `onViewChange` | `(view: `[`ChartView`](#/view/type-ChartView)`) => void` | — | Every change of the view, once, always the whole view - the one to keep, or to hand another chart as its `initialView`. A pan or zoom is reported at most once per frame. Not called for the view the chart starts with.<br>Shown in: [Keep charts in step (Zoom and pan)](#/zoom-and-pan/cursor-sync), [Read it by keyboard and screen reader (Chart)](#/chart/keyboard-and-screen-reader), [Keep and restore a view (View)](#/view/keep-and-restore) |
9593
+ | `onViewChange` | `(view: `[`ChartView`](#/view/type-ChartView)`) => void` | — | Every change the reader makes, once, always the whole view - the one to keep, or to hand another chart's `setView`. A pan or zoom is reported at most once per frame. Not called for the view the chart starts with, nor for one `setView` applies.<br>Shown in: [Keep charts in step (Zoom and pan)](#/zoom-and-pan/cursor-sync), [Read it by keyboard and screen reader (Chart)](#/chart/keyboard-and-screen-reader) |
9588
9594
  | `onSelect` | `(hit: `[`TooltipHit`](#type-TooltipHit)`<Z>) => void` | — | The reader chose a point: a click on a hit (a tap too), or Enter on the Active point - the same hit the tooltip's `render` receives. Once per click; the end of a drag does not report, and the second click of a double click does not either. The chart holds no selection and draws none: what is chosen is the application's state. Needs a `<Tooltip>`, which makes the hits; the hit does not travel over `syncId`.<br>Shown in: [Choose a hit](#/tooltip/choose-a-hit) |
9589
9595
 
9590
9596
  ##### Types on this page
@@ -9630,7 +9636,7 @@ A box's further numbers beside its median, by name.
9630
9636
 
9631
9637
  ###### `BoxExtras<V = number>`
9632
9638
 
9633
- The optional numbers of a box (box-plot 04), by name.
9639
+ The optional numbers of a box by name.
9634
9640
 
9635
9641
  | Prop | Type | Default | Description |
9636
9642
  |---|---|---|---|
@@ -9950,20 +9956,39 @@ interface LoadPoint {
9950
9956
  s1: number;
9951
9957
  s2: number;
9952
9958
  s3: number;
9953
- }
9959
+ /** A state code 0..3 that holds for a run of about ten points. */
9960
+ st: number;
9961
+ /** Column, row and level of the same points laid out as a grid 200 rows high. */
9962
+ c: number;
9963
+ r: number;
9964
+ lvl: number;
9965
+ }
9966
+
9967
+ const STATES = [
9968
+ { label: "A", color: "#2f6fb4" },
9969
+ { label: "B", color: "#c08a2e" },
9970
+ { label: "C", color: "#8a8f98" },
9971
+ { label: "D", color: "#6b8e5a" },
9972
+ ] as const;
9973
+ const ROWS = 200;
9954
9974
 
9955
- /** Three random walks of any length. */
9975
+ /** Three random walks of any length, with a state, and a grid laid over them. */
9956
9976
  function load(seed: number, n: number): LoadPoint[] {
9957
9977
  const r = random(seed);
9958
9978
  const points = new Array<LoadPoint>(n);
9959
9979
  let s1 = 100;
9960
9980
  let s2 = 60;
9961
9981
  let s3 = 140;
9982
+ let st = 0;
9983
+ const columns = Math.max(1, Math.ceil(n / ROWS));
9962
9984
  for (let i = 0; i < n; i++) {
9963
9985
  s1 += r() - 0.5;
9964
9986
  s2 += (r() - 0.5) * 0.8;
9965
9987
  s3 += (r() - 0.5) * 1.2;
9966
- points[i] = { t: i, s1, s2, s3 };
9988
+ if (r() < 0.1) st = Math.floor(r() * 4);
9989
+ const c = i % columns;
9990
+ const row = Math.floor(i / columns);
9991
+ points[i] = { t: i, s1, s2, s3, st, c, r: row, lvl: 0.5 + 0.5 * Math.sin(c / 40) * Math.cos(row / 15) + (r() - 0.5) * 0.2 };
9967
9992
  }
9968
9993
  return points;
9969
9994
  }
@@ -9974,11 +9999,15 @@ const WINDOW = 400;
9974
9999
  /** Series kinds of the measuring run. A filled mark and a rectangle per point are
9975
10000
  different work from a stroked path - the measurements in the capability record
9976
10001
  must not hold for lines only. */
9977
- type Mode = "lines" | "mixed";
10002
+ type Mode = "lines" | "mixed" | "bars" | "scatter" | "state" | "matrix";
10003
+ const MODES: readonly Mode[] = ["lines", "mixed", "bars", "scatter", "state", "matrix"];
10004
+
10005
+ /** How many points along x (columns for the matrix) a zoom shows. */
10006
+ const ZOOMED = 400;
9978
10007
 
9979
10008
  export default function Benchmark() {
9980
10009
  const [data, setData] = useState<readonly LoadPoint[]>(() => load(5, 1_000));
9981
- const { Chart, XAxis, YAxis, Line, Bar, Area } = useChart(data);
10010
+ const { Chart, XAxis, YAxis, Line, Bar, Area, Scatter, StateBand, Matrix, setDomain } = useChart(data);
9982
10011
  const [perf, setPerf] = useState<ChartPerf>({
9983
10012
  materializeMs: 0,
9984
10013
  seriesDrawMs: 0,
@@ -9987,6 +10016,14 @@ export default function Benchmark() {
9987
10016
  const [fps, setFps] = useState<number | null>(null);
9988
10017
  const [live, setLive] = useState(false);
9989
10018
  const [mode, setMode] = useState<Mode>("lines");
10019
+ /* The time the chart's handlers take for one pointer move, the mean of the
10020
+ last twenty: the hit test of the matrix is in it. */
10021
+ const [hoverMs, setHoverMs] = useState<number | null>(null);
10022
+ const moves = useRef<number[]>([]);
10023
+ const moveStart = useRef(0);
10024
+ const matrix = mode === "matrix";
10025
+ const columns = matrix ? Math.max(1, Math.ceil(data.length / ROWS)) : data.length;
10026
+ const course = mode === "lines" || mode === "mixed";
9990
10027
 
9991
10028
  const onPerf = useCallback((p: ChartPerf) => setPerf(p), []);
9992
10029
 
@@ -10030,6 +10067,10 @@ export default function Benchmark() {
10030
10067
  s1: last.s1 + (r() - 0.5) * 3,
10031
10068
  s2: last.s2 + (r() - 0.5) * 2.4,
10032
10069
  s3: last.s3 + (r() - 0.5) * 3.6,
10070
+ st: r() < 0.1 ? Math.floor(r() * 4) : last.st,
10071
+ c: last.c + 1,
10072
+ r: last.r,
10073
+ lvl: last.lvl,
10033
10074
  };
10034
10075
  const grown = [...previous, next];
10035
10076
  return grown.length > WINDOW ? grown.slice(grown.length - WINDOW) : grown;
@@ -10041,62 +10082,90 @@ export default function Benchmark() {
10041
10082
  const loadPoints = (n: number) => {
10042
10083
  setLive(false);
10043
10084
  setData(load(5, n));
10085
+ setDomain("x", null);
10086
+ moves.current = [];
10087
+ };
10088
+ const pick = (m: Mode) => {
10089
+ setMode(m);
10090
+ setDomain("x", null);
10091
+ moves.current = [];
10092
+ };
10093
+ /* A span in the middle of the data: a small part of the volume is in view. */
10094
+ const zoom = () => {
10095
+ const from = Math.floor(columns / 2);
10096
+ setDomain("x", [from, from + ZOOMED]);
10044
10097
  };
10045
10098
 
10046
10099
  return (
10047
10100
  <>
10048
10101
  <div className="demo-actions">
10049
10102
  {SIZES.map((n) => (
10050
- <button key={n} className="demo-button" onClick={() => loadPoints(n)}>
10103
+ <button key={n} className="demo-button" data-role={`points-${n}`} onClick={() => loadPoints(n)}>
10051
10104
  {n.toLocaleString("en-US")} points
10052
10105
  </button>
10053
10106
  ))}
10054
10107
  <button className="demo-button" onClick={() => setLive((v) => !v)}>{live ? "Stop live" : "Live"}</button>
10055
- <button
10056
- className="demo-button"
10057
- data-role="mode"
10058
- onClick={() => setMode((m) => (m === "lines" ? "mixed" : "lines"))}
10059
- >
10060
- {mode === "lines" ? "Mixed" : "Lines only"}
10108
+ {MODES.map((m) => (
10109
+ <button key={m} className="demo-button" data-role={`kind-${m}`} aria-pressed={mode === m} onClick={() => pick(m)}>
10110
+ {m}
10111
+ </button>
10112
+ ))}
10113
+ <button className="demo-button" data-role="zoom" onClick={zoom}>
10114
+ Zoom in
10115
+ </button>
10116
+ <button className="demo-button" data-role="unzoom" onClick={() => setDomain("x", null)}>
10117
+ Whole
10061
10118
  </button>
10062
10119
  </div>
10063
10120
  <dl className="metrics">
10064
10121
  <div>
10065
10122
  <dt>Points</dt>
10066
- <dd>{perf.points.toLocaleString("en-US")}</dd>
10123
+ <dd data-role="points">{perf.points.toLocaleString("en-US")}</dd>
10067
10124
  </div>
10068
10125
  <div>
10069
10126
  <dt>Materialisation</dt>
10070
- <dd>{perf.materializeMs.toFixed(1)} ms</dd>
10127
+ <dd data-role="materialize-ms">{perf.materializeMs.toFixed(1)} ms</dd>
10071
10128
  </div>
10072
10129
  <div>
10073
10130
  <dt>Series draw</dt>
10074
- <dd>{perf.seriesDrawMs.toFixed(1)} ms</dd>
10131
+ <dd data-role="series-draw-ms">{perf.seriesDrawMs.toFixed(1)} ms</dd>
10075
10132
  </div>
10076
10133
  <div>
10077
10134
  <dt>FPS (hover)</dt>
10078
10135
  <dd>{fps === null ? "–" : fps}</dd>
10079
10136
  </div>
10137
+ <div>
10138
+ <dt>Pointer move</dt>
10139
+ <dd data-role="hover-ms">{hoverMs === null ? "–" : `${hoverMs.toFixed(2)} ms`}</dd>
10140
+ </div>
10080
10141
  </dl>
10081
- <div onPointerEnter={startMeasuring} onPointerLeave={stopMeasuring}>
10142
+ <div
10143
+ data-role="plot"
10144
+ onPointerEnter={startMeasuring}
10145
+ onPointerLeave={stopMeasuring}
10146
+ onPointerMoveCapture={() => {
10147
+ moveStart.current = performance.now();
10148
+ }}
10149
+ onPointerMove={() => {
10150
+ moves.current.push(performance.now() - moveStart.current);
10151
+ if (moves.current.length > 20) moves.current.shift();
10152
+ setHoverMs(moves.current.reduce((a, b) => a + b, 0) / moves.current.length);
10153
+ }}
10154
+ >
10082
10155
  <Chart
10083
10156
  height={320}
10084
10157
  ariaLabel="Benchmark with three series"
10085
10158
  onPerf={onPerf}
10086
10159
  >
10087
- <XAxis value="t" label="Index" />
10088
- <YAxis />
10089
- {mode === "lines" ? (
10090
- <Line value="s1" name="S1" />
10091
- ) : (
10092
- <Bar value="s1" name="S1" />
10093
- )}
10094
- {mode === "lines" ? (
10095
- <Line value="s2" name="S2" />
10096
- ) : (
10097
- <Area value="s2" name="S2" />
10098
- )}
10099
- <Line value="s3" name="S3" />
10160
+ <XAxis value={matrix ? "c" : "t"} label="Index" domain="data" zoomable />
10161
+ <YAxis domain={mode === "state" ? [0, 1] : undefined} />
10162
+ {mode === "scatter" ? <Scatter value="s1" name="S1" /> : null}
10163
+ {mode === "state" ? <StateBand value="st" states={STATES} name="State" /> : null}
10164
+ {matrix ? <Matrix value="r" level="lvl" name="Level" /> : null}
10165
+ {mode === "bars" ? <Bar value="s1" name="S1" /> : null}
10166
+ {course ? mode === "lines" ? <Line value="s1" name="S1" /> : <Bar value="s1" name="S1" /> : null}
10167
+ {course ? mode === "lines" ? <Line value="s2" name="S2" /> : <Area value="s2" name="S2" /> : null}
10168
+ {course ? <Line value="s3" name="S3" /> : null}
10100
10169
  <Legend placement="top" />
10101
10170
  <Tooltip mode="x" />
10102
10171
  </Chart>
@@ -10278,7 +10347,7 @@ From `XAxisProps` — the full table stands on [Axis](#/axis/type-XAxisProps).
10278
10347
  | [`value`](#/axis/XAxisProps-value) *required* | [`AxisField`](#/axis/type-AxisField)`<T> \| ((d: T, index: number) => `[`AxisValue`](#/axis/type-AxisValue)`)` | — | Where a row lies on this axis: a field of the row, compared by its name, or a function of it, compared by its source text as a series' is (`ValueFunction`) - with the same closure limit. A number is a position, a `Date` an instant, a string a category: every distinct one gets a place of its own, in the order the rows bring them, a tick and its name as the label ([ADR-0052](https://github.com/romanhaendler/umriss-ui/blob/main/docs/adr/0052-a-chart-reads-its-rows-as-they-come.md)). The type decides, never the content - `"2024"` is a category, `2024` a number - and a row without a value has no place. The axis reads the rows of every series bound to it; where those bring their own `data`, name their row: `<XAxis<HourCount> value="hour" />`. |
10279
10348
  | [`domain`](#/axis/XAxisProps-domain) | `"nice" \| "data" \| readonly [number, number] \| readonly [Date, Date]` | `"nice"` | `"nice"` widens the data's extent to ticks - to named `ticks` where there are any, on a time axis to whole units of a step of hours or longer -, `"data"` keeps it, a pair is fixed: numbers, on a time axis milliseconds or two `Date`s, on a category axis places. On a `zoomable` axis it is the start: what the axis shows while the chart's view names no span for it. |
10280
10349
  | [`time`](#/axis/XAxisProps-time) | `boolean` | — | The values are instants: milliseconds since the epoch, or with `time` said ISO 8601 strings as an API sends them, read by the platform's rule - a date with a time and no offset is local time, a date alone is UTC; a string that is none is not drawn. Rows that hold a `Date` put the axis in time without `time`. Ticks on local boundaries from the minute to the month, labels by level in en-GB with a 24-hour clock - `15:00`, `17 Mar`, `Mar 2026` - and the date on the first tick and on the first of a new day (`17 Mar 00:00`); a day tick there carries the year. The tooltip's x value carries the seconds where the readings lie less than a minute apart. Another language is a `tickFormat`, which is handed the instant in milliseconds. `calendar` implies it. |
10281
- | [`zoomable`](#/axis/XAxisProps-zoomable) | `boolean` | `false` | Zoom and pan: Ctrl or ⌘ with the wheel - and a pinch - zoom around the pointer, a drag, a horizontal wheel or Shift with the wheel pan, a double click goes back to `domain`; with the focus on the chart, + and − zoom, Shift with ← or → pans and 0 goes back. The span shown is part of the chart's view, by this axis' `id` (`useChart`'s `initialView`, `onViewChange`, `setDomain`). The plain wheel always scrolls the page. |
10350
+ | [`zoomable`](#/axis/XAxisProps-zoomable) | `boolean` | `false` | Zoom and pan: Ctrl or ⌘ with the wheel - and a pinch - zoom around the pointer, a drag, a horizontal wheel or Shift with the wheel pan, a double click goes back to `domain`; with the focus on the chart, + and − zoom, Shift with ← or → pans and 0 goes back. The span shown is part of the chart's view, by this axis' `id` (`useChart`'s `initialView`, `onViewChange`, `setView`, `setDomain`). The plain wheel always scrolls the page. |
10282
10351
  | [`id`](#/axis/XAxisProps-id) | `string` | `"x"` | Axis id, through which series bind themselves. |
10283
10352
  | [`label`](#/axis/XAxisProps-label) | `string` | — | Axis title. |
10284
10353
 
@@ -10313,6 +10382,29 @@ From `BarProps` — the full table stands on [Bar](#/bar/type-BarProps).
10313
10382
  | [`value`](#/bar/BarProps-value) *required* | [`Value`](#/bar/type-Value)`<T>` | — | Height - a number field of the row or a function of it; null/undefined/NaN/±Infinity means a gap. |
10314
10383
  | [`name`](#/bar/BarProps-name) | `string` | "Series n", after its place in the chart | The name in legend and tooltip. Without one a warning stands in DEV - an unnamed series is a colour nobody can look up. |
10315
10384
 
10385
+ From `ScatterProps` — the full table stands on [Scatter](#/scatter/type-ScatterProps).
10386
+
10387
+ | Prop | Type | Default | Description |
10388
+ |---|---|---|---|
10389
+ | [`value`](#/scatter/ScatterProps-value) *required* | [`Value`](#/scatter/type-Value)`<T>` | — | Y value - a number field of the row or a function of it; null/undefined/NaN/±Infinity means a gap. |
10390
+ | [`name`](#/scatter/ScatterProps-name) | `string` | "Series n", after its place in the chart | The name in legend and tooltip. Without one a warning stands in DEV - an unnamed series is a colour nobody can look up. |
10391
+
10392
+ From `StateBandProps` — the full table stands on [StateBand](#/stateband/type-StateBandProps).
10393
+
10394
+ | Prop | Type | Default | Description |
10395
+ |---|---|---|---|
10396
+ | [`value`](#/stateband/StateBandProps-value) *required* | [`Value`](#/stateband/type-Value)`<T>` | — | Index of the state in `states` - a number field of the row or a function of it; null/undefined/NaN/±Infinity is a gap - and a gap stays a hole, it gets no colour for "unknown". A colour would be a claim about the interval. |
10397
+ | [`states`](#/stateband/StateBandProps-states) *required* | `readonly `[`StateEntry`](#/stateband/type-StateEntry)`[]` | — | The closed set of states, in the order of their codes. |
10398
+ | [`name`](#/stateband/StateBandProps-name) | `string` | "Series n", after its place in the chart | The name in legend and tooltip. Without one a warning stands in DEV - an unnamed series is a colour nobody can look up. |
10399
+
10400
+ From `MatrixProps` — the full table stands on [Matrix](#/matrix/type-MatrixProps).
10401
+
10402
+ | Prop | Type | Default | Description |
10403
+ |---|---|---|---|
10404
+ | [`value`](#/matrix/MatrixProps-value) *required* | [`AxisField`](#/matrix/type-AxisField)`<T, number \| string \| null \| undefined> \| ((d: T, index: number) => number \| string \| null \| undefined)` | — | The row on the y axis - a field of the data's row or a function of it. A number is a position, as every series' y is; a string is a category: the y axis then has a named row per distinct one, the first at the top, in the order the data bring them or the y axis' `categories` ([ADR-0052](https://github.com/romanhaendler/umriss-ui/blob/main/docs/adr/0052-a-chart-reads-its-rows-as-they-come.md)). Never an instant: a `Date` is refused. |
10405
+ | [`level`](#/matrix/MatrixProps-level) *required* | [`Value`](#/matrix/type-Value)`<T>` | — | The level that decides the colour - a number field of the row or a function of it. A missing level is a hole, not a zero. |
10406
+ | [`name`](#/matrix/MatrixProps-name) | `string` | "Series n", after its place in the chart | The name in legend and tooltip. Without one a warning stands in DEV - an unnamed series is a colour nobody can look up. |
10407
+
10316
10408
  From `TooltipProps` — the full table stands on [Tooltip](#/tooltip/type-TooltipProps).
10317
10409
 
10318
10410
  | Prop | Type | Default | Description |
@@ -10494,15 +10586,6 @@ for a grid up to the next clock change.
10494
10586
  function localOffset(instant: number): number;
10495
10587
  ```
10496
10588
 
10497
- ##### `mapSeries`
10498
-
10499
- Map a whole series inwards - the route materialisation takes when it wants to
10500
- go it in one piece. Only the first n values are touched.
10501
-
10502
- ```ts
10503
- function mapSeries(input: CalendarInput, source: Float64Array, n: number, target: Float64Array): void;
10504
- ```
10505
-
10506
10589
  ##### `pareto`
10507
10590
 
10508
10591
  Sorts descending, accumulates, collects the tail and finds the cutoff
@@ -10546,55 +10629,6 @@ colours of
10546
10629
  function resolveColours<K extends string>(root: Element, colours: Readonly<Record<K, string>>): Record<K, string>;
10547
10630
  ```
10548
10631
 
10549
- ##### `ruleOutlier`
10550
-
10551
- Rule 1 (Nelson 1, Western Electric 1): one point beyond three sigma.
10552
- Beyond, not on it - a point exactly on the limit violates nothing.
10553
-
10554
- ```ts
10555
- function ruleOutlier(values: readonly number[], limits: ControlLimits): number[];
10556
- ```
10557
-
10558
- ##### `ruleRun`
10559
-
10560
- Rule 2 (Nelson 2): a run of points on one side of the centre line. The
10561
- default length is nine - Nelson. Western Electric counts eight; that is why
10562
- the length is a parameter and not a literal, so that a works with a rule of
10563
- its own need not argue with the library.
10564
-
10565
- ```ts
10566
- function ruleRun(values: readonly number[], limits: ControlLimits, length?: number): number[];
10567
- ```
10568
-
10569
- ##### `ruleTrend`
10570
-
10571
- Rule 3 (Nelson 3): a run of nothing but rises or nothing but falls. The
10572
- default length is six points, so five steps - Nelson. Two equal values are
10573
- neither a rise nor a fall and break the run.
10574
-
10575
- ```ts
10576
- function ruleTrend(values: readonly number[], length?: number): number[];
10577
- ```
10578
-
10579
- ##### `ruleTwoOfThree`
10580
-
10581
- Rule 4 (Nelson 5): two of three consecutive points beyond two sigma on the
10582
- same side. Reported are the points beyond the zone, not the one in between -
10583
- that one is unremarkable and, marked, would look like a measurement error.
10584
-
10585
- ```ts
10586
- function ruleTwoOfThree(values: readonly number[], limits: ControlLimits): number[];
10587
- ```
10588
-
10589
- ##### `sigmaFromLimit`
10590
-
10591
- Sigma calculated back from a limit that stands on paper. For callers whose
10592
- baseline has been handed down as a centre line and a control limit.
10593
-
10594
- ```ts
10595
- function sigmaFromLimit(center: number, upper: number): number;
10596
- ```
10597
-
10598
10632
  ##### `subscribeTheme`
10599
10633
 
10600
10634
  Subscribe to theme invalidations - a switch of `color-scheme` on the
@@ -10629,26 +10663,6 @@ interval has no next and comes back as itself.
10629
10663
  function toWallClock(workingTime: number, input: CalendarInput): number;
10630
10664
  ```
10631
10665
 
10632
- ##### `toWorkingTime`
10633
-
10634
- Wall clock time → working time.
10635
-
10636
- A point in a removed interval is a gap and becomes `NaN` - the encoding every
10637
- gap of this library already uses, and the drawing loop breaks the mark at it
10638
- of its own accord. Not the edge of the interval: a measurement from a time
10639
- which, according to the calendar, did not exist could not be laid there
10640
- honestly; it would pile up on what really does lie there. The same holds
10641
- before the first and after the last interval.
10642
-
10643
- The end of one interval and the beginning of the next fall on the same value:
10644
- in working time they are neighbours, and the line between two points on
10645
- either side is drawn. That is not a lie but the whole purpose of the axis; the
10646
- mark in the axis band tells the reader that time was taken out there.
10647
-
10648
- ```ts
10649
- function toWorkingTime(wallClock: number, input: CalendarInput): number;
10650
- ```
10651
-
10652
10666
  ##### `toWorkingTimeClamped`
10653
10667
 
10654
10668
  Wall clock time → working time, but without NaN: whatever lies in removed
@@ -10656,10 +10670,8 @@ time falls onto the seam that this span collapses onto anyway; whatever lies
10656
10670
  before the first or after the last interval onto 0 or onto the whole
10657
10671
  working time respectively.
10658
10672
 
10659
- Why this exists: the materialised x values must stay ascending. Binary search
10660
- - for a hit as for a segment boundary - assumes that, and every comparison
10661
- with NaN is false, so that a search over a block of NaN silently lands on the
10662
- wrong point. The clamped value is a POSITION, not a statement: the point
10673
+ The materialised x values must stay ascending: binary search assumes it, and
10674
+ a search over NaN silently lands on the wrong point. The clamped value is a POSITION, not a statement: the point
10663
10675
  itself is carried as a gap and is never drawn and never hit.
10664
10676
 
10665
10677
  ```ts
@@ -10710,22 +10722,6 @@ function workingCalendar(intervals: readonly WorkingInterval[]): WorkingCalendar
10710
10722
 
10711
10723
  Used on [Axis](#/axis).
10712
10724
 
10713
- ##### `workingTicks`
10714
-
10715
- Tick values for an axis extent that already stands in WORKING TIME - the
10716
- route the axis layout takes.
10717
-
10718
- The extent is trimmed to the working time that exists (an extent widened to
10719
- nice boundaries reaches beyond it), calculated back into wall clock time, and
10720
- the candidates arise there. The step comes from the span in working time and
10721
- not from the one in wall clock time: roughly one candidate per step of
10722
- working time survives, and calculated from the wall clock span, four out of
10723
- ten wanted ticks would be left.
10724
-
10725
- ```ts
10726
- function workingTicks(input: CalendarInput, from: number, to: number, count: number, offset?: number): number[];
10727
- ```
10728
-
10729
10725
  ##### `workingTimeTicks`
10730
10726
 
10731
10727
  Ticks for a working time axis, from an extent in WALL CLOCK TIME.
@@ -10798,42 +10794,6 @@ const DEFAULT_GRADIENT: readonly string[];
10798
10794
 
10799
10795
  Used on [Matrix](#/matrix).
10800
10796
 
10801
- ##### `defaultRules`
10802
-
10803
- All four rules, with Nelson's run lengths: nine points on one side, six
10804
- points in succession rising or falling. Western Electric counts eight; both
10805
- lengths are therefore parameters.
10806
-
10807
- ```ts
10808
- const defaultRules: RuleOptions;
10809
- ```
10810
-
10811
- ##### `Echoes`
10812
-
10813
- The views a component reported that may still come back, by their
10814
- content key - the chart's and the schedule's ([ADR-0047](https://github.com/romanhaendler/umriss-ui/blob/main/docs/adr/0047-a-component-holds-its-own-view.md)), the table holding
10815
- a copy of its own. An application keeping the view hands
10816
- it back a frame or more late - by then a pan has moved on, and going to the
10817
- view handed in would jump back. So a view handed in that equals one
10818
- reported since the last one handed in, within a second, is the component's
10819
- own state coming back, not a view to go to. The echoes come in order: one drops
10820
- itself and every older report, a view from outside drops them all. The
10821
- second bounds the list where nothing is handed back, and lets such an
10822
- application still restore a view it kept.
10823
-
10824
- ```ts
10825
- class Echoes {
10826
- private reports;
10827
- /** Notes a view reported, by its key. */
10828
- reported(key: string): void;
10829
- /** Whether the view handed in is a report coming back. */
10830
- has(key: string): boolean;
10831
- /** Forgets what the view handed in answers. */
10832
- handed(key: string): void;
10833
- private at;
10834
- }
10835
- ```
10836
-
10837
10797
  ##### `HOUR`
10838
10798
 
10839
10799
  One hour in milliseconds.
@@ -10873,16 +10833,6 @@ const MINUTE: number;
10873
10833
 
10874
10834
  Used on [Scenarios](#/), [Installation](#/installation), [Chart](#/chart), [Axis](#/axis), [Zoom and pan](#/zoom-and-pan), [View](#/view), [Line](#/line), [Area](#/area), [Scatter](#/scatter), [BoxPlot](#/boxplot), [StateBand](#/stateband), [LimitLine](#/limitline), [Tooltip](#/tooltip), [Legend](#/legend) and [Benchmark](#/benchmark).
10875
10835
 
10876
- ##### `paretoDefaults`
10877
-
10878
- What [`pareto`](#/api/pareto) assumes where a call says nothing: a cutoff of 80 %, and no
10879
- collecting of the tail.
10880
-
10881
- ```ts
10882
- const defaultOptions: Omit<ParetoOptions, "remainderName">;
10883
- // exported as paretoDefaults
10884
- ```
10885
-
10886
10836
  ##### `SECOND`
10887
10837
 
10888
10838
  One second in milliseconds, the unit of a time axis.
@@ -10916,8 +10866,8 @@ An `Area` as the chart holds it once registered.
10916
10866
  | `format` | `(value: number) => string` | — | The value in the tooltip; before the y axis' `tickFormat`. Compared by its source text, as an accessor is. From `SeriesBase`. |
10917
10867
  | `color` | `string` | — | From `SeriesBase`. |
10918
10868
  | `tone` | `"ok" \| "warning" \| "alarm"` | — | A role instead of a colour value: the theme resolves it, in both themes. For series that mean something rather than just being the next one - the violating points of a control chart, say. `color` beats it. From `SeriesBase`. |
10919
- | `stack` | `string` | — | The stack this series stands in: series with the same id, on the same x and y axis, stack in registration order (K1). From `Stackable`. |
10920
- | `normalize` | `boolean` | — | On any member, the whole stack sums to 100 at every x (K5). From `Stackable`. |
10869
+ | `stack` | `string` | — | The stack this series stands in: series with the same id, on the same x and y axis, stack in registration order. From `Stackable`. |
10870
+ | `normalize` | `boolean` | — | On any member, the whole stack sums to 100 at every x. From `Stackable`. |
10921
10871
 
10922
10872
  ##### `Assessment`
10923
10873
 
@@ -11026,8 +10976,8 @@ A `Bar` as the chart holds it once registered.
11026
10976
  | `format` | `(value: number) => string` | — | The value in the tooltip; before the y axis' `tickFormat`. Compared by its source text, as an accessor is. From `SeriesBase`. |
11027
10977
  | `color` | `string` | — | From `SeriesBase`. |
11028
10978
  | `tone` | `"ok" \| "warning" \| "alarm"` | — | A role instead of a colour value: the theme resolves it, in both themes. For series that mean something rather than just being the next one - the violating points of a control chart, say. `color` beats it. From `SeriesBase`. |
11029
- | `stack` | `string` | — | The stack this series stands in: series with the same id, on the same x and y axis, stack in registration order (K1). From `Stackable`. |
11030
- | `normalize` | `boolean` | — | On any member, the whole stack sums to 100 at every x (K5). From `Stackable`. |
10979
+ | `stack` | `string` | — | The stack this series stands in: series with the same id, on the same x and y axis, stack in registration order. From `Stackable`. |
10980
+ | `normalize` | `boolean` | — | On any member, the whole stack sums to 100 at every x. From `Stackable`. |
11031
10981
 
11032
10982
  ##### `Bin`
11033
10983
 
@@ -11070,7 +11020,7 @@ is a gap; and its outliers ([ADR-0040](https://github.com/romanhaendler/umriss-u
11070
11020
 
11071
11021
  ##### `BoxExtras<V = number>`
11072
11022
 
11073
- The optional numbers of a box (box-plot 04), by name.
11023
+ The optional numbers of a box by name.
11074
11024
 
11075
11025
  | Prop | Type | Default | Description |
11076
11026
  |---|---|---|---|
@@ -11149,18 +11099,21 @@ is typed by that `data` instead.
11149
11099
  | `Line` *required* | `<T = Z>(props: `[`LineProps`](#/line/type-LineProps)`<T>) => null` | — | <br>Shown in: [Draw a first chart (Installation)](#/installation/first-chart), [Size a chart by its container (Installation)](#/installation/in-its-container), [Mix series kinds (Chart)](#/chart/mixed) and 47 more |
11150
11100
  | `Area` *required* | `<T = Z>(props: `[`AreaProps`](#/area/type-AreaProps)`<T>) => null` | — | <br>Shown in: [Mix series kinds (Chart)](#/chart/mixed), [Mark every kind (Chart)](#/chart/marks-on-every-kind), [Bind every kind of series to a second axis (Axis)](#/axis/every-kind-on-a-second-axis) and 5 more |
11151
11101
  | `Bar` *required* | `<T = Z>(props: `[`BarProps`](#/bar/type-BarProps)`<T>) => null` | — | <br>Shown in: [Mix series kinds (Chart)](#/chart/mixed), [Mark every kind (Chart)](#/chart/marks-on-every-kind), [Bind every kind of series to a second axis (Axis)](#/axis/every-kind-on-a-second-axis) and 13 more |
11152
- | `Scatter` *required* | `<T = Z>(props: `[`ScatterProps`](#/scatter/type-ScatterProps)`<T>) => null` | — | <br>Shown in: [Mix series kinds (Chart)](#/chart/mixed), [Mark every kind (Chart)](#/chart/marks-on-every-kind), [Bind every kind of series to a second axis (Axis)](#/axis/every-kind-on-a-second-axis) and 2 more |
11153
- | `StateBand` *required* | `<T = Z>(props: `[`StateBandProps`](#/stateband/type-StateBandProps)`<T> & `[`OneLane`](#type-OneLane)`) => null` | — | <br>Shown in: [Mark bands, limits and cells (Chart)](#/chart/bands-limits-and-cells), [One vehicle through the day (StateBand)](#/stateband/one-vehicle), [Lay a state under a course (StateBand)](#/stateband/under-a-course) and 3 more |
11154
- | `Matrix` *required* | `<T = Z>(props: `[`MatrixProps`](#/matrix/type-MatrixProps)`<T>) => null` | — | <br>Shown in: [Mark bands, limits and cells (Chart)](#/chart/bands-limits-and-cells), [Colour cells by their limits (Matrix)](#/matrix/by-limits), [Colour cells along a gradient (Matrix)](#/matrix/gradient) |
11102
+ | `Scatter` *required* | `<T = Z>(props: `[`ScatterProps`](#/scatter/type-ScatterProps)`<T>) => null` | — | <br>Shown in: [Mix series kinds (Chart)](#/chart/mixed), [Mark every kind (Chart)](#/chart/marks-on-every-kind), [Bind every kind of series to a second axis (Axis)](#/axis/every-kind-on-a-second-axis) and 3 more |
11103
+ | `StateBand` *required* | `<T = Z>(props: `[`StateBandProps`](#/stateband/type-StateBandProps)`<T> & `[`OneLane`](#type-OneLane)`) => null` | — | <br>Shown in: [Mark bands, limits and cells (Chart)](#/chart/bands-limits-and-cells), [One vehicle through the day (StateBand)](#/stateband/one-vehicle), [Lay a state under a course (StateBand)](#/stateband/under-a-course) and 4 more |
11104
+ | `Matrix` *required* | `<T = Z>(props: `[`MatrixProps`](#/matrix/type-MatrixProps)`<T>) => null` | — | <br>Shown in: [Mark bands, limits and cells (Chart)](#/chart/bands-limits-and-cells), [Colour cells by their limits (Matrix)](#/matrix/by-limits), [Colour cells along a gradient (Matrix)](#/matrix/gradient) and 1 more |
11155
11105
  | `BoxPlot` *required* | `<T = Z>(props: `[`BoxPlotProps`](#/boxplot/type-BoxPlotProps)`<T>) => null` | — | <br>Shown in: [One box per service (BoxPlot)](#/boxplot/minimal), [A box per hour on a time axis (BoxPlot)](#/boxplot/over-time), [With outliers (BoxPlot)](#/boxplot/outliers) and 4 more |
11156
- | `view` *required* | [`ChartView`](#/view/type-ChartView) | — | How the reader is looking at the chart. |
11106
+ | `view` *required* | [`ChartView`](#/view/type-ChartView) | — | How the reader is looking at the chart.<br>Shown in: [Keep and restore a view (View)](#/view/keep-and-restore) |
11157
11107
  | `domains` *required* | [`AxisSpans`](#type-AxisSpans) | — | The span each zoomable x axis shows, by axis `id`; an axis absent shows its own `domain`. |
11158
- | `setDomain` *required* | `(axisId: string, span: readonly [number, number] \| null) => void` | — | Puts a span in view on a zoomable x axis - a lone one is `"x"`; `null` shows the axis' own `domain` again. |
11108
+ | `setView` *required* | `(view: `[`ChartView`](#/view/type-ChartView)`) => void` | — | Goes to a whole view; what it leaves out is shown whole again. Not reported through `onViewChange`: two charts kept in step by `onViewChange: (v) => other.setView(v)` in both directions do not answer each other. A view with the content already shown changes nothing.<br>Shown in: [Read it by keyboard and screen reader (Chart)](#/chart/keyboard-and-screen-reader), [Keep charts in step (Zoom and pan)](#/zoom-and-pan/cursor-sync), [Keep and restore a view (View)](#/view/keep-and-restore) |
11109
+ | `setDomain` *required* | `(axisId: string, span: readonly [number, number] \| null) => void` | — | Puts a span in view on a zoomable x axis - a lone one is `"x"`; `null` shows the axis' own `domain` again.<br>Shown in: [Measure a million points (Benchmark)](#/benchmark/benchmark) |
11159
11110
  | `hidden` *required* | `readonly string[]` | — | The hidden series, by `name`. |
11160
11111
  | `toggleSeries` *required* | `(name: string) => void` | — | Hides the series `name`, or shows it where it is hidden - as a click on its legend entry does. Hiding the last series visible shows all. |
11161
11112
  | `showOnly` *required* | `(name: string) => void` | — | Hides every series but `name`; all are shown where none carries it.<br>Shown in: [Hide a series from the legend (Legend)](#/legend/hide-a-series) |
11162
11113
  | `showAllSeries` *required* | `() => void` | — | Shows every series again.<br>Shown in: [Hide a series from the legend (Legend)](#/legend/hide-a-series) |
11163
11114
 
11115
+ Used on [Chart](#/chart).
11116
+
11164
11117
  ##### `ChartPerf`
11165
11118
 
11166
11119
  Measurements of the instrumentation for the benchmark page.
@@ -11183,6 +11136,7 @@ Everything the charts put out as text.
11183
11136
 
11184
11137
  | Prop | Type | Default | Description |
11185
11138
  |---|---|---|---|
11139
+ | `locale` *required* | `string` | — | The BCP 47 tag every number and every date or time label of the chart is formatted in (`en-GB`, `de-DE`). The one input for the locale: the browser's language is not read. The clock stays 24-hour in both. |
11186
11140
  | `roleDescription` *required* | `string` | — | What a screen reader calls the plot area that takes the keys (`aria-roledescription`). |
11187
11141
  | `empty` *required* | `string` | — | Shown in the plot area when no visible series has a point to show. |
11188
11142
  | `seriesList` *required* | `(names: readonly string[]) => string` | — | The summary's visible series, by name. |
@@ -11190,15 +11144,15 @@ Everything the charts put out as text.
11190
11144
  | `seriesExtent` *required* | `(name: string, min: string, max: string) => string` | — | The summary's lowest and highest value of one series in that stretch. |
11191
11145
  | `limitList` *required* | `(limits: readonly { name: string; value: string }[]) => string` | — | The summary's labelled limits, each with its value in its axis' format (a band's two edges as one value). |
11192
11146
  | `readout` *required* | `(x: string, rows: readonly { name: string; value: string; x: string }[]) => string` | — | What is read after a key: the position, then each series with its value (and its own x where it stands on another x axis), the emphasised one first. |
11193
- | `stackTotal` *required* | `string` | — | The last row of a stack in the tooltip and the readout: the sum of its members at the point (charts-stacking K4). |
11194
- | `percent` *required* | `(value: string) => string` | — | A share in a normalised stack, its number already formatted (K5). |
11147
+ | `stackTotal` *required* | `string` | — | The last row of a stack in the tooltip and the readout: the sum of its members at the point. |
11148
+ | `percent` *required* | `(value: string) => string` | — | A share in a normalised stack, its number already formatted. |
11195
11149
  | `walkHelp` *required* | `string` | — | The keys that walk the chart. |
11196
11150
  | `selectHelp` *required* | `string` | — | The key that reports the Active point - only where `onSelect` is given. |
11197
11151
  | `zoomHelp` *required* | `string` | — | The keys that zoom and pan it - only where the chart can be zoomed. |
11198
11152
  | `legendHelp` *required* | `string` | — | The keys of the legend's entries - only where it has one to press. |
11199
11153
  | `allShown` *required* | `string` | — | Read out where hiding would leave nothing to see, and every series is shown instead. |
11200
11154
  | `showAll` *required* | `string` | — | The control over a zoomed plot that brings every zoomed axis back to its own domain (component-view 04). |
11201
- | `showData` *required* | `string` | — | The data table's disclosure key, closed and open (charts-alternatives C1). |
11155
+ | `showData` *required* | `string` | — | The data table's disclosure key, closed and open. |
11202
11156
  | `hideData` *required* | `string` | — | |
11203
11157
  | `positionColumn` *required* | `string` | — | The heading of the table's x column where its axis has no `label`, and of a matrix' row column where its y axis has none. |
11204
11158
  | `rowColumn` *required* | `string` | — | |
@@ -11213,13 +11167,13 @@ Everything the charts put out as text.
11213
11167
  | `notch` *required* | `string` | — | |
11214
11168
  | `count` *required* | `string` | — | |
11215
11169
  | `outlierList` *required* | `(values: readonly string[], more: number) => string` | — | |
11216
- | `downsampled` *required* | `(readings: number) => string` | — | Added to the caption where the table shows the downsampled course (C2): how many readings its rows stand for. |
11170
+ | `downsampled` *required* | `(readings: number) => string` | — | Added to the caption where the table shows the downsampled course: how many readings its rows stand for. |
11217
11171
 
11218
11172
  ##### `ChartView`
11219
11173
 
11220
11174
  Its table stands on [View](#/view/type-ChartView).
11221
11175
 
11222
- Used on [Chart](#/chart), [Zoom and pan](#/zoom-and-pan) and [View](#/view).
11176
+ Used on [Zoom and pan](#/zoom-and-pan) and [View](#/view).
11223
11177
 
11224
11178
  ##### `ControlChartProps`
11225
11179
 
@@ -11296,7 +11250,7 @@ to `to`.
11296
11250
  | `kind` *required* | `"band"` | — | |
11297
11251
  | `from` *required* | `number` | — | |
11298
11252
  | `to` *required* | `number` | — | |
11299
- | `axisId` | `string` | — | Axis on which the value lies; without one, the first axis of its orientation (charts-fixes 08). From `LimitBase`. |
11253
+ | `axisId` | `string` | — | Axis on which the value lies; without one, the first axis of its orientation. From `LimitBase`. |
11300
11254
  | `orientation` *required* | [`AxisOrientation`](#type-AxisOrientation)<br>`"x" \| "y"` | — | From `LimitBase`. |
11301
11255
  | `severity` *required* | [`Severity`](#type-Severity)<br>`"warning" \| "alarm"` | — | From `LimitBase`. |
11302
11256
  | `label` | `string` | — | From `LimitBase`. |
@@ -11329,7 +11283,7 @@ A `LimitLine` as the chart holds it once registered.
11329
11283
  |---|---|---|---|
11330
11284
  | `kind` *required* | `"line"` | — | |
11331
11285
  | `value` *required* | `number` | — | |
11332
- | `axisId` | `string` | — | Axis on which the value lies; without one, the first axis of its orientation (charts-fixes 08). From `LimitBase`. |
11286
+ | `axisId` | `string` | — | Axis on which the value lies; without one, the first axis of its orientation. From `LimitBase`. |
11333
11287
  | `orientation` *required* | [`AxisOrientation`](#type-AxisOrientation)<br>`"x" \| "y"` | — | From `LimitBase`. |
11334
11288
  | `severity` *required* | [`Severity`](#type-Severity)<br>`"warning" \| "alarm"` | — | From `LimitBase`. |
11335
11289
  | `label` | `string` | — | From `LimitBase`. |
@@ -11553,7 +11507,7 @@ The settings of `pareto`, complete; a call gives `ParetoSettings`.
11553
11507
  |---|---|---|---|
11554
11508
  | `cutoff` *required* | `number` | `0.8` | The share whose crossing is sought. Whoever lands exactly on it counts as the crossing: the question is "which reasons make up eighty per cent", and whoever reaches eighty exactly belongs to them. |
11555
11509
  | `collectRank` *required* | `number` | `Infinity` | How many items stay on their own. Everything behind that becomes a single entry. Beyond the number of items no remainder arises at all - not an empty one. |
11556
- | `remainderName` | `string` | none - the caller names it | Name of the collected remainder. `@umriss-ui/charts` has no wording module - every string it draws comes from the caller - and no module is introduced for a single label. Until library-audit 03 the name here was "Sonstige", the one German word the package brought along itself. |
11510
+ | `remainderName` | `string` | none - the caller names it | Name of the collected remainder. The helper has no default wording for it. |
11557
11511
 
11558
11512
  ##### `ParetoResult`
11559
11513