@lilt-ui/charts 0.2.0 → 0.3.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 +26 -0
- package/README.md +45 -0
- package/dist/cards/area-chart-card.d.ts +10 -1
- package/dist/cards/cartesian-card.d.ts +35 -6
- package/dist/cards/chart-card.d.ts +12 -1
- package/dist/cards/line-chart-card.d.ts +10 -1
- package/dist/{cartesian-card-BDZs0v6E.js → cartesian-card-Dcd0ZnQL.js} +2745 -2976
- package/dist/chart.d.ts +1 -1
- package/dist/finance/cards/depth-chart-card.d.ts +2 -2
- package/dist/finance.js +220 -219
- package/dist/index.d.ts +5 -4
- package/dist/index.js +1635 -1631
- package/dist/interaction/axis-cursor.d.ts +12 -2
- package/dist/interaction/chart-sync.d.ts +11 -1
- package/dist/interaction/inspection-layer.d.ts +6 -0
- package/dist/interaction/pin-glyphs.d.ts +8 -0
- package/dist/interaction/pin-marker.d.ts +9 -1
- package/dist/model/cartesian-model.d.ts +3 -3
- package/dist/primitives/axis-segments.d.ts +23 -0
- package/dist/report-context-Cz0AYdV2.js +895 -0
- package/dist/styles.css +1 -1
- package/dist/types.d.ts +34 -3
- package/dist/watch/board/board-state.d.ts +74 -0
- package/dist/watch/board/board-toast.d.ts +19 -0
- package/dist/watch/board/chart-board.d.ts +97 -0
- package/dist/watch/board/report-context.d.ts +3 -0
- package/dist/watch/engine/describe.d.ts +9 -0
- package/dist/watch/engine/explain.d.ts +48 -0
- package/dist/watch/engine/normal.d.ts +114 -0
- package/dist/watch/engine/robust.d.ts +7 -0
- package/dist/watch/engine/rules.d.ts +22 -0
- package/dist/watch/engine/status.d.ts +39 -0
- package/dist/watch/index.d.ts +14 -0
- package/dist/watch/normal-layer.d.ts +18 -0
- package/dist/watch.d.ts +2 -0
- package/dist/watch.js +628 -0
- package/package.json +6 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
Charts that know what normal looks like, dashboards that arrange themselves around what needs attention, pins shared across linked charts, and segmented axes.
|
|
6
|
+
|
|
7
|
+
### Watch
|
|
8
|
+
|
|
9
|
+
- `normal` on Line and unstacked Area cards watches one series. Layers are off unless set: `limits`, `around` another series with a `tolerance`, `learn` from its own history by `week`, `day`, or `all`, `given` similar conditions, `when` to skip rows such as maintenance, `rules` across series, and `history` to learn from rows the card does not draw.
|
|
10
|
+
- The card draws the normal band, recolors unusual stretches, keeps limits on screen, and says "Unusually low since Tue 2 PM". With `breakdown`, an unusual reading says which segment caused it: "98% of the drop is Mobile Safari".
|
|
11
|
+
- `onNormalChange` reports whether the series is unusual, how badly, why, and since when.
|
|
12
|
+
- `ChartBoard` and `BoardItem`, from `@lilt-ui/charts/watch`, rank cards by what needs attention. Each card carries its state in its glass tab and on its edge: Needs attention with Acknowledge, Seen, Back to normal, or Pinned. Nothing moves while the viewer points at or works inside the board.
|
|
13
|
+
- `toast` alerts the viewer to cards that turn unusual off screen, with View; `memory` marks incidents new since the last visit; `onEvent` and its `show()` feed your own alerts.
|
|
14
|
+
- The engine is exported for custom UI: `evaluateNormal`, `trackNormalStatus`, `explainReadings`, `explainDeviation`, `describeFlag`, `describeExplanation`, `flatline`, `jump`, `boardReducer`, and `rankBoard`.
|
|
15
|
+
- `CardFrameContext` lets a container give the card inside it a tab, an edge tone, and a handle.
|
|
16
|
+
|
|
17
|
+
### Axes
|
|
18
|
+
|
|
19
|
+
- `axis="segmented"` draws rounded segments between ticks instead of one continuous line, with y labels beside them; the segment under the pointer lights up.
|
|
20
|
+
- `axis` takes one preset per axis, e.g. `{ x: 'minimal', y: 'segmented' }`; an axis left out is `minimal`.
|
|
21
|
+
- A segmented axis takes a `gradient` to read as a range: `true` fades the first series' color from faint to full, or pass colors low to high, e.g. `['var(--lilt-positive)', 'var(--lilt-negative)']`.
|
|
22
|
+
|
|
23
|
+
### Pins
|
|
24
|
+
|
|
25
|
+
- A click on a linked card pins every card in its `sync` group. The clicked card shows the pin, the others show a ghost of it that names where it came from, and any of them releases it.
|
|
26
|
+
- Alt-click (Option-click) pins one card only, and Alt+Enter does the same from the keyboard; linked cards keep following the pointer. `model.actions.pin(x, { local: true })` does it in code.
|
|
27
|
+
- Pins travel between points with the crosshair's quick spring, and the pin glyph sits centered in its marker.
|
|
28
|
+
|
|
3
29
|
## 0.2.0
|
|
4
30
|
|
|
5
31
|
Finance charts, range charts, and series that carry more than one value.
|
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
<a href="https://liltui.vercel.app"><strong>Documentation</strong></a> ·
|
|
16
16
|
<a href="https://liltui.vercel.app/charts/area">Charts</a> ·
|
|
17
17
|
<a href="https://liltui.vercel.app/finance/candlestick">Finance</a> ·
|
|
18
|
+
<a href="https://liltui.vercel.app/watch">Watch</a> ·
|
|
18
19
|
<a href="https://liltui.vercel.app/llms.txt">llms.txt</a>
|
|
19
20
|
</p>
|
|
20
21
|
|
|
@@ -142,12 +143,56 @@ export function MarketCard() {
|
|
|
142
143
|
|
|
143
144
|
Candles draw into a handful of paths however many there are, so years of daily history stay fast. `scale="log"` spaces long histories by ratio, and `live` follows new rows as they arrive. The indicator math (`sma`, `ema`, `rsi`, `macd`, `bollinger`, `drawdown`, `depthLevels`) is exported too, for your own layouts.
|
|
144
145
|
|
|
146
|
+
## Watch
|
|
147
|
+
|
|
148
|
+
Tell a chart what normal looks like, and it says when something isn't:
|
|
149
|
+
|
|
150
|
+
```tsx
|
|
151
|
+
<LineChartCard
|
|
152
|
+
title="Orders"
|
|
153
|
+
data={lastTwoDays}
|
|
154
|
+
x="hour"
|
|
155
|
+
series={[{ key: 'orders' }]}
|
|
156
|
+
normal={{
|
|
157
|
+
history: earlierWeeks, // learn from weeks you don't draw
|
|
158
|
+
learn: 'week', // same hour, same weekday
|
|
159
|
+
limits: { min: 10 }, // a line you set
|
|
160
|
+
when: (hour) => !hour.maintenance, // never judge downtime
|
|
161
|
+
breakdown: (hour) => hour.devices, // say which device caused it
|
|
162
|
+
}}
|
|
163
|
+
/>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
The card draws a calm band where the series should be, recolors unusual stretches, and says "Unusually low since Tue 2 PM". Hover an unusual reading and it says why: "98% of the drop is Mobile Safari". Every layer is off until you set it.
|
|
167
|
+
|
|
168
|
+
Wrap cards in a board and the dashboard arranges itself around what needs attention:
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
import { BoardItem, ChartBoard } from '@lilt-ui/charts/watch';
|
|
172
|
+
|
|
173
|
+
<ChartBoard aria-label="Store health" toast>
|
|
174
|
+
<BoardItem id="orders" title="Orders">
|
|
175
|
+
<AreaChartCard
|
|
176
|
+
title="Orders"
|
|
177
|
+
data={rows}
|
|
178
|
+
x="hour"
|
|
179
|
+
series={[{ key: 'orders' }]}
|
|
180
|
+
normal={{ learn: 'week' }}
|
|
181
|
+
/>
|
|
182
|
+
</BoardItem>
|
|
183
|
+
{/* …more cards */}
|
|
184
|
+
</ChartBoard>;
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Cards that need attention rise, what you've seen calms down, and what clears settles back. Nothing moves while you're reading, and a toast finds you when something breaks off screen.
|
|
188
|
+
|
|
145
189
|
## Built in, one prop away
|
|
146
190
|
|
|
147
191
|
- **Linked hover.** Give cards the same `sync` name and they read the same moment together.
|
|
148
192
|
- **Targets and forecasts.** `target` draws a goal line and counts the points that reach it. `forecast` marks projected rows and keeps them out of the headline.
|
|
149
193
|
- **Pin and compare.** Click to pin a point. Add `compare` and drag across a chart to see what changed.
|
|
150
194
|
- **Honest data.** `null` is a gap, never a zero, and missing values say so.
|
|
195
|
+
- **Watch.** `normal` flags what's unusual and says why; a `ChartBoard` raises what needs attention.
|
|
151
196
|
- **Calm by default.** Keyboard navigation, screen reader labels, and motion that respects reduced-motion settings.
|
|
152
197
|
|
|
153
198
|
## Fits your design system
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ReactElement } from 'react';
|
|
2
|
-
import { CartesianCardProps } from './cartesian-card';
|
|
2
|
+
import { CardNormal, CartesianCardProps } from './cartesian-card';
|
|
3
3
|
import { NumericKey } from './keys';
|
|
4
|
+
import { NormalReport } from '../watch/board/board-state';
|
|
4
5
|
export type { CardRange, CardSeries } from './cartesian-card';
|
|
5
6
|
export interface AreaChartCardProps<Row, Key extends NumericKey<Row>> extends CartesianCardProps<Row, Key> {
|
|
6
7
|
/**
|
|
@@ -11,6 +12,14 @@ export interface AreaChartCardProps<Row, Key extends NumericKey<Row>> extends Ca
|
|
|
11
12
|
stack?: boolean | 'percent';
|
|
12
13
|
/** `smooth` uses a monotone curve; `linear` draws straight segments. */
|
|
13
14
|
curve?: 'smooth' | 'linear';
|
|
15
|
+
/**
|
|
16
|
+
* Watch one series against what is normal for it: a calm band where it is expected, a ring on
|
|
17
|
+
* each unusual reading, and a header note while it stays unusual. Every layer is off unless
|
|
18
|
+
* set. Unstacked cards only.
|
|
19
|
+
*/
|
|
20
|
+
normal?: CardNormal<Row, NoInfer<Key>>;
|
|
21
|
+
/** Called when the watched series' status changes, such as when an incident starts or clears. */
|
|
22
|
+
onNormalChange?: (report: NormalReport | null) => void;
|
|
14
23
|
}
|
|
15
24
|
/**
|
|
16
25
|
* A complete area chart card: headline, delta, period, plot, and value tiles.
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { CSSProperties, ReactElement, ReactNode } from 'react';
|
|
2
|
-
import { ChartController, ChartMargins, ChartTooltipContext, NumericXConfig, TimeXConfig,
|
|
2
|
+
import { ChartController, ChartMargins, ChartTooltipContext, NumericXConfig, TimeXConfig, ChartAxis, ChartBarAppearance, ChartBackground, ChartCurve, ChartMotion, ChartPalette, ChartHoverReadout, ChartHoverStyle, ChartSeries, ChartTooltipIndicator, ChartStyle, ChartSurface } from '../types';
|
|
3
3
|
import { NumericKey, ResolvedX, XKey, XKind } from './keys';
|
|
4
4
|
import { CardAggregate } from './format';
|
|
5
5
|
import { AnimatedNumberVariant } from '../motion/animated-number';
|
|
6
|
+
import { NormalSpec } from '../watch/engine/normal';
|
|
7
|
+
import { NormalBreakdown } from '../watch/engine/explain';
|
|
8
|
+
import { NormalReport } from '../watch/board/board-state';
|
|
6
9
|
export interface CardSeries<Key extends string> {
|
|
7
10
|
/** A numeric field of each row. */
|
|
8
11
|
key: Key;
|
|
@@ -31,6 +34,24 @@ export interface CardForecast<Row> {
|
|
|
31
34
|
/** Names the projected region and the hover caption. Defaults to "Forecast". */
|
|
32
35
|
label?: string;
|
|
33
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* What normal looks like for one series of a line or unstacked area card. Every layer is off
|
|
39
|
+
* unless set; see `NormalSpec`. Projected rows are never judged.
|
|
40
|
+
*/
|
|
41
|
+
export interface CardNormal<Row, Key extends string = string> extends NormalSpec<Row> {
|
|
42
|
+
/** The watched series. Defaults to the headline series, then the first solid series. */
|
|
43
|
+
series?: Key;
|
|
44
|
+
/**
|
|
45
|
+
* Earlier rows to learn from without drawing them, such as the weeks before the day on screen.
|
|
46
|
+
* They come before `data`, in the same shape.
|
|
47
|
+
*/
|
|
48
|
+
history?: readonly Row[];
|
|
49
|
+
/**
|
|
50
|
+
* Split a reading into the segments that add up to it, such as orders by device, so an unusual
|
|
51
|
+
* reading can say which segment caused it: "91% of the drop is Mobile Safari".
|
|
52
|
+
*/
|
|
53
|
+
breakdown?: NormalBreakdown<Row>;
|
|
54
|
+
}
|
|
34
55
|
export interface CardRange<Row> {
|
|
35
56
|
id: string;
|
|
36
57
|
label: string;
|
|
@@ -76,8 +97,11 @@ export interface CartesianCardProps<Row, Key extends NumericKey<Row>> {
|
|
|
76
97
|
formatX?: (value: string | number | Date) => string;
|
|
77
98
|
/** Override x inference. Numbers default to `number`; use `time` for timestamps. */
|
|
78
99
|
xType?: XKind;
|
|
79
|
-
/**
|
|
80
|
-
|
|
100
|
+
/**
|
|
101
|
+
* Axis preset: `minimal` (default), `dots`, `inline`, `ruler`, `classic`, or `segmented`, for
|
|
102
|
+
* both axes or one per axis, e.g. `{ x: 'minimal', y: { style: 'segmented', gradient: true } }`.
|
|
103
|
+
*/
|
|
104
|
+
axis?: ChartAxis;
|
|
81
105
|
/** Texture behind the plot: `dots` (default), `grid`, `lines`, or `none`. */
|
|
82
106
|
background?: ChartBackground;
|
|
83
107
|
/** Brighten the background around the hovered point. Defaults to true. */
|
|
@@ -143,7 +167,8 @@ export interface CartesianCardProps<Row, Key extends NumericKey<Row>> {
|
|
|
143
167
|
/**
|
|
144
168
|
* Link hover and pins with every card that uses the same name. Cards match by x: labels
|
|
145
169
|
* exactly, dates and numbers to the nearest row. Every linked card shows its hover marks,
|
|
146
|
-
* pills, and headline at that point
|
|
170
|
+
* pills, and headline at that point. A click pins every linked card: the clicked card shows the
|
|
171
|
+
* pin and the others a ghost of it, and any of them releases it. Alt-click pins one card only.
|
|
147
172
|
*/
|
|
148
173
|
sync?: string;
|
|
149
174
|
loading?: boolean;
|
|
@@ -228,7 +253,7 @@ export interface CardPaneContext<Row> {
|
|
|
228
253
|
/** The main plot's `axisInset` and `slots`, so a pane's observations sit under its own. */
|
|
229
254
|
axisInset: number;
|
|
230
255
|
slots: boolean;
|
|
231
|
-
axis:
|
|
256
|
+
axis: ChartAxis;
|
|
232
257
|
loading: boolean;
|
|
233
258
|
motion?: ChartMotion;
|
|
234
259
|
hoverStyle: ChartHoverStyle;
|
|
@@ -241,7 +266,7 @@ export declare const CARD_PADDING = 20;
|
|
|
241
266
|
* The shared card body: headline, delta, period, plot, and value tiles, with hover sync and
|
|
242
267
|
* range comparison. Area, Line, and Bar cards differ only in their `shape`.
|
|
243
268
|
*/
|
|
244
|
-
export declare function CartesianCard<Row, Key extends NumericKey<Row>>({ shape, title, data: suppliedData, x, series: seriesInput, headline: suppliedHeadline, aggregate: suppliedAggregate, headlineSeries, delta: suppliedDelta, deltaTone, range, ranges, defaultRange, tiles, height, valueFormat, locale, formatValue: suppliedFormatValue, formatAxisValue: suppliedFormatAxisValue, formatX, xType, compare, target: suppliedTarget, forecast, sync, axis, hover, hoverStyle, background, spotlight, surface, badge, numberStyle, palette, bleed, axisInset, pillSeries, pillValue, pillPosition, tooltipIndicator, loading, motion, className, style, panes, live, heading, restCaption, }: Omit<CartesianCardProps<Row, Key>, 'series'> & {
|
|
269
|
+
export declare function CartesianCard<Row, Key extends NumericKey<Row>>({ shape, title, data: suppliedData, x, series: seriesInput, headline: suppliedHeadline, aggregate: suppliedAggregate, headlineSeries, delta: suppliedDelta, deltaTone, range, ranges, defaultRange, tiles, height, valueFormat, locale, formatValue: suppliedFormatValue, formatAxisValue: suppliedFormatAxisValue, formatX, xType, compare, target: suppliedTarget, forecast, sync, axis, hover, hoverStyle, background, spotlight, surface, badge, numberStyle, palette, bleed, axisInset, pillSeries, pillValue, pillPosition, tooltipIndicator, loading, motion, className, style, panes, live, heading, restCaption, normal, onNormalChange, }: Omit<CartesianCardProps<Row, Key>, 'series'> & {
|
|
245
270
|
series: readonly CoreSeries<Key>[];
|
|
246
271
|
shape: CardShape;
|
|
247
272
|
/** Linked panes under the plot, such as volume or indicators. */
|
|
@@ -252,6 +277,10 @@ export declare function CartesianCard<Row, Key extends NumericKey<Row>>({ shape,
|
|
|
252
277
|
heading?: ReactNode;
|
|
253
278
|
/** Text beside the delta at rest, such as an absolute change, from the active data. */
|
|
254
279
|
restCaption?: (data: readonly Row[]) => ReactNode;
|
|
280
|
+
/** Watch one series against its normal. Line and unstacked area cards only. */
|
|
281
|
+
normal?: CardNormal<Row, NoInfer<Key>>;
|
|
282
|
+
/** Called when the watched series' status changes. */
|
|
283
|
+
onNormalChange?: (report: NormalReport | null) => void;
|
|
255
284
|
}): ReactElement;
|
|
256
285
|
/** The plot position where projections begin: a label's row, or the date or number itself. */
|
|
257
286
|
export declare function forecastPosition<Row>(data: readonly Row[], x: string, resolved: ResolvedX<Row>, from: string | number): number | null;
|
|
@@ -20,8 +20,19 @@ export interface ChartCardProps {
|
|
|
20
20
|
style?: CSSProperties | ChartStyle;
|
|
21
21
|
'aria-label'?: string;
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* What a container such as a watch board adds to the card directly inside it: a tab that takes
|
|
25
|
+
* the badge's place, a tone for the card's edge, and a control that floats on the top edge.
|
|
26
|
+
*/
|
|
27
|
+
export interface CardFrame {
|
|
28
|
+
badge?: ReactNode;
|
|
29
|
+
tone?: 'warning' | 'critical' | null;
|
|
30
|
+
handle?: ReactNode;
|
|
31
|
+
}
|
|
32
|
+
/** Set by a container around one card. Cards nested inside that card do not see it. */
|
|
33
|
+
export declare const CardFrameContext: import('react').Context<CardFrame | null>;
|
|
23
34
|
/** The card surface every Lilt card shares: padding, radius, border, and theme tokens. */
|
|
24
|
-
export declare function ChartCard({ children, surface, palette, motion, numberStyle, badge, className, style, 'aria-label': ariaLabel, }: ChartCardProps): ReactElement;
|
|
35
|
+
export declare function ChartCard({ children, surface, palette, motion, numberStyle, badge: ownBadge, className, style, 'aria-label': ariaLabel, }: ChartCardProps): ReactElement;
|
|
25
36
|
export interface CardBadgeProps {
|
|
26
37
|
children?: ReactNode;
|
|
27
38
|
className?: string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ReactElement } from 'react';
|
|
2
|
-
import { CartesianCardProps } from './cartesian-card';
|
|
2
|
+
import { CardNormal, CartesianCardProps } from './cartesian-card';
|
|
3
3
|
import { NumericKey } from './keys';
|
|
4
|
+
import { NormalReport } from '../watch/board/board-state';
|
|
4
5
|
export interface LineChartCardProps<Row, Key extends NumericKey<Row>> extends CartesianCardProps<Row, Key> {
|
|
5
6
|
/** `smooth` uses a monotone curve, `linear` straight segments, `step` holds each value flat. */
|
|
6
7
|
curve?: 'smooth' | 'linear' | 'step';
|
|
@@ -11,6 +12,14 @@ export interface LineChartCardProps<Row, Key extends NumericKey<Row>> extends Ca
|
|
|
11
12
|
* zero when the absolute level matters.
|
|
12
13
|
*/
|
|
13
14
|
baseline?: 'auto' | 'zero';
|
|
15
|
+
/**
|
|
16
|
+
* Watch one series against what is normal for it: a calm band where it is expected, a ring on
|
|
17
|
+
* each unusual reading, and a header note while it stays unusual. Every layer is off unless
|
|
18
|
+
* set. Unstacked cards only.
|
|
19
|
+
*/
|
|
20
|
+
normal?: CardNormal<Row, NoInfer<Key>>;
|
|
21
|
+
/** Called when the watched series' status changes, such as when an incident starts or clears. */
|
|
22
|
+
onNormalChange?: (report: NormalReport | null) => void;
|
|
14
23
|
}
|
|
15
24
|
/**
|
|
16
25
|
* A complete line chart card: headline, delta, period, plot, and value tiles.
|