@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.
@@ -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: 60,
385
- * height: 30,
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: 60, height: 30, headHeightRatio: 0.45, shaftWidthRatio: 6, buyColor: "#22c55e", sellColor: "#ef4444", buyBorderColor: "#ffffff", sellBorderColor: "#ffffff", borderWidth: 1, opacity: 1 },
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: 60, height: 30, 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] } },
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.