@gunkin/uiify 0.0.2-alpha → 0.0.4-alpha
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/dist/components/behavior.css +16 -1
- package/dist/components/behavior.css.map +1 -1
- package/dist/components/candle-chart/CandleChart.d.ts +10 -1
- package/dist/components/candle-chart/CandleChart.d.ts.map +1 -1
- package/dist/components/candle-chart/CandleChart.js +82 -42
- package/dist/components/candle-chart/CandleChart.js.map +1 -1
- package/dist/components/candle-chart/client/CandleChartClient.d.ts +2 -2
- package/dist/components/candle-chart/client/CandleChartClient.d.ts.map +1 -1
- package/dist/components/candle-chart/client/CandleChartClient.js +103 -14
- package/dist/components/candle-chart/client/CandleChartClient.js.map +1 -1
- package/dist/components/candle-chart/client/index.d.ts +1 -0
- package/dist/components/candle-chart/client/index.d.ts.map +1 -1
- package/dist/components/candle-chart/client/index.js.map +1 -1
- package/dist/components/candle-chart/types.d.ts +39 -0
- package/dist/components/candle-chart/types.d.ts.map +1 -1
- package/dist/components/internal/chart-scrollbar/use-scrollbar-reserve.d.ts +11 -0
- package/dist/components/internal/chart-scrollbar/use-scrollbar-reserve.d.ts.map +1 -0
- package/dist/components/internal/chart-scrollbar/use-scrollbar-reserve.js +21 -0
- package/dist/components/internal/chart-scrollbar/use-scrollbar-reserve.js.map +1 -0
- package/dist/components/internal/live-chart/types.d.ts +36 -0
- package/dist/components/internal/live-chart/types.d.ts.map +1 -0
- package/dist/components/internal/live-chart/types.js +1 -0
- package/dist/components/internal/live-chart/types.js.map +1 -0
- package/dist/components/internal/live-chart/use-live-chart-window.d.ts +18 -0
- package/dist/components/internal/live-chart/use-live-chart-window.d.ts.map +1 -0
- package/dist/components/internal/live-chart/use-live-chart-window.js +75 -0
- package/dist/components/internal/live-chart/use-live-chart-window.js.map +1 -0
- package/dist/components/line-chart/LineChart.d.ts +6 -1
- package/dist/components/line-chart/LineChart.d.ts.map +1 -1
- package/dist/components/line-chart/LineChart.js +82 -48
- package/dist/components/line-chart/LineChart.js.map +1 -1
- package/dist/components/line-chart/client/LineChartClient.d.ts +2 -2
- package/dist/components/line-chart/client/LineChartClient.d.ts.map +1 -1
- package/dist/components/line-chart/client/LineChartClient.js +106 -14
- package/dist/components/line-chart/client/LineChartClient.js.map +1 -1
- package/dist/components/line-chart/client/index.d.ts +1 -1
- package/dist/components/line-chart/client/index.d.ts.map +1 -1
- package/dist/components/line-chart/client/index.js.map +1 -1
- package/dist/components/line-chart/line-chart-geometry.d.ts +7 -0
- package/dist/components/line-chart/line-chart-geometry.d.ts.map +1 -1
- package/dist/components/line-chart/line-chart-geometry.js +14 -2
- package/dist/components/line-chart/line-chart-geometry.js.map +1 -1
- package/dist/components/line-chart/types.d.ts +42 -0
- package/dist/components/line-chart/types.d.ts.map +1 -1
- package/dist/components/virtual-scroll/VirtualScroll.d.ts.map +1 -1
- package/dist/components/virtual-scroll/VirtualScroll.js +40 -44
- package/dist/components/virtual-scroll/VirtualScroll.js.map +1 -1
- package/dist/components/virtual-scroll/index.d.ts +1 -1
- package/dist/components/virtual-scroll/index.d.ts.map +1 -1
- package/dist/components/virtual-scroll/index.js.map +1 -1
- package/dist/components/virtual-scroll/types.d.ts +5 -0
- package/dist/components/virtual-scroll/types.d.ts.map +1 -1
- package/dist/components/virtual-scroll/types.js.map +1 -1
- package/dist/components/virtual-scroll/virtual-scroll-axis.d.ts +9 -0
- package/dist/components/virtual-scroll/virtual-scroll-axis.d.ts.map +1 -0
- package/dist/components/virtual-scroll/virtual-scroll-axis.js +18 -0
- package/dist/components/virtual-scroll/virtual-scroll-axis.js.map +1 -0
- package/dist/styles/index.css +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/candle-chart/client/index.ts"],"sourcesContent":["export { CandleChartClient } from \"./CandleChartClient.js\";\n"],"mappings":"AAAA,SAAS,yBAAyB;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/candle-chart/client/index.ts"],"sourcesContent":["export { CandleChartClient } from \"./CandleChartClient.js\";\nexport type { CandleChartClientOwnProps, CandleChartClientProps } from \"../types.js\";\n"],"mappings":"AAAA,SAAS,yBAAyB;","names":[]}
|
|
@@ -31,4 +31,43 @@ export interface CandleChartOwnProps {
|
|
|
31
31
|
readonly yAxis?: readonly CandleChartAxisLabel[];
|
|
32
32
|
}
|
|
33
33
|
export type CandleChartProps<TAs extends ElementType = "figure"> = RenderableProps<TAs, CandleChartOwnProps, Record<string, never>, HTMLElement>;
|
|
34
|
+
export interface CandleChartClientOwnProps extends CandleChartOwnProps {
|
|
35
|
+
/**
|
|
36
|
+
* Live mode: sizes candles so `visibleCount` fill the viewport and virtualizes
|
|
37
|
+
* the full history with a horizontal VirtualScroll. The chart follows new
|
|
38
|
+
* candles while the reader is at the newest one; the price scale, axes,
|
|
39
|
+
* readout, and data table follow the visible candles. Zoom is disabled.
|
|
40
|
+
*/
|
|
41
|
+
readonly visibleCount?: number;
|
|
42
|
+
}
|
|
43
|
+
export type CandleChartClientProps<TAs extends ElementType = "figure"> = RenderableProps<TAs, CandleChartClientOwnProps, Record<string, never>, HTMLElement>;
|
|
44
|
+
/** Internal props the client entry passes to `CandleChart`; not part of the public API. */
|
|
45
|
+
export interface CandleChartViewProps extends CandleChartOwnProps {
|
|
46
|
+
/** Replaces the static candle list (e.g. with a virtualized layer). */
|
|
47
|
+
readonly candleLayer?: ReactNode;
|
|
48
|
+
/** Announce readout changes; off for streaming data. Defaults to `true`. */
|
|
49
|
+
readonly announceReadout?: boolean;
|
|
50
|
+
/** Slots the crosshair is positioned across. Defaults to `data.length`. */
|
|
51
|
+
readonly slotCount?: number;
|
|
52
|
+
/** Slot of `data[0]` within those slots, when `data` is a slice. Defaults to `0`. */
|
|
53
|
+
readonly slotOffset?: number;
|
|
54
|
+
}
|
|
55
|
+
export interface CandleChartCandleProps {
|
|
56
|
+
readonly as: "div" | "li";
|
|
57
|
+
readonly candle: CandleChartData;
|
|
58
|
+
/** Index reported to the pointer and click callbacks. */
|
|
59
|
+
readonly index: number;
|
|
60
|
+
/** Candle position and width, as percentages of the candle layer. */
|
|
61
|
+
readonly x: number;
|
|
62
|
+
readonly slot: number;
|
|
63
|
+
readonly min: number;
|
|
64
|
+
readonly max: number;
|
|
65
|
+
readonly interactive: boolean;
|
|
66
|
+
readonly isActive: boolean;
|
|
67
|
+
readonly isSelected: boolean;
|
|
68
|
+
readonly cursorY?: number | undefined;
|
|
69
|
+
readonly onCandleClick?: ((index: number) => void) | undefined;
|
|
70
|
+
readonly onCandlePointerLeave?: (() => void) | undefined;
|
|
71
|
+
readonly onCandlePointerMove?: ((position: CandleChartPointerPosition) => void) | undefined;
|
|
72
|
+
}
|
|
34
73
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/candle-chart/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAEjE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,gEAAgE;IAChE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,SAAS,eAAe,EAAE,CAAC;IAC1C,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3C,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC,QAAQ,EAAE,0BAA0B,KAAK,IAAI,CAAC;IAC9E,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACjD,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;CAClD;AAED,MAAM,MAAM,gBAAgB,CAAC,GAAG,SAAS,WAAW,GAAG,QAAQ,IAAI,eAAe,CAChF,GAAG,EACH,mBAAmB,EACnB,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EACrB,WAAW,CACZ,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/candle-chart/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type RefObject } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Publishes the horizontal scrollbar thickness of a chart's
|
|
4
|
+
* `[data-part="scroll-viewport"]` as `variable` on the chart element, so the
|
|
5
|
+
* plot grid can reserve that height below the time axis. A classic scrollbar
|
|
6
|
+
* otherwise takes its height from the scroll viewport, and the flexible
|
|
7
|
+
* candle row absorbs it, misaligning the value axis. Overlay scrollbars
|
|
8
|
+
* measure 0. Read from ResizeObserver box sizes: no forced layout.
|
|
9
|
+
*/
|
|
10
|
+
export declare function useScrollbarReserve(chartRef: RefObject<HTMLElement | null>, variable: `--${string}`): void;
|
|
11
|
+
//# sourceMappingURL=use-scrollbar-reserve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-scrollbar-reserve.d.ts","sourceRoot":"","sources":["../../../../src/components/internal/chart-scrollbar/use-scrollbar-reserve.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAElD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EACvC,QAAQ,EAAE,KAAK,MAAM,EAAE,GACtB,IAAI,CAeN"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useEffect } from "react";
|
|
3
|
+
function useScrollbarReserve(chartRef, variable) {
|
|
4
|
+
useEffect(() => {
|
|
5
|
+
const chart = chartRef.current;
|
|
6
|
+
const scroller = chart?.querySelector('[data-part="scroll-viewport"]');
|
|
7
|
+
if (!chart || !scroller || typeof ResizeObserver === "undefined") return;
|
|
8
|
+
const observer = new ResizeObserver(([entry]) => {
|
|
9
|
+
const border = entry?.borderBoxSize[0]?.blockSize;
|
|
10
|
+
const content = entry?.contentBoxSize[0]?.blockSize;
|
|
11
|
+
if (border === void 0 || content === void 0) return;
|
|
12
|
+
chart.style.setProperty(variable, `${Math.max(0, border - content)}px`);
|
|
13
|
+
});
|
|
14
|
+
observer.observe(scroller);
|
|
15
|
+
return () => observer.disconnect();
|
|
16
|
+
}, [chartRef, variable]);
|
|
17
|
+
}
|
|
18
|
+
export {
|
|
19
|
+
useScrollbarReserve
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=use-scrollbar-reserve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/internal/chart-scrollbar/use-scrollbar-reserve.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, type RefObject } from \"react\";\n\n/**\n * Publishes the horizontal scrollbar thickness of a chart's\n * `[data-part=\"scroll-viewport\"]` as `variable` on the chart element, so the\n * plot grid can reserve that height below the time axis. A classic scrollbar\n * otherwise takes its height from the scroll viewport, and the flexible\n * candle row absorbs it, misaligning the value axis. Overlay scrollbars\n * measure 0. Read from ResizeObserver box sizes: no forced layout.\n */\nexport function useScrollbarReserve(\n chartRef: RefObject<HTMLElement | null>,\n variable: `--${string}`,\n): void {\n useEffect(() => {\n const chart = chartRef.current;\n const scroller = chart?.querySelector<HTMLElement>('[data-part=\"scroll-viewport\"]');\n if (!chart || !scroller || typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(([entry]) => {\n const border = entry?.borderBoxSize[0]?.blockSize;\n const content = entry?.contentBoxSize[0]?.blockSize;\n if (border === undefined || content === undefined) return;\n // The scroll viewport has no padding or border, so the difference is the scrollbar.\n chart.style.setProperty(variable, `${Math.max(0, border - content)}px`);\n });\n observer.observe(scroller);\n return () => observer.disconnect();\n }, [chartRef, variable]);\n}\n"],"mappings":";AAEA,SAAS,iBAAiC;AAUnC,SAAS,oBACd,UACA,UACM;AACN,YAAU,MAAM;AACd,UAAM,QAAQ,SAAS;AACvB,UAAM,WAAW,OAAO,cAA2B,+BAA+B;AAClF,QAAI,CAAC,SAAS,CAAC,YAAY,OAAO,mBAAmB,YAAa;AAClE,UAAM,WAAW,IAAI,eAAe,CAAC,CAAC,KAAK,MAAM;AAC/C,YAAM,SAAS,OAAO,cAAc,CAAC,GAAG;AACxC,YAAM,UAAU,OAAO,eAAe,CAAC,GAAG;AAC1C,UAAI,WAAW,UAAa,YAAY,OAAW;AAEnD,YAAM,MAAM,YAAY,UAAU,GAAG,KAAK,IAAI,GAAG,SAAS,OAAO,CAAC,IAAI;AAAA,IACxE,CAAC;AACD,aAAS,QAAQ,QAAQ;AACzB,WAAO,MAAM,SAAS,WAAW;AAAA,EACnC,GAAG,CAAC,UAAU,QAAQ,CAAC;AACzB;","names":[]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ReactNode, RefObject } from "react";
|
|
2
|
+
import type { VirtualScrollHandle, VirtualScrollRangeChange } from "../../virtual-scroll/types.js";
|
|
3
|
+
export interface LiveChartAxisLabel {
|
|
4
|
+
readonly label: ReactNode;
|
|
5
|
+
/** Position across the whole scrolled content, as a percentage from 0 to 100. */
|
|
6
|
+
readonly position: number;
|
|
7
|
+
}
|
|
8
|
+
export interface UseLiveChartWindowOptions {
|
|
9
|
+
/** Total number of items (candles or points) in the chart. */
|
|
10
|
+
readonly count: number;
|
|
11
|
+
/** Items that fill the viewport; `undefined` or `0` turns live mode off. */
|
|
12
|
+
readonly visibleCount: number | undefined;
|
|
13
|
+
/** Measured width of one item slot, in CSS pixels. */
|
|
14
|
+
readonly itemWidth: number;
|
|
15
|
+
/** Measured content height of the chart `<figure>`, once known. */
|
|
16
|
+
readonly figureHeight: number | undefined;
|
|
17
|
+
/** Custom property that receives the scroll offset, e.g. `--candle-scroll-x`. */
|
|
18
|
+
readonly scrollVariable: `--${string}`;
|
|
19
|
+
}
|
|
20
|
+
export interface UseLiveChartWindowResult {
|
|
21
|
+
readonly live: boolean;
|
|
22
|
+
/** Pass to the chart's VirtualScroll `scrollRef`. */
|
|
23
|
+
readonly scrollRef: RefObject<VirtualScrollHandle | null>;
|
|
24
|
+
/** Merge into the chart `<figure>` ref; the scroll offset variable is written there. */
|
|
25
|
+
readonly chartRef: RefObject<HTMLElement | null>;
|
|
26
|
+
/** Pass to the chart's VirtualScroll `onRangeChange`. */
|
|
27
|
+
readonly onRangeChange: (range: VirtualScrollRangeChange) => void;
|
|
28
|
+
/** Visible slice `[sliceStart, sliceEnd)` that drives the scale, readout, and table. */
|
|
29
|
+
readonly sliceStart: number;
|
|
30
|
+
readonly sliceEnd: number;
|
|
31
|
+
/** Width of all item slots, in CSS pixels. */
|
|
32
|
+
readonly contentSize: number;
|
|
33
|
+
/** Block size of the item viewport, in CSS pixels. */
|
|
34
|
+
readonly plotHeight: number;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/internal/live-chart/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,KAAK,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAEnG,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,iFAAiF;IACjF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,yBAAyB;IACxC,8DAA8D;IAC9D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,4EAA4E;IAC5E,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,sDAAsD;IACtD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,mEAAmE;IACnE,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,iFAAiF;IACjF,QAAQ,CAAC,cAAc,EAAE,KAAK,MAAM,EAAE,CAAC;CACxC;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,qDAAqD;IACrD,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;IAC1D,wFAAwF;IACxF,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACjD,yDAAyD;IACzD,QAAQ,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,IAAI,CAAC;IAClE,wFAAwF;IACxF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,8CAA8C;IAC9C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,sDAAsD;IACtD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { LiveChartAxisLabel, UseLiveChartWindowOptions, UseLiveChartWindowResult } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Time ticks pinned to absolute item indices and positioned at slot centers
|
|
4
|
+
* across the whole scrolled content, so labels scroll with their items. Only
|
|
5
|
+
* ticks near the visible slice are returned.
|
|
6
|
+
*/
|
|
7
|
+
export declare function liveTimeAxis(data: readonly {
|
|
8
|
+
readonly time: string | number;
|
|
9
|
+
}[], start: number, end: number, visibleCount: number): LiveChartAxisLabel[];
|
|
10
|
+
/**
|
|
11
|
+
* Live chart window over a horizontal VirtualScroll: follows appends while the
|
|
12
|
+
* reader is at the newest item, leaves a scrolled-back reader in place, and
|
|
13
|
+
* reports the visible slice. The chart pins the scroll position itself rather
|
|
14
|
+
* than using VirtualScroll's `anchor`, and publishes the offset as a CSS
|
|
15
|
+
* variable so axes and crosshairs scroll without re-rendering.
|
|
16
|
+
*/
|
|
17
|
+
export declare function useLiveChartWindow(options: UseLiveChartWindowOptions): UseLiveChartWindowResult;
|
|
18
|
+
//# sourceMappingURL=use-live-chart-window.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-live-chart-window.d.ts","sourceRoot":"","sources":["../../../../src/components/internal/live-chart/use-live-chart-window.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,kBAAkB,EAClB,yBAAyB,EACzB,wBAAwB,EACzB,MAAM,YAAY,CAAC;AAQpB;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,SAAS;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,EAAE,EACnD,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,GACnB,kBAAkB,EAAE,CAYtB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,wBAAwB,CAqE/F"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
|
+
import { useIsomorphicLayoutEffect } from "../../../hooks/use-isomorphic-layout-effect.js";
|
|
4
|
+
const TIME_AXIS_ROW_HEIGHT = 24;
|
|
5
|
+
const MIN_PLOT_HEIGHT = 288;
|
|
6
|
+
const LIVE_TIME_TICKS = 4;
|
|
7
|
+
function liveTimeAxis(data, start, end, visibleCount) {
|
|
8
|
+
const step = Math.max(1, Math.ceil(visibleCount / LIVE_TIME_TICKS));
|
|
9
|
+
const labels = [];
|
|
10
|
+
const first = Math.max(0, Math.floor(start / step) - 1) * step;
|
|
11
|
+
const last = Math.min(data.length, end + step);
|
|
12
|
+
for (let index = first; index < last; index += step) {
|
|
13
|
+
labels.push({
|
|
14
|
+
label: String(data[index]?.time),
|
|
15
|
+
position: (index + 0.5) / data.length * 100
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
return labels;
|
|
19
|
+
}
|
|
20
|
+
function useLiveChartWindow(options) {
|
|
21
|
+
const { count, visibleCount = 0, itemWidth, figureHeight, scrollVariable } = options;
|
|
22
|
+
const live = visibleCount > 0;
|
|
23
|
+
const scrollRef = useRef(null);
|
|
24
|
+
const chartRef = useRef(null);
|
|
25
|
+
const [visibleRange, setVisibleRange] = useState(null);
|
|
26
|
+
const [following, setFollowing] = useState(true);
|
|
27
|
+
const contentSize = count * itemWidth;
|
|
28
|
+
const viewportWidth = itemWidth * visibleCount;
|
|
29
|
+
const layoutRef = useRef({ contentSize, itemWidth, viewportWidth });
|
|
30
|
+
layoutRef.current = { contentSize, itemWidth, viewportWidth };
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (!live) return;
|
|
33
|
+
const element = scrollRef.current?.element;
|
|
34
|
+
const chart = chartRef.current;
|
|
35
|
+
if (!element || !chart) return;
|
|
36
|
+
const onScroll = () => {
|
|
37
|
+
const offset = element.scrollLeft;
|
|
38
|
+
chart.style.setProperty(scrollVariable, `${offset}px`);
|
|
39
|
+
const layout = layoutRef.current;
|
|
40
|
+
setFollowing(
|
|
41
|
+
offset + layout.viewportWidth >= layout.contentSize - Math.max(1, layout.itemWidth)
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
element.addEventListener("scroll", onScroll, { passive: true });
|
|
45
|
+
return () => element.removeEventListener("scroll", onScroll);
|
|
46
|
+
}, [live, scrollVariable]);
|
|
47
|
+
useIsomorphicLayoutEffect(() => {
|
|
48
|
+
if (!live || !following) return;
|
|
49
|
+
const element = scrollRef.current?.element;
|
|
50
|
+
const chart = chartRef.current;
|
|
51
|
+
if (!element || !chart) return;
|
|
52
|
+
const end = Math.max(0, contentSize - viewportWidth);
|
|
53
|
+
element.scrollLeft = end;
|
|
54
|
+
chart.style.setProperty(scrollVariable, `${end}px`);
|
|
55
|
+
}, [live, following, contentSize, viewportWidth, scrollVariable]);
|
|
56
|
+
const tail = following || !visibleRange;
|
|
57
|
+
const sliceStart = tail ? Math.max(0, count - visibleCount) : Math.min(visibleRange.startIndex, Math.max(0, count - 1));
|
|
58
|
+
const sliceEnd = tail ? count : Math.min(count, Math.max(sliceStart + 1, visibleRange.endIndex + 1));
|
|
59
|
+
const plotHeight = figureHeight === void 0 ? MIN_PLOT_HEIGHT : Math.max(MIN_PLOT_HEIGHT, figureHeight - TIME_AXIS_ROW_HEIGHT);
|
|
60
|
+
return {
|
|
61
|
+
live,
|
|
62
|
+
scrollRef,
|
|
63
|
+
chartRef,
|
|
64
|
+
onRangeChange: setVisibleRange,
|
|
65
|
+
sliceStart,
|
|
66
|
+
sliceEnd,
|
|
67
|
+
contentSize,
|
|
68
|
+
plotHeight
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export {
|
|
72
|
+
liveTimeAxis,
|
|
73
|
+
useLiveChartWindow
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=use-live-chart-window.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/internal/live-chart/use-live-chart-window.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { useIsomorphicLayoutEffect } from \"../../../hooks/use-isomorphic-layout-effect.js\";\nimport type { VirtualScrollHandle, VirtualScrollRangeChange } from \"../../virtual-scroll/types.js\";\nimport type {\n LiveChartAxisLabel,\n UseLiveChartWindowOptions,\n UseLiveChartWindowResult,\n} from \"./types.js\";\n\n/** The plot's 1.5rem time-axis row below the item viewport (candle-chart.css, line-chart.css). */\nconst TIME_AXIS_ROW_HEIGHT = 24;\n/** The item viewport's 18rem minimum block size, used until the figure is measured. */\nconst MIN_PLOT_HEIGHT = 288;\nconst LIVE_TIME_TICKS = 4;\n\n/**\n * Time ticks pinned to absolute item indices and positioned at slot centers\n * across the whole scrolled content, so labels scroll with their items. Only\n * ticks near the visible slice are returned.\n */\nexport function liveTimeAxis(\n data: readonly { readonly time: string | number }[],\n start: number,\n end: number,\n visibleCount: number,\n): LiveChartAxisLabel[] {\n const step = Math.max(1, Math.ceil(visibleCount / LIVE_TIME_TICKS));\n const labels: LiveChartAxisLabel[] = [];\n const first = Math.max(0, Math.floor(start / step) - 1) * step;\n const last = Math.min(data.length, end + step);\n for (let index = first; index < last; index += step) {\n labels.push({\n label: String(data[index]?.time),\n position: ((index + 0.5) / data.length) * 100,\n });\n }\n return labels;\n}\n\n/**\n * Live chart window over a horizontal VirtualScroll: follows appends while the\n * reader is at the newest item, leaves a scrolled-back reader in place, and\n * reports the visible slice. The chart pins the scroll position itself rather\n * than using VirtualScroll's `anchor`, and publishes the offset as a CSS\n * variable so axes and crosshairs scroll without re-rendering.\n */\nexport function useLiveChartWindow(options: UseLiveChartWindowOptions): UseLiveChartWindowResult {\n const { count, visibleCount = 0, itemWidth, figureHeight, scrollVariable } = options;\n const live = visibleCount > 0;\n const scrollRef = useRef<VirtualScrollHandle>(null);\n const chartRef = useRef<HTMLElement | null>(null);\n const [visibleRange, setVisibleRange] = useState<VirtualScrollRangeChange | null>(null);\n // True while the reader sits at the newest item; appends then keep it in view.\n const [following, setFollowing] = useState(true);\n const contentSize = count * itemWidth;\n const viewportWidth = itemWidth * visibleCount;\n const layoutRef = useRef({ contentSize, itemWidth, viewportWidth });\n layoutRef.current = { contentSize, itemWidth, viewportWidth };\n\n // Publish the scroll offset (a CSS variable, so scrolling re-renders nothing)\n // and track whether the reader is at the end.\n useEffect(() => {\n if (!live) return;\n const element = scrollRef.current?.element;\n const chart = chartRef.current;\n if (!element || !chart) return;\n const onScroll = (): void => {\n const offset = element.scrollLeft; // banned-read-ok: scroll position drives the axis offset.\n chart.style.setProperty(scrollVariable, `${offset}px`);\n const layout = layoutRef.current;\n // Within one item of the end counts: an item appended while the reader\n // scrolls there moves the end by exactly one item width.\n setFollowing(\n offset + layout.viewportWidth >= layout.contentSize - Math.max(1, layout.itemWidth),\n );\n };\n element.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => element.removeEventListener(\"scroll\", onScroll);\n }, [live, scrollVariable]);\n\n // Keep the newest item in view while following: on appends, resizes, and once measured.\n useIsomorphicLayoutEffect(() => {\n if (!live || !following) return;\n const element = scrollRef.current?.element;\n const chart = chartRef.current;\n if (!element || !chart) return;\n const end = Math.max(0, contentSize - viewportWidth);\n element.scrollLeft = end; // banned-read-ok: pin the newest item before paint.\n chart.style.setProperty(scrollVariable, `${end}px`);\n }, [live, following, contentSize, viewportWidth, scrollVariable]);\n\n // While following, the slice is the tail, so an append rescales in the same\n // commit that adds the item.\n const tail = following || !visibleRange;\n const sliceStart = tail\n ? Math.max(0, count - visibleCount)\n : Math.min(visibleRange.startIndex, Math.max(0, count - 1));\n const sliceEnd = tail\n ? count\n : Math.min(count, Math.max(sliceStart + 1, visibleRange.endIndex + 1));\n const plotHeight =\n figureHeight === undefined\n ? MIN_PLOT_HEIGHT\n : Math.max(MIN_PLOT_HEIGHT, figureHeight - TIME_AXIS_ROW_HEIGHT);\n\n return {\n live,\n scrollRef,\n chartRef,\n onRangeChange: setVisibleRange,\n sliceStart,\n sliceEnd,\n contentSize,\n plotHeight,\n };\n}\n"],"mappings":";AAEA,SAAS,WAAW,QAAQ,gBAAgB;AAC5C,SAAS,iCAAiC;AAS1C,MAAM,uBAAuB;AAE7B,MAAM,kBAAkB;AACxB,MAAM,kBAAkB;AAOjB,SAAS,aACd,MACA,OACA,KACA,cACsB;AACtB,QAAM,OAAO,KAAK,IAAI,GAAG,KAAK,KAAK,eAAe,eAAe,CAAC;AAClE,QAAM,SAA+B,CAAC;AACtC,QAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,IAAI;AAC1D,QAAM,OAAO,KAAK,IAAI,KAAK,QAAQ,MAAM,IAAI;AAC7C,WAAS,QAAQ,OAAO,QAAQ,MAAM,SAAS,MAAM;AACnD,WAAO,KAAK;AAAA,MACV,OAAO,OAAO,KAAK,KAAK,GAAG,IAAI;AAAA,MAC/B,WAAY,QAAQ,OAAO,KAAK,SAAU;AAAA,IAC5C,CAAC;AAAA,EACH;AACA,SAAO;AACT;AASO,SAAS,mBAAmB,SAA8D;AAC/F,QAAM,EAAE,OAAO,eAAe,GAAG,WAAW,cAAc,eAAe,IAAI;AAC7E,QAAM,OAAO,eAAe;AAC5B,QAAM,YAAY,OAA4B,IAAI;AAClD,QAAM,WAAW,OAA2B,IAAI;AAChD,QAAM,CAAC,cAAc,eAAe,IAAI,SAA0C,IAAI;AAEtF,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,IAAI;AAC/C,QAAM,cAAc,QAAQ;AAC5B,QAAM,gBAAgB,YAAY;AAClC,QAAM,YAAY,OAAO,EAAE,aAAa,WAAW,cAAc,CAAC;AAClE,YAAU,UAAU,EAAE,aAAa,WAAW,cAAc;AAI5D,YAAU,MAAM;AACd,QAAI,CAAC,KAAM;AACX,UAAM,UAAU,UAAU,SAAS;AACnC,UAAM,QAAQ,SAAS;AACvB,QAAI,CAAC,WAAW,CAAC,MAAO;AACxB,UAAM,WAAW,MAAY;AAC3B,YAAM,SAAS,QAAQ;AACvB,YAAM,MAAM,YAAY,gBAAgB,GAAG,MAAM,IAAI;AACrD,YAAM,SAAS,UAAU;AAGzB;AAAA,QACE,SAAS,OAAO,iBAAiB,OAAO,cAAc,KAAK,IAAI,GAAG,OAAO,SAAS;AAAA,MACpF;AAAA,IACF;AACA,YAAQ,iBAAiB,UAAU,UAAU,EAAE,SAAS,KAAK,CAAC;AAC9D,WAAO,MAAM,QAAQ,oBAAoB,UAAU,QAAQ;AAAA,EAC7D,GAAG,CAAC,MAAM,cAAc,CAAC;AAGzB,4BAA0B,MAAM;AAC9B,QAAI,CAAC,QAAQ,CAAC,UAAW;AACzB,UAAM,UAAU,UAAU,SAAS;AACnC,UAAM,QAAQ,SAAS;AACvB,QAAI,CAAC,WAAW,CAAC,MAAO;AACxB,UAAM,MAAM,KAAK,IAAI,GAAG,cAAc,aAAa;AACnD,YAAQ,aAAa;AACrB,UAAM,MAAM,YAAY,gBAAgB,GAAG,GAAG,IAAI;AAAA,EACpD,GAAG,CAAC,MAAM,WAAW,aAAa,eAAe,cAAc,CAAC;AAIhE,QAAM,OAAO,aAAa,CAAC;AAC3B,QAAM,aAAa,OACf,KAAK,IAAI,GAAG,QAAQ,YAAY,IAChC,KAAK,IAAI,aAAa,YAAY,KAAK,IAAI,GAAG,QAAQ,CAAC,CAAC;AAC5D,QAAM,WAAW,OACb,QACA,KAAK,IAAI,OAAO,KAAK,IAAI,aAAa,GAAG,aAAa,WAAW,CAAC,CAAC;AACvE,QAAM,aACJ,iBAAiB,SACb,kBACA,KAAK,IAAI,iBAAiB,eAAe,oBAAoB;AAEnE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { ElementType, ReactElement } from "react";
|
|
2
|
-
import type { LineChartProps } from "./types.js";
|
|
2
|
+
import type { LineChartPointProps, LineChartProps } from "./types.js";
|
|
3
|
+
/** One point and the segment from its predecessor; shared by the static list and virtual rows. */
|
|
4
|
+
export declare function LineChartPoint({ as: Tag, point, previousPoint, index, count, min, max, interactive, isActive, isSelected, cursorY, onPointClick, onPointPointerLeave, onPointPointerMove, }: LineChartPointProps): ReactElement;
|
|
5
|
+
export declare namespace LineChartPoint {
|
|
6
|
+
var displayName: string;
|
|
7
|
+
}
|
|
3
8
|
export declare function LineChart<TAs extends ElementType = "figure">(props: LineChartProps<TAs>): ReactElement | null;
|
|
4
9
|
export declare namespace LineChart {
|
|
5
10
|
var displayName: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LineChart.d.ts","sourceRoot":"","sources":["../../../src/components/line-chart/LineChart.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAA+B,YAAY,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"LineChart.d.ts","sourceRoot":"","sources":["../../../src/components/line-chart/LineChart.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAA+B,YAAY,EAAE,MAAM,OAAO,CAAC;AAepF,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAsB,MAAM,YAAY,CAAC;AAE1F,kGAAkG;AAClG,wBAAgB,cAAc,CAAC,EAC7B,EAAE,EAAE,GAAG,EACP,KAAK,EACL,aAAa,EACb,KAAK,EACL,KAAK,EACL,GAAG,EACH,GAAG,EACH,WAAW,EACX,QAAQ,EACR,UAAU,EACV,OAAO,EACP,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,GACnB,EAAE,mBAAmB,GAAG,YAAY,CAmCpC;yBAlDe,cAAc;;;AAqD9B,wBAAgB,SAAS,CAAC,GAAG,SAAS,WAAW,GAAG,QAAQ,EAC1D,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,GACzB,YAAY,GAAG,IAAI,CAqJrB;yBAvJe,SAAS"}
|
|
@@ -10,8 +10,59 @@ import {
|
|
|
10
10
|
monthLabelsFor,
|
|
11
11
|
pointStyle,
|
|
12
12
|
pointsStyle,
|
|
13
|
+
slotCrosshairStyle,
|
|
13
14
|
valueLabelsFor
|
|
14
15
|
} from "./line-chart-geometry.js";
|
|
16
|
+
function LineChartPoint({
|
|
17
|
+
as: Tag,
|
|
18
|
+
point,
|
|
19
|
+
previousPoint,
|
|
20
|
+
index,
|
|
21
|
+
count,
|
|
22
|
+
min,
|
|
23
|
+
max,
|
|
24
|
+
interactive,
|
|
25
|
+
isActive,
|
|
26
|
+
isSelected,
|
|
27
|
+
cursorY,
|
|
28
|
+
onPointClick,
|
|
29
|
+
onPointPointerLeave,
|
|
30
|
+
onPointPointerMove
|
|
31
|
+
}) {
|
|
32
|
+
const geometry = geometryFor(point, previousPoint, index, count, min, max);
|
|
33
|
+
const handleKeyDown = (event) => {
|
|
34
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
35
|
+
event.preventDefault();
|
|
36
|
+
onPointClick?.(index);
|
|
37
|
+
};
|
|
38
|
+
return /* @__PURE__ */ jsx(
|
|
39
|
+
Tag,
|
|
40
|
+
{
|
|
41
|
+
"aria-hidden": interactive ? void 0 : true,
|
|
42
|
+
"data-part": "point",
|
|
43
|
+
"data-first": previousPoint === void 0 ? "" : void 0,
|
|
44
|
+
"data-crosshair-active": interactive && isActive ? "" : void 0,
|
|
45
|
+
"data-point-selected": interactive && isSelected ? "" : void 0,
|
|
46
|
+
"data-time": String(point.time),
|
|
47
|
+
"data-trend": geometry.trend,
|
|
48
|
+
style: pointStyle(geometry, isActive ? cursorY : void 0),
|
|
49
|
+
children: interactive ? /* @__PURE__ */ jsx(
|
|
50
|
+
"button",
|
|
51
|
+
{
|
|
52
|
+
"data-part": "point-hit",
|
|
53
|
+
type: "button",
|
|
54
|
+
"aria-label": `Point ${String(point.time)}`,
|
|
55
|
+
"aria-pressed": isSelected,
|
|
56
|
+
onClick: () => onPointClick?.(index),
|
|
57
|
+
onKeyDown: handleKeyDown,
|
|
58
|
+
onPointerLeave: onPointPointerLeave,
|
|
59
|
+
onPointerMove: (event) => onPointPointerMove?.({ index, offsetY: event.nativeEvent.offsetY })
|
|
60
|
+
}
|
|
61
|
+
) : null
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
LineChartPoint.displayName = "LineChartPoint";
|
|
15
66
|
function LineChart(props) {
|
|
16
67
|
const {
|
|
17
68
|
as,
|
|
@@ -27,6 +78,10 @@ function LineChart(props) {
|
|
|
27
78
|
onPointPointerLeave,
|
|
28
79
|
onPointPointerMove,
|
|
29
80
|
selectedPointIndex,
|
|
81
|
+
pointLayer,
|
|
82
|
+
announceReadout = true,
|
|
83
|
+
slotCount,
|
|
84
|
+
slotOffset = 0,
|
|
30
85
|
...consumerProps
|
|
31
86
|
} = props;
|
|
32
87
|
const { min, max } = getValueBounds(data);
|
|
@@ -36,41 +91,27 @@ function LineChart(props) {
|
|
|
36
91
|
const readoutIndex = activePointIndex ?? selectedPointIndex ?? (data.length > 0 ? data.length - 1 : void 0);
|
|
37
92
|
const readoutPoint = readoutIndex === void 0 ? void 0 : data[readoutIndex];
|
|
38
93
|
const crosshairPoint = activePointIndex === void 0 ? void 0 : data[activePointIndex];
|
|
39
|
-
const points = data.map((point, index) =>
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
"data-part": "point-hit",
|
|
61
|
-
type: "button",
|
|
62
|
-
"aria-label": `Point ${String(point.time)}`,
|
|
63
|
-
"aria-pressed": isSelected,
|
|
64
|
-
onClick: () => onPointClick?.(index),
|
|
65
|
-
onKeyDown: handleKeyDown,
|
|
66
|
-
onPointerLeave: onPointPointerLeave,
|
|
67
|
-
onPointerMove: (event) => onPointPointerMove?.({ index, offsetY: event.nativeEvent.offsetY })
|
|
68
|
-
}
|
|
69
|
-
) : null
|
|
70
|
-
},
|
|
71
|
-
`${point.time}-${index}`
|
|
72
|
-
);
|
|
73
|
-
});
|
|
94
|
+
const points = pointLayer ?? /* @__PURE__ */ jsx("ol", { "data-part": "points", "aria-label": `${label} points`, style: pointsStyle(data.length), children: data.map((point, index) => /* @__PURE__ */ jsx(
|
|
95
|
+
LineChartPoint,
|
|
96
|
+
{
|
|
97
|
+
as: "li",
|
|
98
|
+
point,
|
|
99
|
+
previousPoint: data[index - 1],
|
|
100
|
+
index,
|
|
101
|
+
count: data.length,
|
|
102
|
+
min,
|
|
103
|
+
max,
|
|
104
|
+
interactive,
|
|
105
|
+
isActive: activePointIndex === index,
|
|
106
|
+
isSelected: selectedPointIndex === index,
|
|
107
|
+
cursorY,
|
|
108
|
+
onPointClick,
|
|
109
|
+
onPointPointerLeave,
|
|
110
|
+
onPointPointerMove
|
|
111
|
+
},
|
|
112
|
+
`${point.time}-${index}`
|
|
113
|
+
)) });
|
|
114
|
+
const crosshairFor = (index, y) => slotCount === void 0 ? crosshairStyle(index, data.length, y) : slotCrosshairStyle(slotOffset + index, slotCount, y);
|
|
74
115
|
return useRenderElement({
|
|
75
116
|
as,
|
|
76
117
|
defaultTag: "figure",
|
|
@@ -81,28 +122,20 @@ function LineChart(props) {
|
|
|
81
122
|
"data-interactive": interactive ? "" : void 0,
|
|
82
123
|
children: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
83
124
|
/* @__PURE__ */ jsx("figcaption", { children: label }),
|
|
84
|
-
interactive && readoutPoint ? /* @__PURE__ */ jsxs("div", { "data-part": "readout", "aria-live": "polite", children: [
|
|
125
|
+
interactive && readoutPoint ? /* @__PURE__ */ jsxs("div", { "data-part": "readout", "aria-live": announceReadout ? "polite" : "off", children: [
|
|
85
126
|
/* @__PURE__ */ jsx("span", { "data-part": "readout-time", children: String(readoutPoint.time) }),
|
|
86
127
|
/* @__PURE__ */ jsx("span", { children: readoutPoint.value })
|
|
87
128
|
] }) : null,
|
|
88
129
|
/* @__PURE__ */ jsxs("div", { "data-part": "plot", "aria-hidden": interactive ? void 0 : true, children: [
|
|
89
130
|
/* @__PURE__ */ jsx("div", { "data-part": "scroll-viewport", children: /* @__PURE__ */ jsxs("div", { "data-part": "canvas", children: [
|
|
90
131
|
/* @__PURE__ */ jsxs("div", { "data-part": "viewport", children: [
|
|
91
|
-
|
|
92
|
-
"ol",
|
|
93
|
-
{
|
|
94
|
-
"data-part": "points",
|
|
95
|
-
"aria-label": `${label} points`,
|
|
96
|
-
style: pointsStyle(data.length),
|
|
97
|
-
children: points
|
|
98
|
-
}
|
|
99
|
-
),
|
|
132
|
+
points,
|
|
100
133
|
interactive && crosshairPoint && activePointIndex !== void 0 ? /* @__PURE__ */ jsx(
|
|
101
134
|
"div",
|
|
102
135
|
{
|
|
103
136
|
"data-part": "crosshair",
|
|
104
137
|
"aria-hidden": "true",
|
|
105
|
-
style:
|
|
138
|
+
style: crosshairFor(activePointIndex, cursorY),
|
|
106
139
|
children: /* @__PURE__ */ jsx("span", { "data-part": "crosshair-marker", children: "+" })
|
|
107
140
|
}
|
|
108
141
|
) : null
|
|
@@ -120,7 +153,7 @@ function LineChart(props) {
|
|
|
120
153
|
"li",
|
|
121
154
|
{
|
|
122
155
|
"data-part": "crosshair-time",
|
|
123
|
-
style:
|
|
156
|
+
style: crosshairFor(activePointIndex, void 0),
|
|
124
157
|
children: String(crosshairPoint.time)
|
|
125
158
|
}
|
|
126
159
|
) : null
|
|
@@ -156,6 +189,7 @@ function LineChart(props) {
|
|
|
156
189
|
}
|
|
157
190
|
LineChart.displayName = "LineChart";
|
|
158
191
|
export {
|
|
159
|
-
LineChart
|
|
192
|
+
LineChart,
|
|
193
|
+
LineChartPoint
|
|
160
194
|
};
|
|
161
195
|
//# sourceMappingURL=LineChart.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/line-chart/LineChart.tsx"],"sourcesContent":["import type { ElementType, KeyboardEvent, PointerEvent, ReactElement } from \"react\";\nimport { useRenderElement } from \"@gunkin/uiify/core/render\";\nimport {\n axisLabelsFor,\n axisStyle,\n crosshairStyle,\n cursorStyle,\n geometryFor,\n getValueBounds,\n monthLabelsFor,\n pointStyle,\n pointsStyle,\n valueLabelsFor,\n} from \"./line-chart-geometry.js\";\nimport type { LineChartProps } from \"./types.js\";\n\nexport function LineChart<TAs extends ElementType = \"figure\">(\n props: LineChartProps<TAs>,\n): ReactElement | null {\n const {\n as,\n render,\n data,\n xAxis,\n yAxis,\n \"aria-label\": ariaLabel,\n activePointIndex,\n cursorY,\n interactive = false,\n onPointClick,\n onPointPointerLeave,\n onPointPointerMove,\n selectedPointIndex,\n ...consumerProps\n } = props as LineChartProps<\"figure\">;\n const { min, max } = getValueBounds(data);\n const label = ariaLabel ?? \"Line chart\";\n const timeLabels = axisLabelsFor(xAxis, monthLabelsFor(data));\n const valueLabels = axisLabelsFor(yAxis, valueLabelsFor(min, max));\n const readoutIndex =\n activePointIndex ?? selectedPointIndex ?? (data.length > 0 ? data.length - 1 : undefined);\n const readoutPoint = readoutIndex === undefined ? undefined : data[readoutIndex];\n const crosshairPoint = activePointIndex === undefined ? undefined : data[activePointIndex];\n const points = data.map((point, index) => {\n const geometry = geometryFor(point, data[index - 1], index, data.length, min, max);\n const isActive = activePointIndex === index;\n const isSelected = selectedPointIndex === index;\n const handleKeyDown = (event: KeyboardEvent<HTMLButtonElement>) => {\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n onPointClick?.(index);\n };\n\n return (\n <li\n key={`${point.time}-${index}`}\n aria-hidden={interactive ? undefined : true}\n data-crosshair-active={interactive && isActive ? \"\" : undefined}\n data-point-selected={interactive && isSelected ? \"\" : undefined}\n data-time={String(point.time)}\n data-trend={geometry.trend}\n style={pointStyle(geometry, isActive ? cursorY : undefined)}\n >\n {interactive ? (\n <button\n data-part=\"point-hit\"\n type=\"button\"\n aria-label={`Point ${String(point.time)}`}\n aria-pressed={isSelected}\n onClick={() => onPointClick?.(index)}\n onKeyDown={handleKeyDown}\n onPointerLeave={onPointPointerLeave}\n onPointerMove={(event: PointerEvent<HTMLButtonElement>) =>\n onPointPointerMove?.({ index, offsetY: event.nativeEvent.offsetY })\n }\n />\n ) : null}\n </li>\n );\n });\n\n return useRenderElement({\n as,\n defaultTag: \"figure\",\n props: {\n ...consumerProps,\n \"aria-label\": label,\n \"data-uiify-line-chart\": \"\",\n \"data-interactive\": interactive ? \"\" : undefined,\n children: (\n <>\n <figcaption>{label}</figcaption>\n {interactive && readoutPoint ? (\n <div data-part=\"readout\" aria-live=\"polite\">\n <span data-part=\"readout-time\">{String(readoutPoint.time)}</span>\n <span>{readoutPoint.value}</span>\n </div>\n ) : null}\n <div data-part=\"plot\" aria-hidden={interactive ? undefined : true}>\n <div data-part=\"scroll-viewport\">\n <div data-part=\"canvas\">\n <div data-part=\"viewport\">\n <ol\n data-part=\"points\"\n aria-label={`${label} points`}\n style={pointsStyle(data.length)}\n >\n {points}\n </ol>\n {interactive && crosshairPoint && activePointIndex !== undefined ? (\n <div\n data-part=\"crosshair\"\n aria-hidden=\"true\"\n style={crosshairStyle(activePointIndex, data.length, cursorY)}\n >\n <span data-part=\"crosshair-marker\">+</span>\n </div>\n ) : null}\n </div>\n <div data-part=\"time-viewport\">\n <ol data-part=\"time-axis\" data-axis=\"time\" aria-label={`${label} dates`}>\n {timeLabels.map((axisLabel, index) => (\n <li\n key={`${axisLabel.position}-${index}`}\n style={axisStyle(\"x\", axisLabel.position)}\n >\n {axisLabel.label}\n </li>\n ))}\n {interactive && crosshairPoint && activePointIndex !== undefined ? (\n <li\n data-part=\"crosshair-time\"\n style={crosshairStyle(activePointIndex, data.length, undefined)}\n >\n {String(crosshairPoint.time)}\n </li>\n ) : null}\n </ol>\n </div>\n </div>\n </div>\n <ol data-part=\"value-axis\" data-axis=\"value\" aria-label={`${label} values`}>\n {valueLabels.map((axisLabel, index) => (\n <li\n key={`${axisLabel.position}-${index}`}\n style={axisStyle(\"y\", axisLabel.position)}\n >\n {axisLabel.label}\n </li>\n ))}\n {interactive && crosshairPoint && activePointIndex !== undefined ? (\n <li data-part=\"crosshair-value\" style={cursorStyle(cursorY)}>\n {crosshairPoint.value}\n </li>\n ) : null}\n </ol>\n </div>\n <table data-part=\"data\" aria-label={`${label} data`}>\n <thead>\n <tr>\n <th scope=\"col\">Time</th>\n <th scope=\"col\">Value</th>\n </tr>\n </thead>\n <tbody>\n {data.map((point, index) => (\n <tr key={`${point.time}-${index}`}>\n <th scope=\"row\">{String(point.time)}</th>\n <td>{point.value}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </>\n ),\n },\n render,\n state: {},\n });\n}\nLineChart.displayName = \"LineChart\";\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/line-chart/LineChart.tsx"],"sourcesContent":["import type { ElementType, KeyboardEvent, PointerEvent, ReactElement } from \"react\";\nimport { useRenderElement } from \"@gunkin/uiify/core/render\";\nimport {\n axisLabelsFor,\n axisStyle,\n crosshairStyle,\n cursorStyle,\n geometryFor,\n getValueBounds,\n monthLabelsFor,\n pointStyle,\n pointsStyle,\n slotCrosshairStyle,\n valueLabelsFor,\n} from \"./line-chart-geometry.js\";\nimport type { LineChartPointProps, LineChartProps, LineChartViewProps } from \"./types.js\";\n\n/** One point and the segment from its predecessor; shared by the static list and virtual rows. */\nexport function LineChartPoint({\n as: Tag,\n point,\n previousPoint,\n index,\n count,\n min,\n max,\n interactive,\n isActive,\n isSelected,\n cursorY,\n onPointClick,\n onPointPointerLeave,\n onPointPointerMove,\n}: LineChartPointProps): ReactElement {\n const geometry = geometryFor(point, previousPoint, index, count, min, max);\n const handleKeyDown = (event: KeyboardEvent<HTMLButtonElement>) => {\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n onPointClick?.(index);\n };\n\n return (\n <Tag\n aria-hidden={interactive ? undefined : true}\n data-part=\"point\"\n data-first={previousPoint === undefined ? \"\" : undefined}\n data-crosshair-active={interactive && isActive ? \"\" : undefined}\n data-point-selected={interactive && isSelected ? \"\" : undefined}\n data-time={String(point.time)}\n data-trend={geometry.trend}\n style={pointStyle(geometry, isActive ? cursorY : undefined)}\n >\n {interactive ? (\n <button\n data-part=\"point-hit\"\n type=\"button\"\n aria-label={`Point ${String(point.time)}`}\n aria-pressed={isSelected}\n onClick={() => onPointClick?.(index)}\n onKeyDown={handleKeyDown}\n onPointerLeave={onPointPointerLeave}\n onPointerMove={(event: PointerEvent<HTMLButtonElement>) =>\n onPointPointerMove?.({ index, offsetY: event.nativeEvent.offsetY })\n }\n />\n ) : null}\n </Tag>\n );\n}\nLineChartPoint.displayName = \"LineChartPoint\";\n\nexport function LineChart<TAs extends ElementType = \"figure\">(\n props: LineChartProps<TAs>,\n): ReactElement | null {\n const {\n as,\n render,\n data,\n xAxis,\n yAxis,\n \"aria-label\": ariaLabel,\n activePointIndex,\n cursorY,\n interactive = false,\n onPointClick,\n onPointPointerLeave,\n onPointPointerMove,\n selectedPointIndex,\n pointLayer,\n announceReadout = true,\n slotCount,\n slotOffset = 0,\n ...consumerProps\n } = props as LineChartProps<\"figure\"> & LineChartViewProps;\n const { min, max } = getValueBounds(data);\n const label = ariaLabel ?? \"Line chart\";\n const timeLabels = axisLabelsFor(xAxis, monthLabelsFor(data));\n const valueLabels = axisLabelsFor(yAxis, valueLabelsFor(min, max));\n const readoutIndex =\n activePointIndex ?? selectedPointIndex ?? (data.length > 0 ? data.length - 1 : undefined);\n const readoutPoint = readoutIndex === undefined ? undefined : data[readoutIndex];\n const crosshairPoint = activePointIndex === undefined ? undefined : data[activePointIndex];\n const points = pointLayer ?? (\n <ol data-part=\"points\" aria-label={`${label} points`} style={pointsStyle(data.length)}>\n {data.map((point, index) => (\n <LineChartPoint\n key={`${point.time}-${index}`}\n as=\"li\"\n point={point}\n previousPoint={data[index - 1]}\n index={index}\n count={data.length}\n min={min}\n max={max}\n interactive={interactive}\n isActive={activePointIndex === index}\n isSelected={selectedPointIndex === index}\n cursorY={cursorY}\n onPointClick={onPointClick}\n onPointPointerLeave={onPointPointerLeave}\n onPointPointerMove={onPointPointerMove}\n />\n ))}\n </ol>\n );\n const crosshairFor = (index: number, y: number | undefined) =>\n slotCount === undefined\n ? crosshairStyle(index, data.length, y)\n : slotCrosshairStyle(slotOffset + index, slotCount, y);\n\n return useRenderElement({\n as,\n defaultTag: \"figure\",\n props: {\n ...consumerProps,\n \"aria-label\": label,\n \"data-uiify-line-chart\": \"\",\n \"data-interactive\": interactive ? \"\" : undefined,\n children: (\n <>\n <figcaption>{label}</figcaption>\n {interactive && readoutPoint ? (\n <div data-part=\"readout\" aria-live={announceReadout ? \"polite\" : \"off\"}>\n <span data-part=\"readout-time\">{String(readoutPoint.time)}</span>\n <span>{readoutPoint.value}</span>\n </div>\n ) : null}\n <div data-part=\"plot\" aria-hidden={interactive ? undefined : true}>\n <div data-part=\"scroll-viewport\">\n <div data-part=\"canvas\">\n <div data-part=\"viewport\">\n {points}\n {interactive && crosshairPoint && activePointIndex !== undefined ? (\n <div\n data-part=\"crosshair\"\n aria-hidden=\"true\"\n style={crosshairFor(activePointIndex, cursorY)}\n >\n <span data-part=\"crosshair-marker\">+</span>\n </div>\n ) : null}\n </div>\n <div data-part=\"time-viewport\">\n <ol data-part=\"time-axis\" data-axis=\"time\" aria-label={`${label} dates`}>\n {timeLabels.map((axisLabel, index) => (\n <li\n key={`${axisLabel.position}-${index}`}\n style={axisStyle(\"x\", axisLabel.position)}\n >\n {axisLabel.label}\n </li>\n ))}\n {interactive && crosshairPoint && activePointIndex !== undefined ? (\n <li\n data-part=\"crosshair-time\"\n style={crosshairFor(activePointIndex, undefined)}\n >\n {String(crosshairPoint.time)}\n </li>\n ) : null}\n </ol>\n </div>\n </div>\n </div>\n <ol data-part=\"value-axis\" data-axis=\"value\" aria-label={`${label} values`}>\n {valueLabels.map((axisLabel, index) => (\n <li\n key={`${axisLabel.position}-${index}`}\n style={axisStyle(\"y\", axisLabel.position)}\n >\n {axisLabel.label}\n </li>\n ))}\n {interactive && crosshairPoint && activePointIndex !== undefined ? (\n <li data-part=\"crosshair-value\" style={cursorStyle(cursorY)}>\n {crosshairPoint.value}\n </li>\n ) : null}\n </ol>\n </div>\n <table data-part=\"data\" aria-label={`${label} data`}>\n <thead>\n <tr>\n <th scope=\"col\">Time</th>\n <th scope=\"col\">Value</th>\n </tr>\n </thead>\n <tbody>\n {data.map((point, index) => (\n <tr key={`${point.time}-${index}`}>\n <th scope=\"row\">{String(point.time)}</th>\n <td>{point.value}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </>\n ),\n },\n render,\n state: {},\n });\n}\nLineChart.displayName = \"LineChart\";\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ElementType, ReactElement } from "react";
|
|
2
|
-
import type {
|
|
3
|
-
export declare function LineChartClient<TAs extends ElementType = "figure">(props:
|
|
2
|
+
import type { LineChartClientProps } from "../types.js";
|
|
3
|
+
export declare function LineChartClient<TAs extends ElementType = "figure">(props: LineChartClientProps<TAs>): ReactElement | null;
|
|
4
4
|
export declare namespace LineChartClient {
|
|
5
5
|
var displayName: string;
|
|
6
6
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LineChartClient.d.ts","sourceRoot":"","sources":["../../../../src/components/line-chart/client/LineChartClient.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAiB,WAAW,EAAE,YAAY,EAAO,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"LineChartClient.d.ts","sourceRoot":"","sources":["../../../../src/components/line-chart/client/LineChartClient.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAiB,WAAW,EAAE,YAAY,EAAO,MAAM,OAAO,CAAC;AAY3E,OAAO,KAAK,EACV,oBAAoB,EAKrB,MAAM,aAAa,CAAC;AAwBrB,wBAAgB,eAAe,CAAC,GAAG,SAAS,WAAW,GAAG,QAAQ,EAChE,KAAK,EAAE,oBAAoB,CAAC,GAAG,CAAC,GAC/B,YAAY,GAAG,IAAI,CAqJrB;yBAvJe,eAAe"}
|