@umriss-ui/charts 0.3.0-rc.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/CHANGELOG.md ADDED
@@ -0,0 +1,158 @@
1
+ # Changes to `@umriss-ui/charts`
2
+
3
+ This document describes what changes for **callers** of the package: exports,
4
+ props, behaviour. What was worked on in the repository — rebuilds, tests,
5
+ decisions that are invisible from outside — stands in the repository's journal
6
+ (`docs/journal.md`) and in the specs under `.scratch/`.
7
+
8
+ **The numbers.** The middle digit rises when something is added; the last one
9
+ when something is repaired. As long as the first digit is `0`, no number
10
+ promises compatibility — which is why a rule stronger than the figure applies as
11
+ well: **whatever changes existing behaviour stands under a heading "Changed" of
12
+ its own**, no matter which digit rose. Whoever reads only one section before an
13
+ upgrade reads that one.
14
+
15
+ **Names read forwards.** Where an entry describes a name that has since been
16
+ renamed, it is named here as it is called today; names that were removed stand
17
+ as they stood.
18
+
19
+ The versions 0.1.0 and 0.2.0 were reconstructed afterwards, out of the
20
+ specs; the document itself came into being only with
21
+ `library-audit` 08. They are grouped by unit of delivery, not by commit, and were
22
+ never published.
23
+
24
+ **Release candidates.** `0.3.0-rc.0` is the first version for the registry, under
25
+ the tag `next` rather than `latest`: `pnpm add @umriss-ui/charts@next`. A release
26
+ candidate promises nothing a `0.x` does not already fail to promise; it says the
27
+ interface is still expected to move before `0.3.0`.
28
+
29
+ ---
30
+
31
+ ## 0.3.0-rc.0 – One language, one scope (Sep. 2026)
32
+
33
+ Delivery report for `.scratch/english-and-umriss-ui/spec.md`, the charts' share.
34
+
35
+ - **The package is called `@umriss-ui/charts`.** The npm scope moved from
36
+ `@umriss/*` to `@umriss-ui/*`, which is the org actually secured for this
37
+ library. The sibling package `@umriss/ui` is `@umriss-ui/core` and lies at
38
+ `packages/core`; `@umriss/table` is `@umriss-ui/table`. Nothing was ever
39
+ published under the old names — all three returned 404 from the registry — so
40
+ there is no alias and no deprecation window, and the version number stays where
41
+ it is.
42
+ - **Every identifier and every document in the workspace is English** (ADR-0018,
43
+ which supersedes ADR-0015). For a caller of this package that changes little,
44
+ because its exported names were English already; what changed is the inside —
45
+ the pure modules' internal identifiers, the long prose headers that carry the
46
+ design reasoning, and the demo. The headers were translated, not shortened.
47
+ - **The library ships two wordings, English by default** (ADR-0019). That
48
+ concerns `@umriss-ui/core`, whose German moved to the subpath
49
+ `@umriss-ui/core/wording/de`. This package is untouched by it and stays
50
+ untouched by it: it has no text layer at all, and every string it draws comes
51
+ from the caller — the one reason `pareto` has no default name for its remainder
52
+ and `ControlChart` no default labels.
53
+ - **`@umriss-ui/charts` still depends on nothing**, and will keep depending on
54
+ nothing (ADR-0016). "Core" names the package one installs first, not a layer
55
+ this package sits on.
56
+ - The licence is MIT, and a `LICENSE` file ships in the package.
57
+
58
+ ### Changed — the limit model's values
59
+
60
+ `Verdict` is `"ok" | "unknown" | "warning" | "alarm"`, `Severity` is
61
+ `"warning" | "alarm"`, `Side` is `"upper" | "lower"`, and the fields of `Limit`,
62
+ `LimitSet` and `Assessment` are `value`, `side`, `severity`, `limits`, `target`,
63
+ `verdict`, `limit`, `excess`, `deviation`.
64
+
65
+ ADR-0006 holds this model twice — once here, once in `@umriss-ui/core` — and the
66
+ copies are pinned together by a runtime conformance test that compares both
67
+ results structurally rather than importing either. The two packages, the shared
68
+ case table and that test therefore moved in a single commit; a divergence stays a
69
+ red test and not a report from the field.
70
+
71
+ `--uc-color-alarm` is unchanged. What moved beside the model is
72
+ `.kc-limit-label[data-severity="warnung"]`, which now reads `"warning"` — the
73
+ same word `tone` has carried all along.
74
+
75
+ ## 0.3.0-rc.0 – Where the library contradicted itself (Sep. 2026)
76
+
77
+ Delivery report for `.scratch/library-audit/spec.md`, tickets 03 and 05.
78
+
79
+ ### Changed
80
+
81
+ **The package brings no text along any more.** It has no text layer, and four
82
+ German defaults stood there regardless:
83
+
84
+ - `ControlChart` no longer labels the control limits without being told to —
85
+ previously `"OEG"` and `"UEG"`. Whoever wants the labels passes
86
+ `labelUpper`/`labelLower`.
87
+ - The scatter of the violations was called `` `${name} – Regelverletzung` ``. It
88
+ is now called what `violationName` says, and without a statement not at all —
89
+ a `Legend` then carries it as "Series n".
90
+ - `pareto` has no default name for the remainder any more (previously
91
+ `"Sonstige"`). Whoever names `collectRank` names `remainderName` with it — in
92
+ the type (`ParetoSettings`) and in DEV as an error. `paretoDefaults` no longer
93
+ contains `remainderName`.
94
+ - The labelling of an operating-time axis without a `tickFormat` of its own is
95
+ `dd.MM. HH:mm`, set by hand. Previously it came out of
96
+ `toLocaleString(undefined, …)` and looked different on every machine.
97
+ - `"Series n"` remains the last resort for a series without a `name`, but warns
98
+ once in DEV.
99
+
100
+ **A series keeps its colour.** The palette followed the position in the
101
+ registration; a series that unregistered and registered again landed at the back,
102
+ and every series of the chart changed colour. The palette now follows the `name`:
103
+ on first mounting as before in JSX order, after that a returning series gets its
104
+ colour back. A series without a `name` still takes the colour of its position and
105
+ warns in DEV when that shifts. Drawing happens unchanged in registration order.
106
+
107
+ **`role="img"` and `aria-label` stand at the plot area** (`.kc-plot`), no longer
108
+ at the root. The root contains the legend, and the descendants of an image are
109
+ presentation to a screen reader — the legend was unreachable. Whoever looked for
110
+ the role at `.kc-root` finds it one level deeper.
111
+
112
+ ### New
113
+
114
+ - `ControlChart violationName`.
115
+ - The type `ParetoSettings`: what a call of `pareto` may specify.
116
+
117
+ ## 0.2.0 – Limits, states, instruments (Aug. 2026)
118
+
119
+ Delivery report for `.scratch/judging-values/spec.md`,
120
+ `.scratch/shopfloor-instruments/spec.md` and
121
+ `.scratch/plant-at-a-glance/spec.md`, the charts' share. The decisions stand in
122
+ ADR-0006 to ADR-0011.
123
+
124
+ ### New
125
+
126
+ - **Three series kinds:** `StateBand` (one state per interval, ADR-0007),
127
+ `Matrix` (one value per cell, with `DEFAULT_GRADIENT` as the colouring) and
128
+ `Span` (an interval with an explicit end on a lane).
129
+ - **`LimitLine` and `LimitBand`:** a limit as a rule with severity and role
130
+ (specification, control limit, zone), which draws the value range of its axis.
131
+ - **`ControlChart`:** the control chart as a composition out of `Line`,
132
+ `LimitLine` and `Scatter` (ADR-0008), and with it the pure modules
133
+ `controlLimits`, `zones`, the four rules and `violations`.
134
+ - **The operating-time axis:** `calendar` on `XAxis`/`YAxis` and the pure modules
135
+ out of `operatingTime.ts` — wall clock ↔ operating time, ticks, breaks.
136
+ - **`pareto`** as a pure module.
137
+ - **The limit as a rule:** `assess` and `verdictWeight` with their types — the
138
+ same rule as in `@umriss-ui/core`, deliberately there twice (ADR-0006).
139
+
140
+ Nothing changes in the behaviour of the four existing series kinds.
141
+
142
+ ## 0.1.0 – Takeover state and mixed series kinds (Aug. 2026)
143
+
144
+ The number stood at `0.1.0` the whole time; it covers the takeover state
145
+ (packages C.1–C.7) and `.scratch/mixed-series-kinds/`.
146
+
147
+ ### New
148
+
149
+ - `Chart` with two canvas layers and one HTML layer above them, `XAxis`/`YAxis`
150
+ with axis bands on all four sides, `Tooltip`, `Legend`, `LinearScale` and
151
+ `invalidateTheme`.
152
+ - Four series kinds mixable within one chart: `Line`, `Scatter`, `Area` with a
153
+ baseline, and `Bar` on the numeric X axis (ADR-0002).
154
+
155
+ ### Changed
156
+
157
+ **`LineChart` is called `Chart`** and is generic over the series kinds within it
158
+ (`mixed-series-kinds` 01). The takeover state knew only lines.
package/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Roman Händler
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,109 @@
1
+ # @umriss-ui/charts
2
+
3
+ Canvas-based charts for data-dense applications: few chart kinds, each one drawn
4
+ properly. Lines, areas, bars, scatters, state bands, matrices and spans compose
5
+ into one chart on shared axes — together with the instruments a plant screen is
6
+ made of: limit lines and bands, a control chart, a Pareto and an operating-time
7
+ axis.
8
+
9
+ The package depends on **nothing but React**, and it will keep doing so (R-1.2).
10
+ It brings no component library, no date library and no chart framework, and the
11
+ lint rule over `packages/charts/src/**` holds that fast.
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ pnpm add @umriss-ui/charts@next
17
+ ```
18
+
19
+ The package is a **release candidate**, published under the tag `next`. As long
20
+ as no released version exists, npm points `latest` at the candidate too — a plain
21
+ `pnpm add @umriss-ui/charts` installs it as well.
22
+
23
+ React 18 or 19 as a peer, and nothing else. `@umriss-ui/core` is **not** a
24
+ dependency and not a peer dependency — if an application uses both packages, it
25
+ does so because it chose to, not because this one required it (ADR-0020).
26
+
27
+ No fonts are shipped either. The charts use Geist when the application loads it
28
+ (`@fontsource/geist-sans`, `@fontsource/geist-mono`) and the system fonts
29
+ otherwise.
30
+
31
+ ## The smallest chart that runs
32
+
33
+ ```tsx
34
+ import { Chart, Line, XAxis, YAxis, Tooltip } from "@umriss-ui/charts";
35
+ import "@umriss-ui/charts/styles.css";
36
+
37
+ interface Point {
38
+ t: number;
39
+ a: number;
40
+ }
41
+
42
+ const DATA: Point[] = [
43
+ { t: 0, a: 12 },
44
+ { t: 1, a: 18 },
45
+ { t: 2, a: 15 },
46
+ { t: 3, a: 24 },
47
+ ];
48
+
49
+ export function Course() {
50
+ return (
51
+ <Chart data={DATA} height={280} ariaLabel="Course of one series">
52
+ <XAxis accessor={(d: Point) => d.t} label="Index" />
53
+ <YAxis accessor={(d: Point) => d.a} />
54
+ <Line accessor={(d: Point) => d.a} name="Series A" />
55
+ <Tooltip />
56
+ </Chart>
57
+ );
58
+ }
59
+ ```
60
+
61
+ A series is an element, not an entry in a configuration object: the order in the
62
+ JSX decides what lies over what, and at the same time the palette colour.
63
+
64
+ ## The stylesheet
65
+
66
+ ```ts
67
+ import "@umriss-ui/charts/styles.css";
68
+ ```
69
+
70
+ The axes, ticks, legend and tooltip are DOM and take their values from the
71
+ stylesheet; only the series themselves are drawn on canvas. The JavaScript loads
72
+ no CSS of its own, so the application imports the stylesheet itself.
73
+
74
+ ## What it can do
75
+
76
+ * **Seven series kinds** in one chart on shared axes: `Line`, `Area`, `Bar`,
77
+ `Scatter`, `StateBand`, `Matrix`, `Span`.
78
+ * **Several axes per orientation**, each with its own extent; only the first
79
+ registered axis per orientation draws a grid.
80
+ * **The instruments**: `LimitLine` and `LimitBand`, `ControlChart` with its four
81
+ rule violations, `pareto()` with a collected remainder, and an operating-time
82
+ axis that takes the empty hours out and marks every removed span.
83
+ * **The pure modules are exported**, not hidden: `assess`, `controlLimits`,
84
+ `zones`, `violations`, `pareto`, `operatingCalendar` and the rest. Whoever
85
+ wants to draw something other than the composition offers should reach the
86
+ arithmetic without rebuilding it.
87
+ * **Performance, measured rather than claimed.** Three series of 100,000 points
88
+ each: 10.5 ms materialisation, 10.8 ms series draw, 60 FPS on hover; at three
89
+ million points, 49.8 ms and 49.6 ms. The measuring run, its conditions and the
90
+ mixed series set stand in [`docs/capabilities.md`](docs/capabilities.md).
91
+
92
+ What it deliberately cannot do — zoom and pan, animations, stacking, a category
93
+ scale, horizontal bars — stands in the same record, with the reason.
94
+
95
+ ## More
96
+
97
+ * The demo: <https://romanhaendler.github.io/umriss-ui/charts/>, or locally
98
+ `pnpm dev:charts` (port 4174). It is the documentation — every page
99
+ shows running examples with their source and the props table generated from
100
+ `src/`.
101
+ * [`CHANGELOG.md`](CHANGELOG.md) — what changes for a caller.
102
+ * [`docs/capabilities.md`](docs/capabilities.md) — every capability with the
103
+ level at which it is proved.
104
+ * [`../../docs/design-language.md`](../../docs/design-language.md) — the design
105
+ language all three packages share.
106
+
107
+ ## Licence
108
+
109
+ MIT — see [`LICENSE`](LICENSE).
@@ -0,0 +1 @@
1
+ .kc-root{--uc-color-axis: var(--u-edge-color-strong, rgba(23, 23, 23, .17));--uc-color-grid: var(--u-hairline, rgba(23, 23, 23, .06));--uc-color-text: var(--u-color-text-muted, #71717a);--uc-color-bg: var(--u-color-surface, #ffffff);--uc-font: var( --u-font-sans, "Geist Sans", "Geist", -apple-system, "Segoe UI", system-ui, sans-serif );--uc-font-mono: var( --u-font-mono, "Geist Mono", ui-monospace, "Cascadia Mono", "Consolas", monospace );--uc-color-warning: var(--u-color-warning, #8a5c00);--uc-color-alarm: var(--u-color-danger, #b13636);--uc-color-ok: var(--u-color-success, #217a4b);--uc-series-1: var(--u-chart-1, #2563eb);--uc-series-2: var(--u-chart-2, #db2777);--uc-series-3: var(--u-chart-3, #059669);--uc-series-4: var(--u-chart-4, #d97706);--uc-series-5: var(--u-chart-5, #7c3aed);--uc-series-6: var(--u-chart-6, #0891b2);--uc-size-tick: 11.5px;--uc-size-title: 12px;--uc-size-legend: 12.5px;--uc-radius: 6px;--uc-shadow: 0 1px 2px rgba(0, 0, 0, .06), 0 4px 12px rgba(0, 0, 0, .08);position:relative;display:flex;flex-direction:column;font-family:var(--uc-font);color:var(--uc-color-text);font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}.kc-plot{position:relative;flex:1 1 auto;min-height:0;min-width:0}.kc-plot>canvas{position:absolute;top:0;right:0;bottom:0;left:0;display:block;pointer-events:none}.kc-axes{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none}.kc-axis{position:absolute}.kc-axis-line{position:absolute;background:var(--uc-color-axis)}.kc-axis-y>.kc-axis-line{top:0;width:1px;height:100%}.kc-axis-left>.kc-axis-line{right:0}.kc-axis-right>.kc-axis-line{left:0}.kc-axis-x>.kc-axis-line{left:0;width:100%;height:1px}.kc-axis-bottom>.kc-axis-line{top:0}.kc-axis-top>.kc-axis-line{bottom:0}.kc-tick{position:absolute}.kc-axis-y>.kc-tick{left:0;right:0;height:1px}.kc-axis-x>.kc-tick{top:0;bottom:0;width:1px}.kc-tick-mark{position:absolute;background:var(--uc-color-axis)}.kc-axis-y>.kc-tick>.kc-tick-mark{top:0;width:5px;height:1px}.kc-axis-left>.kc-tick>.kc-tick-mark{right:0}.kc-axis-right>.kc-tick>.kc-tick-mark{left:0}.kc-axis-x>.kc-tick>.kc-tick-mark{left:0;width:1px;height:5px}.kc-axis-bottom>.kc-tick>.kc-tick-mark{top:0}.kc-axis-top>.kc-tick>.kc-tick-mark{bottom:0}.kc-tick-label{position:absolute;white-space:pre;font-size:var(--uc-size-tick);line-height:1.25;letter-spacing:.005em;color:var(--uc-color-text)}.kc-axis-y>.kc-tick>.kc-tick-label{top:50%;transform:translateY(-50%)}.kc-axis-left>.kc-tick>.kc-tick-label{text-align:right}.kc-axis-right>.kc-tick>.kc-tick-label{text-align:left}.kc-axis-title{position:absolute;white-space:pre;font-size:var(--uc-size-title);line-height:1.25;letter-spacing:.01em;color:var(--uc-color-text)}.kc-axis-x>.kc-axis-title{left:0;right:0;text-align:center}.kc-axis-bottom>.kc-axis-title{bottom:0}.kc-axis-top>.kc-axis-title{top:0}.kc-axis-y>.kc-axis-title{top:50%;writing-mode:vertical-rl}.kc-axis-left>.kc-axis-title{left:0;transform:translateY(-50%) rotate(180deg)}.kc-axis-right>.kc-axis-title{right:0;transform:translateY(-50%)}.kc-legend{display:flex;flex-wrap:wrap;gap:4px 14px;font-size:var(--uc-size-legend);line-height:1.35;color:var(--uc-color-text)}.kc-legend-top{order:-1;padding-bottom:8px}.kc-legend-bottom{order:1;padding-top:8px}.kc-legend-item{display:inline-flex;align-items:center;gap:6px;cursor:default}.kc-legend-chip{display:inline-block;width:10px;height:10px;border-radius:2px}.kc-tooltip{position:absolute;top:0;left:0;z-index:2;pointer-events:none;opacity:0;transition:opacity 80ms ease-out;min-width:96px;padding:7px 9px;border:1px solid var(--uc-color-axis);border-radius:var(--uc-radius);background:var(--uc-color-bg);box-shadow:var(--uc-shadow);font-size:12px;line-height:1.35;color:var(--uc-color-text)}.kc-tooltip-head{font-family:var(--uc-font-mono);font-size:11.5px;letter-spacing:.01em;padding-bottom:5px;margin-bottom:5px;border-bottom:1px solid var(--uc-color-grid)}.kc-tooltip-list{display:grid;grid-template-columns:auto 1fr auto;gap:3px 8px;align-items:center}.kc-tooltip-row{display:contents}.kc-tooltip-chip{width:8px;height:8px;border-radius:2px}.kc-tooltip-name{white-space:nowrap}.kc-tooltip-value{font-family:var(--uc-font-mono);text-align:right;white-space:nowrap}@media(prefers-reduced-motion:reduce){.kc-tooltip{transition:none}}.kc-measure{position:absolute;top:0;left:0;right:auto;bottom:auto;transform:none;visibility:hidden;pointer-events:none;white-space:pre;writing-mode:horizontal-tb}.kc-limit-label{position:absolute;font-size:var(--uc-size-tick);line-height:1.25;white-space:nowrap;font-variant-numeric:tabular-nums;background:var(--uc-color-bg);padding:0 2px}.kc-limit-label[data-severity=warning]{color:var(--uc-color-warning)}.kc-limit-label[data-severity=alarm]{color:var(--uc-color-alarm)}.kc-limit-label[data-role=control],.kc-limit-label[data-role=zone]{color:var(--uc-color-text)}.kc-axis-y .kc-limit-label{transform:translateY(-50%)}.kc-axis-left .kc-limit-label{right:9px}.kc-axis-right .kc-limit-label{left:9px}.kc-break{position:absolute;top:0;width:7px;height:9px;margin-left:-3.5px;color:var(--uc-color-text)}.kc-break:before,.kc-break:after{content:"";position:absolute;top:0;width:1px;height:9px;background:currentColor;opacity:.55;transform:skew(-20deg)}.kc-break:before{left:1px}.kc-break:after{left:4px}