From ad73131131a0b23b340e6b79438ee75965d725db Mon Sep 17 00:00:00 2001 From: Cris Mihalache Date: Tue, 25 Jun 2024 10:36:13 +0200 Subject: [PATCH 1/9] fix: update onLoadMoreCB if it changes in the Chart react component --- src/components/Chart/Chart.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/Chart/Chart.js b/src/components/Chart/Chart.js index fabf028..898c2cb 100644 --- a/src/components/Chart/Chart.js +++ b/src/components/Chart/Chart.js @@ -111,9 +111,13 @@ class Chart extends React.Component { const { isFullscreen } = this.state const { candles, width, height, trades, indicators, drawings, candleWidth, orders, - position, disableToolbar, disableTopbar, marketLabel + position, disableToolbar, disableTopbar, marketLabel, onLoadMore } = this.props + if (onLoadMore !== prevProps.onLoadMore) { + this.chart.onLoadMoreCB = onLoadMore + } + if (candles !== prevProps.candles || candleWidth !== prevProps.candleWidth) { this.chart.updateData(candles, candleWidth, `${marketLabel}${candleWidth}`) } From ae6f85943cd92330662c85d1be1e34d42ddc2900 Mon Sep 17 00:00:00 2001 From: Cris Mihalache Date: Tue, 25 Jun 2024 10:36:27 +0200 Subject: [PATCH 2/9] fix: set internal chart ref to null on unmount --- src/components/Chart/Chart.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/Chart/Chart.js b/src/components/Chart/Chart.js index 898c2cb..b7b75a3 100644 --- a/src/components/Chart/Chart.js +++ b/src/components/Chart/Chart.js @@ -161,6 +161,8 @@ class Chart extends React.Component { document.removeEventListener('mozfullscreenchange', this.onFullscreenExit) document.removeEventListener('MSFullscreenChange', this.onFullscreenExit) document.removeEventListener('webkitfullscreenchange', this.onFullscreenExit) + + this.chart = null } onHoveredCandle (hoveredCandle) { From bd5e9b63535c5de69700687e617ff567a011d75c Mon Sep 17 00:00:00 2001 From: Cris Mihalache Date: Tue, 25 Jun 2024 10:36:56 +0200 Subject: [PATCH 3/9] fix: prevent redundant calls to onLoadMoreCB --- src/components/Chart/lib/chart.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/Chart/lib/chart.js b/src/components/Chart/lib/chart.js index 9efb6d7..72a9d6f 100644 --- a/src/components/Chart/lib/chart.js +++ b/src/components/Chart/lib/chart.js @@ -981,7 +981,12 @@ export default class BitfinexTradingChart { const candlePanOffset = panX > 0 ? Math.floor(panX / this.candleWidthPX) : 0 if (candlePanOffset + this.viewportWidthCandles > this.data.length) { - this.onLoadMoreCB(this.viewportWidthCandles) + const newOnLoadMoreKey = `${(this.data[0] ?? [])[0]}-${(_last(this.data) ?? [])[0]}-${this.dataKey}` + + if (this.onLoadMoreKey !== newOnLoadMoreKey) { + this.onLoadMoreCB(this.viewportWidthCandles) + this.onLoadMoreKey = newOnLoadMoreKey + } } } } else { From 9925289a36edd421690ad4f71bece8bcac3903e7 Mon Sep 17 00:00:00 2001 From: Cris Mihalache Date: Tue, 25 Jun 2024 10:38:54 +0200 Subject: [PATCH 4/9] feat: bump version to 1.0.14 & build --- dist/Demo.js | 33 +--- dist/components/Chart/Chart.js | 92 ++------- dist/components/Chart/Chart.props.js | 6 +- dist/components/Chart/index.js | 6 +- dist/components/Chart/lib/chart.js | 180 ++---------------- dist/components/Chart/lib/config.js | 2 - dist/components/Chart/lib/data_transformer.js | 18 +- dist/components/Chart/lib/draw/line.js | 5 - dist/components/Chart/lib/draw/ohlc_series.js | 22 +-- .../lib/draw/transformed_line_from_data.js | 8 +- dist/components/Chart/lib/draw/x_axis.js | 38 ++-- dist/components/Chart/lib/draw/y_axis.js | 18 +- dist/components/Chart/lib/drawings/drawing.js | 23 +-- .../Chart/lib/drawings/horizontal_line.js | 12 +- dist/components/Chart/lib/drawings/line.js | 17 +- .../Chart/lib/drawings/parallel_lines.js | 17 +- .../Chart/lib/drawings/vertical_line.js | 12 +- dist/components/Chart/lib/util/distance.js | 1 - .../Chart/lib/util/format_axis_tick.js | 1 - .../Chart/lib/util/serialize_indicators.js | 1 - .../Chart/lib/util/unserialize_indicators.js | 6 +- dist/components/Dropdown/Dropdown.js | 28 +-- dist/components/Dropdown/index.js | 6 +- .../IndicatorSettingsModal.js | 23 +-- .../IndicatorSettingsModal/index.js | 6 +- .../LoadingBeeSpinner/LoadingBeeSpinner.js | 9 +- dist/components/LoadingBeeSpinner/index.js | 6 +- dist/index.js | 22 +-- dist/serviceWorker.js | 30 ++- package.json | 2 +- 30 files changed, 97 insertions(+), 553 deletions(-) diff --git a/dist/Demo.js b/dist/Demo.js index 51f5ee5..d9a5b18 100644 --- a/dist/Demo.js +++ b/dist/Demo.js @@ -3,53 +3,38 @@ Object.defineProperty(exports, "__esModule", { value: true }); - var _react = require("react"); - var _react2 = _interopRequireDefault(_react); - var _reactVirtualized = require("react-virtualized"); - var _Chart = require("./components/Chart"); - var _Chart2 = _interopRequireDefault(_Chart); - var _btc_candle_data = require("./btc_candle_data.json"); - var _btc_candle_data2 = _interopRequireDefault(_btc_candle_data); - require("./Demo.css"); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } +function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } const INDICATORS_STORAGE_KEY = 'bfxc-demo-indicators'; const DEFAULT_INDICATORS_JSON = '[["ema",[20,"close"],["#2da3c4"]],["ema",[100,"close"],["#fcfcba"]],["macd",[12,26,9],["#2acca1","#02f73b","#1073ba"]],["rsi",[14],["#7320bc"]],["mo",[10],["#f8fc0a"]],["acc",[10],["#b4e560"]]]'; - _btc_candle_data2.default.sort((a, b) => a[0] - b[0]); - class Demo extends _react2.default.PureComponent { static loadIndicators() { if (!localStorage) { return []; } - try { return _Chart2.default.unserializeIndicators(localStorage.getItem(INDICATORS_STORAGE_KEY) || DEFAULT_INDICATORS_JSON); } catch { return []; } } - constructor(props) { super(props); - _defineProperty(this, "state", { drawings: [], indicators: [] }); - this.onUpdateIndicatorArgs = this.onUpdateIndicatorArgs.bind(this); this.onDeleteIndicator = this.onDeleteIndicator.bind(this); this.onAddIndicator = this.onAddIndicator.bind(this); @@ -57,7 +42,6 @@ class Demo extends _react2.default.PureComponent { this.chartRef = _react2.default.createRef(); this.state.indicators = Demo.loadIndicators(); } - onAddIndicator(i) { this.setState(({ indicators @@ -66,7 +50,6 @@ class Demo extends _react2.default.PureComponent { })); this.deferSaveState(); } - onAddDrawing(D) { this.setState(({ drawings @@ -74,7 +57,6 @@ class Demo extends _react2.default.PureComponent { drawings: [new D(this.chartRef.current.chart), ...drawings] })); } - onDeleteIndicator(index) { this.setState(({ indicators @@ -87,7 +69,6 @@ class Demo extends _react2.default.PureComponent { }); this.deferSaveState(); } - onUpdateIndicatorArgs(args, index) { this.setState(({ indicators @@ -102,24 +83,20 @@ class Demo extends _react2.default.PureComponent { }); this.deferSaveState(); } - deferSaveState() { setTimeout(() => { this.saveState(); }, 0); } - saveState() { if (!localStorage) { return; } - const { indicators } = this.state; localStorage.setItem(INDICATORS_STORAGE_KEY, _Chart2.default.serializeIndicators(indicators)); } - render() { const { drawings, @@ -146,7 +123,5 @@ class Demo extends _react2.default.PureComponent { onAddDrawing: this.onAddDrawing }))); } - } - exports.default = Demo; \ No newline at end of file diff --git a/dist/components/Chart/Chart.js b/dist/components/Chart/Chart.js index 827162b..433fbd1 100644 --- a/dist/components/Chart/Chart.js +++ b/dist/components/Chart/Chart.js @@ -3,77 +3,47 @@ Object.defineProperty(exports, "__esModule", { value: true }); - var _react = require("react"); - var _react2 = _interopRequireDefault(_react); - var _bfxHfUtil = require("bfx-hf-util"); - var _bfxHfIndicators = require("bfx-hf-indicators"); - var _bfxHfIndicators2 = _interopRequireDefault(_bfxHfIndicators); - var _randomcolor = require("randomcolor"); - var _randomcolor2 = _interopRequireDefault(_randomcolor); - var _Dropdown = require("../Dropdown"); - var _Dropdown2 = _interopRequireDefault(_Dropdown); - var _chart = require("./lib/chart"); - var _chart2 = _interopRequireDefault(_chart); - var _line = require("./lib/drawings/line"); - var _line2 = _interopRequireDefault(_line); - var _horizontal_line = require("./lib/drawings/horizontal_line"); - var _horizontal_line2 = _interopRequireDefault(_horizontal_line); - var _vertical_line = require("./lib/drawings/vertical_line"); - var _vertical_line2 = _interopRequireDefault(_vertical_line); - var _parallel_lines = require("./lib/drawings/parallel_lines"); - var _parallel_lines2 = _interopRequireDefault(_parallel_lines); - var _serialize_indicators = require("./lib/util/serialize_indicators"); - var _serialize_indicators2 = _interopRequireDefault(_serialize_indicators); - var _unserialize_indicators = require("./lib/util/unserialize_indicators"); - var _unserialize_indicators2 = _interopRequireDefault(_unserialize_indicators); - var _LoadingBeeSpinner = require("../LoadingBeeSpinner"); - var _LoadingBeeSpinner2 = _interopRequireDefault(_LoadingBeeSpinner); - var _IndicatorSettingsModal = require("../IndicatorSettingsModal"); - var _IndicatorSettingsModal2 = _interopRequireDefault(_IndicatorSettingsModal); - require("./Chart.css"); - require("./icon_font/styles.css"); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } +function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } const TOPBAR_HEIGHT = 45; -const TOOLBAR_HEIGHT = 45; // Library methods are made available on the class before export -// (to maintain CRA index.js) +const TOOLBAR_HEIGHT = 45; +// Library methods are made available on the class before export +// (to maintain CRA index.js) class Chart extends _react2.default.Component { constructor(props) { super(props); - _defineProperty(this, "state", { hoveredCandle: null, indicatorSettings: [], @@ -81,7 +51,6 @@ class Chart extends _react2.default.Component { settingsModalIndicatorIndex: -1, isFullscreen: false }); - this.onHoveredCandle = this.onHoveredCandle.bind(this); this.onCloseIndicatorSettings = this.onCloseIndicatorSettings.bind(this); this.onOpenIndicatorSettings = this.onOpenIndicatorSettings.bind(this); @@ -97,7 +66,6 @@ class Chart extends _react2.default.Component { this.crosshairCanvasRef = _react2.default.createRef(); this.chart = null; } - componentDidMount() { const { width, @@ -122,17 +90,14 @@ class Chart extends _react2.default.Component { const drawingCanvas = this.drawingCanvasRef.current; const indicatorCanvas = this.indicatorCanvasRef.current; const crosshairCanvas = this.crosshairCanvasRef.current; - if (!ohlcCanvas || !axisCanvas || !drawingCanvas || !indicatorCanvas || !crosshairCanvas) { console.error('mounted without all canvases!'); return; } - if (this.chart) { console.error('chart library initialized before mount!'); return; } - this.chart = new _chart2.default({ ohlcCanvas, axisCanvas, @@ -155,7 +120,6 @@ class Chart extends _react2.default.Component { config }); } - componentDidUpdate(prevProps) { const { isFullscreen @@ -172,13 +136,15 @@ class Chart extends _react2.default.Component { position, disableToolbar, disableTopbar, - marketLabel + marketLabel, + onLoadMore } = this.props; - + if (onLoadMore !== prevProps.onLoadMore) { + this.chart.onLoadMoreCB = onLoadMore; + } if (candles !== prevProps.candles || candleWidth !== prevProps.candleWidth) { this.chart.updateData(candles, candleWidth, `${marketLabel}${candleWidth}`); } - if (width !== prevProps.width || height !== prevProps.height || disableToolbar !== prevProps.disableToolbar || disableTopbar !== prevProps.disableTopbar) { if (isFullscreen) { this.chart.updateDimensions(window.innerWidth, this.getChartHeight()); @@ -186,47 +152,40 @@ class Chart extends _react2.default.Component { this.chart.updateDimensions(width, this.getChartHeight()); } } - if (trades !== prevProps.trades) { this.chart.updateTrades(trades); } - if (indicators !== prevProps.indicators) { this.chart.updateIndicators(indicators); } - if (drawings !== prevProps.drawings) { this.chart.updateDrawings(drawings); } - if (orders !== prevProps.orders) { this.chart.updateOrders(orders); } - if (position !== prevProps.position) { this.chart.updatePosition(position); } } - componentWillUnmount() { document.removeEventListener('fullscreenchange', this.onFullscreenExit); document.removeEventListener('mozfullscreenchange', this.onFullscreenExit); document.removeEventListener('MSFullscreenChange', this.onFullscreenExit); document.removeEventListener('webkitfullscreenchange', this.onFullscreenExit); + this.chart = null; } - onHoveredCandle(hoveredCandle) { this.setState(() => ({ hoveredCandle })); } + /** * @param {Array[]} indicators - array of [iClass, args] * @param {number} ohlcVPHeight - height of OHLC viewport * @param {number} slotHeight - external indicator slot height */ - - onUpdateIndicatorSettings(indicators, slotHeight) { const extCount = indicators.filter(([Class]) => Class.ui.position === 'external').length; let currentExtSlot = 0; @@ -251,21 +210,18 @@ class Chart extends _react2.default.Component { indicatorSettings })); } - onOpenIndicatorSettings(index) { this.setState(() => ({ settingsModalOpen: true, settingsModalIndicatorIndex: index })); } - onCloseIndicatorSettings() { this.setState(() => ({ settingsModalOpen: false, settingsModalIndicatorIndex: -1 })); } - onSaveIndicatorSettings(args) { const { onUpdateIndicatorArgs @@ -276,7 +232,6 @@ class Chart extends _react2.default.Component { onUpdateIndicatorArgs(args, settingsModalIndicatorIndex); this.onCloseIndicatorSettings(); } - onToggleFullscreen() { if (!document.fullscreenElement && !document.mozFullscreenElement && !document.msFullscreenElement && !document.webkitFullscreenElement) { if (this.wrapperRef.current) { @@ -294,12 +249,10 @@ class Chart extends _react2.default.Component { } } } - onFullscreenExit() { if (document.fullscreenElement || document.mozFullscreenElement || document.msFullscreenElement || document.webkitFullscreenElement) { return; } - const { width } = this.props; @@ -308,16 +261,13 @@ class Chart extends _react2.default.Component { })); this.chart.updateDimensions(width, this.getChartHeight()); } - onAddIndicator(i) { const { onAddIndicator } = this.props; - if (!onAddIndicator) { return; } - const { ui } = i; @@ -326,7 +276,6 @@ class Chart extends _react2.default.Component { } = ui; const args = i.args.map(a => a.default); const colors = []; - switch (type) { case 'rsi': case 'line': @@ -334,13 +283,11 @@ class Chart extends _react2.default.Component { colors.push((0, _randomcolor2.default)()); break; } - case 'lines': { ui.lines.forEach(() => colors.push((0, _randomcolor2.default)())); break; } - case 'bbands': { colors.push((0, _randomcolor2.default)()); @@ -348,7 +295,6 @@ class Chart extends _react2.default.Component { colors.push((0, _randomcolor2.default)()); break; } - case 'macd': { colors.push((0, _randomcolor2.default)()); @@ -356,34 +302,27 @@ class Chart extends _react2.default.Component { colors.push((0, _randomcolor2.default)()); break; } - default: { throw new Error(`unknown indicator type: ${type}`); } } - onAddIndicator([i, args, colors]); } - getTopReservedSpace() { const { disableTopbar, disableToolbar } = this.props; let space = 0; - if (!disableToolbar) { space += TOOLBAR_HEIGHT; } - if (!disableTopbar) { space += TOPBAR_HEIGHT; } - return space; } - getChartHeight() { const { isFullscreen @@ -391,7 +330,6 @@ class Chart extends _react2.default.Component { const height = isFullscreen ? window.innerHeight : this.props.height; return height - this.getTopReservedSpace(); } - render() { const { indicatorSettings, @@ -531,9 +469,7 @@ class Chart extends _react2.default.Component { top: this.getTopReservedSpace() })); } - } - Chart.serializeIndicators = _serialize_indicators2.default; Chart.unserializeIndicators = _unserialize_indicators2.default; exports.default = Chart; \ No newline at end of file diff --git a/dist/components/Chart/Chart.props.js b/dist/components/Chart/Chart.props.js index 9355a82..f2ff9a5 100644 --- a/dist/components/Chart/Chart.props.js +++ b/dist/components/Chart/Chart.props.js @@ -4,13 +4,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.defaultProps = exports.propTypes = undefined; - var _propTypes = require("prop-types"); - var _propTypes2 = _interopRequireDefault(_propTypes); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const propTypes = exports.propTypes = { width: _propTypes2.default.number.isRequired, height: _propTypes2.default.number.isRequired, diff --git a/dist/components/Chart/index.js b/dist/components/Chart/index.js index 252b6e3..92f6eed 100644 --- a/dist/components/Chart/index.js +++ b/dist/components/Chart/index.js @@ -3,11 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); - var _Chart = require("./Chart"); - var _Chart2 = _interopRequireDefault(_Chart); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } exports.default = _Chart2.default; \ No newline at end of file diff --git a/dist/components/Chart/lib/chart.js b/dist/components/Chart/lib/chart.js index e942a80..0fee948 100644 --- a/dist/components/Chart/lib/chart.js +++ b/dist/components/Chart/lib/chart.js @@ -3,77 +3,41 @@ Object.defineProperty(exports, "__esModule", { value: true }); - var _isFunction2 = require("lodash/isFunction"); - var _isFunction3 = _interopRequireDefault(_isFunction2); - var _isFinite2 = require("lodash/isFinite"); - var _isFinite3 = _interopRequireDefault(_isFinite2); - var _isObject2 = require("lodash/isObject"); - var _isObject3 = _interopRequireDefault(_isObject2); - var _isEmpty2 = require("lodash/isEmpty"); - var _isEmpty3 = _interopRequireDefault(_isEmpty2); - var _last2 = require("lodash/last"); - var _last3 = _interopRequireDefault(_last2); - var _max2 = require("lodash/max"); - var _max3 = _interopRequireDefault(_max2); - var _min2 = require("lodash/min"); - var _min3 = _interopRequireDefault(_min2); - var _bfxApiNodeModels = require("bfx-api-node-models"); - var _bfxHfUtil = require("bfx-hf-util"); - var _mouseWheel = require("mouse-wheel"); - var _mouseWheel2 = _interopRequireDefault(_mouseWheel); - var _format_axis_tick = require("./util/format_axis_tick"); - var _format_axis_tick2 = _interopRequireDefault(_format_axis_tick); - var _line = require("./draw/line"); - var _line2 = _interopRequireDefault(_line); - var _data_transformer = require("./data_transformer"); - var _data_transformer2 = _interopRequireDefault(_data_transformer); - var _transformed_line_from_data = require("./draw/transformed_line_from_data"); - var _transformed_line_from_data2 = _interopRequireDefault(_transformed_line_from_data); - var _ohlc_series = require("./draw/ohlc_series"); - var _ohlc_series2 = _interopRequireDefault(_ohlc_series); - var _x_axis = require("./draw/x_axis"); - var _x_axis2 = _interopRequireDefault(_x_axis); - var _y_axis = require("./draw/y_axis"); - var _y_axis2 = _interopRequireDefault(_y_axis); - var _config = require("./config"); - var _config2 = _interopRequireDefault(_config); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } class BitfinexTradingChart { constructor({ ohlcCanvas, @@ -155,7 +119,6 @@ class BitfinexTradingChart { this.clearAll(); this.renderAll(); } - clipCanvases() { const drawingCTX = this.drawingCanvas.getContext('2d'); const ohlcCTX = this.ohlcCanvas.getContext('2d'); @@ -165,43 +128,37 @@ class BitfinexTradingChart { ohlcCTX.clip(clipRegion); drawingCTX.clip(clipRegion); } - updateDrawings(drawings = []) { this.drawings = drawings; - if (drawings[0] && drawings[0].isActive()) { this.activeDrawing = drawings[0]; } } - updateIndicators(indicators = []) { this.indicators = indicators; this.updateData(this.data); const ohlcHeight = this.getOHLCVPHeight(); const slotHeight = this.externalIndicators === 0 ? 0 : (this.vp.size.h - ohlcHeight) / this.externalIndicators; - if (this.onUpdateIndicatorSettingsCB) { this.onUpdateIndicatorSettingsCB(indicators, slotHeight); } } - updateTrades(trades = []) { this.trades = trades; this.clearAll(); this.renderAll(); } - updateOrders(orders = []) { this.orders = orders; this.clearAll(); this.renderAll(); } - updatePosition(position) { this.position = position; this.clearAll(); this.renderAll(); } + /** * Updates internal candle & indicator data sets * @@ -209,98 +166,77 @@ class BitfinexTradingChart { * @param {number?} dataWidth - candle width, default unchanged * @param {string} dataKey - optional, resets pan on change */ - - updateData(data = [], dataWidth, dataKey) { if (dataWidth) { this.dataWidth = _bfxHfUtil.TIME_FRAME_WIDTHS[dataWidth]; } - if (this.dataKey && this.dataKey !== dataKey) { this.onDataReset(); } - this.data = data; this.dataKey = dataKey; this.indicatorData = []; this.externalIndicators = 0; const indicatorInstances = []; - for (let i = 0; i < this.indicators.length; i += 1) { const ind = new this.indicators[i][0](this.indicators[i][1]); ind.colors = this.indicators[i][2]; - if (ind.ui.position === 'external') { this.externalIndicators += 1; } - indicatorInstances.push([ind, this.indicators[i][0]]); } - for (let i = 0; i < data.length; i += 1) { for (let j = 0; j < indicatorInstances.length; j += 1) { const ind = indicatorInstances[j][0]; - if (ind.getDataType() === 'trade') { continue; } - const c = new _bfxApiNodeModels.Candle(data[i]); - if (ind.getDataKey() === '*') { ind.add(c); } else { ind.add(c[ind.getDataKey()]); } - if (!this.indicatorData[j]) { this.indicatorData[j] = []; } - const v = ind.v(); let nullP = 0; - if (indicatorInstances[j][1].ui.lines) { nullP = {}; indicatorInstances[j][1].ui.lines.forEach(key => nullP[key] = 0); } - this.indicatorData[j].push((0, _isFinite3.default)(v) || (0, _isObject3.default)(v) ? v : nullP); } } - this.clearAll(); this.renderAll(); } - updateDimensions(width, height) { this.width = width; this.height = height; this.vp.size.w = width - _config2.default.MARGIN_RIGHT - 0.5; this.vp.size.h = height - _config2.default.MARGIN_BOTTOM - _config2.default.AXIS_MARGIN_BOTTOM - 0.5; - if (this.onUpdateIndicatorSettingsCB) { const ohlcHeight = this.getOHLCVPHeight(); const slotHeight = this.externalIndicators === 0 ? 0 : (this.vp.size.h - ohlcHeight) / this.externalIndicators; this.onUpdateIndicatorSettingsCB(this.indicators, slotHeight); } - this.clipCanvases(); this.clearAll(); this.renderAll(); } + /** * Called when updated w/ data having a different dataKey. Resets pan */ - - onDataReset() { this.vp.pan.x = 0; this.vp.pan.y = 0; this.vp.origin.x = 0; this.vp.origin.y = 0; } - clearAll() { this.clear(this.ohlcCanvas); this.clear(this.axisCanvas); @@ -308,7 +244,6 @@ class BitfinexTradingChart { this.clear(this.indicatorCanvas); this.clear(this.crosshairCanvas); } - clear(canvas) { const ctx = canvas.getContext('2d'); const { @@ -317,34 +252,27 @@ class BitfinexTradingChart { } = this; ctx.clearRect(0, 0, width, height); } - getCandlesInView() { const panX = this.vp.pan.x + this.vp.origin.x; const candlePanOffset = panX > 0 ? Math.floor(panX / this.candleWidthPX) : 0; const start = this.data.length - 1 - this.viewportWidthCandles - candlePanOffset; const end = this.data.length - 1 - candlePanOffset; - if (end < 0) { return []; } - return this.data.slice((0, _max3.default)([0, start]), end); } - getIndicatorDataInView() { const panX = this.vp.pan.x + this.vp.origin.x; const candlePanOffset = panX > 0 ? Math.floor(panX / this.candleWidthPX) : 0; const dataInView = []; - for (let i = 0; i < this.indicatorData.length; i += 1) { const start = this.indicatorData[i].length - 1 - this.viewportWidthCandles - candlePanOffset; const end = this.indicatorData[i].length - 1 - candlePanOffset; dataInView.push(this.indicatorData[i].slice((0, _max3.default)([0, start]), end)); } - return dataInView; } - renderAll() { this.renderOHLC(); this.renderHoveredOHLC(); @@ -355,16 +283,13 @@ class BitfinexTradingChart { this.renderOrders(); this.renderPosition(); } - renderIndicators() { if (this.data.length < 2) { return; } - const indicatorData = this.getIndicatorDataInView(); let currentExtSlot = 0; let currentOverlaySlot = 0; - for (let i = 0; i < this.indicators.length; i += 1) { const indicator = this.indicators[i]; const data = indicatorData[i]; @@ -376,11 +301,9 @@ class BitfinexTradingChart { position, type } = ui; - if (data.length === 0) { continue; } - if (position === 'external') { if (type === 'rsi') { this.renderRSIIndicator(indicator, data, currentExtSlot++); @@ -402,14 +325,11 @@ class BitfinexTradingChart { } } } - renderBBandsIndicator(indicator, data) { const candlesToRender = this.getCandlesInView(); - if ((0, _isEmpty3.default)(candlesToRender)) { return; } - const colors = indicator[2]; const vpHeight = this.getOHLCVPHeight(); const rightMTS = (0, _last3.default)(candlesToRender)[0]; @@ -420,7 +340,6 @@ class BitfinexTradingChart { const topLinePoints = []; const middleLinePoints = []; const bottomLinePoints = []; - for (let i = 0; i < candlesToRender.length; i += 1) { const d = candlesToRender[i]; const [mts] = d; @@ -441,19 +360,15 @@ class BitfinexTradingChart { y: vpHeight - bottom }); } - (0, _line2.default)(this.ohlcCanvas, colors[0], topLinePoints); (0, _line2.default)(this.ohlcCanvas, colors[1], middleLinePoints); (0, _line2.default)(this.ohlcCanvas, colors[2], bottomLinePoints); } - renderRSIIndicator(indicator, data, exSlot) { const candlesToRender = this.getCandlesInView(); - if ((0, _isEmpty3.default)(candlesToRender)) { return; } - const color = indicator[2][0]; const iInstance = new indicator[0](indicator[1]); const vpHeight = this.getOHLCVPHeight(); @@ -472,14 +387,11 @@ class BitfinexTradingChart { }); this.renderExternalSlotMeta(transformer, iInstance.getName(), [30, 70], exSlot); } - renderMACDIndicator(indicator, data, exSlot) { const candlesToRender = this.getCandlesInView(); - if ((0, _isEmpty3.default)(candlesToRender)) { return; } - const colors = indicator[2]; const iInstance = new indicator[0](indicator[1]); const vpHeight = this.getOHLCVPHeight(); @@ -500,7 +412,6 @@ class BitfinexTradingChart { yOffset: slotHeight + slotY, xOffset: 0 }); - if (i === 0) { this.renderExternalSlotMeta(transformer, iInstance.getName(), [0], exSlot); } @@ -508,7 +419,6 @@ class BitfinexTradingChart { const maxV = (0, _max3.default)(data.map(p => (0, _max3.default)([p.macd, p.signal]))); const minV = (0, _min3.default)(data.map(p => (0, _min3.default)([p.macd, p.signal]))); const divergenceTransformer = (0, _data_transformer2.default)([maxV, minV], vWidth, rightMTS); - for (let i = 0; i < candlesToRender.length; i += 1) { const mts = candlesToRender[i][0]; (0, _transformed_line_from_data2.default)(this.indicatorCanvas, colors[2], divergenceTransformer, { @@ -521,14 +431,11 @@ class BitfinexTradingChart { }); } } - renderExternalLineIndicator(indicator, data, exSlot) { const candlesToRender = this.getCandlesInView(); - if ((0, _isEmpty3.default)(candlesToRender)) { return; } - const color = indicator[2][0]; const iInstance = new indicator[0](indicator[1]); const vpHeight = this.getOHLCVPHeight(); @@ -547,14 +454,11 @@ class BitfinexTradingChart { }); this.renderExternalSlotMeta(transformer, iInstance.getName(), [0], exSlot); } - renderExternalLinesIndicator(indicator, data, exSlot) { const candlesToRender = this.getCandlesInView(); - if ((0, _isEmpty3.default)(candlesToRender)) { return; } - const colors = indicator[2]; const iInstance = new indicator[0](indicator[1]); const vpHeight = this.getOHLCVPHeight(); @@ -573,19 +477,16 @@ class BitfinexTradingChart { yOffset: slotY + slotHeight, xOffset: 0 }); - if (i === 0) { this.renderExternalSlotMeta(transformer, iInstance.getName(), [0], exSlot); } }); } - renderExternalSlotMeta(transformer, label, xAxes, exSlot) { const vpHeight = this.getOHLCVPHeight(); const slotHeight = (this.vp.size.h - vpHeight) / this.externalIndicators; const slotY = vpHeight + slotHeight * exSlot + _config2.default.AXIS_MARGIN_BOTTOM; const ctx = this.indicatorCanvas.getContext('2d'); - for (let i = 0; i < xAxes.length; i += 1) { const axis = xAxes[i]; const axisY = transformer.y(axis, slotHeight); @@ -595,14 +496,11 @@ class BitfinexTradingChart { ctx.fillText((0, _format_axis_tick2.default)(axis), this.vp.size.w + 5, slotY + slotHeight - axisY + 3); } } - renderOverlayLineIndicator(indicator, data) { const candlesToRender = this.getCandlesInView(); - if ((0, _isEmpty3.default)(candlesToRender)) { return; } - const color = indicator[2][0]; const vpHeight = this.getOHLCVPHeight(); const rightMTS = (0, _last3.default)(candlesToRender)[0]; @@ -611,7 +509,6 @@ class BitfinexTradingChart { const minP = (0, _min3.default)(candlesToRender.map(ohlc => ohlc[4])); const pd = maxP - minP; const linePoints = []; - for (let i = 0; i < candlesToRender.length; i += 1) { const d = candlesToRender[i]; const [mts] = d; @@ -622,17 +519,13 @@ class BitfinexTradingChart { y: vpHeight - y }); } - (0, _line2.default)(this.ohlcCanvas, color, linePoints); } - renderOverlayLinesIndicator(indicator, data) { const candlesToRender = this.getCandlesInView(); - if ((0, _isEmpty3.default)(candlesToRender)) { return; } - const colors = indicator[2]; const vpHeight = this.getOHLCVPHeight(); const rightMTS = (0, _last3.default)(candlesToRender)[0]; @@ -640,11 +533,9 @@ class BitfinexTradingChart { const maxP = (0, _max3.default)(candlesToRender.map(ohlc => ohlc[3])); const minP = (0, _min3.default)(candlesToRender.map(ohlc => ohlc[4])); const pd = maxP - minP; - for (let i = 0; i < indicator[0].ui.lines.length; i += 1) { const lineKey = indicator[0].ui.lines[i]; const linePoints = []; - for (let j = 0; j < candlesToRender.length; j += 1) { const d = candlesToRender[j]; const [mts] = d; @@ -655,15 +546,13 @@ class BitfinexTradingChart { y: vpHeight - y }); } - (0, _line2.default)(this.ohlcCanvas, colors[i], linePoints); } } + /** * Renders the crosshair and updates the toolbar OHLC stats */ - - renderCrosshair() { const { width, @@ -686,11 +575,9 @@ class BitfinexTradingChart { }]); const ctx = this.crosshairCanvas.getContext('2d'); const candlesInView = this.getCandlesInView(); - if (candlesInView.length === 0) { return; } - const maxP = (0, _max3.default)(candlesInView.map(ohlc => ohlc[3])); const minP = (0, _min3.default)(candlesInView.map(ohlc => ohlc[4])); const rightMTS = (0, _last3.default)(candlesInView)[0]; @@ -708,48 +595,41 @@ class BitfinexTradingChart { ctx.fillRect(mousePosition.x - labelXWidth / 2, height - 17, labelXWidth, 14); ctx.fillStyle = '#000'; ctx.fillText(labelX, mousePosition.x, height - 5); - if (mousePosition.y <= this.getOHLCVPHeight()) { ctx.textAlign = 'left'; ctx.fillStyle = '#ccc'; ctx.fillRect(this.vp.size.w, mousePosition.y, labelYWidth, 14); ctx.fillStyle = '#000'; ctx.fillText(labelY, this.vp.size.w, mousePosition.y + 12); - } // Find nearest candle - + } + // Find nearest candle const candleDistances = candlesInView.map((c, i) => [Math.abs(c[0] - mouseMTS), i]); candleDistances.sort((a, b) => a[0] - b[0]); const lastHoveredCandle = candlesInView[candleDistances[0][1]]; this.lastHoveredCandle = lastHoveredCandle; - if (this.onHoveredCandleCB) { this.onHoveredCandleCB(lastHoveredCandle); } } - renderDrawings() { for (let i = 0; i < this.drawings.length; i += 1) { this.drawings[i].render(); } } - renderOrders() { if (this.data.length < 2) { return; } - const candles = this.getCandlesInView(); const maxP = (0, _max3.default)(candles.map(ohlc => ohlc[3])); const minP = (0, _min3.default)(candles.map(ohlc => ohlc[4])); const visibleOrders = this.orders.filter(({ price }) => price >= minP && price <= maxP); - if (visibleOrders.length === 0) { return; } - const ctx = this.drawingCanvas.getContext('2d'); const transformer = this.getOHLCTransformer(); visibleOrders.forEach(o => { @@ -773,12 +653,10 @@ class BitfinexTradingChart { ctx.fillText(label, labelX + 8, y + 4); }); } - renderPosition() { if (this.data.length < 2 || !this.position) { return; } - const candles = this.getCandlesInView(); const maxP = (0, _max3.default)(candles.map(ohlc => ohlc[3])); const minP = (0, _min3.default)(candles.map(ohlc => ohlc[4])); @@ -786,11 +664,9 @@ class BitfinexTradingChart { basePrice, amount } = this.position; - if (basePrice < minP || basePrice > maxP) { return; } - const ctx = this.drawingCanvas.getContext('2d'); const transformer = this.getOHLCTransformer(); const color = amount < 0 ? _config2.default.FALLING_CANDLE_FILL : _config2.default.RISING_CANDLE_FILL; @@ -812,7 +688,6 @@ class BitfinexTradingChart { ctx.fillStyle = '#000'; ctx.fillText(label, labelX + 8, y + 4); } - getMTSForRawX(x) { const candlesInView = this.getCandlesInView(); const rightMTS = (0, _last3.default)(candlesInView)[0]; @@ -820,7 +695,6 @@ class BitfinexTradingChart { const mtsPerPX = (rightMTS - leftMTS) / this.vp.size.w; return leftMTS + mtsPerPX * x; } - getPriceForRawY(y) { const candlesInView = this.getCandlesInView(); const vpHeight = this.getOHLCVPHeight(); @@ -829,14 +703,11 @@ class BitfinexTradingChart { const pricePerPX = (high - low) / vpHeight; return high - pricePerPX * y; } - getOHLCTransformer() { const candlesToRender = this.getCandlesInView(); - if ((0, _isEmpty3.default)(candlesToRender)) { return; } - const vpHeight = this.getOHLCVPHeight(); const rightMTS = (0, _last3.default)(candlesToRender)[0]; const vWidth = this.viewportWidthCandles * this.dataWidth; @@ -848,7 +719,6 @@ class BitfinexTradingChart { transformer.setYModifier(y => vpHeight - y); return transformer; } - drawHorizontalVPLine(canvas, color, y) { (0, _line2.default)(canvas, color, [{ x: 0, @@ -858,29 +728,23 @@ class BitfinexTradingChart { y }]); } - renderAxis() { const candles = this.getCandlesInView(); - if (candles.length === 0) { return; } - const vpWidth = this.viewportWidthCandles * this.dataWidth; const vpHeight = this.getOHLCVPHeight(); (0, _x_axis2.default)(this.axisCanvas, candles, vpHeight, vpWidth, this.vp.size.w); (0, _y_axis2.default)(this.axisCanvas, candles, this.vp.size.w, this.height, vpHeight); } - getOHLCVPHeight() { return this.vp.size.h - (0, _min3.default)([this.vp.size.h / 2, this.externalIndicators * 100]); } - renderHoveredOHLC() { if (!this.lastHoveredCandle) { return; } - const ctx = this.crosshairCanvas.getContext('2d'); let x = _config2.default.OHLC_LABEL_POSITION_X; let y = _config2.default.OHLC_LABEL_POSITION_Y; @@ -917,28 +781,22 @@ class BitfinexTradingChart { ctx.fillStyle = _config2.default.OHLC_LABEL_VALUE_COLOR; ctx.fillText(c, x + cWidth + _config2.default.OHLC_LABEL_SPACING, y); } - renderOHLC() { const ctx = this.ohlcCanvas.getContext('2d'); const candles = this.getCandlesInView(); - if (candles.length === 0) { return; } - const vpHeight = this.getOHLCVPHeight(); const vpWidth = this.viewportWidthCandles * this.dataWidth; (0, _ohlc_series2.default)(ctx, candles, this.candleWidthPX, vpWidth, vpHeight, this.vp.size.w); } - renderTrades() { if (this.data.length === 0 || this.trades.length === 0) { return; } - const ctx = this.ohlcCanvas.getContext('2d'); const transformer = this.getOHLCTransformer(); - for (let i = 0; i < this.trades.length; i += 1) { ctx.strokeStyle = this.trades[i].amount > 0 ? _config2.default.TRADE_MARKER_BUY_COLOR : _config2.default.TRADE_MARKER_SELL_COLOR; ctx.beginPath(); @@ -946,19 +804,16 @@ class BitfinexTradingChart { ctx.stroke(); } } - getOHLCMousePosition() { return { mts: this.getMTSForRawX(this.mousePosition.x), price: this.getPriceForRawY(this.mousePosition.y) }; } - onMouseLeave() { this.clear(this.crosshairCanvas); this.isDragging = false; } - onMouseUp() { this.isDragging = false; this.dragStart = null; @@ -966,54 +821,50 @@ class BitfinexTradingChart { this.vp.origin.y += this.vp.pan.y; this.vp.pan.x = 0; this.vp.pan.y = 0; - if (this.activeDrawing) { this.activeDrawing.onMouseUp(); } } - onMouseDown(e) { const rect = this.ohlcCanvas.getBoundingClientRect(); const x = e.pageX - rect.left; - const y = e.pageY - rect.top; // Drawings can prevent drag-start (i.e. when editing) + const y = e.pageY - rect.top; + // Drawings can prevent drag-start (i.e. when editing) if (this.activeDrawing) { if (this.activeDrawing.onMouseDown(x, y)) { return; } } - this.isDragging = true; this.dragStart = { x, y }; } - onMouseMove(e) { const rect = e.target.getBoundingClientRect(); this.mousePosition = { x: e.pageX - rect.left, y: e.pageY - rect.top }; - if (this.activeDrawing) { this.activeDrawing.onMouseMove(this.mousePosition.x, this.mousePosition.y); } - this.crosshairCanvas.style.cursor = this.activeDrawing && this.activeDrawing.isActive() ? 'crosshair' : 'default'; - if (this.isDragging && (!this.activeDrawing || !this.activeDrawing.isActive())) { this.vp.pan.x = this.mousePosition.x - this.dragStart.x; this.clearAll(); this.renderAll(); - if ((0, _isFunction3.default)(this.onLoadMoreCB)) { const panX = this.vp.pan.x + this.vp.origin.x; const candlePanOffset = panX > 0 ? Math.floor(panX / this.candleWidthPX) : 0; - if (candlePanOffset + this.viewportWidthCandles > this.data.length) { - this.onLoadMoreCB(this.viewportWidthCandles); + const newOnLoadMoreKey = `${(this.data[0] ?? [])[0]}-${((0, _last3.default)(this.data) ?? [])[0]}-${this.dataKey}`; + if (this.onLoadMoreKey !== newOnLoadMoreKey) { + this.onLoadMoreCB(this.viewportWidthCandles); + this.onLoadMoreKey = newOnLoadMoreKey; + } } } } else { @@ -1026,23 +877,18 @@ class BitfinexTradingChart { this.renderHoveredOHLC(); } } - onMouseWheel(dx, dy, dz, ev) { // differing values in Chrome/FF, normalize const delta = dy < 0 ? -_config2.default.ZOOM_CANDLE_STEP : _config2.default.ZOOM_CANDLE_STEP; this.viewportWidthCandles += delta; - if (this.viewportWidthCandles < _config2.default.ZOOM_MIN_LIMIT_CANDLES) { this.viewportWidthCandles = _config2.default.ZOOM_MIN_LIMIT_CANDLES; } - this.candleWidthPX = Math.max(1, 7 - Math.floor(this.viewportWidthCandles / 50)); this.clearAll(); this.renderAll(); ev.preventDefault(); ev.stopPropagation(); } - } - exports.default = BitfinexTradingChart; \ No newline at end of file diff --git a/dist/components/Chart/lib/config.js b/dist/components/Chart/lib/config.js index 415f4eb..d38c7d6 100644 --- a/dist/components/Chart/lib/config.js +++ b/dist/components/Chart/lib/config.js @@ -34,10 +34,8 @@ const CONFIG = { ZOOM_CANDLE_STEP: 5, ZOOM_MIN_LIMIT_CANDLES: 20 }; - const set = (key, value) => { CONFIG[key] = value; }; - exports.default = CONFIG; exports.set = set; \ No newline at end of file diff --git a/dist/components/Chart/lib/data_transformer.js b/dist/components/Chart/lib/data_transformer.js index 145c959..2117f40 100644 --- a/dist/components/Chart/lib/data_transformer.js +++ b/dist/components/Chart/lib/data_transformer.js @@ -3,49 +3,38 @@ Object.defineProperty(exports, "__esModule", { value: true }); - exports.default = function (data, vWidth, rightMTS) { const maxP = (0, _max3.default)(data); const minP = (0, _min3.default)(data); const pd = maxP - minP; let defaultTargetWidth; let defaultTargetHeight; - let defaultYModifier = y => y; - let defaultXModifier = x => x; - const x = (dX, targetWidth = defaultTargetWidth) => { return defaultXModifier((vWidth - (rightMTS - dX)) / vWidth * targetWidth); }; - const y = (dY, targetHeight = defaultTargetHeight) => { return defaultYModifier((dY - minP) / pd * targetHeight); }; - const point = p => { return { x: x(p.mts), y: y(p.price) }; }; - const setTargetWidth = targetWidth => { defaultTargetWidth = targetWidth; }; - const setTargetHeight = targetHeight => { defaultTargetHeight = targetHeight; }; - const setYModifier = cb => { defaultYModifier = cb; }; - const setXModifier = cb => { defaultXModifier = cb; }; - return { x, y, @@ -56,13 +45,8 @@ exports.default = function (data, vWidth, rightMTS) { setXModifier }; }; - var _max2 = require("lodash/max"); - var _max3 = _interopRequireDefault(_max2); - var _min2 = require("lodash/min"); - var _min3 = _interopRequireDefault(_min2); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } \ No newline at end of file diff --git a/dist/components/Chart/lib/draw/line.js b/dist/components/Chart/lib/draw/line.js index 737dcac..3d79e2c 100644 --- a/dist/components/Chart/lib/draw/line.js +++ b/dist/components/Chart/lib/draw/line.js @@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.default = drawLine; - /** * Draw a line composed of multiple points * @@ -16,20 +15,16 @@ exports.default = drawLine; function drawLine(canvas, style, points = [], dashed) { const ctx = canvas.getContext('2d'); ctx.strokeStyle = style; - if (dashed) { ctx.setLineDash([5, 3]); } else { ctx.setLineDash([]); } - ctx.beginPath(); ctx.moveTo(points[0].x, points[0].y); - for (let i = 1; i < points.length; i += 1) { ctx.lineTo(points[i].x, points[i].y); } - ctx.stroke(); ctx.closePath(); } \ No newline at end of file diff --git a/dist/components/Chart/lib/draw/ohlc_series.js b/dist/components/Chart/lib/draw/ohlc_series.js index 33452d8..0844c8b 100644 --- a/dist/components/Chart/lib/draw/ohlc_series.js +++ b/dist/components/Chart/lib/draw/ohlc_series.js @@ -3,25 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true }); - var _last2 = require("lodash/last"); - var _last3 = _interopRequireDefault(_last2); - var _max2 = require("lodash/max"); - var _max3 = _interopRequireDefault(_max2); - var _min2 = require("lodash/min"); - var _min3 = _interopRequireDefault(_min2); - var _config = require("../config"); - var _config2 = _interopRequireDefault(_config); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } /** * Renders a series of candles on the target 2D context, using the specified * viewport dimensions (scaled appropriately) @@ -39,7 +29,6 @@ exports.default = (ctx, candles, candleWidth, targetWidth, targetHeight, vpWidth const maxP = (0, _max3.default)(candles.map(ohlc => ohlc[3])); const minP = (0, _min3.default)(candles.map(ohlc => ohlc[4])); const pd = maxP - minP; - for (let i = 0; i < candles.length; i += 1) { const d = candles[i]; const [mts, o, c, h, l, v] = d; @@ -48,15 +37,18 @@ exports.default = (ctx, candles, candleWidth, targetWidth, targetHeight, vpWidth const lPX = (l - minP) / pd * targetHeight; const cPX = (c - minP) / pd * targetHeight; const x = (targetWidth - (rightMTS - mts)) / targetWidth * (vpWidth - candleWidth / 2); - const y = targetHeight - (0, _max3.default)([oPX, cPX]); // volume + const y = targetHeight - (0, _max3.default)([oPX, cPX]); + // volume ctx.fillStyle = c >= o ? _config2.default.RISING_VOL_FILL : _config2.default.FALLING_VOL_FILL; ctx.fillRect(x - candleWidth / 2, targetHeight, candleWidth, -(v / maxVol * targetHeight)); ctx.fillStyle = c >= o ? _config2.default.RISING_CANDLE_FILL : _config2.default.FALLING_CANDLE_FILL; - ctx.strokeStyle = ctx.fillStyle; // body + ctx.strokeStyle = ctx.fillStyle; - ctx[c >= o ? 'strokeRect' : 'fillRect'](x - candleWidth / 2, y, candleWidth, (0, _max3.default)([oPX, cPX]) - (0, _min3.default)([oPX, cPX])); // wicks + // body + ctx[c >= o ? 'strokeRect' : 'fillRect'](x - candleWidth / 2, y, candleWidth, (0, _max3.default)([oPX, cPX]) - (0, _min3.default)([oPX, cPX])); + // wicks ctx.beginPath(); ctx.moveTo(x, targetHeight - (0, _max3.default)([oPX, cPX])); ctx.lineTo(x, targetHeight - hPX); diff --git a/dist/components/Chart/lib/draw/transformed_line_from_data.js b/dist/components/Chart/lib/draw/transformed_line_from_data.js index ae26eb1..23089bd 100644 --- a/dist/components/Chart/lib/draw/transformed_line_from_data.js +++ b/dist/components/Chart/lib/draw/transformed_line_from_data.js @@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true }); - exports.default = function (canvas, color, transformer, { yData, xData, @@ -13,19 +12,14 @@ exports.default = function (canvas, color, transformer, { xOffset = 0 }) { const points = []; - for (let i = 0; i < xData.length; i += 1) { points.push({ y: yOffset - transformer.y(yData[i], ySize), x: transformer.x(xData[i], xSize) + xOffset }); } - (0, _line2.default)(canvas, color, points); }; - var _line = require("./line"); - var _line2 = _interopRequireDefault(_line); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } \ No newline at end of file diff --git a/dist/components/Chart/lib/draw/x_axis.js b/dist/components/Chart/lib/draw/x_axis.js index 752eb8d..645d946 100644 --- a/dist/components/Chart/lib/draw/x_axis.js +++ b/dist/components/Chart/lib/draw/x_axis.js @@ -3,27 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true }); - var _moment = require("moment"); - var _moment2 = _interopRequireDefault(_moment); - var _last2 = require("lodash/last"); - var _last3 = _interopRequireDefault(_last2); - var _bfxHfUtil = require("bfx-hf-util"); - var _line = require("./line"); - var _line2 = _interopRequireDefault(_line); - var _config = require("../config"); - var _config2 = _interopRequireDefault(_config); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } /** * Renders an X-axis at the specified y coord with dynamic tick rendering based * on the provided candle dataset. @@ -38,66 +27,61 @@ exports.default = (canvas, candles, y, width, vpWidth) => { const ctx = canvas.getContext('2d'); ctx.font = `${_config2.default.AXIS_LABEL_FONT_SIZE_PX} ${_config2.default.AXIS_LABEL_FONT_NAME}`; ctx.fillStyle = _config2.default.AXIS_LABEL_COLOR; - ctx.textAlign = 'center'; // axis line + ctx.textAlign = 'center'; + // axis line (0, _line2.default)(canvas, _config2.default.AXIS_COLOR, [{ x: 0, y }, { x: vpWidth, y - }]); // resolve tick width depending on domain + }]); + // resolve tick width depending on domain const rightMTS = (0, _last3.default)(candles)[0]; const leftMTS = candles[0][0]; const rangeLengthMTS = rightMTS - leftMTS; const tickWidthPX = vpWidth / _config2.default.AXIS_X_TICK_COUNT; let ticks = []; let tickDivisor = 60 * 60 * 1000; // 1hr by default, overriden below - const dayCount = rangeLengthMTS / _bfxHfUtil.TIME_FRAME_WIDTHS['1D']; - if (dayCount > 30) { tickDivisor = 30 * 24 * 60 * 60 * 1000; } else if (dayCount > 1) { tickDivisor = 24 * 60 * 60 * 1000; } else { const hourCount = rangeLengthMTS / _bfxHfUtil.TIME_FRAME_WIDTHS['1h']; - if (hourCount > 1 && hourCount < _config2.default.AXIS_X_TICK_COUNT) { tickDivisor = 60 * 60 * 1000; } - } // generate ticks - + } + // generate ticks const paddedLeftMTS = leftMTS - leftMTS % tickDivisor; - for (let i = 0; i < rangeLengthMTS / tickDivisor; i += 1) { ticks.push(paddedLeftMTS + i * tickDivisor); - if (paddedLeftMTS + (i + 1) * tickDivisor > rightMTS) { break; } } + let previousTick; - let previousTick; // render ticks - + // render ticks for (let i = 0; i < ticks.length; i += 1) { const mts = ticks[i]; // (tickWidthMTS * i) + leftMTS - const tickX = (width - (rightMTS - mts)) / width * vpWidth; const tickY = y + _config2.default.AXIS_LABEL_FONT_SIZE_PX + _config2.default.AXIS_LABEL_MARGIN_PX; const date = new Date(mts); let label; - if (previousTick && previousTick.getDay() === date.getDay()) { label = (0, _moment2.default)(date).format('HH:mm'); } else { label = (0, _moment2.default)(date).format('DD/MM'); } + ctx.fillText(label, tickX, tickY, tickWidthPX); - ctx.fillText(label, tickX, tickY, tickWidthPX); // tick - + // tick (0, _line2.default)(canvas, _config2.default.AXIS_TICK_COLOR, [{ x: tickX, y: tickY - _config2.default.AXIS_LABEL_FONT_SIZE_PX diff --git a/dist/components/Chart/lib/draw/y_axis.js b/dist/components/Chart/lib/draw/y_axis.js index a0d7033..f782d2f 100644 --- a/dist/components/Chart/lib/draw/y_axis.js +++ b/dist/components/Chart/lib/draw/y_axis.js @@ -3,29 +3,17 @@ Object.defineProperty(exports, "__esModule", { value: true }); - var _max2 = require("lodash/max"); - var _max3 = _interopRequireDefault(_max2); - var _min2 = require("lodash/min"); - var _min3 = _interopRequireDefault(_min2); - var _line = require("./line"); - var _line2 = _interopRequireDefault(_line); - var _format_axis_tick = require("../util/format_axis_tick"); - var _format_axis_tick2 = _interopRequireDefault(_format_axis_tick); - var _config = require("../config"); - var _config2 = _interopRequireDefault(_config); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } /** * Renders a Y-axis at the specified X coord with dynamic tick rendering based * on the provided candle dataset. @@ -53,13 +41,13 @@ exports.default = (canvas, candles, x, height, vpHeight) => { const pd = maxP - minP; const tickHeightPX = vpHeight / _config2.default.AXIS_Y_TICK_COUNT; const tickHeightPrice = pd / _config2.default.AXIS_Y_TICK_COUNT; - for (let i = 0; i < _config2.default.AXIS_Y_TICK_COUNT; i += 1) { const tickY = vpHeight - tickHeightPX * i; const tickX = x + _config2.default.AXIS_LABEL_MARGIN_PX; const tick = minP + tickHeightPrice * i; - ctx.fillText((0, _format_axis_tick2.default)(tick), tickX, tickY + _config2.default.AXIS_LABEL_FONT_SIZE_PX / 2, canvas.width - x); // tick + ctx.fillText((0, _format_axis_tick2.default)(tick), tickX, tickY + _config2.default.AXIS_LABEL_FONT_SIZE_PX / 2, canvas.width - x); + // tick (0, _line2.default)(canvas, _config2.default.AXIS_TICK_COLOR, [{ x: tickX - 3, y: tickY diff --git a/dist/components/Chart/lib/drawings/drawing.js b/dist/components/Chart/lib/drawings/drawing.js index 8f00de9..697b113 100644 --- a/dist/components/Chart/lib/drawings/drawing.js +++ b/dist/components/Chart/lib/drawings/drawing.js @@ -3,23 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true }); - var _get2 = require("lodash/get"); - var _get3 = _interopRequireDefault(_get2); - var _set2 = require("lodash/set"); - var _set3 = _interopRequireDefault(_set2); - var _distance = require("../util/distance"); - var _distance2 = _interopRequireDefault(_distance); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const PROXIMITY_LIMIT_PX = 7; - class Drawing { constructor(chart, anchors = []) { this.chart = chart; @@ -30,13 +21,10 @@ class Drawing { a.render = false; }); } - isActive() { return this.active; } - render() {} - renderAnchors() { const ctx = this.chart.drawingCanvas.getContext('2d'); const transformer = this.chart.getOHLCTransformer(); @@ -45,7 +33,6 @@ class Drawing { if (!a.render) { return; } - const anchorX = a.keyX === '__mouse' ? this.lastMouseX : transformer.x((0, _get3.default)(this, a.keyX)); const anchorY = a.keyY === '__mouse' ? this.lastMouseY : transformer.y((0, _get3.default)(this, a.keyY)); ctx.beginPath(); @@ -53,23 +40,19 @@ class Drawing { ctx.stroke(); }); } - onMouseUp() { this.anchors.forEach(a => a.moving = false); } - onMouseDown() { let hasMovingAnchor = false; this.anchors.forEach(a => { a.moving = a.render; - if (a.moving) { hasMovingAnchor = true; } }); return hasMovingAnchor; } - onMouseMove(x, y) { this.lastMouseX = x; this.lastMouseY = y; @@ -78,19 +61,15 @@ class Drawing { const anchorX = a.keyX === '__mouse' ? this.lastMouseX : transformer.x((0, _get3.default)(this, a.keyX)); const anchorY = a.keyY === '__mouse' ? this.lastMouseY : transformer.y((0, _get3.default)(this, a.keyY)); a.render = (0, _distance2.default)(x, y, anchorX, anchorY) < PROXIMITY_LIMIT_PX; - if (a.moving) { if (a.keyX !== '__mouse') { (0, _set3.default)(this, a.keyX, this.chart.getMTSForRawX(x)); } - if (a.keyY !== '__mouse') { (0, _set3.default)(this, a.keyY, this.chart.getPriceForRawY(y)); } } }); } - } - exports.default = Drawing; \ No newline at end of file diff --git a/dist/components/Chart/lib/drawings/horizontal_line.js b/dist/components/Chart/lib/drawings/horizontal_line.js index ba8e9c3..f0cdb82 100644 --- a/dist/components/Chart/lib/drawings/horizontal_line.js +++ b/dist/components/Chart/lib/drawings/horizontal_line.js @@ -3,13 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); - var _drawing = require("./drawing"); - var _drawing2 = _interopRequireDefault(_drawing); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } class HorizontalLineDrawing extends _drawing2.default { constructor(chart) { super(chart, [{ @@ -18,21 +14,17 @@ class HorizontalLineDrawing extends _drawing2.default { }]); this.price = null; } - onMouseDown(x, y) { if (this.active) { this.price = this.chart.getPriceForRawY(y); this.active = false; } - return super.onMouseDown(x, y); } - render() { if (!this.price) { return; } - const ctx = this.chart.drawingCanvas.getContext('2d'); const transformer = this.chart.getOHLCTransformer(); const y = transformer.y(this.price); @@ -43,7 +35,5 @@ class HorizontalLineDrawing extends _drawing2.default { ctx.stroke(); this.renderAnchors(); } - } - exports.default = HorizontalLineDrawing; \ No newline at end of file diff --git a/dist/components/Chart/lib/drawings/line.js b/dist/components/Chart/lib/drawings/line.js index 2b27e9e..a043608 100644 --- a/dist/components/Chart/lib/drawings/line.js +++ b/dist/components/Chart/lib/drawings/line.js @@ -3,17 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true }); - var _line = require("../draw/line"); - var _line2 = _interopRequireDefault(_line); - var _drawing = require("./drawing"); - var _drawing2 = _interopRequireDefault(_drawing); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } class LineDrawing extends _drawing2.default { constructor(chart) { super(chart, [{ @@ -26,11 +20,9 @@ class LineDrawing extends _drawing2.default { this.start = null; this.end = null; } - onMouseDown(x, y) { const mts = this.chart.getMTSForRawX(x); const price = this.chart.getPriceForRawY(y); - if (this.active) { if (!this.start) { this.start = { @@ -45,29 +37,22 @@ class LineDrawing extends _drawing2.default { this.active = false; } } - return super.onMouseDown(x, y); } - render() { if (!this.start) { return; } - const transformer = this.chart.getOHLCTransformer(); const linePoints = []; linePoints.push(transformer.point(this.start)); - if (!this.end) { linePoints.push(transformer.point(this.chart.getOHLCMousePosition())); } else { linePoints.push(transformer.point(this.end)); } - (0, _line2.default)(this.chart.drawingCanvas, '#fff', linePoints); this.renderAnchors(); } - } - exports.default = LineDrawing; \ No newline at end of file diff --git a/dist/components/Chart/lib/drawings/parallel_lines.js b/dist/components/Chart/lib/drawings/parallel_lines.js index e45d5fd..7f0fd59 100644 --- a/dist/components/Chart/lib/drawings/parallel_lines.js +++ b/dist/components/Chart/lib/drawings/parallel_lines.js @@ -3,17 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true }); - var _line = require("../draw/line"); - var _line2 = _interopRequireDefault(_line); - var _drawing = require("./drawing"); - var _drawing2 = _interopRequireDefault(_drawing); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } class ParallelLineDrawing extends _drawing2.default { constructor(chart) { super(chart, [{ @@ -30,11 +24,9 @@ class ParallelLineDrawing extends _drawing2.default { this.end = null; this.parallel = null; } - onMouseDown(x, y) { const mts = this.chart.getMTSForRawX(x); const price = this.chart.getPriceForRawY(y); - if (this.active) { if (this.end && this.start) { this.parallel = { @@ -54,15 +46,12 @@ class ParallelLineDrawing extends _drawing2.default { }; } } - return super.onMouseDown(x, y); } - render() { if (!this.start) { return; } - const linePoints = []; const transformer = this.chart.getOHLCTransformer(); const start = transformer.point(this.start); @@ -78,7 +67,6 @@ class ParallelLineDrawing extends _drawing2.default { y: m * this.chart.vp.size.w + b }); (0, _line2.default)(this.chart.drawingCanvas, '#fff', linePoints); - if (this.start && this.end) { const pLinePoints = []; const parallel = this.parallel ? transformer.point(this.parallel) : transformer.point(this.chart.getOHLCMousePosition()); @@ -93,10 +81,7 @@ class ParallelLineDrawing extends _drawing2.default { }); (0, _line2.default)(this.chart.drawingCanvas, '#fff', pLinePoints); } - this.renderAnchors(); } - } - exports.default = ParallelLineDrawing; \ No newline at end of file diff --git a/dist/components/Chart/lib/drawings/vertical_line.js b/dist/components/Chart/lib/drawings/vertical_line.js index 38252bb..685f15c 100644 --- a/dist/components/Chart/lib/drawings/vertical_line.js +++ b/dist/components/Chart/lib/drawings/vertical_line.js @@ -3,13 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); - var _drawing = require("./drawing"); - var _drawing2 = _interopRequireDefault(_drawing); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } class VerticalLineDrawing extends _drawing2.default { constructor(chart) { super(chart, [{ @@ -18,21 +14,17 @@ class VerticalLineDrawing extends _drawing2.default { }]); this.mts = null; } - onMouseDown(x, y) { if (this.active) { this.mts = this.chart.getMTSForRawX(x); this.active = false; } - return super.onMouseDown(x, y); } - render() { if (!this.mts) { return; } - const ctx = this.chart.drawingCanvas.getContext('2d'); const transformer = this.chart.getOHLCTransformer(); const x = transformer.x(this.mts); @@ -42,7 +34,5 @@ class VerticalLineDrawing extends _drawing2.default { ctx.stroke(); this.renderAnchors(); } - } - exports.default = VerticalLineDrawing; \ No newline at end of file diff --git a/dist/components/Chart/lib/util/distance.js b/dist/components/Chart/lib/util/distance.js index 5d1c7bf..429af92 100644 --- a/dist/components/Chart/lib/util/distance.js +++ b/dist/components/Chart/lib/util/distance.js @@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true }); - /** * Returns the distance between two points * diff --git a/dist/components/Chart/lib/util/format_axis_tick.js b/dist/components/Chart/lib/util/format_axis_tick.js index 26d5f74..01fe0c0 100644 --- a/dist/components/Chart/lib/util/format_axis_tick.js +++ b/dist/components/Chart/lib/util/format_axis_tick.js @@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true }); - exports.default = tick => { return +tick.toPrecision(8).toLocaleString('en-US', { maximumFractionDigits: 8 diff --git a/dist/components/Chart/lib/util/serialize_indicators.js b/dist/components/Chart/lib/util/serialize_indicators.js index 1e2f78b..8d4872d 100644 --- a/dist/components/Chart/lib/util/serialize_indicators.js +++ b/dist/components/Chart/lib/util/serialize_indicators.js @@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true }); - exports.default = indicators => { return JSON.stringify(indicators.map(([iClass, iArgs, iColors]) => [iClass.id, iArgs, iColors])); }; \ No newline at end of file diff --git a/dist/components/Chart/lib/util/unserialize_indicators.js b/dist/components/Chart/lib/util/unserialize_indicators.js index 8fa1b6c..4188ece 100644 --- a/dist/components/Chart/lib/util/unserialize_indicators.js +++ b/dist/components/Chart/lib/util/unserialize_indicators.js @@ -3,13 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); - var _bfxHfIndicators = require("bfx-hf-indicators"); - var _bfxHfIndicators2 = _interopRequireDefault(_bfxHfIndicators); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } exports.default = indicators => { try { return JSON.parse(indicators).map(([iClassID, iArgs, iColors]) => [Object.values(_bfxHfIndicators2.default).find(i => i.id === iClassID), iArgs, iColors]); diff --git a/dist/components/Dropdown/Dropdown.js b/dist/components/Dropdown/Dropdown.js index 1d2e34e..0db090b 100644 --- a/dist/components/Dropdown/Dropdown.js +++ b/dist/components/Dropdown/Dropdown.js @@ -3,42 +3,30 @@ Object.defineProperty(exports, "__esModule", { value: true }); - var _react = require("react"); - var _react2 = _interopRequireDefault(_react); - var _reactOnclickoutside = require("react-onclickoutside"); - var _reactOnclickoutside2 = _interopRequireDefault(_reactOnclickoutside); - var _reactCustomScrollbars = require("react-custom-scrollbars"); - require("./Dropdown.css"); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } - -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } +function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } +function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } class Dropdown extends _react2.default.Component { constructor(props) { super(props); - _defineProperty(this, "state", { open: false }); - this.onToggle = this.onToggle.bind(this); } - handleClickOutside() { this.setState(() => ({ open: false })); } - onToggle() { this.setState(({ open @@ -46,7 +34,6 @@ class Dropdown extends _react2.default.Component { open: !open })); } - render() { const { label, @@ -66,13 +53,12 @@ class Dropdown extends _react2.default.Component { style, ...props }) => /*#__PURE__*/_react2.default.createElement("div", _extends({ - style: { ...style, + style: { + ...style, backgroundColor: '#333' } }, props)) }, children))); } - } - exports.default = (0, _reactOnclickoutside2.default)(Dropdown); \ No newline at end of file diff --git a/dist/components/Dropdown/index.js b/dist/components/Dropdown/index.js index dba5340..7be7738 100644 --- a/dist/components/Dropdown/index.js +++ b/dist/components/Dropdown/index.js @@ -3,11 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); - var _Dropdown = require("./Dropdown"); - var _Dropdown2 = _interopRequireDefault(_Dropdown); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } exports.default = _Dropdown2.default; \ No newline at end of file diff --git a/dist/components/IndicatorSettingsModal/IndicatorSettingsModal.js b/dist/components/IndicatorSettingsModal/IndicatorSettingsModal.js index affb9bb..9b9f0e5 100644 --- a/dist/components/IndicatorSettingsModal/IndicatorSettingsModal.js +++ b/dist/components/IndicatorSettingsModal/IndicatorSettingsModal.js @@ -3,33 +3,23 @@ Object.defineProperty(exports, "__esModule", { value: true }); - var _react = require("react"); - var _react2 = _interopRequireDefault(_react); - var _isFinite2 = require("lodash/isFinite"); - var _isFinite3 = _interopRequireDefault(_isFinite2); - var _isString2 = require("lodash/isString"); - var _isString3 = _interopRequireDefault(_isString2); - require("./IndicatorSettingsModal.css"); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } +function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } class IndicatorSettingsModal extends _react2.default.PureComponent { constructor(props) { super(props); - _defineProperty(this, "state", { values: [] }); - const { settings = {} } = this.props; @@ -41,7 +31,6 @@ class IndicatorSettingsModal extends _react2.default.PureComponent { this.onValueChange = this.onValueChange.bind(this); this.onSave = this.onSave.bind(this); } - onValueChange(index, value) { this.setState(({ values @@ -53,7 +42,6 @@ class IndicatorSettingsModal extends _react2.default.PureComponent { }; }); } - onSave() { const { onSave @@ -63,7 +51,6 @@ class IndicatorSettingsModal extends _react2.default.PureComponent { } = this.state; onSave(values); } - render() { const { values @@ -104,7 +91,5 @@ class IndicatorSettingsModal extends _react2.default.PureComponent { className: "green" }, "Save"))))); } - } - exports.default = IndicatorSettingsModal; \ No newline at end of file diff --git a/dist/components/IndicatorSettingsModal/index.js b/dist/components/IndicatorSettingsModal/index.js index e78f31b..71d3371 100644 --- a/dist/components/IndicatorSettingsModal/index.js +++ b/dist/components/IndicatorSettingsModal/index.js @@ -3,11 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); - var _IndicatorSettingsModal = require("./IndicatorSettingsModal"); - var _IndicatorSettingsModal2 = _interopRequireDefault(_IndicatorSettingsModal); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } exports.default = _IndicatorSettingsModal2.default; \ No newline at end of file diff --git a/dist/components/LoadingBeeSpinner/LoadingBeeSpinner.js b/dist/components/LoadingBeeSpinner/LoadingBeeSpinner.js index ed50770..85fc3ed 100644 --- a/dist/components/LoadingBeeSpinner/LoadingBeeSpinner.js +++ b/dist/components/LoadingBeeSpinner/LoadingBeeSpinner.js @@ -3,15 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); - var _react = require("react"); - var _react2 = _interopRequireDefault(_react); - require("./LoadingBeeSpinner.css"); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } class LoadingBeeSpinner extends _react2.default.PureComponent { render() { const { @@ -128,7 +123,5 @@ class LoadingBeeSpinner extends _react2.default.PureComponent { d: "M24.713,34.872c-0.08-0.312-3.092-0.897-5.703,3.527c-2.611,4.423-0.702,5.55-0.702,5.55 s2.323,1.681,5.55-3.29C26.793,36.137,24.713,34.872,24.713,34.872 M15.07,38.639l-0.007,0.003c-0.005,0-0.006,0.002-0.008,0.003 c-0.003,0-0.007,0-0.011,0.001l-0.008,0.002c-1.556,0.378-2.276,0.974-2.276,0.974c1.013,0.538,2.03,1.653,2.03,1.653l0.871-0.238 l0.011-0.002l0.006-0.003l0.878-0.211c0,0,0.352-1.467,0.977-2.428C17.533,38.393,16.614,38.221,15.07,38.639 M4.772,40.009 c0,0-1.206,2.113,3.548,4.652c5.229,2.792,6.447,0.199,6.447,0.199s1.127-1.91-3.293-4.518C7.049,37.729,4.694,39.696,4.772,40.009 M15.41,49.819c0.648-0.167,1.04-0.829,0.873-1.478s-0.829-1.038-1.478-0.872c-0.647,0.168-1.038,0.829-0.872,1.477 C14.101,49.595,14.764,49.985,15.41,49.819 M20.143,48.599c0.647-0.165,1.041-0.828,0.873-1.476 c-0.168-0.65-0.832-1.039-1.479-0.872c-0.647,0.169-1.039,0.828-0.872,1.477C18.832,48.376,19.494,48.767,20.143,48.599 M25.561,40.32c-1.256,2.5-3.408,4.083-4.17,4.487c0,0-0.059,0-0.055,0.12c0,0.124-0.016,0.472-0.016,0.472 s-0.014,0.033,0.041,0.074c0.055,0.044,0.658,0.411,0.895,1.33c0.236,0.918,0.012,2.572-2.132,3.123c0,0-0.012,0.004-0.052,0.072 c-0.039,0.07-0.766,1.224-1.709,1.468v0.003c-0.002,0-0.004-0.002-0.004-0.002c-0.004,0.001-0.002,0.003-0.002,0.003l-0.002-0.001 c-0.945,0.241-2.141-0.419-2.209-0.46c-0.067-0.041-0.082-0.038-0.082-0.038c-2.141,0.551-3.137-0.786-3.374-1.705 c-0.237-0.919,0.116-1.533,0.141-1.598c0.027-0.062,0-0.083,0-0.083s-0.183-0.297-0.239-0.407 c-0.057-0.106-0.107-0.078-0.107-0.078c-0.86,0.015-3.514-0.331-5.817-1.916c-2.304-1.581-2.972-2.884-3.233-3.904 c-0.264-1.02,0.016-2.775,2.189-3.335c2.175-0.56,4.617,0.442,4.617,0.442c0.072,0.032,0.102-0.02,0.102-0.02 c1.38-1.921,3.828-2.461,3.999-2.498c0.165-0.051,2.572-0.762,4.704,0.256c0,0,0.052,0.028,0.1-0.033c0,0,1.654-2.057,3.828-2.619 c2.178-0.56,3.268,0.84,3.529,1.86C26.764,36.359,26.812,37.822,25.561,40.32 M18.047,34.639c0,0-1.651-0.673-4.039-0.061 c-2.388,0.618-3.509,2.007-3.509,2.007c-0.088,0.106-0.104,0.012-0.104,0.012c-0.242-0.944-0.24-1.435,0.484-2.537 c0.699-1.064,2.465-1.548,2.584-1.582c0,0,0.002,0,0.004-0.001l0.004-0.001c0.121-0.029,1.898-0.455,3.027,0.137 c1.165,0.613,1.403,1.042,1.646,1.986C18.145,34.601,18.178,34.691,18.047,34.639 M15.105,31.604c0,0-0.814-0.297-1.869-0.027 l-0.205-0.79l0.199,0.791c-1.056,0.271-1.622,0.927-1.622,0.927c-0.208,0.161-0.166-0.064-0.166-0.064 c0.188-1.983,1.271-2.482,1.363-2.519l-0.002-0.004l0.003,0.002c0.002-0.003,0.004-0.005,0.004-0.005l0.002,0.006 c0.096-0.011,1.283-0.101,2.408,1.545C15.223,31.468,15.365,31.645,15.105,31.604" }))))); } - } - exports.default = LoadingBeeSpinner; \ No newline at end of file diff --git a/dist/components/LoadingBeeSpinner/index.js b/dist/components/LoadingBeeSpinner/index.js index 6abd283..98b77c3 100644 --- a/dist/components/LoadingBeeSpinner/index.js +++ b/dist/components/LoadingBeeSpinner/index.js @@ -3,11 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); - var _LoadingBeeSpinner = require("./LoadingBeeSpinner"); - var _LoadingBeeSpinner2 = _interopRequireDefault(_LoadingBeeSpinner); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } exports.default = _LoadingBeeSpinner2.default; \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 6691b0c..2943125 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,32 +1,20 @@ "use strict"; var _react = require("react"); - var _react2 = _interopRequireDefault(_react); - var _reactDom = require("react-dom"); - var _reactDom2 = _interopRequireDefault(_reactDom); - var _serviceWorker = require("./serviceWorker"); - var serviceWorker = _interopRequireWildcard(_serviceWorker); - var _Demo = require("./Demo"); - var _Demo2 = _interopRequireDefault(_Demo); - require("./index.css"); +function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } +function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } +_reactDom2.default.render( /*#__PURE__*/_react2.default.createElement(_Demo2.default, null), document.getElementById('root')); -function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } - -function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_reactDom2.default.render( /*#__PURE__*/_react2.default.createElement(_Demo2.default, null), document.getElementById('root')); // If you want your app to work offline and load faster, you can change +// If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: https://bit.ly/CRA-PWA - - serviceWorker.unregister(); \ No newline at end of file diff --git a/dist/serviceWorker.js b/dist/serviceWorker.js index 7faa7fe..e1f21b3 100644 --- a/dist/serviceWorker.js +++ b/dist/serviceWorker.js @@ -7,37 +7,39 @@ exports.register = register; exports.unregister = unregister; // This optional code is used to register a service worker. // register() is not called by default. + // This lets the app load faster on subsequent visits in production, and gives // it offline capabilities. However, it also means that developers (and users) // will only see deployed updates on subsequent visits to a page, after all the // existing tabs open on the page have been closed, since previously cached // resources are updated in the background. + // To learn more about the benefits of this model and instructions on how to // opt-in, read https://bit.ly/CRA-PWA -const isLocalhost = Boolean(window.location.hostname === 'localhost' || // [::1] is the IPv6 localhost address. -window.location.hostname === '[::1]' || // 127.0.0.0/8 are considered localhost for IPv4. -window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)); +const isLocalhost = Boolean(window.location.hostname === 'localhost' || +// [::1] is the IPv6 localhost address. +window.location.hostname === '[::1]' || +// 127.0.0.0/8 are considered localhost for IPv4. +window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)); function register(config) { if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { // The URL constructor is available in all browsers that support SW. const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); - if (publicUrl.origin !== window.location.origin) { // Our service worker won't work if PUBLIC_URL is on a different origin // from what our page is served on. This might happen if a CDN is used to // serve assets; see https://github.com/facebook/create-react-app/issues/2374 return; } - window.addEventListener('load', () => { const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; - if (isLocalhost) { // This is running on localhost. Let's check if a service worker still exists or not. - checkValidServiceWorker(swUrl, config); // Add some additional logging to localhost, pointing developers to the - // service worker/PWA documentation. + checkValidServiceWorker(swUrl, config); + // Add some additional logging to localhost, pointing developers to the + // service worker/PWA documentation. navigator.serviceWorker.ready.then(() => { console.log('This web app is being served cache-first by a service ' + 'worker. To learn more, visit https://bit.ly/CRA-PWA'); }); @@ -48,24 +50,22 @@ function register(config) { }); } } - function registerValidSW(swUrl, config) { navigator.serviceWorker.register(swUrl).then(registration => { registration.onupdatefound = () => { const installingWorker = registration.installing; - if (installingWorker == null) { return; } - installingWorker.onstatechange = () => { if (installingWorker.state === 'installed') { if (navigator.serviceWorker.controller) { // At this point, the updated precached content has been fetched, // but the previous service worker will still serve the older // content until all client tabs are closed. - console.log('New content is available and will be used when all ' + 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'); // Execute callback + console.log('New content is available and will be used when all ' + 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'); + // Execute callback if (config && config.onUpdate) { config.onUpdate(registration); } @@ -73,8 +73,9 @@ function registerValidSW(swUrl, config) { // At this point, everything has been precached. // It's the perfect time to display a // "Content is cached for offline use." message. - console.log('Content is cached for offline use.'); // Execute callback + console.log('Content is cached for offline use.'); + // Execute callback if (config && config.onSuccess) { config.onSuccess(registration); } @@ -86,7 +87,6 @@ function registerValidSW(swUrl, config) { console.error('Error during service worker registration:', error); }); } - function checkValidServiceWorker(swUrl, config) { // Check if the service worker can be found. If it can't reload the page. fetch(swUrl, { @@ -96,7 +96,6 @@ function checkValidServiceWorker(swUrl, config) { }).then(response => { // Ensure service worker exists, and that we really are getting a JS file. const contentType = response.headers.get('content-type'); - if (response.status === 404 || contentType != null && contentType.indexOf('javascript') === -1) { // No service worker found. Probably a different app. Reload the page. navigator.serviceWorker.ready.then(registration => { @@ -112,7 +111,6 @@ function checkValidServiceWorker(swUrl, config) { console.log('No internet connection found. App is running in offline mode.'); }); } - function unregister() { if ('serviceWorker' in navigator) { navigator.serviceWorker.ready.then(registration => { diff --git a/package.json b/package.json index dd1dd7c..39afbec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bfx-hf-chart", - "version": "1.0.13", + "version": "1.0.14", "description": "HF Financial Charting Library", "main": "dist/components/Chart/Chart.js", "author": "Bitfinex", From 790fa447ca7cb92bf2617e72d13421480919b725 Mon Sep 17 00:00:00 2001 From: Cris Mihalache Date: Tue, 25 Jun 2024 10:43:07 +0200 Subject: [PATCH 5/9] feat: bump react & react-dom to 18.2.0 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 39afbec..85360dd 100644 --- a/package.json +++ b/package.json @@ -23,9 +23,9 @@ "moment": "^2.24.0", "mouse-wheel": "^1.2.0", "randomcolor": "^0.5.4", - "react": "^16.12.0", + "react": "^18.2.0", "react-custom-scrollbars": "^4.2.1", - "react-dom": "^16.12.0", + "react-dom": "^18.2.0", "react-onclickoutside": "^6.9.0", "react-scripts": "4.0.3" }, From 0f2dd8628757f90bd02028756d0ba640e149f34d Mon Sep 17 00:00:00 2001 From: Cris Mihalache Date: Fri, 26 Jul 2024 20:48:44 +0200 Subject: [PATCH 6/9] feat: support arbitrary candle widths in ms, or Bitfinex width strings --- src/components/Chart/Chart.js | 29 ++++++++++++++++++++++++----- src/components/Chart/lib/chart.js | 19 +++++++++++++------ 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/components/Chart/Chart.js b/src/components/Chart/Chart.js index b7b75a3..5867af6 100644 --- a/src/components/Chart/Chart.js +++ b/src/components/Chart/Chart.js @@ -1,3 +1,4 @@ +import _isFinite from 'lodash/isFinite' import React from 'react' import { TIME_FRAME_WIDTHS } from 'bfx-hf-util' import HFI from 'bfx-hf-indicators' @@ -57,7 +58,7 @@ class Chart extends React.Component { componentDidMount () { const { width, height, onLoadMore, indicators, candles, candleWidth, trades, - config, onTimeFrameChange, orders, position, marketLabel, + config, onTimeFrameChange, orders, position, marketLabel, timeFrameWidth } = this.props document.addEventListener('fullscreenchange', this.onFullscreenExit, false) @@ -84,6 +85,10 @@ class Chart extends React.Component { return } + const dataKey = _isFinite(timeFrameWidth) + ? `${marketLabel}${timeFrameWidth}` + : `${marketLabel}${TIME_FRAME_WIDTHS[candleWidth]}` + this.chart = new ChartLib({ ohlcCanvas, axisCanvas, @@ -96,8 +101,9 @@ class Chart extends React.Component { onHoveredCandleCB: this.onHoveredCandle, onUpdateIndicatorSettingsCB: this.onUpdateIndicatorSettings, data: candles, - dataKey: `${marketLabel}${candleWidth}`, + dataKey, dataWidth: candleWidth, + timeFrameWidth, trades, orders, position, @@ -111,15 +117,28 @@ class Chart extends React.Component { const { isFullscreen } = this.state const { candles, width, height, trades, indicators, drawings, candleWidth, orders, - position, disableToolbar, disableTopbar, marketLabel, onLoadMore + position, disableToolbar, disableTopbar, marketLabel, onLoadMore, + disableTimeFrames, timeFrameWidth } = this.props if (onLoadMore !== prevProps.onLoadMore) { this.chart.onLoadMoreCB = onLoadMore } - if (candles !== prevProps.candles || candleWidth !== prevProps.candleWidth) { - this.chart.updateData(candles, candleWidth, `${marketLabel}${candleWidth}`) + if ( + candles !== prevProps.candles || + candleWidth !== prevProps.candleWidth || + timeFrameWidth !== prevProps.timeFrameWidth + ) { + const width = _isFinite(timeFrameWidth) + ? timeFrameWidth + : TIME_FRAME_WIDTHS[candleWidth] + + this.chart.updateData(candles, width, `${marketLabel}${width}`) + } + + if (timeFrameWidth !== prevProps.timeFrameWidth) { + this.chart.dataWidth = timeFrameWidth } if ( diff --git a/src/components/Chart/lib/chart.js b/src/components/Chart/lib/chart.js index 72a9d6f..15fb1df 100644 --- a/src/components/Chart/lib/chart.js +++ b/src/components/Chart/lib/chart.js @@ -1,3 +1,4 @@ +import _isUndefined from 'lodash/isUndefined' import _isFunction from 'lodash/isFunction' import _isFinite from 'lodash/isFinite' import _isObject from 'lodash/isObject' @@ -33,6 +34,7 @@ export default class BitfinexTradingChart { position, data, dataWidth, + timeFrameWidth, dataKey, indicators = [], onLoadMoreCB, @@ -55,7 +57,10 @@ export default class BitfinexTradingChart { this.trades = trades this.orders = orders this.position = position - this.dataWidth = TIME_FRAME_WIDTHS[dataWidth] + this.dataWidth = _isFinite(timeFrameWidth) + ? timeFrameWidth + : TIME_FRAME_WIDTHS[dataWidth] + this.onLoadMoreCB = onLoadMoreCB this.onHoveredCandleCB = onHoveredCandleCB this.onUpdateIndicatorSettingsCB = onUpdateIndicatorSettingsCB @@ -89,7 +94,7 @@ export default class BitfinexTradingChart { this.externalIndicators = 0 // set in updateData() this.updateIndicators(indicators) - this.updateData(data, dataWidth, dataKey) + this.updateData(data, this.dataWidth, dataKey) this.clipCanvases() this.clearAll() @@ -152,12 +157,14 @@ export default class BitfinexTradingChart { * Updates internal candle & indicator data sets * * @param {Array[]} data - candle dataset - * @param {number?} dataWidth - candle width, default unchanged + * @param {string|number?} dataWidth - candle width string or ms value * @param {string} dataKey - optional, resets pan on change */ updateData (data = [], dataWidth, dataKey) { - if (dataWidth) { - this.dataWidth = TIME_FRAME_WIDTHS[dataWidth] + if (!_isUndefined(dataWidth)) { + this.dataWidth = _isFinite(dataWidth) + ? dataWidth + : TIME_FRAME_WIDTHS[dataWidth] } if (this.dataKey && this.dataKey !== dataKey) { @@ -984,8 +991,8 @@ export default class BitfinexTradingChart { const newOnLoadMoreKey = `${(this.data[0] ?? [])[0]}-${(_last(this.data) ?? [])[0]}-${this.dataKey}` if (this.onLoadMoreKey !== newOnLoadMoreKey) { - this.onLoadMoreCB(this.viewportWidthCandles) this.onLoadMoreKey = newOnLoadMoreKey + this.onLoadMoreCB(this.viewportWidthCandles) } } } From 82a928e1ac1b101ea9900ae373b1a9104912104a Mon Sep 17 00:00:00 2001 From: Cris Mihalache Date: Fri, 26 Jul 2024 20:49:09 +0200 Subject: [PATCH 7/9] feat: add disableTimeFrames prop --- src/components/Chart/Chart.js | 45 +++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src/components/Chart/Chart.js b/src/components/Chart/Chart.js index 5867af6..c8ea759 100644 --- a/src/components/Chart/Chart.js +++ b/src/components/Chart/Chart.js @@ -145,7 +145,8 @@ class Chart extends React.Component { (width !== prevProps.width) || (height !== prevProps.height) || (disableToolbar !== prevProps.disableToolbar) || - (disableTopbar !== prevProps.disableTopbar) + (disableTopbar !== prevProps.disableTopbar) || + (disableTimeFrames !== prevProps.disableTimeFrames) ) { if (isFullscreen) { this.chart.updateDimensions(window.innerWidth, this.getChartHeight()) @@ -358,7 +359,7 @@ class Chart extends React.Component { marketLabel, bgColor = '#000', candleWidth, candles, onTimeFrameChange, onAddDrawing, isSyncing, disableToolbar, disableTopbar, onDeleteIndicator, disableIndicators, candleLoadingThreshold = 0, extraHeaderComponentsLeft, - extraHeaderComponentsRight, showMarketLabel, + extraHeaderComponentsRight, showMarketLabel, disableTimeFrames } = this.props const height = isFullscreen ? window.innerHeight : this.props.height @@ -399,25 +400,27 @@ class Chart extends React.Component {

)} -
- - {candleWidth} - - - )} - > -
    - {Object.keys(TIME_FRAME_WIDTHS).map(tf => ( -
  • onTimeFrameChange && onTimeFrameChange(tf)} - >{tf}
  • - ))} -
