@pradeepjadhav/trading-reload-chart 1.3.0 → 1.4.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/README.md +44 -2
- package/dist/canvas/layers/ShapesLayer/LineShape.d.ts +1 -1
- package/dist/canvas/layers/ShapesLayer/PathShape.d.ts +1 -1
- package/dist/canvas/layers/ShapesLayer/RectangleShape.d.ts +1 -1
- package/dist/canvas/layers/ShapesLayer/ShapesLayer.helpers.d.ts +1 -1
- package/dist/canvas/layers/TradeLayer/TradeLayer.types.d.ts +1 -1
- package/dist/canvas/layers/WatermarkLayer/WatermarkLayer.d.ts +40 -0
- package/dist/canvas/layers/WatermarkLayer/WatermarkLayer.helpers.d.ts +27 -0
- package/dist/canvas/layers/WatermarkLayer/WatermarkLayer.types.d.ts +66 -0
- package/dist/chart/createChartDom.types.d.ts +1 -0
- package/dist/chart/utils/resolveWheelZoomAxis.d.ts +7 -0
- package/dist/chart/utils/resolveWheelZoomAxis.types.d.ts +1 -0
- package/dist/config/chartConfig.types.d.ts +41 -0
- package/dist/index.d.ts +1 -1
- package/dist/models/Candle.types.d.ts +4 -1
- package/dist/trading-reload-chart.css +1 -1
- package/dist/trading-reload-chart.js +445 -354
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -253,6 +253,46 @@ export function ChartPanel() {
|
|
|
253
253
|
- `TradingReload` fills **100%** of that container.
|
|
254
254
|
- Do **not** import chart CSS manually; styles ship with the component (`src/styles/chart.css`).
|
|
255
255
|
|
|
256
|
+
### Watermark
|
|
257
|
+
|
|
258
|
+
Add a text watermark (symbol / timeframe label, chart id, etc.) through `config.watermark`.
|
|
259
|
+
It renders on its own canvas **beneath** candles, shapes, trades, and the crosshair, so it
|
|
260
|
+
never intercepts pointer events.
|
|
261
|
+
|
|
262
|
+
```tsx
|
|
263
|
+
import {
|
|
264
|
+
TradingReload,
|
|
265
|
+
type ChartConfig,
|
|
266
|
+
type DeepPartial,
|
|
267
|
+
} from "@pradeepjadhav/trading-reload-chart";
|
|
268
|
+
|
|
269
|
+
const config = {
|
|
270
|
+
watermark: {
|
|
271
|
+
text: `${symbol}, ${timeframe}`,
|
|
272
|
+
position: "top-center",
|
|
273
|
+
fontSize: 24,
|
|
274
|
+
fontWeight: 700,
|
|
275
|
+
color: "#FFFFFF",
|
|
276
|
+
opacity: 0.35,
|
|
277
|
+
},
|
|
278
|
+
} satisfies DeepPartial<ChartConfig>;
|
|
279
|
+
|
|
280
|
+
<TradingReload config={config} /* … */ />;
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
| Option | Type | Default | Description |
|
|
284
|
+
| ------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------- | ---------------------------------------- |
|
|
285
|
+
| `text` | `string` | `""` | Empty text hides the watermark |
|
|
286
|
+
| `position` | `"center" \| "top-center" \| "bottom-center" \| "left-center" \| "right-center"` | `"center"` | Anchor inside the plot area |
|
|
287
|
+
| `fontSize` | `number` | `48` | Font size in CSS pixels |
|
|
288
|
+
| `fontWeight` | `number` | `700` | Numeric font weight |
|
|
289
|
+
| `fontFamily` | `string` | `"Inter, system-ui, -apple-system, sans-serif"` | CSS font stack |
|
|
290
|
+
| `color` | `string` | `COLORS.white` | Text color |
|
|
291
|
+
| `opacity` | `number` | `0.25` | Clamped to `0` - `1` |
|
|
292
|
+
| `padding` | `number` | `16` | Inset from the plot edge |
|
|
293
|
+
|
|
294
|
+
> Because `config` is deep-merged, you can pass only the keys you want to change.
|
|
295
|
+
|
|
256
296
|
### 3. Vite / Create React App
|
|
257
297
|
|
|
258
298
|
```tsx
|
|
@@ -286,6 +326,7 @@ Import from the package root:
|
|
|
286
326
|
| `Candle`, `OpenTrade`, `ClosedTrade`, … | Domain types |
|
|
287
327
|
| `Shape`, `ShapeToolType`, shape payloads | Drawing types |
|
|
288
328
|
| `ChartConfig`, `CHART_CONFIG`, `DeepPartial` | Configuration |
|
|
329
|
+
| `WatermarkConfig`, `WatermarkPosition` | Watermark types |
|
|
289
330
|
| `ClosedTradeIndicator`, trade handle types | Trade overlay types |
|
|
290
331
|
|
|
291
332
|
Controlled props (parent owns state):
|
|
@@ -319,7 +360,7 @@ trading-reload-chart/
|
|
|
319
360
|
│ ├── index.ts # Public exports
|
|
320
361
|
│ ├── react/ # TradingReload component
|
|
321
362
|
│ ├── chart/ # ChartController, DOM, utils
|
|
322
|
-
│ ├── canvas/layers/ # Canvas layers (candles, shapes, trades, …)
|
|
363
|
+
│ ├── canvas/layers/ # Canvas layers (candles, volume, watermark, shapes, trades, …)
|
|
323
364
|
│ ├── config/ # CHART_CONFIG and types
|
|
324
365
|
│ ├── models/ # Candle, Trade, ChartViewport, … (*.types.ts)
|
|
325
366
|
│ ├── helpers/ # Shared pure utilities
|
|
@@ -336,11 +377,12 @@ Type declarations live in `*.types.ts` files next to implementation code (see AG
|
|
|
336
377
|
|
|
337
378
|
## Features
|
|
338
379
|
|
|
339
|
-
- Layered canvas rendering (volume, candles, shapes, trades, axes, crosshair)
|
|
380
|
+
- Layered canvas rendering (volume, watermark, candles, shapes, trades, axes, crosshair)
|
|
340
381
|
- Pan, horizontal wheel zoom, Ctrl+wheel vertical zoom
|
|
341
382
|
- Drawing tools (trendline, rectangle, path, fib, long/short position)
|
|
342
383
|
- Open trade SL/TP drag with `onTradeModify` on release
|
|
343
384
|
- Closed trade markers
|
|
385
|
+
- Configurable text watermark layer
|
|
344
386
|
- Deep-merge chart `config` over defaults
|
|
345
387
|
|
|
346
388
|
---
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CommonShapeConfig, ShapeCoordinateConverter, ShapeHandleHitbox, ShapePoint, ShapeVertex, TrendlineShape } from './ShapesLayer.types';
|
|
2
2
|
export declare class LineShape {
|
|
3
3
|
static defaultConfig: CommonShapeConfig;
|
|
4
4
|
static draw({ ctx, shape, converter, config, selected, hovered, }: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PathShapeData, ShapeCoordinateConverter,
|
|
1
|
+
import { CommonShapeConfig, PathShapeData, ShapeCoordinateConverter, ShapeHandleHitbox, ShapePoint, ShapeVertex } from './ShapesLayer.types';
|
|
2
2
|
export declare class PathShape {
|
|
3
3
|
static defaultConfig: CommonShapeConfig;
|
|
4
4
|
static draw({ ctx, shape, converter, config, selected, hovered, }: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RectangleShapeData, ShapeCoordinateConverter, ShapeHandleHitbox, ShapePoint, ShapeVertex
|
|
1
|
+
import { RectangleShapeConfig, RectangleShapeData, ShapeCoordinateConverter, ShapeHandleHitbox, ShapePoint, ShapeVertex } from './ShapesLayer.types';
|
|
2
2
|
export declare class RectangleShape {
|
|
3
3
|
static defaultConfig: RectangleShapeConfig;
|
|
4
4
|
static draw({ ctx, shape, converter, config, selected, hovered, }: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Candle } from '../../../models/Candle.types';
|
|
2
|
-
import { FibLevelValue, Shape, ShapeBoundingBox, ShapeCoordinateConverter,
|
|
2
|
+
import { CommonShapeConfig, FibLevelValue, Shape, ShapeBoundingBox, ShapeCoordinateConverter, ShapeHandleHitbox, ShapeLineStyle, ShapePoint, ShapeVertex } from './ShapesLayer.types';
|
|
3
3
|
export declare const SHAPE_HIT_TOLERANCE = 8;
|
|
4
4
|
export declare const SHAPE_HANDLE_RADIUS = 5;
|
|
5
5
|
export declare const generateShapeId: () => string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ClosedTradeIndicatorArrowConfig, MissingTradeProtectionHandleRectConfig, TemporaryTradeProtectionHandleRectConfig, TradeHandleLineConfig, TradeHandleRectConfig, TradeHandleStyleConfig } from '../../../config/chartConfig.types';
|
|
2
2
|
import { ChartViewport } from '../../../models/ChartViewport.types';
|
|
3
3
|
import { ClosedTrade, OpenTrade, TradeDirection } from '../../../models/Trade.types';
|
|
4
4
|
/**
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { WatermarkConfig } from '../../../config/chartConfig.types';
|
|
2
|
+
import { WatermarkLayerOptions } from './WatermarkLayer.types';
|
|
3
|
+
/**
|
|
4
|
+
* Text watermark drawn on its own canvas beneath the candlestick and
|
|
5
|
+
* interaction layers, so it never intercepts pointer events and is always
|
|
6
|
+
* painted over by candles, shapes, trades, and the crosshair.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const layer = new WatermarkLayer({
|
|
11
|
+
* canvas,
|
|
12
|
+
* config: { ...CHART_CONFIG.watermark, text: "USDJPY, 15m" },
|
|
13
|
+
* });
|
|
14
|
+
* layer.resize(800, 600);
|
|
15
|
+
* layer.render();
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare class WatermarkLayer {
|
|
19
|
+
#private;
|
|
20
|
+
constructor(options: WatermarkLayerOptions);
|
|
21
|
+
setConfig(config: WatermarkConfig): void;
|
|
22
|
+
/**
|
|
23
|
+
* Resizes the canvas and stores the plot size used for placement.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* layer.resize(800, 600);
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
resize(width: number, height: number): void;
|
|
31
|
+
/**
|
|
32
|
+
* Clears the canvas and paints the watermark when it has text.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* layer.render();
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
render(): void;
|
|
40
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ResolveWatermarkTextPlacementOptions, WatermarkTextPlacement } from './WatermarkLayer.types';
|
|
2
|
+
/**
|
|
3
|
+
* Resolves the canvas text anchor for a watermark position.
|
|
4
|
+
*
|
|
5
|
+
* `textAlign` and `textBaseline` are returned alongside the coordinates so the
|
|
6
|
+
* caller can apply them to the context before measuring or drawing the text.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const { x, y, textAlign, textBaseline } = resolveWatermarkTextPlacement({
|
|
11
|
+
* position: "bottom-center",
|
|
12
|
+
* width: 800,
|
|
13
|
+
* height: 600,
|
|
14
|
+
* padding: 16,
|
|
15
|
+
* });
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare const resolveWatermarkTextPlacement: (options: ResolveWatermarkTextPlacementOptions) => WatermarkTextPlacement;
|
|
19
|
+
/**
|
|
20
|
+
* Clamps an opacity into the `0` - `1` range accepted by the canvas context.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* clampWatermarkOpacity(1.4); // 1
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare const clampWatermarkOpacity: (opacity: number) => number;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { WatermarkConfig } from '../../../config/chartConfig.types';
|
|
2
|
+
/**
|
|
3
|
+
* Constructor options for {@link WatermarkLayer}.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* const layer = new WatermarkLayer({
|
|
8
|
+
* canvas,
|
|
9
|
+
* config: { ...CHART_CONFIG.watermark, text: "USDJPY, 15m" },
|
|
10
|
+
* });
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export type WatermarkLayerOptions = {
|
|
14
|
+
/** Canvas the watermark is painted on. */
|
|
15
|
+
canvas: HTMLCanvasElement;
|
|
16
|
+
/** Resolved watermark configuration. */
|
|
17
|
+
config: WatermarkConfig;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Text anchor resolved from a {@link WatermarkPosition} and the plot size.
|
|
21
|
+
*
|
|
22
|
+
* All values are in CSS pixels.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* const placement: WatermarkTextPlacement = {
|
|
27
|
+
* x: 400,
|
|
28
|
+
* y: 16,
|
|
29
|
+
* textAlign: "center",
|
|
30
|
+
* textBaseline: "top",
|
|
31
|
+
* };
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export type WatermarkTextPlacement = {
|
|
35
|
+
/** Horizontal anchor point. */
|
|
36
|
+
x: number;
|
|
37
|
+
/** Vertical anchor point. */
|
|
38
|
+
y: number;
|
|
39
|
+
/** Canvas text alignment applied before measuring. */
|
|
40
|
+
textAlign: CanvasTextAlign;
|
|
41
|
+
/** Canvas text baseline applied before measuring. */
|
|
42
|
+
textBaseline: CanvasTextBaseline;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Inputs used to resolve the watermark text anchor.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* const placement = resolveWatermarkTextPlacement({
|
|
50
|
+
* position: "top-center",
|
|
51
|
+
* width: 800,
|
|
52
|
+
* height: 600,
|
|
53
|
+
* padding: 16,
|
|
54
|
+
* });
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export type ResolveWatermarkTextPlacementOptions = {
|
|
58
|
+
/** Configured watermark position. */
|
|
59
|
+
position: WatermarkConfig["position"];
|
|
60
|
+
/** Plot width in CSS pixels. */
|
|
61
|
+
width: number;
|
|
62
|
+
/** Plot height in CSS pixels. */
|
|
63
|
+
height: number;
|
|
64
|
+
/** Padding between the watermark and the plot edge. */
|
|
65
|
+
padding: number;
|
|
66
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { WheelZoomAxis } from './resolveWheelZoomAxis.types';
|
|
2
|
+
/**
|
|
3
|
+
* Horizontal for a plain wheel, and horizontal for a trackpad pinch so the
|
|
4
|
+
* gesture zooms the time axis. Vertical stays reserved for a real Ctrl/Cmd +
|
|
5
|
+
* mouse wheel so existing mouse and keyboard-driven zoom is untouched.
|
|
6
|
+
*/
|
|
7
|
+
export declare const resolveWheelZoomAxis: (event: WheelEvent) => WheelZoomAxis;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type WheelZoomAxis = "x" | "y";
|
|
@@ -116,6 +116,46 @@ export type VolumeConfig = {
|
|
|
116
116
|
bottomOffset: number;
|
|
117
117
|
minBarHeight: number;
|
|
118
118
|
};
|
|
119
|
+
/**
|
|
120
|
+
* Placement of the watermark inside the plot area.
|
|
121
|
+
*
|
|
122
|
+
* @example `"top-center"`
|
|
123
|
+
*/
|
|
124
|
+
export type WatermarkPosition = "center" | "top-center" | "bottom-center" | "left-center" | "right-center";
|
|
125
|
+
/**
|
|
126
|
+
* Text watermark rendered on a dedicated canvas beneath the candlestick and
|
|
127
|
+
* interaction layers.
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```ts
|
|
131
|
+
* const watermark: WatermarkConfig = {
|
|
132
|
+
* text: "USDJPY, 15m",
|
|
133
|
+
* position: "top-center",
|
|
134
|
+
* fontSize: 24,
|
|
135
|
+
* fontWeight: 700,
|
|
136
|
+
* color: "#ffffff",
|
|
137
|
+
* opacity: 0.35,
|
|
138
|
+
* };
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
export type WatermarkConfig = {
|
|
142
|
+
/** Watermark text. An empty string hides the watermark. */
|
|
143
|
+
text: string;
|
|
144
|
+
/** Watermark placement inside the plot area. */
|
|
145
|
+
position: WatermarkPosition;
|
|
146
|
+
/** Font size in CSS pixels, before device pixel ratio scaling. */
|
|
147
|
+
fontSize: number;
|
|
148
|
+
/** Numeric CSS font weight. */
|
|
149
|
+
fontWeight: number;
|
|
150
|
+
/** CSS font family used to measure and paint the watermark. */
|
|
151
|
+
fontFamily: string;
|
|
152
|
+
/** Watermark color, any CSS color value. */
|
|
153
|
+
color: string;
|
|
154
|
+
/** Watermark opacity between `0` and `1`. */
|
|
155
|
+
opacity: number;
|
|
156
|
+
/** Padding in CSS pixels between the watermark and the plot edge. */
|
|
157
|
+
padding: number;
|
|
158
|
+
};
|
|
119
159
|
/**
|
|
120
160
|
* Crosshair line style.
|
|
121
161
|
*
|
|
@@ -633,6 +673,7 @@ export type ChartConfig = {
|
|
|
633
673
|
zoom: ZoomConfig;
|
|
634
674
|
candles: CandlesConfig;
|
|
635
675
|
volume: VolumeConfig;
|
|
676
|
+
watermark: WatermarkConfig;
|
|
636
677
|
crosshair: CrosshairConfig;
|
|
637
678
|
tradeHandles: TradeHandlesConfig;
|
|
638
679
|
closedTradeIndicators: ClosedTradeIndicatorsConfig;
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export type { ChartControllerProps, PreviousDay, TradeModifyPayload, } from './c
|
|
|
4
4
|
export type { DeepPartial } from './chart/utils/deepPartial.types';
|
|
5
5
|
export type { CanvasPoint } from './chart/utils/getCanvasPoint.types';
|
|
6
6
|
export { CHART_CONFIG } from './config/chartConfig';
|
|
7
|
-
export type { ChartConfig, PreviousDayHighLowConfig } from './config/chartConfig.types';
|
|
7
|
+
export type { ChartConfig, PreviousDayHighLowConfig, WatermarkConfig, WatermarkPosition, } from './config/chartConfig.types';
|
|
8
8
|
export type { Candle } from './models/Candle.types';
|
|
9
9
|
export type { ChartCursorState, ChartViewState } from './models/ChartSync.types';
|
|
10
10
|
export type { ChartViewport } from './models/ChartViewport.types';
|
|
@@ -55,9 +55,12 @@ export type Candle = {
|
|
|
55
55
|
/**
|
|
56
56
|
* Current ask price during this candle.
|
|
57
57
|
*
|
|
58
|
+
* Only the forming candle carries it; feeds that omit a live tick leave it
|
|
59
|
+
* undefined, so the ask line falls back to this candle's close.
|
|
60
|
+
*
|
|
58
61
|
* @example `1.0853`
|
|
59
62
|
*/
|
|
60
|
-
ask
|
|
63
|
+
ask?: number;
|
|
61
64
|
/**
|
|
62
65
|
* `false` while the realtime candle is still forming.
|
|
63
66
|
*
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
.trading-reload-chart{box-sizing:border-box;outline:none;width:100%;height:100%;overflow:hidden}.trading-reload-chart *,.trading-reload-chart :before,.trading-reload-chart :after{box-sizing:border-box}.trading-reload-chart__layout{--axis-x-height:30px;width:100%;height:100%;display:flex;position:relative;overflow:hidden}.trading-reload-chart__stack{flex:1;height:100%;position:relative;overflow:hidden}.trading-reload-chart canvas{display:block}.trading-reload-chart__volume,.trading-reload-chart__plot,.trading-reload-chart__shapes,.trading-reload-chart__trades,.trading-reload-chart__overlay{width:100%;height:calc(100% - var(--axis-x-height));position:absolute;top:0;left:0}.trading-reload-chart__volume{z-index:0;pointer-events:none}.trading-reload-
|
|
1
|
+
.trading-reload-chart{box-sizing:border-box;outline:none;width:100%;height:100%;overflow:hidden}.trading-reload-chart *,.trading-reload-chart :before,.trading-reload-chart :after{box-sizing:border-box}.trading-reload-chart__layout{--axis-x-height:30px;width:100%;height:100%;display:flex;position:relative;overflow:hidden}.trading-reload-chart__stack{flex:1;height:100%;position:relative;overflow:hidden}.trading-reload-chart canvas{display:block}.trading-reload-chart__volume,.trading-reload-chart__watermark,.trading-reload-chart__plot,.trading-reload-chart__shapes,.trading-reload-chart__trades,.trading-reload-chart__overlay{width:100%;height:calc(100% - var(--axis-x-height));position:absolute;top:0;left:0}.trading-reload-chart__volume{z-index:0;pointer-events:none}.trading-reload-chart__watermark{z-index:1;pointer-events:none}.trading-reload-chart__plot{z-index:2}.trading-reload-chart__shapes{z-index:3}.trading-reload-chart__trades{z-index:4}.trading-reload-chart__overlay{z-index:5}.trading-reload-chart__axis-x{width:100%;height:var(--axis-x-height);z-index:6;position:absolute;bottom:0;left:0}.trading-reload-chart__axis-y{height:calc(100% - var(--axis-x-height));z-index:4;flex-shrink:0;position:relative}
|
|
2
2
|
/*$vite$:1*/
|