|
- 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; }; }();
-
- 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; }
-
- // Copyright (c) 2016 - 2017 Uber Technologies, Inc.
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
-
- import React, { PureComponent } from 'react';
-
- import PropTypes from 'prop-types';
-
- import { transformValueToString } from '../utils/data-utils';
-
- import { getAttributeFunctor } from '../utils/scales-utils';
-
- /*
- * Hint provides two options for placement of hint:
- * a) around a data point in one of four quadrants (imagine the point bisected
- * by two axes -vertical, horizontal- creating 4 quadrants around a data
- * point).
- * b) **New** pin to an edge of chart/plot area and position along that edge
- * using data point's other dimension value.
- *
- * To support these two options, deprecate one Hint props (orientation) with two
- * new Hint align prop object (horizontal, vertical) with following values:
- *
- * horizontal: auto, left, right, leftEdge, rightEdge
- * vertical: auto, bottom, top, bottomEdge, topEdge
- *
- * Thus, the following ALIGN constants are the values for horizontal
- * and vertical
- */
- var ALIGN = {
- AUTO: 'auto',
- LEFT: 'left',
- RIGHT: 'right',
- LEFT_EDGE: 'leftEdge',
- RIGHT_EDGE: 'rightEdge',
- BOTTOM: 'bottom',
- TOP: 'top',
- BOTTOM_EDGE: 'bottomEdge',
- TOP_EDGE: 'topEdge'
- };
-
- /**
- * For backwards support, retain the ORIENTATION prop constants
- */
- var ORIENTATION = {
- BOTTOM_LEFT: 'bottomleft',
- BOTTOM_RIGHT: 'bottomright',
- TOP_LEFT: 'topleft',
- TOP_RIGHT: 'topright'
- };
-
- /**
- * Default format function for the value.
- * @param {Object} value Value.
- * @returns {Array} title-value pairs.
- */
- function defaultFormat(value) {
- return Object.keys(value).map(function getProp(key) {
- return { title: key, value: transformValueToString(value[key]) };
- });
- }
-
- var Hint = function (_PureComponent) {
- _inherits(Hint, _PureComponent);
-
- function Hint() {
- _classCallCheck(this, Hint);
-
- return _possibleConstructorReturn(this, (Hint.__proto__ || Object.getPrototypeOf(Hint)).apply(this, arguments));
- }
-
- _createClass(Hint, [{
- key: '_getAlign',
-
-
- /**
- * Obtain align object with horizontal and vertical settings
- * but convert any AUTO values to the non-auto ALIGN depending on the
- * values of x and y.
- * @param {number} x X value.
- * @param {number} y Y value.
- * @returns {Object} Align object w/ horizontal, vertical prop strings.
- * @private
- */
- value: function _getAlign(x, y) {
- var _props = this.props,
- innerWidth = _props.innerWidth,
- innerHeight = _props.innerHeight,
- orientation = _props.orientation,
- _props$align = _props.align,
- horizontal = _props$align.horizontal,
- vertical = _props$align.vertical;
-
- var align = orientation ? this._mapOrientationToAlign(orientation) : { horizontal: horizontal, vertical: vertical };
- if (horizontal === ALIGN.AUTO) {
- align.horizontal = x > innerWidth / 2 ? ALIGN.LEFT : ALIGN.RIGHT;
- }
- if (vertical === ALIGN.AUTO) {
- align.vertical = y > innerHeight / 2 ? ALIGN.TOP : ALIGN.BOTTOM;
- }
- return align;
- }
-
- /**
- * Get the class names from align values.
- * @param {Object} align object with horizontal and vertical prop strings.
- * @returns {string} Class names.
- * @private
- */
-
- }, {
- key: '_getAlignClassNames',
- value: function _getAlignClassNames(align) {
- var orientation = this.props.orientation;
-
- var orientationClass = orientation ? 'rv-hint--orientation-' + orientation : '';
- return orientationClass + ' rv-hint--horizontalAlign-' + align.horizontal + '\n rv-hint--verticalAlign-' + align.vertical;
- }
-
- /**
- * Get a CSS mixin for a proper positioning of the element.
- * @param {Object} align object with horizontal and vertical prop strings.
- * @param {number} x X position.
- * @param {number} y Y position.
- * @returns {Object} Object, that may contain `left` or `right, `top` or
- * `bottom` properties.
- * @private
- */
-
- }, {
- key: '_getAlignStyle',
- value: function _getAlignStyle(align, x, y) {
- return _extends({}, this._getXCSS(align.horizontal, x), this._getYCSS(align.vertical, y));
- }
-
- /**
- * Get the bottom coordinate of the hint.
- * When y undefined or null, edge case, pin bottom.
- * @param {number} y Y.
- * @returns {{bottom: *}} Mixin.
- * @private
- */
-
- }, {
- key: '_getCSSBottom',
- value: function _getCSSBottom(y) {
- if (y === undefined || y === null) {
- return {
- bottom: 0
- };
- }
-
- var _props2 = this.props,
- innerHeight = _props2.innerHeight,
- marginBottom = _props2.marginBottom;
-
- return {
- bottom: marginBottom + innerHeight - y
- };
- }
-
- /**
- * Get the left coordinate of the hint.
- * When x undefined or null, edge case, pin left.
- * @param {number} x X.
- * @returns {{left: *}} Mixin.
- * @private
- */
-
- }, {
- key: '_getCSSLeft',
- value: function _getCSSLeft(x) {
- if (x === undefined || x === null) {
- return {
- left: 0
- };
- }
-
- var marginLeft = this.props.marginLeft;
-
- return {
- left: marginLeft + x
- };
- }
-
- /**
- * Get the right coordinate of the hint.
- * When x undefined or null, edge case, pin right.
- * @param {number} x X.
- * @returns {{right: *}} Mixin.
- * @private
- */
-
- }, {
- key: '_getCSSRight',
- value: function _getCSSRight(x) {
- if (x === undefined || x === null) {
- return {
- right: 0
- };
- }
-
- var _props3 = this.props,
- innerWidth = _props3.innerWidth,
- marginRight = _props3.marginRight;
-
- return {
- right: marginRight + innerWidth - x
- };
- }
-
- /**
- * Get the top coordinate of the hint.
- * When y undefined or null, edge case, pin top.
- * @param {number} y Y.
- * @returns {{top: *}} Mixin.
- * @private
- */
-
- }, {
- key: '_getCSSTop',
- value: function _getCSSTop(y) {
- if (y === undefined || y === null) {
- return {
- top: 0
- };
- }
-
- var marginTop = this.props.marginTop;
-
- return {
- top: marginTop + y
- };
- }
-
- /**
- * Get the position for the hint and the appropriate class name.
- * @returns {{style: Object, positionClassName: string}} Style and className for the
- * hint.
- * @private
- */
-
- }, {
- key: '_getPositionInfo',
- value: function _getPositionInfo() {
- var _props4 = this.props,
- value = _props4.value,
- getAlignStyle = _props4.getAlignStyle;
-
-
- var x = getAttributeFunctor(this.props, 'x')(value);
- var y = getAttributeFunctor(this.props, 'y')(value);
-
- var align = this._getAlign(x, y);
-
- return {
- position: getAlignStyle ? getAlignStyle(align, x, y) : this._getAlignStyle(align, x, y),
- positionClassName: this._getAlignClassNames(align)
- };
- }
- }, {
- key: '_getXCSS',
- value: function _getXCSS(horizontal, x) {
- // obtain xCSS
- switch (horizontal) {
- case ALIGN.LEFT_EDGE:
- // this pins x to left edge
- return this._getCSSLeft(null);
- case ALIGN.RIGHT_EDGE:
- // this pins x to left edge
- return this._getCSSRight(null);
- case ALIGN.LEFT:
- // this places hint text to the left of center, so set its right edge
- return this._getCSSRight(x);
- case ALIGN.RIGHT:
- default:
- // this places hint text to the right of center, so set its left edge
- // default case should not be possible but if it happens set to RIGHT
- return this._getCSSLeft(x);
- }
- }
- }, {
- key: '_getYCSS',
- value: function _getYCSS(verticalAlign, y) {
- // obtain yCSS
- switch (verticalAlign) {
- case ALIGN.TOP_EDGE:
- // this pins x to top edge
- return this._getCSSTop(null);
- case ALIGN.BOTTOM_EDGE:
- // this pins x to bottom edge
- return this._getCSSBottom(null);
- case ALIGN.BOTTOM:
- // this places hint text to the bottom of center, so set its top edge
- return this._getCSSTop(y);
- case ALIGN.TOP:
- default:
- // this places hint text to the top of center, so set its bottom edge
- // default case should not be possible but if it happens set to BOTTOM
- return this._getCSSBottom(y);
- }
- }
- }, {
- key: '_mapOrientationToAlign',
- value: function _mapOrientationToAlign(orientation) {
- // TODO: print warning that this feature is deprecated and support will be
- // removed in next major release.
- switch (orientation) {
- case ORIENTATION.BOTTOM_LEFT:
- return {
- horizontal: ALIGN.LEFT,
- vertical: ALIGN.BOTTOM
- };
- case ORIENTATION.BOTTOM_RIGHT:
- return {
- horizontal: ALIGN.RIGHT,
- vertical: ALIGN.BOTTOM
- };
- case ORIENTATION.TOP_LEFT:
- return {
- horizontal: ALIGN.LEFT,
- vertical: ALIGN.TOP
- };
- case ORIENTATION.TOP_RIGHT:
- return {
- horizontal: ALIGN.RIGHT,
- vertical: ALIGN.TOP
- };
- default:
- // fall back to horizontalAlign, verticalAlign that are either
- // provided or defaulted to AUTO. So, don't change things
- break;
- }
- }
- }, {
- key: 'render',
- value: function render() {
- var _props5 = this.props,
- value = _props5.value,
- format = _props5.format,
- children = _props5.children,
- style = _props5.style,
- className = _props5.className;
-
- var _getPositionInfo2 = this._getPositionInfo(),
- position = _getPositionInfo2.position,
- positionClassName = _getPositionInfo2.positionClassName;
-
- return React.createElement(
- 'div',
- {
- className: 'rv-hint ' + positionClassName + ' ' + className,
- style: _extends({}, style, position, {
- position: 'absolute'
- })
- },
- children ? children : React.createElement(
- 'div',
- { className: 'rv-hint__content', style: style.content },
- format(value).map(function (formattedProp, i) {
- return React.createElement(
- 'div',
- { key: 'rv-hint' + i, style: style.row },
- React.createElement(
- 'span',
- { className: 'rv-hint__title', style: style.title },
- formattedProp.title
- ),
- ': ',
- React.createElement(
- 'span',
- { className: 'rv-hint__value', style: style.value },
- formattedProp.value
- )
- );
- })
- )
- );
- }
- }], [{
- key: 'defaultProps',
- get: function get() {
- return {
- format: defaultFormat,
- align: {
- horizontal: ALIGN.AUTO,
- vertical: ALIGN.AUTO
- },
- style: {}
- };
- }
- }, {
- key: 'propTypes',
- get: function get() {
- return {
- marginTop: PropTypes.number,
- marginLeft: PropTypes.number,
- innerWidth: PropTypes.number,
- innerHeight: PropTypes.number,
- scales: PropTypes.object,
- value: PropTypes.object,
- format: PropTypes.func,
- style: PropTypes.object,
- className: PropTypes.string,
- align: PropTypes.shape({
- horizontal: PropTypes.oneOf([ALIGN.AUTO, ALIGN.LEFT, ALIGN.RIGHT, ALIGN.LEFT_EDGE, ALIGN.RIGHT_EDGE]),
- vertical: PropTypes.oneOf([ALIGN.AUTO, ALIGN.BOTTOM, ALIGN.TOP, ALIGN.BOTTOM_EDGE, ALIGN.TOP_EDGE])
- }),
- getAlignStyle: PropTypes.func,
- orientation: PropTypes.oneOf([ORIENTATION.BOTTOM_LEFT, ORIENTATION.BOTTOM_RIGHT, ORIENTATION.TOP_LEFT, ORIENTATION.TOP_RIGHT])
- };
- }
- }]);
-
- return Hint;
- }(PureComponent);
-
- Hint.displayName = 'Hint';
- Hint.ORIENTATION = ORIENTATION;
- Hint.ALIGN = ALIGN;
-
- export default Hint;
|