sbx-react-stock-chart 3.5.44 → 3.5.46

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 CHANGED
@@ -1,38 +1,538 @@
1
1
  # sbx-react-stock-chart
2
2
 
3
- sbx-react-stock-chart module
3
+ React stock chart component with candlestick/line/area/bars rendering, indicators, drawing tools, alerts, and a runtime API.
4
4
 
5
- ## Requirements
6
- - node >= 10
7
- - sbx >=0.7.1
5
+ ## Installation
8
6
 
9
- ## Peer dependencies
7
+ ```bash
8
+ npm i sbx-react-stock-chart
9
+ ```
10
+
11
+ Alternative:
10
12
 
11
- #### Installation
12
13
  ```bash
13
- $ sbx install sbx-react-stock-chart
14
+ yarn add sbx-react-stock-chart
15
+ pnpm add sbx-react-stock-chart
14
16
  ```
15
17
 
16
- Use license Key
18
+ ## Requirements
17
19
 
18
- #### License
19
- Use license Key
20
+ - `react` 16.x
21
+ - `react-dom` 16.x
22
+ - Browser environment (`window`, `document`, `requestAnimationFrame`)
20
23
 
24
+ ## Quick Start
21
25
 
26
+ ```jsx
27
+ import React, { useRef, useState } from 'react';
28
+ import Chart from 'sbx-react-stock-chart';
22
29
 
23
- ### Icons
24
- https://www.svgrepo.com/collection/zwicon-line-icons/
30
+ const Feed = {
31
+ onFeeder(symbol, cb) {
32
+ // subscribe and call cb({ symbol, bid, ask, time, volume? })
33
+ },
34
+ offFeeder(symbol, cb) {
35
+ // unsubscribe
36
+ },
37
+ };
25
38
 
26
- ## FAQ
39
+ async function getHistory({ symbol, frame, count }) {
40
+ return {
41
+ data: [
42
+ // [open, high, low, close, volume, timeSec]
43
+ [1.081, 1.084, 1.079, 1.082, 1200, 1710000000],
44
+ [1.082, 1.085, 1.080, 1.084, 950, 1710014400],
45
+ ],
46
+ };
47
+ }
27
48
 
28
- ### Developers
29
- - Viktor Semenov
30
- - Vladislav Fisher
49
+ export default function App() {
50
+ const chartRef = useRef(null);
51
+ const [assets, setAssets] = useState([
52
+ {
53
+ key: 'eurusd-main',
54
+ symbol: 'EURUSD',
55
+ digits: 5,
56
+ timeFrame: 4 * 60 * 60,
57
+ type: 'candle',
58
+ indicators: {},
59
+ drawing_tools: {},
60
+ orders: [],
61
+ alerts: [],
62
+ priceLabels: [],
63
+ },
64
+ ]);
65
+
66
+ return (
67
+ <div style={{ height: 560 }}>
68
+ <Chart
69
+ ref={chartRef}
70
+ assets={assets}
71
+ feed={Feed}
72
+ getHistory={getHistory}
73
+ settings={{
74
+ hideTooltips: true,
75
+ showVolume: true,
76
+ showStats: false,
77
+ showPriceAlerts: true,
78
+ autoScale: false,
79
+ display: { contextMenu: true },
80
+ controls: { enable: true },
81
+ }}
82
+ onChange={(ctx) => {
83
+ if (ctx.event === 'change:timeFrame') {
84
+ setAssets((prev) =>
85
+ prev.map((a) => (a.key === ctx._id ? { ...a, timeFrame: ctx.data } : a))
86
+ );
87
+ }
88
+ }}
89
+ />
90
+ </div>
91
+ );
92
+ }
93
+ ```
94
+
95
+ ## Component Props (Wrapper Export)
96
+
97
+ The package default export is the multi-asset wrapper component (`src/Chart/chart-wrapper.jsx`).
98
+
99
+ | Prop | Type | Required | Description |
100
+ |---|---|---|---|
101
+ | `assets` | `Asset[]` | yes | List of charts to render. Each asset is one chart tab/pane. |
102
+ | `feed` | `{ onFeeder, offFeeder }` | yes | Real-time quote subscribe/unsubscribe adapter. |
103
+ | `getHistory` | `(params) => Promise<{data: Candle[]}>` | yes | Historical candles loader. |
104
+ | `settings` | `ChartSettings` | yes (practically) | Main configuration object (UI + rendering + style). |
105
+ | `onChange` | `(ctx) => void` | no | Main event callback. |
106
+ | `tokens` | `Record<string, string>` | no | UI localization overrides. |
107
+ | `templates` | `{ indicators?: any[] }` | no | Indicator templates source for dropdown UI. |
108
+ | `favorites` | `any[]` | no | Favorite indicators list (used in UI). |
109
+ | `containers` | `Array<{name, position, component, collapse?}>` | no | Custom overlay widgets mounted on each chart box. |
110
+ | `delta_width` | `number` | no | Right-side future space (in chart coordinates). |
111
+ | `timeFrame` | `number` | no | Fallback timeframe in seconds (when not set in asset). |
112
+ | `type` | `ChartType` | no | Initial chart type override. |
113
+ | `style` | `Record<string, string>` | no | Custom named colors injected into chart color registry. |
114
+ | `serverUTCTimeOffset` | `number` | no | Seconds offset for grid/time labels. |
115
+ | `mainPaneMask` | `{enable?: boolean, color?: string, opacity?: number}` | no | Runtime main pane mask override. |
116
+ | `license` | `string` | no | License key used by built-in license check. |
117
+ | `onMove` | `(ctx) => void` | no | Passed through but currently not used by core logic. |
118
+
119
+ ## Data Contracts
120
+
121
+ ### Candle
122
+
123
+ ```ts
124
+ type Candle = [open, high, low, close, volume, timeSec];
125
+ ```
126
+
127
+ ### Asset
128
+
129
+ ```ts
130
+ type Asset = {
131
+ key: string;
132
+ symbol: string;
133
+ digits?: number;
134
+ timeFrame?: number; // seconds, e.g. 60 / 300 / 14400
135
+ type?: ChartType;
136
+ indicators?: Record<string, any>;
137
+ drawing_tools?: Record<string, any>;
138
+ orders?: Array<any>;
139
+ alerts?: Array<any>;
140
+ priceLabels?: Array<{ price: number; color: string }>;
141
+ };
142
+ ```
143
+
144
+ ### Feed
145
+
146
+ ```ts
147
+ type Feed = {
148
+ onFeeder: (symbol: string, cb: (tick: Tick) => void) => void;
149
+ offFeeder: (symbol: string, cb: (tick: Tick) => void) => void;
150
+ };
151
+
152
+ type Tick = {
153
+ symbol: string;
154
+ bid: number;
155
+ ask?: number;
156
+ time: number; // unix sec
157
+ volume?: number;
158
+ };
159
+ ```
160
+
161
+ ### getHistory
162
+
163
+ ```ts
164
+ type GetHistory = (params: {
165
+ symbol: string;
166
+ frame: number; // seconds
167
+ count: number;
168
+ }) => Promise<{ data: Candle[] }>;
169
+ ```
170
+
171
+ ## Full `settings` Reference
172
+
173
+ `settings` combines:
174
+ - wrapper/UI settings (controls panel, footer, visibility, menu)
175
+ - render engine settings (candles, grid, cursor, orders, etc.)
176
+
177
+ ### 1) Wrapper/UI settings
178
+
179
+ | Key | Type | Description |
180
+ |---|---|---|
181
+ | `hideTooltips` | `boolean` | Hides tooltips in left controls. |
182
+ | `display.contextMenu` | `boolean` | Enables right-click chart context menu. |
183
+ | `controls.enable` | `boolean` | Enables/disables left controls bar. |
184
+ | `controls.visible` | `string[]` | Controls order/visibility allowlist. |
185
+ | `controls.hidden` | `string[]` | Controls denylist (removed from visible result). |
186
+ | `indicators.visible` | `string[]` | Indicator systemName allowlist in indicator picker. |
187
+ | `indicators.hidden` | `string[]` | Indicator denylist in indicator picker. |
188
+ | `indicators.templates` | `boolean` | Enables indicator templates save/load UI block. |
189
+ | `drawingTools.visible` | `string[]` | Drawing tool systemName allowlist. |
190
+ | `drawingTools.hidden` | `string[]` | Drawing tool denylist. |
191
+ | `footer.enable` | `boolean` | Enables bottom footer with preset periods. |
192
+ | `footer.components` | `ReactComponent[]` | Extra footer right-side components. |
193
+ | `layout` | `React.CSSProperties` | Applied to outer `.chart-main` container. |
194
+
195
+ `controls.visible` supported ids:
196
+
197
+ - `CHART_TYPE`
198
+ - `TIME_FRAME`
199
+ - `INDICATORS`
200
+ - `DT_LINES`
201
+ - `DT_FIBO`
202
+ - `DT_POLY`
203
+ - `DT_GEOMETRY`
204
+ - `DT_TEXT_TOOLS`
205
+ - `HR`
206
+ - `ZOOM_IN`
207
+ - `ZOOM_OUT`
208
+ - `ZOOM_CENTER`
209
+ - `SCREEN_SHOT`
210
+
211
+ ### 2) Render engine settings (all supported keys)
212
+
213
+ ```ts
214
+ type ChartSettings = {
215
+ // UI-level
216
+ hideTooltips?: boolean;
217
+ display?: {
218
+ contextMenu?: boolean;
219
+ };
220
+ controls?: {
221
+ enable?: boolean;
222
+ visible?: string[];
223
+ hidden?: string[];
224
+ };
225
+ indicators?: {
226
+ visible?: string[];
227
+ hidden?: string[];
228
+ templates?: boolean;
229
+ };
230
+ drawingTools?: {
231
+ visible?: string[];
232
+ hidden?: string[];
233
+ };
234
+ footer?: {
235
+ enable?: boolean;
236
+ components?: Array<any>;
237
+ };
238
+ layout?: Record<string, any>;
239
+
240
+ // Core render flags
241
+ showVolume?: boolean;
242
+ showStats?: boolean;
243
+ showPriceAlerts?: boolean;
244
+ autoScale?: boolean;
245
+ animation?: boolean;
246
+ showDeveloperLogo?: boolean;
247
+ orderOffset?: number;
31
248
 
32
- ## License
33
- Copyright (c) 2017-2024 Sobix Group LLC
249
+ currentPrice?: {
250
+ visible?: {
251
+ bid?: boolean;
252
+ middle?: boolean;
253
+ ask?: boolean;
254
+ };
255
+ };
34
256
 
35
- todo
36
- start use key
257
+ volume?: {
258
+ enable?: boolean;
259
+ colors?: { up?: string; down?: string };
260
+ };
37
261
 
262
+ candles?: {
263
+ body?: { enable?: boolean; colors?: { up?: string; down?: string } };
264
+ border?: { enable?: boolean; colors?: { up?: string; down?: string } };
265
+ wick?: { enable?: boolean; colors?: { up?: string; down?: string } };
266
+ };
267
+
268
+ columns?: {
269
+ body?: { enable?: boolean; colors?: { up?: string; down?: string } };
270
+ border?: { enable?: boolean; colors?: { up?: string; down?: string } };
271
+ wick?: { enable?: boolean; colors?: { up?: string; down?: string } };
272
+ };
273
+
274
+ heiken?: {
275
+ body?: { enable?: boolean; colors?: { up?: string; down?: string } };
276
+ border?: { enable?: boolean; colors?: { up?: string; down?: string } };
277
+ wick?: { enable?: boolean; colors?: { up?: string; down?: string } };
278
+ };
279
+
280
+ line?: {
281
+ stroke?: { enable?: boolean; color?: string; width?: number };
282
+ area?: { enable?: boolean; color?: string; opacity?: number };
283
+ };
284
+
285
+ baseline?: {
286
+ stroke?: {
287
+ enable?: boolean;
288
+ width?: number;
289
+ colors?: { up?: string; down?: string };
290
+ };
291
+ base?: {
292
+ color?: string;
293
+ width?: number;
294
+ opacity?: number;
295
+ };
296
+ area?: {
297
+ enable?: boolean;
298
+ opacity?: number;
299
+ colors?: { up?: string; down?: string };
300
+ };
301
+ };
302
+
303
+ bars?: {
304
+ width?: number;
305
+ openEnable?: boolean;
306
+ colors?: { up?: string; down?: string };
307
+ };
308
+
309
+ steps_line?: {
310
+ width?: number;
311
+ color?: string;
312
+ openEnable?: boolean; // supported in settings editor
313
+ };
314
+
315
+ high_low?: {
316
+ body?: { enable?: boolean; color?: string };
317
+ border?: { enable?: boolean; color?: string };
318
+ };
319
+
320
+ grid?: {
321
+ line?: {
322
+ enable?: boolean;
323
+ color?: string;
324
+ width?: number;
325
+ opacity?: number;
326
+ };
327
+ text?: {
328
+ enable?: boolean;
329
+ color?: string;
330
+ };
331
+ };
332
+
333
+ mainPaneMask?: {
334
+ enable?: boolean;
335
+ color?: string;
336
+ opacity?: number; // 0..1
337
+ };
338
+
339
+ orders?: {
340
+ line?: {
341
+ enable?: boolean;
342
+ color?: string;
343
+ width?: number;
344
+ opacity?: number;
345
+ };
346
+ text?: {
347
+ enable?: boolean;
348
+ color?: string;
349
+ };
350
+ badge?: {
351
+ borderColor?: string;
352
+ backgroundColor?: string;
353
+ };
354
+ };
355
+
356
+ cursor?: {
357
+ line?: {
358
+ color?: string;
359
+ width?: number;
360
+ opacity?: number;
361
+ dashed?: boolean;
362
+ dashInterval?: number;
363
+ };
364
+ badge?: {
365
+ borderColor?: string;
366
+ backgroundColor?: string;
367
+ };
368
+ };
369
+
370
+ offset?: {
371
+ top?: number;
372
+ bottom?: number;
373
+ };
374
+
375
+ assetLabel?: {
376
+ fill?: string;
377
+ };
378
+ };
379
+ ```
380
+
381
+ ## Default Engine Settings (from source)
382
+
383
+ This is the default core settings object from `src/Chart/core/Main.js` before merging your `props.settings`:
384
+
385
+ ```js
386
+ {
387
+ showVolume: false,
388
+ showStats: false,
389
+ showPriceAlerts: false,
390
+ autoScale: false,
391
+ animation: true,
392
+ orderOffset: 0,
393
+ currentPrice: { visible: { bid: true, middle: false, ask: false } },
394
+ volume: { enable: true, colors: { up: '#26b276', down: '#f73e4a' } },
395
+ candles: {
396
+ body: { enable: true, colors: { up: '#26b276', down: '#f73e4a' } },
397
+ border: { enable: true, colors: { up: '#26b276', down: '#f73e4a' } },
398
+ wick: { enable: true, colors: { up: '#26b276', down: '#f73e4a' } },
399
+ },
400
+ columns: {
401
+ body: { enable: true, colors: { up: '#26b276', down: '#f73e4a' } },
402
+ border: { enable: true, colors: { up: '#26b276', down: '#f73e4a' } },
403
+ wick: { enable: true, colors: { up: '#26b276', down: '#f73e4a' } },
404
+ },
405
+ heiken: {
406
+ body: { enable: true, colors: { up: '#57a1d0', down: '#f73e4a' } },
407
+ border: { enable: true, colors: { up: '#57a1d0', down: '#f73e4a' } },
408
+ wick: { enable: true, colors: { up: '#57a1d0', down: '#f73e4a' } },
409
+ },
410
+ line: {
411
+ stroke: { enable: true, color: '#2f3342', width: 2 },
412
+ area: { enable: true, color: '#57a1d0', opacity: 0.1 },
413
+ },
414
+ baseline: {
415
+ stroke: { enable: true, width: 2, colors: { up: '#26b276', down: '#f73e4a' } },
416
+ base: { color: '#1f222c', width: 1, opacity: 0.5 },
417
+ area: { enable: true, opacity: 0.12, colors: { up: '#26b276', down: '#f73e4a' } },
418
+ },
419
+ bars: { width: 4, openEnable: true, colors: { up: '#26b276', down: '#f73e4a' } },
420
+ steps_line: { width: 4, color: '#2862ff' },
421
+ high_low: {
422
+ body: { enable: true, color: '#2862ff' },
423
+ border: { enable: true, color: '#2862ff' },
424
+ },
425
+ grid: {
426
+ line: { enable: true, color: '#1f222c', width: 1, opacity: 0.2 },
427
+ text: { enable: true, color: '#2f3342' },
428
+ },
429
+ mainPaneMask: { enable: true, color: '#ffffff', opacity: 1 },
430
+ orders: {
431
+ line: { enable: true, color: '#1f222c', width: 1, opacity: 0.2 },
432
+ text: { enable: true, color: '#2f3342' },
433
+ badge: { borderColor: '#c9c9c9', backgroundColor: '#c9c9c9' },
434
+ },
435
+ cursor: {
436
+ line: { color: '#1f222c', width: 1, opacity: 0.8, dashed: true, dashInterval: 8 },
437
+ badge: { borderColor: '#c9c9c9', backgroundColor: '#c9c9c9' },
438
+ },
439
+ offset: { top: 10, bottom: 10 },
440
+ assetLabel: { fill: 'rgba(0, 0, 0, 0.3)' },
441
+ }
442
+ ```
443
+
444
+ ## Runtime API (`chart.api`)
445
+
446
+ ```js
447
+ const wrapper = chartRef.current;
448
+ const key = wrapper.state.activeChart;
449
+ const api = wrapper[`chart-${key}`].api;
450
+ ```
451
+
452
+ ### Methods
453
+
454
+ - `setSettings(obj, event?)`
455
+ - `getSettings(path)`
456
+ - `setColors(obj)`
457
+ - `setNewCandle({ frame, candle })`
458
+ - `_setNewCandle({ frame, bid, volume?, time })`
459
+ - `setNewQuote(q?)`
460
+ - `changeType(value)`
461
+ - `changeVerticalZoom(value)`
462
+ - `panVerticalByPixels(deltaPx)`
463
+ - `getIndicators()`
464
+ - `getIndicatorByKey(key)`
465
+ - `addIndicator(name, data)`
466
+ - `removeIndicator(name)`
467
+ - `removeIndicatorsAll()`
468
+ - `hideIndicator(name)`
469
+ - `initDrawingTools(data)`
470
+ - `getDrawingTools()`
471
+ - `addDrawingTools(data)`
472
+ - `addText(data?)`
473
+ - `updateText(key, patch)`
474
+ - `removeText(key)`
475
+ - `removeDrawingTools(data)`
476
+ - `removeDrawingToolsAll()`
477
+ - `setCount(count)`
478
+ - `setTimeline(time, count?)`
479
+ - `stopEvent()`
480
+ - `startEvent()`
481
+ - `addStopLoss()`
482
+ - `addTakeProfit()`
483
+ - `reloadChart(asset, digits, options?)`
484
+ - `zoomChart(val)`
485
+ - `goToTime({ time })`
486
+ - `setCenter()`
487
+ - `changeSymbol(asset)`
488
+ - `addOpenPositions(positions)`
489
+ - `switchChart(type='candle')`
490
+ - `setTime(time)`
491
+ - `drawArrow(type)`
492
+ - `toggleCrossTarget()`
493
+ - `panByCandles(delta)`
494
+ - `panToHistory(step=1)`
495
+ - `panToLatest(step=1)`
496
+
497
+ ## Main `onChange` Events
498
+
499
+ - `chart:initial`
500
+ - `chart:activeChange`
501
+ - `chart:contextMenu`
502
+ - `chart:openOrder`
503
+ - `chart:priceAlerts:open`
504
+ - `chart:priceAlerts:remove`
505
+ - `change:timeFrame`
506
+ - `change:count`
507
+ - `change:type`
508
+ - `change:settings`
509
+ - `change:indicators`
510
+ - `favorites:add`
511
+ - `favorites:delete`
512
+
513
+ ## Chart Type Values
514
+
515
+ - `candle`
516
+ - `line`
517
+ - `area`
518
+ - `bars`
519
+ - `heiken_ashi`
520
+ - `high_low`
521
+ - `columns`
522
+ - `line_step`
523
+ - `baseline`
524
+
525
+ ## Local Development
526
+
527
+ ```bash
528
+ npm run dev
529
+ npm run build
530
+ npm run build_package
531
+ ```
532
+
533
+ ## Authors
534
+
535
+ - Viktor Semenov
536
+ - Vladislav Fisher
38
537
 
538
+ Copyright (c) 2017-2026 ScaleTrade & AlfaLabs Group LLC