react-klinecharts-ui 0.6.0 → 1.1.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.
@@ -0,0 +1,92 @@
1
+ import { createContext, useContext } from 'react';
2
+
3
+ // src/provider/ChartTerminalContext.ts
4
+ var KlinechartsUIStateContext = createContext(null);
5
+ var KlinechartsUIDispatchContext = createContext(null);
6
+ function useKlinechartsUIDispatch() {
7
+ const ctx = useContext(KlinechartsUIDispatchContext);
8
+ if (!ctx) {
9
+ throw new Error(
10
+ "useKlinechartsUI must be used within a <KlinechartsUIProvider>"
11
+ );
12
+ }
13
+ return ctx;
14
+ }
15
+ function useKlinechartsUI() {
16
+ const state = useContext(KlinechartsUIStateContext);
17
+ const dispatch = useContext(KlinechartsUIDispatchContext);
18
+ if (!state || !dispatch) {
19
+ throw new Error(
20
+ "useKlinechartsUI must be used within a <KlinechartsUIProvider>"
21
+ );
22
+ }
23
+ return { state, ...dispatch };
24
+ }
25
+
26
+ // src/utils/createDataLoader.ts
27
+ function createDataLoader(datafeed, dispatch) {
28
+ let oldestTimestamp = null;
29
+ let currentGen = 0;
30
+ return {
31
+ getBars: async (params) => {
32
+ try {
33
+ dispatch({ type: "SET_LOADING", isLoading: true });
34
+ if (params.type === "init") {
35
+ oldestTimestamp = null;
36
+ const gen = ++currentGen;
37
+ const data = await datafeed.getHistoryKLineData(
38
+ params.symbol,
39
+ { ...params.period, label: "" },
40
+ 0,
41
+ Date.now()
42
+ );
43
+ if (gen !== currentGen) return;
44
+ if (data.length > 0) {
45
+ oldestTimestamp = data[0].timestamp;
46
+ }
47
+ params.callback(data, {
48
+ forward: data.length > 0,
49
+ backward: false
50
+ });
51
+ } else if (params.type === "forward" && oldestTimestamp !== null) {
52
+ const gen = currentGen;
53
+ const data = await datafeed.getHistoryKLineData(
54
+ params.symbol,
55
+ { ...params.period, label: "" },
56
+ 0,
57
+ oldestTimestamp - 1
58
+ );
59
+ if (gen !== currentGen) return;
60
+ if (data.length > 0) {
61
+ oldestTimestamp = data[0].timestamp;
62
+ }
63
+ params.callback(data, {
64
+ forward: data.length > 0,
65
+ backward: false
66
+ });
67
+ } else if (params.type === "backward") {
68
+ params.callback([], { forward: false, backward: false });
69
+ }
70
+ } catch (error) {
71
+ console.error("Failed to load chart data:", error);
72
+ params.callback([], { forward: false, backward: false });
73
+ } finally {
74
+ dispatch({ type: "SET_LOADING", isLoading: false });
75
+ }
76
+ },
77
+ subscribeBar: (params) => {
78
+ datafeed.subscribe(
79
+ params.symbol,
80
+ { ...params.period, label: "" },
81
+ (klineData) => params.callback(klineData)
82
+ );
83
+ },
84
+ unsubscribeBar: (params) => {
85
+ datafeed.unsubscribe(params.symbol, { ...params.period, label: "" });
86
+ }
87
+ };
88
+ }
89
+
90
+ export { KlinechartsUIDispatchContext, KlinechartsUIStateContext, createDataLoader, useKlinechartsUI, useKlinechartsUIDispatch };
91
+ //# sourceMappingURL=chunk-O7E57I66.js.map
92
+ //# sourceMappingURL=chunk-O7E57I66.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/provider/ChartTerminalContext.ts","../src/utils/createDataLoader.ts"],"names":[],"mappings":"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","file":"chunk-O7E57I66.js","sourcesContent":["import { createContext, useContext } from \"react\";\nimport type {\n KlinechartsUIState,\n KlinechartsUIContextValue,\n KlinechartsUIDispatchValue,\n} from \"./types\";\n\nexport const KlinechartsUIStateContext =\n createContext<KlinechartsUIState | null>(null);\n\nexport const KlinechartsUIDispatchContext =\n createContext<KlinechartsUIDispatchValue | null>(null);\n\n/**\n * @internal\n * Reads only the stable dispatch slice. Hooks that use this won't re-render\n * when chart state changes (e.g. symbol, period, isLoading).\n */\nexport function useKlinechartsUIDispatch(): KlinechartsUIDispatchValue {\n const ctx = useContext(KlinechartsUIDispatchContext);\n if (!ctx) {\n throw new Error(\n \"useKlinechartsUI must be used within a <KlinechartsUIProvider>\"\n );\n }\n return ctx;\n}\n\n/**\n * Primary hook — returns the full combined context value.\n * For performance-sensitive cases, prefer the two split hooks internally.\n */\nexport function useKlinechartsUI(): KlinechartsUIContextValue {\n const state = useContext(KlinechartsUIStateContext);\n const dispatch = useContext(KlinechartsUIDispatchContext);\n if (!state || !dispatch) {\n throw new Error(\n \"useKlinechartsUI must be used within a <KlinechartsUIProvider>\"\n );\n }\n return { state, ...dispatch };\n}\n","import type { Dispatch } from \"react\";\nimport type { DataLoader, KLineData } from \"klinecharts\";\nimport type { Datafeed, KlinechartsUIAction } from \"../provider/types\";\n\n/**\n * Creates a klinecharts DataLoader from a Datafeed instance.\n * This bridges the react-klinecharts-ui Datafeed interface to the\n * klinecharts native DataLoader format used by KLineChart component.\n *\n * In klinecharts terminology:\n * - \"init\" = initial data load\n * - \"forward\" = load older data (user scrolled left into history)\n * - \"backward\" = load newer data (user scrolled right)\n */\nexport function createDataLoader(\n datafeed: Datafeed,\n dispatch: Dispatch<KlinechartsUIAction>,\n): DataLoader {\n let oldestTimestamp: number | null = null;\n // Incremented on every \"init\" request. Forward requests capture the value at\n // their start and bail out if a newer init has begun while they were in-flight.\n let currentGen = 0;\n\n return {\n getBars: async (params) => {\n try {\n dispatch({ type: \"SET_LOADING\", isLoading: true });\n\n if (params.type === \"init\") {\n oldestTimestamp = null;\n const gen = ++currentGen;\n const data = await datafeed.getHistoryKLineData(\n params.symbol,\n { ...params.period, label: \"\" },\n 0,\n Date.now(),\n );\n if (gen !== currentGen) return; // newer init started — discard stale result\n if (data.length > 0) {\n oldestTimestamp = data[0].timestamp;\n }\n params.callback(data as KLineData[], {\n forward: data.length > 0,\n backward: false,\n });\n } else if (params.type === \"forward\" && oldestTimestamp !== null) {\n const gen = currentGen;\n const data = await datafeed.getHistoryKLineData(\n params.symbol,\n { ...params.period, label: \"\" },\n 0,\n oldestTimestamp - 1,\n );\n if (gen !== currentGen) return; // init for new period started — discard\n if (data.length > 0) {\n oldestTimestamp = data[0].timestamp;\n }\n params.callback(data as KLineData[], {\n forward: data.length > 0,\n backward: false,\n });\n } else if (params.type === \"backward\") {\n // Backward pagination (loading data newer than what we have) is generally\n // not needed in typical terminal usage because we subscribe via ws for real-time.\n params.callback([], { forward: false, backward: false });\n }\n } catch (error) {\n console.error(\"Failed to load chart data:\", error);\n params.callback([], { forward: false, backward: false });\n } finally {\n dispatch({ type: \"SET_LOADING\", isLoading: false });\n }\n },\n subscribeBar: (params) => {\n datafeed.subscribe(\n params.symbol,\n { ...params.period, label: \"\" },\n (klineData) => params.callback(klineData as KLineData),\n );\n },\n unsubscribeBar: (params) => {\n datafeed.unsubscribe(params.symbol, { ...params.period, label: \"\" });\n },\n };\n}\n"]}
@@ -0,0 +1,9 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, { get: all[name], enumerable: true });
5
+ };
6
+
7
+ export { __export };
8
+ //# sourceMappingURL=chunk-PZ5AY32C.js.map
9
+ //# sourceMappingURL=chunk-PZ5AY32C.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-PZ5AY32C.js"}
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ var __defProp = Object.defineProperty;
4
+ var __export = (target, all) => {
5
+ for (var name in all)
6
+ __defProp(target, name, { get: all[name], enumerable: true });
7
+ };
8
+
9
+ exports.__export = __export;
10
+ //# sourceMappingURL=chunk-Q7SFCCGT.cjs.map
11
+ //# sourceMappingURL=chunk-Q7SFCCGT.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-Q7SFCCGT.cjs"}
@@ -1,10 +1,5 @@
1
- import { registerFigure, utils, registerOverlay, registerIndicator } from 'react-klinecharts';
2
-
3
- var __defProp = Object.defineProperty;
4
- var __export = (target, all) => {
5
- for (var name in all)
6
- __defProp(target, name, { get: all[name], enumerable: true });
7
- };
1
+ import { __export } from './chunk-PZ5AY32C.js';
2
+ import { utils, registerFigure, registerOverlay, registerIndicator } from 'klinecharts';
8
3
 
