UNPKG

ct-react-stockcharts

Version:

Highly customizable stock charts with ReactJS and d3

581 lines (497 loc) 17.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _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; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); exports.getAxisCanvas = getAxisCanvas; exports.getMouseCanvas = getMouseCanvas; var _react = require("react"); var _react2 = _interopRequireDefault(_react); var _propTypes = require("prop-types"); var _propTypes2 = _interopRequireDefault(_propTypes); var _utils = require("./utils"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var aliases = { mouseleave: "mousemove", // to draw interactive after mouse exit panend: "pan", pinchzoom: "pan", mousedown: "mousemove", click: "mousemove", contextmenu: "mousemove", dblclick: "mousemove", dragstart: "drag", dragend: "drag", dragcancel: "drag" }; var GenericComponent = function (_Component) { _inherits(GenericComponent, _Component); function GenericComponent(props, context) { _classCallCheck(this, GenericComponent); var _this = _possibleConstructorReturn(this, (GenericComponent.__proto__ || Object.getPrototypeOf(GenericComponent)).call(this, props, context)); _this.drawOnCanvas = _this.drawOnCanvas.bind(_this); _this.getMoreProps = _this.getMoreProps.bind(_this); _this.listener = _this.listener.bind(_this); _this.draw = _this.draw.bind(_this); _this.updateMoreProps = _this.updateMoreProps.bind(_this); _this.evaluateType = _this.evaluateType.bind(_this); _this.isHover = _this.isHover.bind(_this); _this.preCanvasDraw = _this.preCanvasDraw.bind(_this); _this.postCanvasDraw = _this.postCanvasDraw.bind(_this); _this.getPanConditions = _this.getPanConditions.bind(_this); _this.shouldTypeProceed = _this.shouldTypeProceed.bind(_this); _this.preEvaluate = _this.preEvaluate.bind(_this); var generateSubscriptionId = context.generateSubscriptionId; _this.suscriberId = generateSubscriptionId(); _this.moreProps = {}; _this.state = { updateCount: 0 }; return _this; } _createClass(GenericComponent, [{ key: "updateMoreProps", value: function updateMoreProps(moreProps) { var _this2 = this; Object.keys(moreProps).forEach(function (key) { _this2.moreProps[key] = moreProps[key]; }); } }, { key: "shouldTypeProceed", value: function shouldTypeProceed() { return true; } }, { key: "preEvaluate", value: function preEvaluate() {} }, { key: "listener", value: function listener(type, moreProps, state, e) { // console.log(e.shiftKey) if ((0, _utils.isDefined)(moreProps)) { this.updateMoreProps(moreProps); } this.evaluationInProgress = true; this.evaluateType(type, e); this.evaluationInProgress = false; } }, { key: "evaluateType", value: function evaluateType(type, e) { var newType = aliases[type] || type; var proceed = this.props.drawOn.indexOf(newType) > -1; // console.log("type ->", type, proceed); if (!proceed) return; // const moreProps = this.getMoreProps(); this.preEvaluate(type, this.moreProps, e); if (!this.shouldTypeProceed(type, this.moreProps)) return; switch (type) { case "zoom": case "mouseenter": // DO NOT DRAW FOR THESE EVENTS break; case "mouseleave": { this.moreProps.hovering = false; var moreProps = this.getMoreProps(); if (this.props.onUnHover) { this.props.onUnHover(moreProps, e); } break; } case "contextmenu": { if (this.props.onContextMenu) { this.props.onContextMenu(this.getMoreProps(), e); } if (this.moreProps.hovering && this.props.onContextMenuWhenHover) { this.props.onContextMenuWhenHover(this.getMoreProps(), e); } break; } case "mousedown": { if (this.props.onMouseDown) { this.props.onMouseDown(this.getMoreProps(), e); } break; } case "click": { var _moreProps = this.getMoreProps(); if (this.moreProps.hovering) { // console.error("TODO use this only for SAR, Line series") this.props.onClickWhenHover(_moreProps, e); } else { this.props.onClickOutside(_moreProps, e); } if (this.props.onClick) { this.props.onClick(_moreProps, e); } break; } case "mousemove": { var prevHover = this.moreProps.hovering; this.moreProps.hovering = this.isHover(e); var _context = this.context, amIOnTop = _context.amIOnTop, setCursorClass = _context.setCursorClass; if (this.moreProps.hovering && !this.props.selected /* && !prevHover */ && amIOnTop(this.suscriberId) && (0, _utils.isDefined)(this.props.onHover)) { setCursorClass("react-stockcharts-pointer-cursor"); this.iSetTheCursorClass = true; } else if (this.moreProps.hovering && this.props.selected && amIOnTop(this.suscriberId)) { setCursorClass(this.props.interactiveCursorClass); this.iSetTheCursorClass = true; } else if (prevHover && !this.moreProps.hovering && this.iSetTheCursorClass) { this.iSetTheCursorClass = false; setCursorClass(null); } var _moreProps2 = this.getMoreProps(); if (this.moreProps.hovering && !prevHover) { if (this.props.onHover) { this.props.onHover(_moreProps2, e); } } if (prevHover && !this.moreProps.hovering) { if (this.props.onUnHover) { this.props.onUnHover(_moreProps2, e); } } if (this.props.onMouseMove) { this.props.onMouseMove(_moreProps2, e); } break; } case "dblclick": { var _moreProps3 = this.getMoreProps(); if (this.props.onDoubleClick) { this.props.onDoubleClick(_moreProps3, e); } if (this.moreProps.hovering && this.props.onDoubleClickWhenHover) { this.props.onDoubleClickWhenHover(_moreProps3, e); } break; } case "pan": { this.moreProps.hovering = false; if (this.props.onPan) { this.props.onPan(this.getMoreProps(), e); } break; } case "panend": { if (this.props.onPanEnd) { this.props.onPanEnd(this.getMoreProps(), e); } break; } case "dragstart": { if (this.getPanConditions().draggable) { var _amIOnTop = this.context.amIOnTop; if (_amIOnTop(this.suscriberId)) { this.dragInProgress = true; this.props.onDragStart(this.getMoreProps(), e); } } this.someDragInProgress = true; break; } case "drag": { if (this.dragInProgress && this.props.onDrag) { this.props.onDrag(this.getMoreProps(), e); } break; } case "dragend": { if (this.dragInProgress && this.props.onDragComplete) { this.props.onDragComplete(this.getMoreProps(), e); } this.dragInProgress = false; this.someDragInProgress = false; break; } case "dragcancel": { if (this.dragInProgress || this.iSetTheCursorClass) { var _setCursorClass = this.context.setCursorClass; _setCursorClass(null); } break; } } } }, { key: "isHover", value: function isHover(e) { return (0, _utils.isDefined)(this.props.isHover) ? this.props.isHover(this.getMoreProps(), e) : false; } }, { key: "getPanConditions", value: function getPanConditions() { var draggable = !!(this.props.selected && this.moreProps.hovering) || this.props.enableDragOnHover && this.moreProps.hovering; return { draggable: draggable, panEnabled: !this.props.disablePan }; } }, { key: "draw", value: function draw() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { force: false }, trigger = _ref.trigger, force = _ref.force; var type = aliases[trigger] || trigger; var proceed = this.props.drawOn.indexOf(type) > -1; if (proceed || this.props.selected /* this is to draw as soon as you select */ || force) { var chartCanvasType = this.context.chartCanvasType; var canvasDraw = this.props.canvasDraw; if ((0, _utils.isNotDefined)(canvasDraw) || chartCanvasType === "svg") { var updateCount = this.state.updateCount; this.setState({ updateCount: updateCount + 1 }); } else { this.drawOnCanvas(); } } } }, { key: "componentWillMount", value: function componentWillMount() { var _context2 = this.context, subscribe = _context2.subscribe, chartId = _context2.chartId; var _props = this.props, clip = _props.clip, edgeClip = _props.edgeClip; subscribe(this.suscriberId, { chartId: chartId, clip: clip, edgeClip: edgeClip, listener: this.listener, draw: this.draw, getPanConditions: this.getPanConditions }); this.componentWillReceiveProps(this.props, this.context); } }, { key: "componentWillUnmount", value: function componentWillUnmount() { var unsubscribe = this.context.unsubscribe; unsubscribe(this.suscriberId); if (this.iSetTheCursorClass) { var setCursorClass = this.context.setCursorClass; setCursorClass(null); } } }, { key: "componentDidMount", value: function componentDidMount() { this.componentDidUpdate(this.props); } }, { key: "componentDidUpdate", value: function componentDidUpdate(prevProps) { var chartCanvasType = this.context.chartCanvasType; var _props2 = this.props, canvasDraw = _props2.canvasDraw, selected = _props2.selected, interactiveCursorClass = _props2.interactiveCursorClass; if (prevProps.selected !== selected) { var setCursorClass = this.context.setCursorClass; if (selected && this.moreProps.hovering) { this.iSetTheCursorClass = true; setCursorClass(interactiveCursorClass); } else { this.iSetTheCursorClass = false; setCursorClass(null); } } if ((0, _utils.isDefined)(canvasDraw) && !this.evaluationInProgress // && !(this.someDragInProgress && this.props.selected) /* prevent double draw of interactive elements during dragging / hover / click etc. */ && chartCanvasType !== "svg") { this.updateMoreProps(this.moreProps); this.drawOnCanvas(); } } }, { key: "componentWillReceiveProps", value: function componentWillReceiveProps(nextProps, nextContext) { var xScale = nextContext.xScale, plotData = nextContext.plotData, chartConfig = nextContext.chartConfig, getMutableState = nextContext.getMutableState; this.props.debug(nextContext); this.moreProps = _extends({}, this.moreProps, getMutableState(), { /* ^ this is so mouseXY, currentCharts, currentItem are available to newly created components like MouseHoverText which is created right after a new interactive object is drawn */ xScale: xScale, plotData: plotData, chartConfig: chartConfig }); } }, { key: "getMoreProps", value: function getMoreProps() { var _context3 = this.context, xScale = _context3.xScale, plotData = _context3.plotData, chartConfig = _context3.chartConfig, morePropsDecorator = _context3.morePropsDecorator, xAccessor = _context3.xAccessor, displayXAccessor = _context3.displayXAccessor, width = _context3.width, height = _context3.height; var _context4 = this.context, chartId = _context4.chartId, fullData = _context4.fullData; var moreProps = _extends({ xScale: xScale, plotData: plotData, chartConfig: chartConfig, xAccessor: xAccessor, displayXAccessor: displayXAccessor, width: width, height: height, chartId: chartId, fullData: fullData }, this.moreProps); return (morePropsDecorator || _utils.identity)(moreProps); } }, { key: "preCanvasDraw", value: function preCanvasDraw() { // do nothing } }, { key: "postCanvasDraw", value: function postCanvasDraw() {} }, { key: "drawOnCanvas", value: function drawOnCanvas() { var _props3 = this.props, canvasDraw = _props3.canvasDraw, canvasToDraw = _props3.canvasToDraw; var getCanvasContexts = this.context.getCanvasContexts; var moreProps = this.getMoreProps(); var ctx = canvasToDraw(getCanvasContexts()); this.preCanvasDraw(ctx, moreProps); canvasDraw(ctx, moreProps); this.postCanvasDraw(ctx, moreProps); } }, { key: "render", value: function render() { var _context5 = this.context, chartCanvasType = _context5.chartCanvasType, chartId = _context5.chartId; var _props4 = this.props, canvasDraw = _props4.canvasDraw, clip = _props4.clip, svgDraw = _props4.svgDraw; if ((0, _utils.isDefined)(canvasDraw) && chartCanvasType !== "svg") { return null; } var suffix = (0, _utils.isDefined)(chartId) ? "-" + chartId : ""; var style = clip ? { "clipPath": "url(#chart-area-clip" + suffix + ")" } : null; return _react2.default.createElement( "g", { style: style }, svgDraw(this.getMoreProps()) ); } }]); return GenericComponent; }(_react.Component); GenericComponent.propTypes = { svgDraw: _propTypes2.default.func.isRequired, canvasDraw: _propTypes2.default.func, drawOn: _propTypes2.default.array.isRequired, clip: _propTypes2.default.bool.isRequired, edgeClip: _propTypes2.default.bool.isRequired, interactiveCursorClass: _propTypes2.default.string, selected: _propTypes2.default.bool.isRequired, enableDragOnHover: _propTypes2.default.bool.isRequired, disablePan: _propTypes2.default.bool.isRequired, canvasToDraw: _propTypes2.default.func.isRequired, isHover: _propTypes2.default.func, onClick: _propTypes2.default.func, onClickWhenHover: _propTypes2.default.func, onClickOutside: _propTypes2.default.func, onPan: _propTypes2.default.func, onPanEnd: _propTypes2.default.func, onDragStart: _propTypes2.default.func, onDrag: _propTypes2.default.func, onDragComplete: _propTypes2.default.func, onDoubleClick: _propTypes2.default.func, onDoubleClickWhenHover: _propTypes2.default.func, onContextMenu: _propTypes2.default.func, onContextMenuWhenHover: _propTypes2.default.func, onMouseMove: _propTypes2.default.func, onMouseDown: _propTypes2.default.func, onHover: _propTypes2.default.func, onUnHover: _propTypes2.default.func, debug: _propTypes2.default.func // owner: PropTypes.string.isRequired, }; GenericComponent.defaultProps = { svgDraw: (0, _utils.functor)(null), draw: [], canvasToDraw: function canvasToDraw(contexts) { return contexts.mouseCoord; }, clip: true, edgeClip: false, selected: false, disablePan: false, enableDragOnHover: false, onClickWhenHover: _utils.noop, onClickOutside: _utils.noop, onDragStart: _utils.noop, onMouseMove: _utils.noop, onMouseDown: _utils.noop, debug: _utils.noop }; GenericComponent.contextTypes = { width: _propTypes2.default.number.isRequired, height: _propTypes2.default.number.isRequired, margin: _propTypes2.default.object.isRequired, chartId: _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.string]), getCanvasContexts: _propTypes2.default.func, chartCanvasType: _propTypes2.default.string, xScale: _propTypes2.default.func.isRequired, xAccessor: _propTypes2.default.func.isRequired, displayXAccessor: _propTypes2.default.func.isRequired, plotData: _propTypes2.default.array.isRequired, fullData: _propTypes2.default.array.isRequired, chartConfig: _propTypes2.default.oneOfType([_propTypes2.default.array, _propTypes2.default.object]).isRequired, morePropsDecorator: _propTypes2.default.func, generateSubscriptionId: _propTypes2.default.func, getMutableState: _propTypes2.default.func.isRequired, amIOnTop: _propTypes2.default.func.isRequired, subscribe: _propTypes2.default.func.isRequired, unsubscribe: _propTypes2.default.func.isRequired, setCursorClass: _propTypes2.default.func.isRequired }; exports.default = GenericComponent; function getAxisCanvas(contexts) { return contexts.axes; } function getMouseCanvas(contexts) { return contexts.mouseCoord; } //# sourceMappingURL=GenericComponent.js.map