@pradeepjadhav/trading-reload-chart 1.1.1 → 1.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/dist/canvas/layers/CrosshairLayer.d.ts +1 -0
- package/dist/canvas/layers/ExistingCandlesLayer.d.ts +37 -0
- package/dist/canvas/layers/ShapesLayer/ShapesLayer.d.ts +1 -0
- package/dist/canvas/layers/ShapesLayer/ShapesLayer.types.d.ts +1 -0
- package/dist/chart/ChartController.d.ts +5 -0
- package/dist/chart/ChartController.types.d.ts +21 -0
- package/dist/config/chartConfig.types.d.ts +4 -4
- package/dist/index.d.ts +1 -0
- package/dist/models/ChartSync.types.d.ts +16 -0
- package/dist/react/TradingReload.types.d.ts +40 -0
- package/dist/trading-reload-chart.js +631 -475
- package/package.json +1 -1
|
@@ -9,6 +9,7 @@ export declare class CrosshairLayer {
|
|
|
9
9
|
crosshairStyle: CrosshairStyle;
|
|
10
10
|
constructor(options: CrosshairLayerOptions);
|
|
11
11
|
updateMousePosition(x: number, y: number, options?: UpdateMousePositionOptions): void;
|
|
12
|
+
setPosition(x: number, y: number): void;
|
|
12
13
|
hide(): void;
|
|
13
14
|
applyCrosshairStyle(): void;
|
|
14
15
|
drawVerticalCrosshairLine(ctx: CanvasRenderingContext2D, height: number): void;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Candle } from '../../models/Candle.types';
|
|
2
|
+
import { ChartCursorState, ChartViewState } from '../../models/ChartSync.types';
|
|
2
3
|
import { ChartViewport } from '../../models/ChartViewport.types';
|
|
3
4
|
import { VisibleRange } from '../../models/VisibleRange.types';
|
|
4
5
|
import { DrawCandlesOptions, DrawPriceLineOptions, DrawSingleCandleOptions, ExistingCandlesLayerOptions } from './ExistingCandlesLayer.types';
|
|
@@ -60,6 +61,14 @@ export declare class ExistingCandlesLayer {
|
|
|
60
61
|
get liveCandle(): Candle;
|
|
61
62
|
get viewport(): ChartViewport;
|
|
62
63
|
getVisibleRange(chartWidth: number): VisibleRange;
|
|
64
|
+
getViewState(): ChartViewState | null;
|
|
65
|
+
setViewState(view: ChartViewState): void;
|
|
66
|
+
setCursorState(cursor: ChartCursorState): {
|
|
67
|
+
candle: Candle;
|
|
68
|
+
candleIndex: number;
|
|
69
|
+
x: number;
|
|
70
|
+
y: number;
|
|
71
|
+
} | null;
|
|
63
72
|
getCandleX(candleIndex: number): number;
|
|
64
73
|
getCandleCenterX(candleIndex: number): number;
|
|
65
74
|
getNearestCandleIndexByX(x: number): number | null;
|
|
@@ -90,12 +99,40 @@ export declare class ExistingCandlesLayer {
|
|
|
90
99
|
private getInitialPriceRange;
|
|
91
100
|
private getInitialFallbackPercent;
|
|
92
101
|
private detectCandleTimeframeMs;
|
|
102
|
+
private hasUsableTimeframe;
|
|
93
103
|
private applyManualViewportOverrides;
|
|
94
104
|
private closeLastCandle;
|
|
95
105
|
private appendLiveCandle;
|
|
96
106
|
private updateAutoFollowAfterAppend;
|
|
97
107
|
private clampCandleIndex;
|
|
98
108
|
private getRightEdgeCandleIndex;
|
|
109
|
+
private getRightmostVisibleTime;
|
|
110
|
+
private getRightmostVisibleX;
|
|
111
|
+
private getRightmostVisibleIndex;
|
|
112
|
+
private getRightEdgeTime;
|
|
113
|
+
private getVisibleDurationMs;
|
|
114
|
+
private getTimeDeltaInCandleSlots;
|
|
115
|
+
/**
|
|
116
|
+
* Resolves a timestamp to the candle whose span contains it.
|
|
117
|
+
*
|
|
118
|
+
* Synced cursors arrive from charts of a different timeframe, so the
|
|
119
|
+
* incoming timestamp is not a multiple of this chart's timeframe away from
|
|
120
|
+
* the first candle. Dividing by this chart's timeframe to derive an index
|
|
121
|
+
* therefore drifts by the timeframe ratio, and clamping that drift pinned
|
|
122
|
+
* the crosshair to the last candle. Binary searching the real candle times
|
|
123
|
+
* is correct for any incoming timestamp and any target timeframe.
|
|
124
|
+
*
|
|
125
|
+
* Containment is measured against the candle's open time, so a finer
|
|
126
|
+
* timeframe hovering partway through a coarse candle snaps to the coarse
|
|
127
|
+
* candle that is actually covering that moment, rather than to whichever
|
|
128
|
+
* neighbour happens to start closest to the timestamp.
|
|
129
|
+
*/
|
|
130
|
+
private getCandleIndexByTime;
|
|
131
|
+
/**
|
|
132
|
+
* Binary search for the first candle whose time is greater than or equal to
|
|
133
|
+
* `targetTime`, falling back to the last index when every candle is earlier.
|
|
134
|
+
*/
|
|
135
|
+
private findCandleIndexAtOrAfter;
|
|
99
136
|
private getNextHorizontalZoom;
|
|
100
137
|
private getNextVerticalPriceRange;
|
|
101
138
|
private clearCanvas;
|
|
@@ -21,6 +21,7 @@ export declare class ShapesLayer {
|
|
|
21
21
|
private onShapeModified?;
|
|
22
22
|
private onShapeSelected?;
|
|
23
23
|
private onShapeDoubleClicked?;
|
|
24
|
+
private onShapeDeleteRequested?;
|
|
24
25
|
private onToolChange?;
|
|
25
26
|
constructor(options: ShapesLayerOptions);
|
|
26
27
|
setCandles(candles: Candle[]): void;
|
|
@@ -441,6 +441,7 @@ export type ShapesLayerOptions = {
|
|
|
441
441
|
onShapeModified?: (payload: ShapeModifiedPayload) => void;
|
|
442
442
|
onShapeSelected?: (payload: ShapeSelectedPayload | null) => void;
|
|
443
443
|
onShapeDoubleClicked?: (payload: ShapeSelectedPayload) => void;
|
|
444
|
+
onShapeDeleteRequested?: (shapeId: ShapeId) => void;
|
|
444
445
|
onToolChange?: (tool: ShapeToolType | null) => void;
|
|
445
446
|
};
|
|
446
447
|
export type InternalDragState = {
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
import { ChartCursorState, ChartViewState } from '../models/ChartSync.types';
|
|
1
2
|
import { ChartControllerProps } from './ChartController.types';
|
|
2
3
|
export declare class ChartController {
|
|
3
4
|
#private;
|
|
4
5
|
constructor(container: HTMLElement, props: ChartControllerProps);
|
|
5
6
|
updateProps(props: ChartControllerProps): void;
|
|
6
7
|
resetChartView(): void;
|
|
8
|
+
setView(view: ChartViewState): void;
|
|
9
|
+
getView(): ChartViewState | null;
|
|
10
|
+
setCursor(cursor: ChartCursorState | null): void;
|
|
11
|
+
hideCursor(): void;
|
|
7
12
|
destroy(): void;
|
|
8
13
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Shape, ShapeAddedPayload, ShapeModifiedPayload, ShapeSelectedPayload, ShapeToolType } from '../canvas/layers/ShapesLayer/ShapesLayer.types';
|
|
2
2
|
import { ChartConfig } from '../config/chartConfig.types';
|
|
3
3
|
import { Candle } from '../models/Candle.types';
|
|
4
|
+
import { ChartCursorState, ChartViewState } from '../models/ChartSync.types';
|
|
4
5
|
import { ClosedTrade, OpenTrade } from '../models/Trade.types';
|
|
5
6
|
import { DeepPartial } from './utils/deepPartial.types';
|
|
6
7
|
/**
|
|
@@ -205,6 +206,17 @@ export type ChartControllerProps = {
|
|
|
205
206
|
* ```
|
|
206
207
|
*/
|
|
207
208
|
onShapeDoubleClicked?: (payload: ShapeSelectedPayload) => void;
|
|
209
|
+
/**
|
|
210
|
+
* Called when the user presses Delete (or Backspace) while a shape is selected.
|
|
211
|
+
*
|
|
212
|
+
* The parent owns the shape list and must remove the requested shape.
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* ```ts
|
|
216
|
+
* onShapeDeleteRequested: (shapeId) => removeShape(shapeId)
|
|
217
|
+
* ```
|
|
218
|
+
*/
|
|
219
|
+
onShapeDeleteRequested?: (shapeId: string) => void;
|
|
208
220
|
/**
|
|
209
221
|
* Called when the chart wants the parent to change the active drawing tool.
|
|
210
222
|
*
|
|
@@ -238,4 +250,13 @@ export type ChartControllerProps = {
|
|
|
238
250
|
onTradeClose?: (payload: {
|
|
239
251
|
ticket: number;
|
|
240
252
|
}) => void;
|
|
253
|
+
/**
|
|
254
|
+
* Called after a local pan, zoom, reset, or resize changes the chart view.
|
|
255
|
+
* The timestamp-based payload can be applied to charts with different candle timeframes.
|
|
256
|
+
*/
|
|
257
|
+
onViewChange?: (view: ChartViewState) => void;
|
|
258
|
+
/**
|
|
259
|
+
* Called when the local crosshair moves, and with `null` when it leaves the chart.
|
|
260
|
+
*/
|
|
261
|
+
onCursorMove?: (cursor: ChartCursorState | null) => void;
|
|
241
262
|
};
|
|
@@ -381,8 +381,8 @@ export type TradeHandlesConfig = {
|
|
|
381
381
|
* ```ts
|
|
382
382
|
* const arrow: ClosedTradeIndicatorArrowConfig = {
|
|
383
383
|
* visible: true,
|
|
384
|
-
* width:
|
|
385
|
-
* height:
|
|
384
|
+
* width: 20,
|
|
385
|
+
* height: 10,
|
|
386
386
|
* headHeightRatio: 0.45,
|
|
387
387
|
* shaftWidthRatio: 6,
|
|
388
388
|
* buyColor: "#22c55e",
|
|
@@ -414,7 +414,7 @@ export type ClosedTradeIndicatorArrowConfig = {
|
|
|
414
414
|
* ```ts
|
|
415
415
|
* const closedTrades: ClosedTradeIndicatorsConfig = {
|
|
416
416
|
* visible: true,
|
|
417
|
-
* arrow: { visible: true, width:
|
|
417
|
+
* arrow: { visible: true, width: 20, height: 10, headHeightRatio: 0.45, shaftWidthRatio: 6, buyColor: "#22c55e", sellColor: "#ef4444", buyBorderColor: "#ffffff", sellBorderColor: "#ffffff", borderWidth: 1, opacity: 1 },
|
|
418
418
|
* connectorLine: { width: 1, color: "#ffffff", opacity: 0.65, style: "dotted", dash: [2, 4] },
|
|
419
419
|
* };
|
|
420
420
|
* ```
|
|
@@ -622,7 +622,7 @@ export type PreviousDayHighLowConfig = {
|
|
|
622
622
|
* volume: { visible: true, bullishColor: "#22c55e", bearishColor: "#ef4444", opacity: 0.35, height: 200, bottomOffset: 0, minBarHeight: 1 },
|
|
623
623
|
* crosshair: { color: "rgba(255,255,255,0.35)", thickness: 1, style: "dashed" },
|
|
624
624
|
* tradeHandles: {} as TradeHandlesConfig,
|
|
625
|
-
* closedTradeIndicators: { visible: true, arrow: { visible: true, width:
|
|
625
|
+
* closedTradeIndicators: { visible: true, arrow: { visible: true, width: 20, height: 10, headHeightRatio: 0.45, shaftWidthRatio: 6, buyColor: "#22c55e", sellColor: "#ef4444", buyBorderColor: "#ffffff", sellBorderColor: "#ffffff", borderWidth: 1, opacity: 1 }, connectorLine: { width: 1, color: "#ffffff", opacity: 0.65, style: "dotted", dash: [2, 4] } },
|
|
626
626
|
* colors: { bullish: "#22c55e", bearish: "#ef4444", background: "#0b1220" },
|
|
627
627
|
* axis: { axisX: { height: 30, backgroundColor: "#0b1220", borderColor: "#1f2937", borderWidth: 1, textColor: "#cbd5e1", font: "12px Arial", textAlign: "center", tickColor: "#334155", tickWidth: 1, tickLength: 4, labelOffsetY: 16, minLabelGap: 16, crosshairLabel: { backgroundColor: "#111827", borderColor: "#111827", borderWidth: 1, textColor: "#ffffff", font: "12px Arial", paddingX: 8, height: 26 } }, axisY: { width: 80, backgroundColor: "#0b1220", borderColor: "#1f2937", borderWidth: 1, textColor: "#cbd5e1", font: "12px Arial", textAlign: "left", tickCount: 12, tickColor: "#334155", tickWidth: 1, tickLength: 4, tickGap: 64, labelOffsetX: 8, crosshairLabel: { backgroundColor: "#111827", borderColor: "#111827", borderWidth: 1, textColor: "#ffffff", font: "12px Arial", paddingX: 8, height: 20 } } },
|
|
628
628
|
* shapes: { trendline: { lineColor: "#22c55e" } },
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export type { CanvasPoint } from './chart/utils/getCanvasPoint.types';
|
|
|
6
6
|
export { CHART_CONFIG } from './config/chartConfig';
|
|
7
7
|
export type { ChartConfig, PreviousDayHighLowConfig } from './config/chartConfig.types';
|
|
8
8
|
export type { Candle } from './models/Candle.types';
|
|
9
|
+
export type { ChartCursorState, ChartViewState } from './models/ChartSync.types';
|
|
9
10
|
export type { ChartViewport } from './models/ChartViewport.types';
|
|
10
11
|
export type { Point2D } from './models/Point.types';
|
|
11
12
|
export type { BaseTrade, ClosedTrade, OpenTrade, TradeDirection } from './models/Trade.types';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type ChartViewState = {
|
|
2
|
+
/** UTC timestamp of the chart's rightmost visible candle. */
|
|
3
|
+
rightmostVisibleTime: number;
|
|
4
|
+
/** Normalized screen position of that candle, from 0 to 1. */
|
|
5
|
+
rightmostVisibleX: number;
|
|
6
|
+
/** UTC timestamp of the plot's right edge. */
|
|
7
|
+
rightEdgeTime: number;
|
|
8
|
+
/** Visible duration represented by the plot, in milliseconds. */
|
|
9
|
+
visibleDurationMs: number;
|
|
10
|
+
};
|
|
11
|
+
export type ChartCursorState = {
|
|
12
|
+
/** UTC timestamp selected by the vertical crosshair. */
|
|
13
|
+
time: number;
|
|
14
|
+
/** Price selected by the horizontal crosshair. */
|
|
15
|
+
price: number;
|
|
16
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CSSProperties } from 'react';
|
|
2
2
|
import { ChartControllerProps } from '../chart/ChartController.types';
|
|
3
|
+
import { ChartCursorState, ChartViewState } from '../models/ChartSync.types';
|
|
3
4
|
/**
|
|
4
5
|
* Imperative methods exposed through the `ref` passed to {@link TradingReload}.
|
|
5
6
|
*
|
|
@@ -24,6 +25,45 @@ export type TradingReloadHandle = {
|
|
|
24
25
|
* ```
|
|
25
26
|
*/
|
|
26
27
|
resetChartView: () => void;
|
|
28
|
+
/**
|
|
29
|
+
* Returns the current timestamp-based view state, or `null` when the chart
|
|
30
|
+
* has no candles to describe.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* const view = chartRef.current?.getView();
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
getView: () => ChartViewState | null;
|
|
38
|
+
/**
|
|
39
|
+
* Applies a timestamp-based view state so charts with different candle
|
|
40
|
+
* timeframes stay aligned. Does not emit `onViewChange`.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```tsx
|
|
44
|
+
* chartRef.current?.setView(sourceView);
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
setView: (view: ChartViewState) => void;
|
|
48
|
+
/**
|
|
49
|
+
* Draws a synced crosshair at the given time and price, snapped to the
|
|
50
|
+
* nearest candle. Does not emit `onCursorMove`.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```tsx
|
|
54
|
+
* chartRef.current?.setCursor({ time, price });
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
setCursor: (cursor: ChartCursorState | null) => void;
|
|
58
|
+
/**
|
|
59
|
+
* Hides the crosshair and axis labels.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```tsx
|
|
63
|
+
* chartRef.current?.hideCursor();
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
hideCursor: () => void;
|
|
27
67
|
};
|
|
28
68
|
/**
|
|
29
69
|
* Props accepted by the public `TradingReload` React component.
|