-
-
+ {!disableTimeFrames && ( +
+ + {candleWidth} + + + )} + > +
    + {Object.keys(TIME_FRAME_WIDTHS).map(tf => ( +
  • onTimeFrameChange && onTimeFrameChange(tf)} + >{tf}
  • + ))} +
+
+
+ )} {!disableIndicators && (
From eac5883b82e6176e0f26b2fab5cc5d47b288702d Mon Sep 17 00:00:00 2001 From: Cris Mihalache Date: Fri, 26 Jul 2024 20:50:24 +0200 Subject: [PATCH 8/9] fix: remove mouse event listeners in componentWillUnmount --- src/components/Chart/Chart.js | 1 + src/components/Chart/lib/chart.js | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/components/Chart/Chart.js b/src/components/Chart/Chart.js index c8ea759..4ff4e3b 100644 --- a/src/components/Chart/Chart.js +++ b/src/components/Chart/Chart.js @@ -182,6 +182,7 @@ class Chart extends React.Component { document.removeEventListener('MSFullscreenChange', this.onFullscreenExit) document.removeEventListener('webkitfullscreenchange', this.onFullscreenExit) + this.chart.removeMouseEventListeners() this.chart = null } diff --git a/src/components/Chart/lib/chart.js b/src/components/Chart/lib/chart.js index 15fb1df..1e92be0 100644 --- a/src/components/Chart/lib/chart.js +++ b/src/components/Chart/lib/chart.js @@ -101,6 +101,13 @@ export default class BitfinexTradingChart { this.renderAll() } + removeMouseEventListeners() { + this.crosshairCanvas.removeEventListener('mouseup', this.onMouseUp) + this.crosshairCanvas.removeEventListener('mousedown', this.onMouseDown) + this.crosshairCanvas.removeEventListener('mousemove', this.onMouseMove) + this.crosshairCanvas.removeEventListener('mouseleave', this.onMouseLeave) + } + clipCanvases () { const drawingCTX = this.drawingCanvas.getContext('2d') const ohlcCTX = this.ohlcCanvas.getContext('2d') From 898ea1a8f34d4ca9abb6927e5f2ecad46a9d1425 Mon Sep 17 00:00:00 2001 From: Cris Mihalache Date: Fri, 26 Jul 2024 20:50:47 +0200 Subject: [PATCH 9/9] chore: build --- dist/components/Chart/Chart.js | 29 +++++++++++++++++++++-------- dist/components/Chart/lib/chart.js | 21 +++++++++++++++------ 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/dist/components/Chart/Chart.js b/dist/components/Chart/Chart.js index 433fbd1..b26aae5 100644 --- a/dist/components/Chart/Chart.js +++ b/dist/components/Chart/Chart.js @@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true }); +var _isFinite2 = require("lodash/isFinite"); +var _isFinite3 = _interopRequireDefault(_isFinite2); var _react = require("react"); var _react2 = _interopRequireDefault(_react); var _bfxHfUtil = require("bfx-hf-util"); @@ -79,7 +81,8 @@ class Chart extends _react2.default.Component { onTimeFrameChange, orders, position, - marketLabel + marketLabel, + timeFrameWidth } = this.props; document.addEventListener('fullscreenchange', this.onFullscreenExit, false); document.addEventListener('mozfullscreenchange', this.onFullscreenExit, false); @@ -98,6 +101,7 @@ class Chart extends _react2.default.Component { console.error('chart library initialized before mount!'); return; } + const dataKey = (0, _isFinite3.default)(timeFrameWidth) ? `${marketLabel}${timeFrameWidth}` : `${marketLabel}${_bfxHfUtil.TIME_FRAME_WIDTHS[candleWidth]}`; this.chart = new _chart2.default({ ohlcCanvas, axisCanvas, @@ -110,8 +114,9 @@ class Chart extends _react2.default.Component { onHoveredCandleCB: this.onHoveredCandle, onUpdateIndicatorSettingsCB: this.onUpdateIndicatorSettings, data: candles, - dataKey: `${marketLabel}${candleWidth}`, + dataKey, dataWidth: candleWidth, + timeFrameWidth, trades, orders, position, @@ -137,15 +142,21 @@ class Chart extends _react2.default.Component { disableToolbar, disableTopbar, marketLabel, - onLoadMore + onLoadMore, + disableTimeFrames, + timeFrameWidth } = this.props; if (onLoadMore !== prevProps.onLoadMore) { this.chart.onLoadMoreCB = onLoadMore; } - if (candles !== prevProps.candles || candleWidth !== prevProps.candleWidth) { - this.chart.updateData(candles, candleWidth, `${marketLabel}${candleWidth}`); + if (candles !== prevProps.candles || candleWidth !== prevProps.candleWidth || timeFrameWidth !== prevProps.timeFrameWidth) { + const width = (0, _isFinite3.default)(timeFrameWidth) ? timeFrameWidth : _bfxHfUtil.TIME_FRAME_WIDTHS[candleWidth]; + this.chart.updateData(candles, width, `${marketLabel}${width}`); + } + if (timeFrameWidth !== prevProps.timeFrameWidth) { + this.chart.dataWidth = timeFrameWidth; } - if (width !== prevProps.width || height !== prevProps.height || disableToolbar !== prevProps.disableToolbar || disableTopbar !== prevProps.disableTopbar) { + if (width !== prevProps.width || height !== prevProps.height || disableToolbar !== prevProps.disableToolbar || disableTopbar !== prevProps.disableTopbar || disableTimeFrames !== prevProps.disableTimeFrames) { if (isFullscreen) { this.chart.updateDimensions(window.innerWidth, this.getChartHeight()); } else { @@ -173,6 +184,7 @@ class Chart extends _react2.default.Component { document.removeEventListener('mozfullscreenchange', this.onFullscreenExit); document.removeEventListener('MSFullscreenChange', this.onFullscreenExit); document.removeEventListener('webkitfullscreenchange', this.onFullscreenExit); + this.chart.removeMouseEventListeners(); this.chart = null; } onHoveredCandle(hoveredCandle) { @@ -352,7 +364,8 @@ class Chart extends _react2.default.Component { candleLoadingThreshold = 0, extraHeaderComponentsLeft, extraHeaderComponentsRight, - showMarketLabel + showMarketLabel, + disableTimeFrames } = this.props; const height = isFullscreen ? window.innerHeight : this.props.height; const width = isFullscreen ? window.innerWidth : this.props.width; @@ -380,7 +393,7 @@ class Chart extends _react2.default.Component { className: "bfxc__topbar" }, extraHeaderComponentsLeft, showMarketLabel && /*#__PURE__*/_react2.default.createElement("p", { className: "bfxcs__topbar-market" - }, marketLabel), /*#__PURE__*/_react2.default.createElement("div", { + }, marketLabel), !disableTimeFrames && /*#__PURE__*/_react2.default.createElement("div", { className: "bfxcs__topbar-tfs bfxcs__topbar-section" }, /*#__PURE__*/_react2.default.createElement(_Dropdown2.default, { label: /*#__PURE__*/_react2.default.createElement("span", null, candleWidth, /*#__PURE__*/_react2.default.createElement("i", { diff --git a/dist/components/Chart/lib/chart.js b/dist/components/Chart/lib/chart.js index 0fee948..0e68889 100644 --- a/dist/components/Chart/lib/chart.js +++ b/dist/components/Chart/lib/chart.js @@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true }); +var _isUndefined2 = require("lodash/isUndefined"); +var _isUndefined3 = _interopRequireDefault(_isUndefined2); var _isFunction2 = require("lodash/isFunction"); var _isFunction3 = _interopRequireDefault(_isFunction2); var _isFinite2 = require("lodash/isFinite"); @@ -52,6 +54,7 @@ class BitfinexTradingChart { position, data, dataWidth, + timeFrameWidth, dataKey, indicators = [], onLoadMoreCB, @@ -72,7 +75,7 @@ class BitfinexTradingChart { this.trades = trades; this.orders = orders; this.position = position; - this.dataWidth = _bfxHfUtil.TIME_FRAME_WIDTHS[dataWidth]; + this.dataWidth = (0, _isFinite3.default)(timeFrameWidth) ? timeFrameWidth : _bfxHfUtil.TIME_FRAME_WIDTHS[dataWidth]; this.onLoadMoreCB = onLoadMoreCB; this.onHoveredCandleCB = onHoveredCandleCB; this.onUpdateIndicatorSettingsCB = onUpdateIndicatorSettingsCB; @@ -114,11 +117,17 @@ class BitfinexTradingChart { this.externalIndicators = 0; // set in updateData() this.updateIndicators(indicators); - this.updateData(data, dataWidth, dataKey); + this.updateData(data, this.dataWidth, dataKey); this.clipCanvases(); this.clearAll(); this.renderAll(); } + removeMouseEventListeners() { + this.crosshairCanvas.removeEventListener('mouseup', this.onMouseUp); + this.crosshairCanvas.removeEventListener('mousedown', this.onMouseDown); + this.crosshairCanvas.removeEventListener('mousemove', this.onMouseMove); + this.crosshairCanvas.removeEventListener('mouseleave', this.onMouseLeave); + } clipCanvases() { const drawingCTX = this.drawingCanvas.getContext('2d'); const ohlcCTX = this.ohlcCanvas.getContext('2d'); @@ -163,12 +172,12 @@ class BitfinexTradingChart { * Updates internal candle & indicator data sets * * @param {Array[]} data - candle dataset - * @param {number?} dataWidth - candle width, default unchanged + * @param {string|number?} dataWidth - candle width string or ms value * @param {string} dataKey - optional, resets pan on change */ updateData(data = [], dataWidth, dataKey) { - if (dataWidth) { - this.dataWidth = _bfxHfUtil.TIME_FRAME_WIDTHS[dataWidth]; + if (!(0, _isUndefined3.default)(dataWidth)) { + this.dataWidth = (0, _isFinite3.default)(dataWidth) ? dataWidth : _bfxHfUtil.TIME_FRAME_WIDTHS[dataWidth]; } if (this.dataKey && this.dataKey !== dataKey) { this.onDataReset(); @@ -862,8 +871,8 @@ class BitfinexTradingChart { if (candlePanOffset + this.viewportWidthCandles > this.data.length) { const newOnLoadMoreKey = `${(this.data[0] ?? [])[0]}-${((0, _last3.default)(this.data) ?? [])[0]}-${this.dataKey}`; if (this.onLoadMoreKey !== newOnLoadMoreKey) { - this.onLoadMoreCB(this.viewportWidthCandles); this.onLoadMoreKey = newOnLoadMoreKey; + this.onLoadMoreCB(this.viewportWidthCandles); } } }