@tradecanvas/svelte 1.3.9 → 1.3.11
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/TradeCanvas.svelte
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { onMount, onDestroy } from 'svelte';
|
|
2
|
+
import { onMount, onDestroy, untrack } from 'svelte';
|
|
3
3
|
import {
|
|
4
4
|
Chart,
|
|
5
5
|
BinanceAdapter,
|
|
@@ -30,7 +30,12 @@
|
|
|
30
30
|
chartType?: ChartType;
|
|
31
31
|
/** Indicators by id (`'rsi'`), or with their inputs (`{ id: 'ema', params: { period: 50 } }`). */
|
|
32
32
|
indicators?: IndicatorSpec[];
|
|
33
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* Bars: the chart shows these, and opens no stream of its own when it has
|
|
35
|
+
* them at mount. A bar pushed onto the same array, or its last bar changed,
|
|
36
|
+
* goes in as a live tick (the view stays where it is); a new array is a new
|
|
37
|
+
* series. An older bar changed in place needs a new array.
|
|
38
|
+
*/
|
|
34
39
|
data?: OHLCBar[];
|
|
35
40
|
adapter?: DataAdapter;
|
|
36
41
|
/** `false`: no stream until you say so (no Binance by default); the chart waits for `data`. Default `true`. */
|
|
@@ -91,6 +96,8 @@
|
|
|
91
96
|
const indicatorIds = new Map<string, string>();
|
|
92
97
|
/** The stream open now (`symbol|timeframe`), or null. */
|
|
93
98
|
let streamKey: string | null = null;
|
|
99
|
+
/** The bars last given to the chart: the array, how many, and the last one as text. */
|
|
100
|
+
let fed: { bars: OHLCBar[]; length: number; last: string } | null = null;
|
|
94
101
|
/** The features last applied, as text. */
|
|
95
102
|
let featuresKey: string | null = null;
|
|
96
103
|
|
|
@@ -126,7 +133,7 @@
|
|
|
126
133
|
chart = instance;
|
|
127
134
|
|
|
128
135
|
if (data) {
|
|
129
|
-
instance
|
|
136
|
+
feed(instance, data);
|
|
130
137
|
} else if (stream) {
|
|
131
138
|
const dataAdapter = adapter ?? new BinanceAdapter();
|
|
132
139
|
instance.connect({ adapter: dataAdapter, symbol, timeframe, historyLimit });
|
|
@@ -175,7 +182,42 @@
|
|
|
175
182
|
|
|
176
183
|
$effect(() => { instance?.setTheme(resolveTheme(theme)); });
|
|
177
184
|
$effect(() => { instance?.setChartType(chartType); });
|
|
178
|
-
|
|
185
|
+
const barKey = (b: OHLCBar | undefined) => (b ? `${b.time},${b.open},${b.high},${b.low},${b.close},${b.volume}` : '');
|
|
186
|
+
const plain = (b: OHLCBar) => $state.snapshot(b) as OHLCBar;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Bars into the chart: on the same array, a bar pushed or the last one
|
|
190
|
+
* changed goes in as a tick, so the view stays put and only the end is
|
|
191
|
+
* recalculated; anything else is a new series. The chart gets plain copies,
|
|
192
|
+
* not $state proxies, to read in its frames.
|
|
193
|
+
*/
|
|
194
|
+
function feed(target: Chart, bars: OHLCBar[]): void {
|
|
195
|
+
const n = bars.length;
|
|
196
|
+
const last = barKey(bars[n - 1]);
|
|
197
|
+
const prev = fed;
|
|
198
|
+
fed = { bars, length: n, last };
|
|
199
|
+
if (prev && prev.bars === bars && prev.length > 0) {
|
|
200
|
+
if (n === prev.length) {
|
|
201
|
+
if (last !== prev.last) target.updateLastBar(plain(bars[n - 1]));
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
if (n === prev.length + 1) {
|
|
205
|
+
target.updateLastBar(plain(bars[n - 2]));
|
|
206
|
+
target.appendBar(plain(bars[n - 1]));
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
target.setData($state.snapshot(bars) as OHLCBar[]);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Follows the array, its length and the last bar's fields: a bar pushed onto
|
|
214
|
+
// $state data or the forming bar changed, without walking every bar.
|
|
215
|
+
$effect(() => {
|
|
216
|
+
const bars = data;
|
|
217
|
+
if (!bars) return;
|
|
218
|
+
void barKey(bars[bars.length - 1]);
|
|
219
|
+
untrack(() => { if (instance) feed(instance, bars); });
|
|
220
|
+
});
|
|
179
221
|
|
|
180
222
|
$effect(() => {
|
|
181
223
|
const specs = $state.snapshot(indicators) as IndicatorSpec[];
|
|
@@ -7,7 +7,12 @@ interface Props {
|
|
|
7
7
|
chartType?: ChartType;
|
|
8
8
|
/** Indicators by id (`'rsi'`), or with their inputs (`{ id: 'ema', params: { period: 50 } }`). */
|
|
9
9
|
indicators?: IndicatorSpec[];
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Bars: the chart shows these, and opens no stream of its own when it has
|
|
12
|
+
* them at mount. A bar pushed onto the same array, or its last bar changed,
|
|
13
|
+
* goes in as a live tick (the view stays where it is); a new array is a new
|
|
14
|
+
* series. An older bar changed in place needs a new array.
|
|
15
|
+
*/
|
|
11
16
|
data?: OHLCBar[];
|
|
12
17
|
adapter?: DataAdapter;
|
|
13
18
|
/** `false`: no stream until you say so (no Binance by default); the chart waits for `data`. Default `true`. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradecanvas/svelte",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Svelte 5 component for @tradecanvas/chart — reactive props, runes, zero boilerplate.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"README.md"
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@tradecanvas/chart": "1.
|
|
42
|
+
"@tradecanvas/chart": "1.29.0"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"svelte": ">=5.0.0"
|