9
4
  // src/overlays/index.ts
10
5
  var overlays_exports = {};
@@ -992,7 +987,10 @@ var parallelChannel_default = parallelChannel;
992
987
  // src/overlays/longPosition.ts
993
988
  var longPosition = {
994
989
  name: "longPosition",
995
- totalStep: 3,
990
+ // totalStep 4 → the user places 3 points interactively (entry, target, stop).
991
+ // With the previous value of 3, only 2 points were captured and the stop was
992
+ // always a hardcoded 40px offset, so R/R was meaningless.
993
+ totalStep: 4,
996
994
  needDefaultPointFigure: true,
997
995
  needDefaultXAxisFigure: true,
998
996
  needDefaultYAxisFigure: true,
@@ -1101,7 +1099,10 @@ var longPosition_default = longPosition;
1101
1099
  // src/overlays/shortPosition.ts
1102
1100
  var shortPosition = {
1103
1101
  name: "shortPosition",
1104
- totalStep: 3,
1102
+ // totalStep 4 → the user places 3 points interactively (entry, target, stop).
1103
+ // With the previous value of 3, only 2 points were captured and the stop was
1104
+ // always a hardcoded 40px offset, so R/R was meaningless.
1105
+ totalStep: 4,
1105
1106
  needDefaultPointFigure: true,
1106
1107
  needDefaultXAxisFigure: true,
1107
1108
  needDefaultYAxisFigure: true,
@@ -1230,8 +1231,10 @@ var measure = {
1230
1231
  const endPoint = overlay.points[1];
1231
1232
  const startCoord = coordinates[0];
1232
1233
  const endCoord = coordinates[1];
1233
- const diff = endPoint.value - startPoint.value;
1234
- const percent = (diff / startPoint.value * 100).toFixed(2);
1234
+ const startValue = startPoint.value ?? 0;
1235
+ const endValue = endPoint.value ?? 0;
1236
+ const diff = endValue - startValue;
1237
+ const percent = startValue !== 0 ? (diff / startValue * 100).toFixed(2) : "0.00";
1235
1238
  const bars = Math.abs(
1236
1239
  (endPoint.dataIndex ?? 0) - (startPoint.dataIndex ?? 0)
1237
1240
  );
@@ -1284,7 +1287,7 @@ var measure = {
1284
1287
  {
1285
1288
  type: "line",
1286
1289
  attrs: { coordinates: [startCoord, endCoord] },
1287
- styles: { color: strokeColor, style: "dash" }
1290
+ styles: { color: strokeColor, style: "dashed" }
1288
1291
  },
1289
1292
  ...textFigures
1290
1293
  ];
@@ -1860,8 +1863,9 @@ var ichimoku = {
1860
1863
  if (index >= kijunPeriod - 1) {
1861
1864
  item.kijun = highLowAvg(dataList, index - kijunPeriod + 1, index);
1862
1865
  }
1863
- if (index + offset < dataList.length) {
1864
- item.chikou = dataList[index + offset].close;
1866
+ const chikouIndex = index - offset;
1867
+ if (chikouIndex >= 0) {
1868
+ item.chikou = dataList[chikouIndex].close;
1865
1869
  }
1866
1870
  const prevIndex = index - offset;
1867
1871
  if (prevIndex >= 0) {
@@ -2001,7 +2005,7 @@ var pivotPoints = {
2001
2005
  let dayLow = Infinity;
2002
2006
  let dayClose = 0;
2003
2007
  return dataList.map((kLineData) => {
2004
- const date = new Date(kLineData.timestamp).toLocaleDateString();
2008
+ const date = new Date(kLineData.timestamp).toISOString().slice(0, 10);
2005
2009
  if (date !== lastDate) {
2006
2010
  if (lastDate !== "") {
2007
2011
  lastP = (dayHigh + dayLow + dayClose) / 3;
@@ -2055,11 +2059,20 @@ var rsiTv = {
2055
2059
  const maPeriod = indicator.calcParams[1];
2056
2060
  const closes = dataList.map((d) => d.close);
2057
2061
  const rsiValues = TA_default.rsi(closes, rsiPeriod);
2058
- const nonNullRsi = rsiValues.map((v) => v ?? 0);
2059
- const maValues = TA_default.sma(nonNullRsi, maPeriod);
2062
+ const rsiMa = new Array(rsiValues.length).fill(null);
2063
+ for (let i = 0; i < rsiValues.length; i++) {
2064
+ if (rsiValues[i] === null) continue;
2065
+ const valid = [];
2066
+ for (let j = i; j >= 0 && valid.length < maPeriod; j--) {
2067
+ if (rsiValues[j] !== null) valid.push(rsiValues[j]);
2068
+ }
2069
+ if (valid.length === maPeriod) {
2070
+ rsiMa[i] = valid.reduce((a, b) => a + b, 0) / maPeriod;
2071
+ }
2072
+ }
2060
2073
  return dataList.map((_, i) => {
2061
2074
  const rsi = rsiValues[i];
2062
- const rsi_ma = rsi !== null && maValues[i] !== null ? maValues[i] : null;
2075
+ const rsi_ma = rsi !== null ? rsiMa[i] : null;
2063
2076
  return { rsi, rsi_ma };
2064
2077
  });
2065
2078
  },
@@ -2281,7 +2294,7 @@ var vwap = {
2281
2294
  let cumulativePriceVolume = 0;
2282
2295
  let lastDate = "";
2283
2296
  return dataList.map((kLineData) => {
2284
- const date = new Date(kLineData.timestamp).toLocaleDateString();
2297
+ const date = new Date(kLineData.timestamp).toISOString().slice(0, 10);
2285
2298
  if (date !== lastDate) {
2286
2299
  cumulativeVolume = 0;
2287
2300
  cumulativePriceVolume = 0;
@@ -2414,7 +2427,7 @@ var depthOverlay = {
2414
2427
  const maxBarPx = bounding.width * maxBarFraction;
2415
2428
  const askColor = d.askColor ?? "rgba(239,83,80,0.25)";
2416
2429
  const bidColor = d.bidColor ?? "rgba(38,166,154,0.25)";
2417
- const maxQty = d.maxQty || 1;
2430
+ const maxQty = d.maxQty ?? 1;
2418
2431
  const figures = [];
2419
2432
  for (const row of d.rows) {
2420
2433
  const y = yAxis.convertToPixel(row.price);
@@ -2567,5 +2580,5 @@ function ensureAlertLineRegistered() {
2567
2580
  }
2568
2581
 
2569
2582
  export { TA_default, abcd_default, alertLine_default, anyWaves_default, arrow_default, bollTv_default, brush_default, cci_default, circle_default, depthOverlay_default, eightWaves_default, elliottWave_default, ensureAlertLineRegistered, featureOverlays, fibRetracement_default, fibonacciCircle_default, fibonacciExtension_default, fibonacciSegment_default, fibonacciSpeedResistanceFan_default, fibonacciSpiral_default, fiveWaves_default, gannBox_default, gannFan_default, hma_default, ichimoku_default, indicators, longPosition_default, maRibbon_default, macdTv_default, measure_default, orderLine_default, overlays, parallelChannel_default, parallelogram_default, pivotPoints_default, ray_default, rect_default, registerExtensions, rsiTv_default, shortPosition_default, stochastic_default, superTrend_default, threeWaves_default, triangle_default, vwap_default, xabcd_default };
2570
- //# sourceMappingURL=chunk-MVD3ILJT.js.map
2571
- //# sourceMappingURL=chunk-MVD3ILJT.js.map
2583
+ //# sourceMappingURL=chunk-RIT2LJQT.js.map
2584
+ //# sourceMappingURL=chunk-RIT2LJQT.js.map