@lilt-ui/charts 0.1.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.
Files changed (68) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/README.md +120 -0
  3. package/dist/analysis-BJRmXHOB.js +62 -0
  4. package/dist/cards/area-chart-card.d.ts +10 -1
  5. package/dist/cards/box-plot-card.d.ts +30 -0
  6. package/dist/cards/cartesian-card.d.ts +86 -6
  7. package/dist/cards/chart-card.d.ts +12 -1
  8. package/dist/cards/line-chart-card.d.ts +10 -1
  9. package/dist/cards/range-chart-card.d.ts +28 -0
  10. package/dist/cartesian-card-Dcd0ZnQL.js +7004 -0
  11. package/dist/chart-context.d.ts +18 -0
  12. package/dist/chart-data-CCwLQeXa.js +44 -0
  13. package/dist/chart.d.ts +3 -1
  14. package/dist/data.js +3 -2
  15. package/dist/engine/box.d.ts +18 -0
  16. package/dist/engine/domains.d.ts +2 -0
  17. package/dist/engine/geometry.d.ts +2 -1
  18. package/dist/engine/normalize.d.ts +2 -4
  19. package/dist/engine/ranges.d.ts +59 -0
  20. package/dist/finance/candle-geometry.d.ts +55 -0
  21. package/dist/finance/candles.d.ts +18 -0
  22. package/dist/finance/cards/candlestick-chart-card.d.ts +41 -0
  23. package/dist/finance/cards/depth-chart-card.d.ts +32 -0
  24. package/dist/finance/cards/indicator-chart-card.d.ts +52 -0
  25. package/dist/finance/cards/pane.d.ts +24 -0
  26. package/dist/finance/cards/portfolio-chart-card.d.ts +22 -0
  27. package/dist/finance/cards/price-chart-card.d.ts +27 -0
  28. package/dist/finance/index.d.ts +17 -0
  29. package/dist/finance/indicators.d.ts +65 -0
  30. package/dist/finance/order-book.d.ts +26 -0
  31. package/dist/finance.d.ts +2 -0
  32. package/dist/finance.js +1158 -0
  33. package/dist/index.d.ts +14 -4
  34. package/dist/index.js +2239 -8793
  35. package/dist/interaction/axis-cursor.d.ts +12 -2
  36. package/dist/interaction/chart-sync.d.ts +11 -1
  37. package/dist/interaction/field-values.d.ts +12 -0
  38. package/dist/interaction/inspection-layer.d.ts +10 -1
  39. package/dist/interaction/pin-glyphs.d.ts +8 -0
  40. package/dist/interaction/pin-marker.d.ts +9 -1
  41. package/dist/marks/contract.d.ts +49 -0
  42. package/dist/marks/use-range-mark.d.ts +19 -0
  43. package/dist/model/cartesian-model.d.ts +3 -3
  44. package/dist/primitives/annotations.d.ts +1 -1
  45. package/dist/primitives/axis-segments.d.ts +23 -0
  46. package/dist/primitives/box-plot.d.ts +4 -0
  47. package/dist/primitives/error-bar.d.ts +4 -0
  48. package/dist/primitives/interval-band.d.ts +2 -2
  49. package/dist/primitives/range-bar.d.ts +4 -0
  50. package/dist/report-context-Cz0AYdV2.js +895 -0
  51. package/dist/styles.css +1 -1
  52. package/dist/types.d.ts +114 -16
  53. package/dist/watch/board/board-state.d.ts +74 -0
  54. package/dist/watch/board/board-toast.d.ts +19 -0
  55. package/dist/watch/board/chart-board.d.ts +97 -0
  56. package/dist/watch/board/report-context.d.ts +3 -0
  57. package/dist/watch/engine/describe.d.ts +9 -0
  58. package/dist/watch/engine/explain.d.ts +48 -0
  59. package/dist/watch/engine/normal.d.ts +114 -0
  60. package/dist/watch/engine/robust.d.ts +7 -0
  61. package/dist/watch/engine/rules.d.ts +22 -0
  62. package/dist/watch/engine/status.d.ts +39 -0
  63. package/dist/watch/index.d.ts +14 -0
  64. package/dist/watch/normal-layer.d.ts +18 -0
  65. package/dist/watch.d.ts +2 -0
  66. package/dist/watch.js +628 -0
  67. package/package.json +16 -2
  68. package/dist/analysis-BLLWEKBw.js +0 -105
@@ -20,6 +20,13 @@ export interface PlotArrangement {
20
20
  series: readonly string[];
21
21
  mode: StackMode;
22
22
  } | null;
23
+ /**
24
+ * Series drawn by column marks such as candles or range bars: each observation takes a
25
+ * bar-like slot, so the plot insets its edges like a bar chart.
26
+ */
27
+ columns?: readonly string[];
28
+ /** Slot every observation like a bar even when nothing is drawn as one. */
29
+ slots?: boolean;
23
30
  }
24
31
  export declare const LINE_ARRANGEMENT: PlotArrangement;
