wick-charts 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/LICENSE +21 -0
- package/README.md +545 -0
- package/dist/axis.d.ts +21 -0
- package/dist/axis.js +44 -0
- package/dist/dataSource.d.ts +24 -0
- package/dist/dataSource.js +1 -0
- package/dist/hitTest.d.ts +31 -0
- package/dist/hitTest.js +46 -0
- package/dist/hybridScale.d.ts +25 -0
- package/dist/hybridScale.js +41 -0
- package/dist/index.d.ts +225 -0
- package/dist/index.js +715 -0
- package/dist/mergeSeries.d.ts +14 -0
- package/dist/mergeSeries.js +21 -0
- package/dist/plugins/types.d.ts +140 -0
- package/dist/plugins/types.js +1 -0
- package/dist/priceAxis.d.ts +7 -0
- package/dist/priceAxis.js +49 -0
- package/dist/priceRange.d.ts +12 -0
- package/dist/priceRange.js +16 -0
- package/dist/renderer.d.ts +79 -0
- package/dist/renderer.js +318 -0
- package/dist/scale.d.ts +20 -0
- package/dist/scale.js +29 -0
- package/dist/series/candlestick.d.ts +20 -0
- package/dist/series/candlestick.js +88 -0
- package/dist/series/registry.d.ts +13 -0
- package/dist/series/registry.js +30 -0
- package/dist/series/types.d.ts +56 -0
- package/dist/series/types.js +1 -0
- package/dist/testHelpers.d.ts +38 -0
- package/dist/testHelpers.js +50 -0
- package/dist/time.d.ts +6 -0
- package/dist/time.js +58 -0
- package/dist/types.d.ts +151 -0
- package/dist/types.js +1 -0
- package/dist/viewport.d.ts +52 -0
- package/dist/viewport.js +87 -0
- package/dist/wasm.d.ts +29 -0
- package/dist/wasm.js +35 -0
- package/dist/wasmImporter.d.ts +6 -0
- package/dist/wasmImporter.js +7 -0
- package/package.json +39 -0
- package/wasm-pkg/package.json +21 -0
- package/wasm-pkg/wickchart_core.d.ts +59 -0
- package/wasm-pkg/wickchart_core.js +227 -0
- package/wasm-pkg/wickchart_core_bg.wasm +0 -0
- package/wasm-pkg/wickchart_core_bg.wasm.d.ts +11 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Perpendicular distance, in px, from `(px, py)` to the line segment
|
|
3
|
+
* `(x1, y1)`-`(x2, y2)` — clamped to the segment itself, so a point beyond
|
|
4
|
+
* either endpoint measures against that endpoint rather than the infinite
|
|
5
|
+
* line the segment sits on.
|
|
6
|
+
*
|
|
7
|
+
* Every interactive plugin that draws a line-shaped thing (a trend line, a
|
|
8
|
+
* ray, an edge of a rectangle) eventually needs to answer "did the user
|
|
9
|
+
* click on/near the thing I already placed" so it can be selected, dragged,
|
|
10
|
+
* or deleted — and the endpoint-clamping is easy to get subtly wrong when
|
|
11
|
+
* re-derived per plugin, so it lives here once instead.
|
|
12
|
+
*/
|
|
13
|
+
export declare function distanceToSegment(px: number, py: number, x1: number, y1: number, x2: number, y2: number): number;
|
|
14
|
+
/**
|
|
15
|
+
* `true` if `(px, py)` is within `tolerancePx` of the segment
|
|
16
|
+
* `(x1, y1)`-`(x2, y2)`. Defaults to 6px — comfortably clickable with a
|
|
17
|
+
* mouse pointer, still forgiving enough for an imprecise fingertip on
|
|
18
|
+
* touch. Call it from `onPointerDown`/`onPointerMove` with the event's
|
|
19
|
+
* `x`/`y` and the shape's own endpoints converted to pixels via the
|
|
20
|
+
* event's `xForIndex`/`yForValue` (a shape stored in data space survives
|
|
21
|
+
* pan/zoom; converting it to pixels at hit-test time, rather than storing
|
|
22
|
+
* pixels directly, is what keeps a placed line lined up with the candles
|
|
23
|
+
* it was drawn against after the user scrolls or zooms).
|
|
24
|
+
*/
|
|
25
|
+
export declare function hitTestSegment(px: number, py: number, x1: number, y1: number, x2: number, y2: number, tolerancePx?: number): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* `true` if `(px, py)` is within `tolerancePx` of the point `(x, y)` — for
|
|
28
|
+
* hit-testing a marker, a drag handle, or a single endpoint of a shape
|
|
29
|
+
* rather than an edge.
|
|
30
|
+
*/
|
|
31
|
+
export declare function hitTestPoint(px: number, py: number, x: number, y: number, tolerancePx?: number): boolean;
|
package/dist/hitTest.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Perpendicular distance, in px, from `(px, py)` to the line segment
|
|
3
|
+
* `(x1, y1)`-`(x2, y2)` — clamped to the segment itself, so a point beyond
|
|
4
|
+
* either endpoint measures against that endpoint rather than the infinite
|
|
5
|
+
* line the segment sits on.
|
|
6
|
+
*
|
|
7
|
+
* Every interactive plugin that draws a line-shaped thing (a trend line, a
|
|
8
|
+
* ray, an edge of a rectangle) eventually needs to answer "did the user
|
|
9
|
+
* click on/near the thing I already placed" so it can be selected, dragged,
|
|
10
|
+
* or deleted — and the endpoint-clamping is easy to get subtly wrong when
|
|
11
|
+
* re-derived per plugin, so it lives here once instead.
|
|
12
|
+
*/
|
|
13
|
+
export function distanceToSegment(px, py, x1, y1, x2, y2) {
|
|
14
|
+
const dx = x2 - x1;
|
|
15
|
+
const dy = y2 - y1;
|
|
16
|
+
const lengthSquared = dx * dx + dy * dy;
|
|
17
|
+
if (lengthSquared === 0)
|
|
18
|
+
return Math.hypot(px - x1, py - y1); // a zero-length "segment" is just a point
|
|
19
|
+
let t = ((px - x1) * dx + (py - y1) * dy) / lengthSquared;
|
|
20
|
+
t = Math.max(0, Math.min(1, t));
|
|
21
|
+
const closestX = x1 + t * dx;
|
|
22
|
+
const closestY = y1 + t * dy;
|
|
23
|
+
return Math.hypot(px - closestX, py - closestY);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* `true` if `(px, py)` is within `tolerancePx` of the segment
|
|
27
|
+
* `(x1, y1)`-`(x2, y2)`. Defaults to 6px — comfortably clickable with a
|
|
28
|
+
* mouse pointer, still forgiving enough for an imprecise fingertip on
|
|
29
|
+
* touch. Call it from `onPointerDown`/`onPointerMove` with the event's
|
|
30
|
+
* `x`/`y` and the shape's own endpoints converted to pixels via the
|
|
31
|
+
* event's `xForIndex`/`yForValue` (a shape stored in data space survives
|
|
32
|
+
* pan/zoom; converting it to pixels at hit-test time, rather than storing
|
|
33
|
+
* pixels directly, is what keeps a placed line lined up with the candles
|
|
34
|
+
* it was drawn against after the user scrolls or zooms).
|
|
35
|
+
*/
|
|
36
|
+
export function hitTestSegment(px, py, x1, y1, x2, y2, tolerancePx = 6) {
|
|
37
|
+
return distanceToSegment(px, py, x1, y1, x2, y2) <= tolerancePx;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* `true` if `(px, py)` is within `tolerancePx` of the point `(x, y)` — for
|
|
41
|
+
* hit-testing a marker, a drag handle, or a single endpoint of a shape
|
|
42
|
+
* rather than an edge.
|
|
43
|
+
*/
|
|
44
|
+
export function hitTestPoint(px, py, x, y, tolerancePx = 6) {
|
|
45
|
+
return Math.hypot(px - x, py - y) <= tolerancePx;
|
|
46
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { WasmModule } from './wasm.js';
|
|
2
|
+
/** Below this many points, a `LinearScale.mapMany` call is already just a
|
|
3
|
+
* handful of multiplications — crossing into WASM would spend more time on
|
|
4
|
+
* the JS↔WASM boundary than the JS version spends on the whole computation. */
|
|
5
|
+
export declare const WASM_SCALE_THRESHOLD = 500;
|
|
6
|
+
export interface Scale {
|
|
7
|
+
map(value: number): number;
|
|
8
|
+
mapMany(values: number[]): number[];
|
|
9
|
+
}
|
|
10
|
+
export interface DisposableScale {
|
|
11
|
+
scale: Scale;
|
|
12
|
+
dispose(): void;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Picks JS or WASM for a domain→range mapping based on how many points
|
|
16
|
+
* will go through it. `wasmModule` defaults to whatever `loadWasm` (see
|
|
17
|
+
* wasm.ts) has cached so far — pass it explicitly in tests instead of
|
|
18
|
+
* depending on that module-level cache.
|
|
19
|
+
*
|
|
20
|
+
* Always returns a `dispose()` — a no-op for the JS path, a real WASM
|
|
21
|
+
* memory free for the WASM path — so call sites can treat both uniformly
|
|
22
|
+
* (`try { ... } finally { result.dispose() }`) without branching on which
|
|
23
|
+
* one they got.
|
|
24
|
+
*/
|
|
25
|
+
export declare function createScale(domainMin: number, domainMax: number, rangeMin: number, rangeMax: number, pointCount: number, wasmModule?: WasmModule | null): DisposableScale;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { LinearScale } from './scale.js';
|
|
2
|
+
import { getCachedWasmModule } from './wasm.js';
|
|
3
|
+
/** Below this many points, a `LinearScale.mapMany` call is already just a
|
|
4
|
+
* handful of multiplications — crossing into WASM would spend more time on
|
|
5
|
+
* the JS↔WASM boundary than the JS version spends on the whole computation. */
|
|
6
|
+
export const WASM_SCALE_THRESHOLD = 500;
|
|
7
|
+
/** A `Scale` backed by a `wasm-bindgen`-generated instance, freeing its
|
|
8
|
+
* WASM-side memory via `dispose()` — callers must call this once done
|
|
9
|
+
* (the renderer does so in a `finally`) since nothing else will. */
|
|
10
|
+
class WasmBackedScale {
|
|
11
|
+
constructor(wasm, domainMin, domainMax, rangeMin, rangeMax) {
|
|
12
|
+
this.inner = new wasm.Scale(domainMin, domainMax, rangeMin, rangeMax);
|
|
13
|
+
}
|
|
14
|
+
map(value) {
|
|
15
|
+
return this.inner.map(value);
|
|
16
|
+
}
|
|
17
|
+
mapMany(values) {
|
|
18
|
+
return Array.from(this.inner.map_many(Float64Array.from(values)));
|
|
19
|
+
}
|
|
20
|
+
dispose() {
|
|
21
|
+
this.inner.free();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Picks JS or WASM for a domain→range mapping based on how many points
|
|
26
|
+
* will go through it. `wasmModule` defaults to whatever `loadWasm` (see
|
|
27
|
+
* wasm.ts) has cached so far — pass it explicitly in tests instead of
|
|
28
|
+
* depending on that module-level cache.
|
|
29
|
+
*
|
|
30
|
+
* Always returns a `dispose()` — a no-op for the JS path, a real WASM
|
|
31
|
+
* memory free for the WASM path — so call sites can treat both uniformly
|
|
32
|
+
* (`try { ... } finally { result.dispose() }`) without branching on which
|
|
33
|
+
* one they got.
|
|
34
|
+
*/
|
|
35
|
+
export function createScale(domainMin, domainMax, rangeMin, rangeMax, pointCount, wasmModule = getCachedWasmModule()) {
|
|
36
|
+
if (wasmModule && pointCount >= WASM_SCALE_THRESHOLD) {
|
|
37
|
+
const scale = new WasmBackedScale(wasmModule, domainMin, domainMax, rangeMin, rangeMax);
|
|
38
|
+
return { scale, dispose: () => scale.dispose() };
|
|
39
|
+
}
|
|
40
|
+
return { scale: new LinearScale(domainMin, domainMax, rangeMin, rangeMax), dispose: () => { } };
|
|
41
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import type { DataLoader } from './dataSource.js';
|
|
2
|
+
import type { ChartPlugin } from './plugins/types.js';
|
|
3
|
+
import type { CandlestickStyle } from './series/candlestick.js';
|
|
4
|
+
import type { Candle, WickChartOptions, SeriesPoint, ValueRange } from './types.js';
|
|
5
|
+
export type { BusinessDay, Candle, WickChartOptions, WickTime, SeriesPoint, UnixMillis, ValueRange } from './types.js';
|
|
6
|
+
export type { DataLoader, DataRequest } from './dataSource.js';
|
|
7
|
+
export type { ChartPlugin, ChartPointerEvent, PluginRenderApi } from './plugins/types.js';
|
|
8
|
+
export { distanceToSegment, hitTestPoint, hitTestSegment } from './hitTest.js';
|
|
9
|
+
export type { Scale } from './hybridScale.js';
|
|
10
|
+
export { mergeSeriesPoints } from './mergeSeries.js';
|
|
11
|
+
export { registerSeries, getSeries } from './series/registry.js';
|
|
12
|
+
export type { SeriesDefinition, SeriesDrawContext } from './series/types.js';
|
|
13
|
+
export type { CandlestickStyle } from './series/candlestick.js';
|
|
14
|
+
export { candlestickSeries } from './series/candlestick.js';
|
|
15
|
+
export { LinearScale } from './scale.js';
|
|
16
|
+
export { toUnixSeconds } from './time.js';
|
|
17
|
+
export { Viewport } from './viewport.js';
|
|
18
|
+
export { getCachedWasmModule, loadWasm } from './wasm.js';
|
|
19
|
+
/**
|
|
20
|
+
* Interactive chart: drag to pan, wheel to zoom, drag the price-axis strip
|
|
21
|
+
* to rescale it, hover a point for a legend. What gets plotted (candles
|
|
22
|
+
* today; a future line/area/bar series) is decided entirely by
|
|
23
|
+
* `options.type` and the `SeriesDefinition` registered under it — this
|
|
24
|
+
* class only owns generic engine concerns (viewport math, mouse/touch/wheel
|
|
25
|
+
* handling, on-demand data loading, render scheduling) and never touches a
|
|
26
|
+
* point's fields directly. Construct once per canvas; call `destroy()`
|
|
27
|
+
* when done with it (unmount) to remove the window-level mouseup listener.
|
|
28
|
+
*/
|
|
29
|
+
export declare class WickChart<TPoint extends SeriesPoint = Candle> {
|
|
30
|
+
private canvas;
|
|
31
|
+
private renderer;
|
|
32
|
+
private seriesDefinition;
|
|
33
|
+
private sorted;
|
|
34
|
+
private times;
|
|
35
|
+
private viewport;
|
|
36
|
+
private hoverIndex;
|
|
37
|
+
/** Device-pixel y of the pointer/finger that produced `hoverIndex` — the
|
|
38
|
+
* crosshair's horizontal line follows this directly, not any property of
|
|
39
|
+
* the hovered point itself (see `ChartRenderer.renderCrosshairAndLegend`
|
|
40
|
+
* for why: pinning it to, say, the candle's close would leave the line
|
|
41
|
+
* motionless while the pointer moves within that candle's column). */
|
|
42
|
+
private hoverY;
|
|
43
|
+
private plugins;
|
|
44
|
+
/** The plugin whose `onPointerDown` returned `true` for the pointer
|
|
45
|
+
* currently down, or `null` when no plugin has claimed the current
|
|
46
|
+
* gesture (the common case — the chart handles it itself). */
|
|
47
|
+
private activeGesturePlugin;
|
|
48
|
+
private dragMode;
|
|
49
|
+
private lastX;
|
|
50
|
+
private lastY;
|
|
51
|
+
private renderScheduled;
|
|
52
|
+
private pendingAnimationFrame;
|
|
53
|
+
/** Distance (CSS px) between two touches on the previous touchmove —
|
|
54
|
+
* `null` whenever fewer than two fingers are down. Compared frame to
|
|
55
|
+
* frame (not against a fixed start value) so it composes naturally with
|
|
56
|
+
* the same incremental-delta style `applyPanDelta`/`applyValueScaleDelta`
|
|
57
|
+
* already use. */
|
|
58
|
+
private pinchLastDistance;
|
|
59
|
+
/** Where the current single-finger touch landed — compared against the
|
|
60
|
+
* live position to tell a hold from a drag; see LONG_PRESS_MOVE_TOLERANCE_PX. */
|
|
61
|
+
private touchStartX;
|
|
62
|
+
private touchStartY;
|
|
63
|
+
private longPressTimer;
|
|
64
|
+
private loader;
|
|
65
|
+
private loadThreshold;
|
|
66
|
+
private loading;
|
|
67
|
+
/** Set once a loader for a direction returns empty — stops re-asking at
|
|
68
|
+
* every threshold crossing until `setData` resets it (a fresh dataset
|
|
69
|
+
* may come from a different source that does have more). */
|
|
70
|
+
private exhausted;
|
|
71
|
+
constructor(canvas: HTMLCanvasElement, options?: WickChartOptions);
|
|
72
|
+
setData(points: TPoint[]): this;
|
|
73
|
+
/**
|
|
74
|
+
* Registers a callback the chart asks for more points when the visible
|
|
75
|
+
* window gets within `threshold` points of either edge of what's
|
|
76
|
+
* currently loaded. The chart never fetches on its own — it only decides
|
|
77
|
+
* *when* more data is needed and merges what the loader returns; the
|
|
78
|
+
* loader owns *how* (REST call, cache, websocket replay, whatever).
|
|
79
|
+
*/
|
|
80
|
+
setDataLoader(loader: DataLoader<TPoint>, threshold?: number): this;
|
|
81
|
+
/** Registers a plugin (marker, annotation, drawing tool, ...) drawn on
|
|
82
|
+
* top of the chart every frame after the series and axes — see
|
|
83
|
+
* `src/plugins/types.ts`. Adding overlay features this way, rather than
|
|
84
|
+
* by extending `WickChart` itself, is what keeps the core closed to
|
|
85
|
+
* modification: a marker implementation never needs to touch this file. */
|
|
86
|
+
addPlugin(plugin: ChartPlugin<TPoint>): this;
|
|
87
|
+
removePlugin(plugin: ChartPlugin<TPoint>): this;
|
|
88
|
+
/** Every currently-registered plugin, in registration order — for an app
|
|
89
|
+
* building a management UI (a list of attached indicators/drawing tools
|
|
90
|
+
* with visibility toggles or delete buttons) without maintaining its own
|
|
91
|
+
* parallel bookkeeping of every `addPlugin` call. A copy, not a live
|
|
92
|
+
* view: mutating the returned array doesn't affect the chart. */
|
|
93
|
+
getPlugins(): readonly ChartPlugin<TPoint>[];
|
|
94
|
+
/** Shows or hides every plugin whose `id` matches (see `ChartPlugin.id`)
|
|
95
|
+
* and re-renders. A no-op, not an error, if nothing matches — plugins
|
|
96
|
+
* with no `id` set are never matched. */
|
|
97
|
+
setPluginVisible(id: string, visible: boolean): this;
|
|
98
|
+
render(): void;
|
|
99
|
+
/** Coalesces render() calls into at most one per animation frame. Mouse
|
|
100
|
+
* events (drag, wheel) can fire far faster than the display refreshes —
|
|
101
|
+
* calling render() directly from each one redraws the full canvas once
|
|
102
|
+
* per event instead of once per frame, which is what actually causes
|
|
103
|
+
* dragging to feel janky, not anything data-loading does. */
|
|
104
|
+
private scheduleRender;
|
|
105
|
+
/** How many points are currently loaded (not just visible) — grows as
|
|
106
|
+
* `setDataLoader`'s loader supplies more history. */
|
|
107
|
+
getPointCount(): number;
|
|
108
|
+
/** The currently visible window, in point indices into the full loaded
|
|
109
|
+
* series. Useful for building UI around the chart (a minimap, a "jump to
|
|
110
|
+
* latest" button) without reaching into private state. */
|
|
111
|
+
getVisibleRange(): {
|
|
112
|
+
startIndex: number;
|
|
113
|
+
endIndex: number;
|
|
114
|
+
visibleCount: number;
|
|
115
|
+
};
|
|
116
|
+
/** The value axis's manual range once the user has dragged or scaled it
|
|
117
|
+
* — `null` if the axis is still auto-fitting to whatever's visible
|
|
118
|
+
* (the default until the user first touches it vertically). */
|
|
119
|
+
getValueRangeOverride(): ValueRange | null;
|
|
120
|
+
/** The point currently under the cursor (crosshair/legend target), or
|
|
121
|
+
* `null` when nothing is hovered. */
|
|
122
|
+
getHoveredPoint(): TPoint | null;
|
|
123
|
+
/** Removes all attached listeners. Call on unmount — the mouseup
|
|
124
|
+
* listener is on `window` (so drags don't get stuck if the cursor
|
|
125
|
+
* leaves the canvas mid-drag) and won't be garbage-collected on its own. */
|
|
126
|
+
destroy(): void;
|
|
127
|
+
private attachEvents;
|
|
128
|
+
private onMouseDown;
|
|
129
|
+
private onMouseMove;
|
|
130
|
+
private onMouseUp;
|
|
131
|
+
private onMouseLeave;
|
|
132
|
+
/** Shared by both mouse drag and single-finger touch drag: shifts the
|
|
133
|
+
* visible time window and, once the value axis is in manual mode, the
|
|
134
|
+
* visible value window too — see the "pan" branch `onMouseMove` used to
|
|
135
|
+
* inline before mouse and touch needed the exact same math. */
|
|
136
|
+
private applyPanDelta;
|
|
137
|
+
/** Shared by both mouse drag and single-finger touch drag on the
|
|
138
|
+
* price-axis strip. */
|
|
139
|
+
private applyValueScaleDelta;
|
|
140
|
+
private onTouchStart;
|
|
141
|
+
private onTouchMove;
|
|
142
|
+
private onTouchEnd;
|
|
143
|
+
private clearLongPressTimer;
|
|
144
|
+
private touchDistance;
|
|
145
|
+
private onWheel;
|
|
146
|
+
private updateHover;
|
|
147
|
+
/** Checks whether the visible window is close enough to either edge of
|
|
148
|
+
* the loaded data to ask `this.loader` for more. Safe to call after
|
|
149
|
+
* every render — guarded so it never fires two overlapping requests for
|
|
150
|
+
* the same direction or re-asks a direction that already came back
|
|
151
|
+
* empty. */
|
|
152
|
+
private maybeLoadMore;
|
|
153
|
+
private requestMore;
|
|
154
|
+
private applyLoadedPoints;
|
|
155
|
+
/** Switches the price/value axis to manual mode if it hasn't been
|
|
156
|
+
* already, seeding it from the current auto-fit range so the first pixel
|
|
157
|
+
* of a drag doesn't jump. No-op on subsequent calls (already manual). */
|
|
158
|
+
private ensureValueRangeOverride;
|
|
159
|
+
/** The value range the *next* render would use — whatever's already
|
|
160
|
+
* manually overridden, or a fresh auto-fit computed the same way
|
|
161
|
+
* `ChartRenderer.render` does. Used outside of a render pass itself, by
|
|
162
|
+
* anything that needs to convert a pixel position to a data value
|
|
163
|
+
* on-demand (`valueForY`, dispatched pointer events) rather than only
|
|
164
|
+
* during `render()`. `null` when there's nothing to compute one from. */
|
|
165
|
+
private frameValueRange;
|
|
166
|
+
/** y pixel -> value in the range the next render would use. `null` if
|
|
167
|
+
* there's no data or no usable chart area to compute one against — see
|
|
168
|
+
* `ChartPointerEvent.value`. */
|
|
169
|
+
private valueForY;
|
|
170
|
+
/** x pixel -> global (possibly fractional) index — the exact inverse of
|
|
171
|
+
* the renderer's own `xForIndex`, so a pointer event lines up with
|
|
172
|
+
* wherever the chart itself would draw that index. */
|
|
173
|
+
private indexForX;
|
|
174
|
+
/** Global (possibly fractional) index -> x pixel — the exact inverse of
|
|
175
|
+
* `indexForX` above, and the same formula `ChartRenderer.render` draws
|
|
176
|
+
* with for the current viewport. Exposed on `ChartPointerEvent` so a
|
|
177
|
+
* plugin can convert a shape it's storing in data space back to pixels
|
|
178
|
+
* for hit-testing, without duplicating this math itself. */
|
|
179
|
+
private xForIndex;
|
|
180
|
+
/** Value in the range the next render would use -> y pixel — the exact
|
|
181
|
+
* inverse of `valueForY` above. `null` under the same conditions
|
|
182
|
+
* `valueForY` returns `null` for. */
|
|
183
|
+
private yForValue;
|
|
184
|
+
private pointerEventAt;
|
|
185
|
+
/** Same as `pointerEventAt`, but starting from `lastX`/`lastY` (raw
|
|
186
|
+
* `clientX`/`clientY`, tracked on every pointer move) instead of
|
|
187
|
+
* already-converted chart-area pixels — for the two touch-end paths
|
|
188
|
+
* where there's no current touch position to read coordinates from. */
|
|
189
|
+
private pointerEventAtLast;
|
|
190
|
+
/** Offers a pointer-down at `(x, y)` (chart-area pixels) to each plugin
|
|
191
|
+
* in reverse-registration order, stopping at the first one whose
|
|
192
|
+
* `onPointerDown` returns `true`. That plugin becomes
|
|
193
|
+
* `activeGesturePlugin` for the rest of the gesture; returns whether
|
|
194
|
+
* anyone claimed it, so callers know whether to skip their own default
|
|
195
|
+
* pan/price-scale handling. */
|
|
196
|
+
private dispatchPointerDown;
|
|
197
|
+
/** Position in canvas backing-store pixels, accounting for the gap
|
|
198
|
+
* between the canvas's CSS display size and its drawing-buffer size
|
|
199
|
+
* (e.g. when the canvas width attribute is device-pixel-ratio scaled).
|
|
200
|
+
* Takes any `{clientX, clientY}` point rather than `MouseEvent`
|
|
201
|
+
* specifically, since a `Touch` (or a synthesized pinch midpoint) has
|
|
202
|
+
* the same two fields and needs the exact same conversion. */
|
|
203
|
+
private cursorPosition;
|
|
204
|
+
/** CSS-pixel-to-backing-store-pixel ratio for the X axis — same
|
|
205
|
+
* conversion `cursorPosition` applies to absolute coordinates, extracted
|
|
206
|
+
* so pixel *deltas* (drag distance, wheel deltaX) can be converted too. */
|
|
207
|
+
private devicePixelScaleX;
|
|
208
|
+
private devicePixelScaleY;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* `new WickChart(canvas, { type: 'candlestick', style: {...} })` type-checks
|
|
212
|
+
* even if `style` has nothing to do with `CandlestickStyle` — `type` is a
|
|
213
|
+
* runtime string the registry resolves, so nothing ties it to a specific
|
|
214
|
+
* `TStyle` at the type level (see `src/series/registry.ts`). This factory
|
|
215
|
+
* pins both `TPoint` (`Candle`) and `TStyle` (`CandlestickStyle`) for the
|
|
216
|
+
* one series built into the library, so `style` is fully checked here.
|
|
217
|
+
*
|
|
218
|
+
* A new series type gets the same treatment: export an equivalent
|
|
219
|
+
* `create<Name>Chart` next to it (in your own module, or a file like this
|
|
220
|
+
* one) rather than widening `WickChartOptions` itself — that keeps every
|
|
221
|
+
* series's style shape independent of every other's.
|
|
222
|
+
*/
|
|
223
|
+
export declare function createCandlestickChart(canvas: HTMLCanvasElement, options?: Omit<WickChartOptions, 'type' | 'style'> & {
|
|
224
|
+
style?: Partial<CandlestickStyle>;
|
|
225
|
+
}): WickChart<Candle>;
|