25
32
  export interface ChartSnapshot<T> {
@@ -39,6 +46,12 @@ export interface ChartSnapshot<T> {
39
46
  yTicks: readonly number[];
40
47
  xToPixel: (value: number) => number;
41
48
  yToPixel: (value: number) => number;
49
+ /** Maps a value in a series' own unit, following `scale: 'secondary'`. */
50
+ yToPixelFor: (seriesId: string) => (value: number) => number;
51
+ /** Width of one observation's column in pixels, for bars and column marks. */
52
+ columnWidth: number;
53
+ /** Series drawn by column marks. */
54
+ columns: readonly string[];
42
55
  geometry: PlotGeometry | null;
43
56
  plot: PlotBox;
44
57
  formatX: (value: number) => string;
@@ -96,6 +109,11 @@ export declare function makeAxisTicks(snapshot: ChartSnapshot<unknown>, previous
96
109
  x: AxisTick[];
97
110
  y: AxisTick[];
98
111
  };
112
+ /**
113
+ * Log ticks on 1, 2 and 5 times powers of ten when the domain spans decades; within a narrow
114
+ * range, evenly spaced round values read better, so those come from a linear scale.
115
+ */
116
+ export declare function logTicks(domain: readonly [number, number], count: number): number[];
99
117
  export declare function buildSnapshot<T>(data: NormalizedData<T>, series: readonly ChartSeries<T>[], xConfig: ChartXConfig<T>, yConfig: ChartYConfig, margins: ChartMargins, width: number, height: number, yDomainOverride?: readonly [number, number] | null, xDomainOverride?: readonly [number, number] | null, geometrySeries?: readonly ChartSeries<T>[], arrangement?: PlotArrangement, stackWeights?: Readonly<Record<string, number>>, barLayout?: ChartBarLayout,
100
118
  /** Keeps line and area observations off the plot edges so labels can center on them. */
101
119
  edgeInset?: number): ChartSnapshot<T>;
@@ -0,0 +1,44 @@
1
+ //#region src/data/chart-data.ts
2
+ function e(e, t) {
3
+ let n = t.range;
4
+ if (n && (!Number.isFinite(n.startX) || !Number.isFinite(n.endX))) throw Error("Range bounds must be finite.");
5
+ let r = n ? Math.min(n.startX, n.endX) : -Infinity, i = n ? Math.max(n.startX, n.endX) : Infinity, a = 0, o = 0, s = 0, c = Infinity, l = -Infinity, u = Infinity, d = -Infinity, f = null, p = null, m = /* @__PURE__ */ new Set();
6
+ for (let n of e) {
7
+ let e = Number(t.x(n));
8
+ if (!Number.isFinite(e)) throw Error("Summary positions must be finite numbers or valid dates.");
9
+ if (e < r || e > i) continue;
10
+ if (m.has(e)) throw Error("Summary positions must be unique.");
11
+ m.add(e);
12
+ let h = t.value(n);
13
+ if (h !== null && (typeof h != "number" || !Number.isFinite(h))) throw Error("Summary values must be finite numbers or null.");
14
+ if (e < u && (u = e, f = h), e > d && (d = e, p = h), h === null) {
15
+ o++;
16
+ continue;
17
+ }
18
+ a++, s += h, c = Math.min(c, h), l = Math.max(l, h);
19
+ }
20
+ if (!Number.isFinite(s)) throw Error("Summary total exceeds the finite numeric range.");
21
+ return {
22
+ count: a,
23
+ missing: o,
24
+ total: a ? s : null,
25
+ mean: a ? s / a : null,
26
+ min: a ? c : null,
27
+ max: a ? l : null,
28
+ first: f,
29
+ last: p,
30
+ change: f === null || p === null ? null : p - f
31
+ };
32
+ }
33
+ function t(e, t) {
34
+ if (!t.length) throw Error("CSV needs at least one column.");
35
+ let n = (e) => {
36
+ if (typeof e == "number" && !Number.isFinite(e)) throw Error("CSV numbers must be finite.");
37
+ if (e instanceof Date && !Number.isFinite(e.getTime())) throw Error("CSV dates must be valid.");
38
+ let t = e === null ? "" : e instanceof Date ? e.toISOString() : String(e);
39
+ return typeof e == "string" && /^[\s]*[=+\-@]|^[\t\r\n]/.test(t) && (t = "'" + t), /[",\r\n]/.test(t) ? `"${t.replaceAll("\"", "\"\"")}"` : t;
40
+ };
41
+ return [t.map((e) => n(e.header)).join(","), ...e.map((e) => t.map((t) => n(t.value(e))).join(","))].join("\r\n") + "\r\n";
42
+ }
43
+ //#endregion
44
+ export { t as n, e as t };
package/dist/chart.d.ts CHANGED
@@ -1,10 +1,12 @@
1
1
  import { ReactElement, ReactNode } from 'react';
2
2
  import { PlotArrangement } from './chart-context';
3
+ import { PlotMark } from './marks/contract';
3
4
  import { ChartBarLayout, ChartPlotProps, ChartProps } from './types';
4
5
  import { ToolkitStore } from './runtime/chart-runtime';
5
6
  import { CartesianChartModel } from './model/cartesian-model';
6
7
  type ChartPlotRendererProps<T> = Omit<ChartProps<T>, 'className' | 'style'> & Omit<ChartPlotProps, 'bars' | 'stack' | 'tooltip'> & {
7
8
  arrangement?: PlotArrangement;
9
+ marks?: readonly PlotMark[];
8
10
  barLayout?: ChartBarLayout;
9
11
  selectedCategoryId?: string | null;
10
12
  onSelectedCategoryIdChange?: (id: string | null) => void;
@@ -13,5 +15,5 @@ type ChartPlotRendererProps<T> = Omit<ChartProps<T>, 'className' | 'style'> & Om
13
15
  controllerLinked?: boolean;
14
16
  tooltipNode?: ReactNode;
15
17
  };
16
- export declare function ChartPlotRenderer<T>({ data, x, y, series, height, compactHeight, margins: marginProps, arrangement, barLayout: barsProps, compact, tooltipNode, inspectionSeries: plotInspectionSeries, className, style, 'aria-label': ariaLabel, children, status, interactive, error, renderRetry, motion: motionPreference, animateIn, resetKey, onSelectionChange, controller, linkedSelection, selectedCategoryId, onSelectedCategoryIdChange, compare, focus, live, brush, visibleSeries, onVisibleSeriesChange, toolkit, model, controllerLinked, axis: axisStyle, pill, pillSeries, pillValue, pillPosition, axisInset, runoff, labelOverhang, }: ChartPlotRendererProps<T>): ReactElement;
18
+ export declare function ChartPlotRenderer<T>({ data, x, y, series, height, compactHeight, margins: marginProps, arrangement, marks, barLayout: barsProps, compact, tooltipNode, inspectionSeries: plotInspectionSeries, className, style, 'aria-label': ariaLabel, children, status, interactive, error, renderRetry, motion: motionPreference, animateIn, resetKey, onSelectionChange, controller, linkedSelection, selectedCategoryId, onSelectedCategoryIdChange, compare, focus, live, brush, visibleSeries, onVisibleSeriesChange, toolkit, model, controllerLinked, axis: axisProp, pill, pillSeries, pillValue, pillPosition, axisInset, runoff, labelOverhang, }: ChartPlotRendererProps<T>): ReactElement;
17
19
  export {};
package/dist/data.js CHANGED
@@ -1,2 +1,3 @@
1
- import { o as e, s as t, t as n } from "./analysis-BLLWEKBw.js";
2
- export { n as summarizeFunnelStages, e as summarizeRange, t as toChartCsv };
1
+ import { n as e, t } from "./chart-data-CCwLQeXa.js";
2
+ import { t as n } from "./analysis-BJRmXHOB.js";
3
+ export { n as summarizeFunnelStages, t as summarizeRange, e as toChartCsv };
@@ -0,0 +1,18 @@
1
+ export interface BoxSummary {
2
+ /** Lowest sample within 1.5 × IQR below the first quartile: the lower whisker. */
3
+ min: number;
4
+ q1: number;
5
+ median: number;
6
+ q3: number;
7
+ /** Highest sample within 1.5 × IQR above the third quartile: the upper whisker. */
8
+ max: number;
9
+ /** Samples beyond the whiskers, ascending. */
10
+ outliers: number[];
11
+ count: number;
12
+ }
13
+ /**
14
+ * Quartiles with Tukey whiskers: each whisker reaches the furthest sample within 1.5 times the
15
+ * interquartile range, and anything beyond is an outlier. Non-finite samples are ignored;
16
+ * returns null when none remain.
17
+ */
18
+ export declare function summarizeBox(samples: readonly number[]): BoxSummary | null;
@@ -1,5 +1,7 @@
1
1
  import { ChartSeries, ChartYConfig } from '../types';
2
2
  import { NormalizedData } from './normalize';
3
+ /** A row's finite companion values for one series; fields share the series' unit. */
4
+ export declare function fieldValues(fields: Readonly<Record<string, number | null>> | undefined): number[];
3
5
  export declare function computeYDomain<T>(data: NormalizedData<T>, series: readonly ChartSeries<T>[], config?: ChartYConfig): readonly [number, number];
4
6
  export declare function interpolateDomain(from: readonly [number, number], to: readonly [number, number], progress: number): readonly [number, number];
5
7
  /** The smallest of 1, 2, 2.5, 5 × 10ⁿ at or above `value`. */
@@ -37,7 +37,6 @@ export interface SeriesGeometry {
37
37
  export interface PlotGeometry {
38
38
  series: Readonly<Record<string, SeriesGeometry>>;
39
39
  bars: Readonly<Record<string, readonly BarGeometry[]>>;
40
- bands: Readonly<Record<string, readonly string[]>>;
41
40
  baselineY: number;
42
41
  }
43
42
  /** Series that stack, in chart series order, and how their layers are drawn. */
@@ -68,6 +67,8 @@ export interface GeometryBuildOptions<T> {
68
67
  stack?: GeometryStack;
69
68
  /** Series plotted against their own value scale, e.g. a rate line over revenue bars. */
70
69
  yDomainBySeries?: Readonly<Record<string, readonly [number, number]>>;
70
+ /** Map values on a logarithmic scale; every plotted value is positive. */
71
+ yLog?: boolean;
71
72
  }
72
73
  export declare function buildGeometry<T>(data: NormalizedData<T>, options: GeometryBuildOptions<T>): PlotGeometry;
73
74
  export declare function pointAtX(geometry: SeriesGeometry, x: number): ScreenPoint | null;
@@ -6,10 +6,8 @@ export interface NormalizedRow<T> {
6
6
  categoryId?: string;
7
7
  values: Readonly<Record<string, number | null>>;
8
8
  statuses: Readonly<Record<string, ChartObservationStatus>>;
9
- intervals: Readonly<Record<string, {
10
- lower: number;
11
- upper: number;
12
- } | null>>;
9
+ /** Companion field values by series ID, then field ID. Series without fields map to {}. */
10
+ fields: Readonly<Record<string, Readonly<Record<string, number | null>>>>;
13
11
  }
14
12
  export interface NormalizedData<T> {
15
13
  rows: readonly NormalizedRow<T>[];
@@ -0,0 +1,59 @@
1
+ import { NormalizedRow } from './normalize';
2
+ /** Pixel mappings a range mark draws with. */
3
+ export interface RangeScales {
4
+ x: (value: number) => number;
5
+ y: (value: number) => number;
6
+ xDomain: readonly [number, number];
7
+ /** Width of one observation's column in pixels. */
8
+ columnWidth: number;
9
+ }
10
+ /**
11
+ * Throws when a present row breaks the order a mark relies on, e.g. low ≤ high. Rows missing
12
+ * any listed value are gaps and skip the check.
13
+ */
14
+ export declare function assertOrdered<T>(mark: string, rows: readonly NormalizedRow<T>[], series: string, ids: readonly (string | {
15
+ value: true;
16
+ })[]): void;
17
+ /** Closed band paths between two fields, split wherever a row lacks either edge. */
18
+ export declare function bandPaths<T>(rows: readonly NormalizedRow<T>[], series: string, lower: string, upper: string, scales: RangeScales): string[];
19
+ /** A rounded rectangle as path data; the radius shrinks to fit. */
20
+ export declare function roundedRect(x: number, y: number, width: number, height: number, radius: number): string;
21
+ /** A dot as path data, so many dots share one path element. */
22
+ export declare function dotPath(x: number, y: number, radius: number): string;
23
+ /** Path data grouped by color, so a mark draws one element per color. */
24
+ export declare class ColorBatches {
25
+ private readonly batches;
26
+ add(color: string, path: string): void;
27
+ entries(): {
28
+ color: string;
29
+ d: string;
30
+ }[];
31
+ }
32
+ /** Column geometry shared by candles and range marks: center and body width per row. */
33
+ export declare function columnFrame(scales: RangeScales): {
34
+ width: number;
35
+ half: number;
36
+ };
37
+ export interface RangeColumn<T> {
38
+ row: NormalizedRow<T>;
39
+ cx: number;
40
+ }
41
+ /** Rows in view with their pixel centers. */
42
+ export declare function columnsInView<T>(rows: readonly NormalizedRow<T>[], scales: RangeScales): RangeColumn<T>[];
43
+ /** One floating bar from low to high. */
44
+ export declare function rangeBarPath(cx: number, low: number, high: number, scales: RangeScales): string;
45
+ /** A whisker from low to high with caps a little narrower than the column. */
46
+ export declare function whiskerPath(cx: number, low: number, high: number, scales: RangeScales): string;
47
+ export interface BoxShape {
48
+ box: string;
49
+ median: string;
50
+ whiskers: string;
51
+ }
52
+ /** A box from q1 to q3 with a median line and capped whiskers to min and max. */
53
+ export declare function boxShape(cx: number, values: {
54
+ min: number;
55
+ q1: number;
56
+ median: number;
57
+ q3: number;
58
+ max: number;
59
+ }, scales: RangeScales): BoxShape;
@@ -0,0 +1,55 @@
1
+ import { NormalizedRow } from '../engine/normalize';
2
+ import { RangeScales } from '../engine/ranges';
3
+ /**
4
+ * How a candle is drawn: a filled `candle`, a `hollow` candle whose rising bodies are outlined
5
+ * so direction reads without color, or `ohlc` bars with an open tick left and a close tick right.
6
+ */
7
+ export type CandleDisplay = 'candle' | 'hollow' | 'ohlc';
8
+ export declare const CANDLE_UP = "var(--lilt-candle-up)";
9
+ export declare const CANDLE_DOWN = "var(--lilt-candle-down)";
10
+ export interface CandleFields {
11
+ open: string;
12
+ high: string;
13
+ low: string;
14
+ }
15
+ export interface Candle {
16
+ open: number;
17
+ high: number;
18
+ low: number;
19
+ close: number;
20
+ /** Close at or above open; a flat candle counts as rising. */
21
+ up: boolean;
22
+ }
23
+ export interface CandlePaths {
24
+ /** Filled bodies, one path per color. */
25
+ bodies: {
26
+ color: string;
27
+ d: string;
28
+ }[];
29
+ /** Outlined bodies of hollow rising candles, one path per color. */
30
+ hollow: {
31
+ color: string;
32
+ d: string;
33
+ }[];
34
+ /** Wicks, and for OHLC bars the whole bar, stroked, one path per color. */
35
+ strokes: {
36
+ color: string;
37
+ d: string;
38
+ }[];
39
+ }
40
+ export declare function candleAt(row: NormalizedRow<unknown>, series: string, fields: CandleFields): Candle | null;
41
+ /** Throws on a candle whose high or low does not contain its open and close. */
42
+ export declare function assertCandles(rows: readonly NormalizedRow<unknown>[], series: string, fields: CandleFields): void;
43
+ interface CandleShape {
44
+ body: string | null;
45
+ hollow: string | null;
46
+ stroke: string;
47
+ }
48
+ /** One candle's geometry. Wicks stop at the body, so a hollow body stays empty. */
49
+ export declare function candleShape(cx: number, candle: Candle, scales: RangeScales, display: CandleDisplay): CandleShape;
50
+ /**
51
+ * Every candle in view batched into a handful of paths: bodies, hollow bodies and strokes,
52
+ * each grouped by color. Thousands of candles stay a few DOM nodes.
53
+ */
54
+ export declare function candlePaths(rows: readonly NormalizedRow<unknown>[], series: string, fields: CandleFields, scales: RangeScales, display: CandleDisplay, colorOf: (row: NormalizedRow<unknown>, candle: Candle) => string): CandlePaths;
55
+ export {};
@@ -0,0 +1,18 @@
1
+ import { ReactElement } from 'react';
2
+ import { CandleDisplay } from './candle-geometry';
3
+ export interface CandlesProps {
4
+ /** The series whose value is each candle's close. */
5
+ series: string;
6
+ /** Field IDs of each candle's open, high and low. */
7
+ open: string;
8
+ high: string;
9
+ low: string;
10
+ /** `candle` (default), `hollow` rising bodies, or `ohlc` bars. */
11
+ display?: CandleDisplay;
12
+ className?: string;
13
+ }
14
+ /**
15
+ * Open-high-low-close candles. The series value is the close; `open`, `high` and `low` name its
16
+ * fields. Every candle in view draws into a few batched paths, so long histories stay fast.
17
+ */
18
+ export declare const Candles: (props: CandlesProps) => ReactElement;
@@ -0,0 +1,41 @@
1
+ import { ReactElement } from 'react';
2
+ import { CartesianCardProps } from '../../cards/cartesian-card';
3
+ import { NumericKey } from '../../cards/keys';
4
+ import { ChartTooltipContext } from '../../types';
5
+ import { CandleDisplay } from '../candle-geometry';
6
+ type SharedProps<Row, Key extends NumericKey<Row>> = Omit<CartesianCardProps<Row, Key>, 'series' | 'headlineSeries' | 'pillSeries' | 'aggregate' | 'target' | 'forecast' | 'bleed' | 'tiles'>;
7
+ export interface CandlestickChartCardProps<Row, Key extends NumericKey<Row>> extends SharedProps<Row, Key> {
8
+ /** Fields holding each period's open, high, low and close. */
9
+ open: Key;
10
+ high: Key;
11
+ low: Key;
12
+ close: Key;
13
+ /** Field holding traded volume, drawn as a linked pane under the price. */
14
+ volume?: Key;
15
+ /**
16
+ * `candle` (default), `hollow` rising bodies, `ohlc` bars, or `area` for the close alone,
17
+ * colored by the period's direction.
18
+ */
19
+ display?: CandleDisplay | 'area';
20
+ /** `log` spaces prices by ratio, for long histories. Defaults to `linear`. */
21
+ scale?: 'linear' | 'log';
22
+ /** Names the price series in hover. Defaults to "Price". */
23
+ label?: string;
24
+ /** Follow the newest candle as rows arrive, with a control to return to it. */
25
+ live?: boolean;
26
+ /** Plot height in pixels. Defaults to 240. */
27
+ height?: number;
28
+ /** Volume pane height in pixels. Defaults to 64. */
29
+ volumeHeight?: number;
30
+ }
31
+ /** Change from the first open to the last close. */
32
+ export declare function periodChange<Row>(data: readonly Row[], open: string, close: string): number | undefined;
33
+ /** A hovered candle's open, high and low, formatted for the headline caption. */
34
+ export declare function describeCandle(format: (value: number) => string): (inspection: ChartTooltipContext) => string | null;
35
+ /**
36
+ * A market chart card: open-high-low-close candles (or an area of the close) with an optional
37
+ * linked volume pane, a headline that follows the hovered candle, and its open, high and low
38
+ * beside the date.
39
+ */
40
+ export declare function CandlestickChartCard<Row, const Key extends NumericKey<Row>>({ open, high, low, close, volume, display, scale, label, live, data, ranges, delta, valueFormat, locale, volumeHeight, ...props }: CandlestickChartCardProps<Row, Key>): ReactElement;
41
+ export {};
@@ -0,0 +1,32 @@
1
+ import { CSSProperties, ReactElement } from 'react';
2
+ import { ChartAxis, ChartBackground, ChartHoverStyle, ChartMotion, ChartStyle, ChartSurface } from '../../types';
3
+ import { AnimatedNumberVariant } from '../../motion/animated-number';
4
+ import { BookLevel } from '../indicators';
5
+ export interface DepthChartCardProps {
6
+ title: string;
7
+ /** Resting buy orders: a price and the size at it. Order does not matter. */
8
+ bids: readonly BookLevel[];
9
+ /** Resting sell orders. */
10
+ asks: readonly BookLevel[];
11
+ /** Price format for the mid, spread and axis, e.g. `{ style: 'currency', currency: 'USD' }`. */
12
+ valueFormat?: Intl.NumberFormatOptions;
13
+ /** Size format for depth. Defaults to compact numbers. */
14
+ sizeFormat?: Intl.NumberFormatOptions;
15
+ locale?: string;
16
+ /** Plot height in pixels. Defaults to 220. */
17
+ height?: number;
18
+ axis?: ChartAxis;
19
+ background?: ChartBackground;
20
+ hoverStyle?: ChartHoverStyle;
21
+ surface?: ChartSurface;
22
+ numberStyle?: AnimatedNumberVariant;
23
+ loading?: boolean;
24
+ motion?: ChartMotion;
25
+ className?: string;
26
+ style?: CSSProperties | ChartStyle;
27
+ }
28
+ /**
29
+ * Order book depth: how much could trade at each price, buying and selling, as stepped areas, with
30
+ * the mid, spread and total depth in the header. Hover reads the size resting at each price.
31
+ */
32
+ export declare function DepthChartCard({ title, bids, asks, valueFormat, sizeFormat, locale, height, axis, background, hoverStyle, surface, numberStyle, loading, motion, className, style, }: DepthChartCardProps): ReactElement;
@@ -0,0 +1,52 @@
1
+ import { ReactElement } from 'react';
2
+ import { CartesianCardProps } from '../../cards/cartesian-card';
3
+ import { NumericKey } from '../../cards/keys';
4
+ import { CandleDisplay } from '../candle-geometry';
5
+ /** A line over the price: a simple or exponential average, or Bollinger bands. */
6
+ export type IndicatorOverlay = 'sma' | 'ema' | 'bollinger' | {
7
+ kind: 'sma' | 'ema';
8
+ period: number;
9
+ } | {
10
+ kind: 'bollinger';
11
+ period?: number;
12
+ deviations?: number;
13
+ };
14
+ /** A linked pane under the price. */
15
+ export type IndicatorPane = 'rsi' | 'macd' | 'volume' | {
16
+ kind: 'rsi';
17
+ period: number;
18
+ } | {
19
+ kind: 'macd';
20
+ fast?: number;
21
+ slow?: number;
22
+ signal?: number;
23
+ };
24
+ type SharedProps<Row, Key extends NumericKey<Row>> = Omit<CartesianCardProps<Row, Key>, 'series' | 'headlineSeries' | 'pillSeries' | 'aggregate' | 'target' | 'forecast' | 'bleed' | 'tiles'>;
25
+ export interface IndicatorChartCardProps<Row, Key extends NumericKey<Row>> extends SharedProps<Row, Key> {
26
+ /** Field holding each period's close; every indicator derives from it. */
27
+ close: Key;
28
+ /** Fields for candles. With all three, the price draws as candles; otherwise as a line. */
29
+ open?: Key;
30
+ high?: Key;
31
+ low?: Key;
32
+ /** Field holding traded volume, for a `volume` pane. */
33
+ volume?: Key;
34
+ /** `candle`, `hollow`, `ohlc`, or `line`. Defaults to candles when open, high and low are set. */
35
+ display?: CandleDisplay | 'line';
36
+ /** Lines drawn over the price. Defaults to none. */
37
+ overlays?: readonly IndicatorOverlay[];
38
+ /** Linked panes under the price, top to bottom. Defaults to RSI then MACD. */
39
+ panes?: readonly IndicatorPane[];
40
+ /** Names the price series in hover. Defaults to "Price". */
41
+ label?: string;
42
+ scale?: 'linear' | 'log';
43
+ live?: boolean;
44
+ /** Height of each indicator pane in pixels. Defaults to 72. */
45
+ paneHeight?: number;
46
+ }
47
+ /**
48
+ * Price with technical indicators: moving averages or Bollinger bands over candles or a line, and
49
+ * RSI, MACD or volume panes below that move together as you hover.
50
+ */
51
+ export declare function IndicatorChartCard<Row, const Key extends NumericKey<Row>>({ close, open, high, low, volume, display: suppliedDisplay, overlays, panes, label, scale, live, data, ranges, delta, valueFormat, locale, paneHeight, ...props }: IndicatorChartCardProps<Row, Key>): ReactElement;
52
+ export {};
@@ -0,0 +1,24 @@
1
+ import { ReactElement, ReactNode } from 'react';
2
+ import { CardPaneContext } from '../../cards/cartesian-card';
3
+ import { ChartBars, ChartSeries, ChartYConfig } from '../../types';
4
+ export interface PaneProps<Row> {
5
+ context: CardPaneContext<Row>;
6
+ /** Names the pane for screen readers and in its corner label. */
7
+ label: string;
8
+ /** Short text in the pane's top-left corner, e.g. "RSI 14". */
9
+ caption?: ReactNode;
10
+ /** Values beside the caption for the hovered row, or the latest row at rest. */
11
+ readout?: (row: Row) => ReactNode;
12
+ series: readonly ChartSeries<Row>[];
13
+ height: number;
14
+ y?: ChartYConfig;
15
+ bars?: ChartBars;
16
+ /** Label the x axis under this pane; only the lowest pane should. */
17
+ xAxis?: boolean;
18
+ children: ReactNode;
19
+ }
20
+ /**
21
+ * A plot under a card's main plot, sharing its data, x, margins, and crosshair, so hover in any
22
+ * pane reads the same observation in all of them.
23
+ */
24
+ export declare function Pane<Row>({ context, label, caption, readout, series, height, y, bars, xAxis, children, }: PaneProps<Row>): ReactElement;
@@ -0,0 +1,22 @@
1
+ import { ReactElement } from 'react';
2
+ import { CartesianCardProps } from '../../cards/cartesian-card';
3
+ import { NumericKey } from '../../cards/keys';
4
+ type SharedProps<Row, Key extends NumericKey<Row>> = Omit<CartesianCardProps<Row, Key>, 'series' | 'headlineSeries' | 'pillSeries' | 'aggregate' | 'target' | 'forecast' | 'tiles'>;
5
+ export interface PortfolioChartCardProps<Row, Key extends NumericKey<Row>> extends SharedProps<Row, Key> {
6
+ /** Field holding the account's value. */
7
+ value: Key;
8
+ /** Field holding the cost basis: what went in. Drawn as a stepped dashed line. */
9
+ basis?: Key;
10
+ /** Names the value series. Defaults to "Value". */
11
+ label?: string;
12
+ /** Shade how far the value sits below its best in a linked pane. Defaults to true. */
13
+ drawdown?: boolean;
14
+ /** Drawdown pane height in pixels. Defaults to 64. */
15
+ drawdownHeight?: number;
16
+ }
17
+ /**
18
+ * Account value next to its cost basis, with how far it sits below its best shaded in a
19
+ * linked pane. The delta is the gain over basis; the pane reads the current and worst drawdown.
20
+ */
21
+ export declare function PortfolioChartCard<Row, const Key extends NumericKey<Row>>({ value, basis, label, drawdown: showDrawdown, drawdownHeight, data, ranges, delta, locale, ...props }: PortfolioChartCardProps<Row, Key>): ReactElement;
22
+ export {};
@@ -0,0 +1,27 @@
1
+ import { ReactElement, ReactNode } from 'react';
2
+ import { CardSeries, CartesianCardProps } from '../../cards/cartesian-card';
3
+ import { NumericKey } from '../../cards/keys';
4
+ type SharedProps<Row, Key extends NumericKey<Row>> = Omit<CartesianCardProps<Row, Key>, 'series' | 'headlineSeries' | 'pillSeries' | 'aggregate' | 'target' | 'forecast' | 'tiles'>;
5
+ export interface PriceChartCardProps<Row, Key extends NumericKey<Row>> extends SharedProps<Row, Key> {
6
+ /** Field holding the price, or any level such as protocol TVL. */
7
+ price: Key;
8
+ /** Ticker shown in the heading, e.g. "SOL". */
9
+ symbol?: string;
10
+ /** Full name beside the ticker, e.g. "Solana". */
11
+ name?: string;
12
+ /** A logo or glyph before the ticker. */
13
+ icon?: ReactNode;
14
+ /** `area` (default) or `line`. */
15
+ display?: 'area' | 'line';
16
+ /**
17
+ * Other instruments to compare. Every series is then rebased to its change since the first
18
+ * row, so different price levels share one axis.
19
+ */
20
+ versus?: readonly CardSeries<Key>[];
21
+ }
22
+ /**
23
+ * A ticker card: symbol and name, the latest price, and its signed change over the period, over
24
+ * an area colored by direction. With `versus`, every instrument is rebased to percent change.
25
+ */
26
+ export declare function PriceChartCard<Row, const Key extends NumericKey<Row>>({ price, symbol, name, icon, display, versus, data, ranges, delta, valueFormat, locale, title, ...props }: PriceChartCardProps<Row, Key>): ReactElement;
27
+ export {};
@@ -0,0 +1,17 @@
1
+ export { Candles } from './candles';
2
+ export type { CandlesProps } from './candles';
3
+ export type { CandleDisplay } from './candle-geometry';
4
+ export { CandlestickChartCard } from './cards/candlestick-chart-card';
5
+ export type { CandlestickChartCardProps } from './cards/candlestick-chart-card';
6
+ export { IndicatorChartCard } from './cards/indicator-chart-card';
7
+ export type { IndicatorChartCardProps, IndicatorOverlay, IndicatorPane, } from './cards/indicator-chart-card';
8
+ export { DepthChartCard } from './cards/depth-chart-card';
9
+ export type { DepthChartCardProps } from './cards/depth-chart-card';
10
+ export { PortfolioChartCard } from './cards/portfolio-chart-card';
11
+ export type { PortfolioChartCardProps } from './cards/portfolio-chart-card';
12
+ export { PriceChartCard } from './cards/price-chart-card';
13
+ export type { PriceChartCardProps } from './cards/price-chart-card';
14
+ export { OrderBook } from './order-book';
15
+ export type { OrderBookProps } from './order-book';
16
+ export { bollinger, depthLevels, drawdown, ema, macd, rebase, rsi, sma } from './indicators';
17
+ export type { BollingerResult, BookLevel, DepthLevel, DepthSummary, MacdResult, } from './indicators';
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Pure finance helpers. Each takes values in time order and returns an array of the same length,
3
+ * with `null` wherever the input is missing or the window has not filled yet, so results line up
4
+ * with the rows they came from.
5
+ */
6
+ export type Series = readonly (number | null | undefined)[];
7
+ /** Simple moving average over the last `period` values; a gap in the window yields null. */
8
+ export declare function sma(values: Series, period: number): (number | null)[];
9
+ /**
10
+ * Exponential moving average, seeded with the simple average of the first `period` values.
11
+ * A missing value reads null and leaves the average where it was.
12
+ */
13
+ export declare function ema(values: Series, period: number): (number | null)[];
14
+ /**
15
+ * Relative strength index with Wilder's smoothing, from 0 to 100. The first reading needs
16
+ * `period` changes, so it lands on index `period`.
17
+ */
18
+ export declare function rsi(values: Series, period?: number): (number | null)[];
19
+ export interface MacdResult {
20
+ macd: (number | null)[];
21
+ signal: (number | null)[];
22
+ histogram: (number | null)[];
23
+ }
24
+ /** Moving average convergence divergence: fast EMA minus slow EMA, its signal EMA, and the gap. */
25
+ export declare function macd(values: Series, fast?: number, slow?: number, signal?: number): MacdResult;
26
+ export interface BollingerResult {
27
+ middle: (number | null)[];
28
+ upper: (number | null)[];
29
+ lower: (number | null)[];
30
+ }
31
+ /** Bollinger bands: a simple average with bands `deviations` population deviations either side. */
32
+ export declare function bollinger(values: Series, period?: number, deviations?: number): BollingerResult;
33
+ /** How far each value sits below the highest so far: 0 at a new high, −0.05 five percent below. */
34
+ export declare function drawdown(values: Series): (number | null)[];
35
+ /** Change from the first present value as a fraction, so series of different sizes compare. */
36
+ export declare function rebase(values: Series): (number | null)[];
37
+ export interface BookLevel {
38
+ price: number;
39
+ size: number;
40
+ }
41
+ export interface DepthLevel {
42
+ price: number;
43
+ /** Cumulative bid size from the best bid down to this price; null on the ask side. */
44
+ bid: number | null;
45
+ /** Cumulative ask size from the best ask up to this price; null on the bid side. */
46
+ ask: number | null;
47
+ /** Size resting at exactly this price. */
48
+ size: number;
49
+ side: 'bid' | 'ask';
50
+ }
51
+ export interface DepthSummary {
52
+ /** Every level in ascending price, bids then asks. */
53
+ levels: DepthLevel[];
54
+ bestBid: number | null;
55
+ bestAsk: number | null;
56
+ mid: number | null;
57
+ spread: number | null;
58
+ bidDepth: number;
59
+ askDepth: number;
60
+ }
61
+ /**
62
+ * Cumulative depth on each side of the book. Bids accumulate from the best (highest) bid down,
63
+ * asks from the best (lowest) ask up. Prices at one level merge.
64
+ */
65
+ export declare function depthLevels(bids: readonly BookLevel[], asks: readonly BookLevel[]): DepthSummary;
@@ -0,0 +1,26 @@
1
+ import { CSSProperties, ReactElement } from 'react';
2
+ import { ChartMotion, ChartStyle, ChartSurface } from '../types';
3
+ import { BookLevel } from './indicators';
4
+ export interface OrderBookProps {
5
+ title: string;
6
+ bids: readonly BookLevel[];
7
+ asks: readonly BookLevel[];
8
+ /** Price levels shown on each side of the spread. Defaults to 8. */
9
+ depth?: number;
10
+ /** Price format, e.g. `{ style: 'currency', currency: 'USD' }`. */
11
+ valueFormat?: Intl.NumberFormatOptions;
12
+ /** Size format. Defaults to compact numbers. */
13
+ sizeFormat?: Intl.NumberFormatOptions;
14
+ locale?: string;
15
+ /** Briefly highlight levels whose size changed. Defaults to true; reduced motion turns it off. */
16
+ flash?: boolean;
17
+ surface?: ChartSurface;
18
+ motion?: ChartMotion;
19
+ className?: string;
20
+ style?: CSSProperties | ChartStyle;
21
+ }
22
+ /**
23
+ * A price ladder: asks above, bids below, a spread row between, and a depth bar behind each
24
+ * level sized by its running total. It is a real table, so screen readers read it row by row.
25
+ */
26
+ export declare function OrderBook({ title, bids, asks, depth, valueFormat, sizeFormat, locale, flash, surface, motion, className, style, }: OrderBookProps): ReactElement;
@@ -0,0 +1,2 @@
1
+ export * from './finance/index'
2
+ export {}