Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 

458 рядки
15 KiB

  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. 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; };
  6. 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; }; }();
  7. var _react = require('react');
  8. var _react2 = _interopRequireDefault(_react);
  9. var _propTypes = require('prop-types');
  10. var _propTypes2 = _interopRequireDefault(_propTypes);
  11. var _dataUtils = require('../utils/data-utils');
  12. var _scalesUtils = require('../utils/scales-utils');
  13. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  14. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  15. 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; }
  16. 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.
  17. //
  18. // Permission is hereby granted, free of charge, to any person obtaining a copy
  19. // of this software and associated documentation files (the "Software"), to deal
  20. // in the Software without restriction, including without limitation the rights
  21. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  22. // copies of the Software, and to permit persons to whom the Software is
  23. // furnished to do so, subject to the following conditions:
  24. //
  25. // The above copyright notice and this permission notice shall be included in
  26. // all copies or substantial portions of the Software.
  27. //
  28. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  29. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  30. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  31. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  32. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  33. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  34. // THE SOFTWARE.
  35. /*
  36. * Hint provides two options for placement of hint:
  37. * a) around a data point in one of four quadrants (imagine the point bisected
  38. * by two axes -vertical, horizontal- creating 4 quadrants around a data
  39. * point).
  40. * b) **New** pin to an edge of chart/plot area and position along that edge
  41. * using data point's other dimension value.
  42. *
  43. * To support these two options, deprecate one Hint props (orientation) with two
  44. * new Hint align prop object (horizontal, vertical) with following values:
  45. *
  46. * horizontal: auto, left, right, leftEdge, rightEdge
  47. * vertical: auto, bottom, top, bottomEdge, topEdge
  48. *
  49. * Thus, the following ALIGN constants are the values for horizontal
  50. * and vertical
  51. */
  52. var ALIGN = {
  53. AUTO: 'auto',
  54. LEFT: 'left',
  55. RIGHT: 'right',
  56. LEFT_EDGE: 'leftEdge',
  57. RIGHT_EDGE: 'rightEdge',
  58. BOTTOM: 'bottom',
  59. TOP: 'top',
  60. BOTTOM_EDGE: 'bottomEdge',
  61. TOP_EDGE: 'topEdge'
  62. };
  63. /**
  64. * For backwards support, retain the ORIENTATION prop constants
  65. */
  66. var ORIENTATION = {
  67. BOTTOM_LEFT: 'bottomleft',
  68. BOTTOM_RIGHT: 'bottomright',
  69. TOP_LEFT: 'topleft',
  70. TOP_RIGHT: 'topright'
  71. };
  72. /**
  73. * Default format function for the value.
  74. * @param {Object} value Value.
  75. * @returns {Array} title-value pairs.
  76. */
  77. function defaultFormat(value) {
  78. return Object.keys(value).map(function getProp(key) {
  79. return { title: key, value: (0, _dataUtils.transformValueToString)(value[key]) };
  80. });
  81. }
  82. var Hint = function (_PureComponent) {
  83. _inherits(Hint, _PureComponent);
  84. function Hint() {
  85. _classCallCheck(this, Hint);
  86. return _possibleConstructorReturn(this, (Hint.__proto__ || Object.getPrototypeOf(Hint)).apply(this, arguments));
  87. }
  88. _createClass(Hint, [{
  89. key: '_getAlign',
  90. /**
  91. * Obtain align object with horizontal and vertical settings
  92. * but convert any AUTO values to the non-auto ALIGN depending on the
  93. * values of x and y.
  94. * @param {number} x X value.
  95. * @param {number} y Y value.
  96. * @returns {Object} Align object w/ horizontal, vertical prop strings.
  97. * @private
  98. */
  99. value: function _getAlign(x, y) {
  100. var _props = this.props,
  101. innerWidth = _props.innerWidth,
  102. innerHeight = _props.innerHeight,
  103. orientation = _props.orientation,
  104. _props$align = _props.align,
  105. horizontal = _props$align.horizontal,
  106. vertical = _props$align.vertical;
  107. var align = orientation ? this._mapOrientationToAlign(orientation) : { horizontal: horizontal, vertical: vertical };
  108. if (horizontal === ALIGN.AUTO) {
  109. align.horizontal = x > innerWidth / 2 ? ALIGN.LEFT : ALIGN.RIGHT;
  110. }
  111. if (vertical === ALIGN.AUTO) {
  112. align.vertical = y > innerHeight / 2 ? ALIGN.TOP : ALIGN.BOTTOM;
  113. }
  114. return align;
  115. }
  116. /**
  117. * Get the class names from align values.
  118. * @param {Object} align object with horizontal and vertical prop strings.
  119. * @returns {string} Class names.
  120. * @private
  121. */
  122. }, {
  123. key: '_getAlignClassNames',
  124. value: function _getAlignClassNames(align) {
  125. var orientation = this.props.orientation;
  126. var orientationClass = orientation ? 'rv-hint--orientation-' + orientation : '';
  127. return orientationClass + ' rv-hint--horizontalAlign-' + align.horizontal + '\n rv-hint--verticalAlign-' + align.vertical;
  128. }
  129. /**
  130. * Get a CSS mixin for a proper positioning of the element.
  131. * @param {Object} align object with horizontal and vertical prop strings.
  132. * @param {number} x X position.
  133. * @param {number} y Y position.
  134. * @returns {Object} Object, that may contain `left` or `right, `top` or
  135. * `bottom` properties.
  136. * @private
  137. */
  138. }, {
  139. key: '_getAlignStyle',
  140. value: function _getAlignStyle(align, x, y) {
  141. return _extends({}, this._getXCSS(align.horizontal, x), this._getYCSS(align.vertical, y));
  142. }
  143. /**
  144. * Get the bottom coordinate of the hint.
  145. * When y undefined or null, edge case, pin bottom.
  146. * @param {number} y Y.
  147. * @returns {{bottom: *}} Mixin.
  148. * @private
  149. */
  150. }, {
  151. key: '_getCSSBottom',
  152. value: function _getCSSBottom(y) {
  153. if (y === undefined || y === null) {
  154. return {
  155. bottom: 0
  156. };
  157. }
  158. var _props2 = this.props,
  159. innerHeight = _props2.innerHeight,
  160. marginBottom = _props2.marginBottom;
  161. return {
  162. bottom: marginBottom + innerHeight - y
  163. };
  164. }
  165. /**
  166. * Get the left coordinate of the hint.
  167. * When x undefined or null, edge case, pin left.
  168. * @param {number} x X.
  169. * @returns {{left: *}} Mixin.
  170. * @private
  171. */
  172. }, {
  173. key: '_getCSSLeft',
  174. value: function _getCSSLeft(x) {
  175. if (x === undefined || x === null) {
  176. return {
  177. left: 0
  178. };
  179. }
  180. var marginLeft = this.props.marginLeft;
  181. return {
  182. left: marginLeft + x
  183. };
  184. }
  185. /**
  186. * Get the right coordinate of the hint.
  187. * When x undefined or null, edge case, pin right.
  188. * @param {number} x X.
  189. * @returns {{right: *}} Mixin.
  190. * @private
  191. */
  192. }, {
  193. key: '_getCSSRight',
  194. value: function _getCSSRight(x) {
  195. if (x === undefined || x === null) {
  196. return {
  197. right: 0
  198. };
  199. }
  200. var _props3 = this.props,
  201. innerWidth = _props3.innerWidth,
  202. marginRight = _props3.marginRight;
  203. return {
  204. right: marginRight + innerWidth - x
  205. };
  206. }
  207. /**
  208. * Get the top coordinate of the hint.
  209. * When y undefined or null, edge case, pin top.
  210. * @param {number} y Y.
  211. * @returns {{top: *}} Mixin.
  212. * @private
  213. */
  214. }, {
  215. key: '_getCSSTop',
  216. value: function _getCSSTop(y) {
  217. if (y === undefined || y === null) {
  218. return {
  219. top: 0
  220. };
  221. }
  222. var marginTop = this.props.marginTop;
  223. return {
  224. top: marginTop + y
  225. };
  226. }
  227. /**
  228. * Get the position for the hint and the appropriate class name.
  229. * @returns {{style: Object, positionClassName: string}} Style and className for the
  230. * hint.
  231. * @private
  232. */
  233. }, {
  234. key: '_getPositionInfo',
  235. value: function _getPositionInfo() {
  236. var _props4 = this.props,
  237. value = _props4.value,
  238. getAlignStyle = _props4.getAlignStyle;
  239. var x = (0, _scalesUtils.getAttributeFunctor)(this.props, 'x')(value);
  240. var y = (0, _scalesUtils.getAttributeFunctor)(this.props, 'y')(value);
  241. var align = this._getAlign(x, y);
  242. return {
  243. position: getAlignStyle ? getAlignStyle(align, x, y) : this._getAlignStyle(align, x, y),
  244. positionClassName: this._getAlignClassNames(align)
  245. };
  246. }
  247. }, {
  248. key: '_getXCSS',
  249. value: function _getXCSS(horizontal, x) {
  250. // obtain xCSS
  251. switch (horizontal) {
  252. case ALIGN.LEFT_EDGE:
  253. // this pins x to left edge
  254. return this._getCSSLeft(null);
  255. case ALIGN.RIGHT_EDGE:
  256. // this pins x to left edge
  257. return this._getCSSRight(null);
  258. case ALIGN.LEFT:
  259. // this places hint text to the left of center, so set its right edge
  260. return this._getCSSRight(x);
  261. case ALIGN.RIGHT:
  262. default:
  263. // this places hint text to the right of center, so set its left edge
  264. // default case should not be possible but if it happens set to RIGHT
  265. return this._getCSSLeft(x);
  266. }
  267. }
  268. }, {
  269. key: '_getYCSS',
  270. value: function _getYCSS(verticalAlign, y) {
  271. // obtain yCSS
  272. switch (verticalAlign) {
  273. case ALIGN.TOP_EDGE:
  274. // this pins x to top edge
  275. return this._getCSSTop(null);
  276. case ALIGN.BOTTOM_EDGE:
  277. // this pins x to bottom edge
  278. return this._getCSSBottom(null);
  279. case ALIGN.BOTTOM:
  280. // this places hint text to the bottom of center, so set its top edge
  281. return this._getCSSTop(y);
  282. case ALIGN.TOP:
  283. default:
  284. // this places hint text to the top of center, so set its bottom edge
  285. // default case should not be possible but if it happens set to BOTTOM
  286. return this._getCSSBottom(y);
  287. }
  288. }
  289. }, {
  290. key: '_mapOrientationToAlign',
  291. value: function _mapOrientationToAlign(orientation) {
  292. // TODO: print warning that this feature is deprecated and support will be
  293. // removed in next major release.
  294. switch (orientation) {
  295. case ORIENTATION.BOTTOM_LEFT:
  296. return {
  297. horizontal: ALIGN.LEFT,
  298. vertical: ALIGN.BOTTOM
  299. };
  300. case ORIENTATION.BOTTOM_RIGHT:
  301. return {
  302. horizontal: ALIGN.RIGHT,
  303. vertical: ALIGN.BOTTOM
  304. };
  305. case ORIENTATION.TOP_LEFT:
  306. return {
  307. horizontal: ALIGN.LEFT,
  308. vertical: ALIGN.TOP
  309. };
  310. case ORIENTATION.TOP_RIGHT:
  311. return {
  312. horizontal: ALIGN.RIGHT,
  313. vertical: ALIGN.TOP
  314. };
  315. default:
  316. // fall back to horizontalAlign, verticalAlign that are either
  317. // provided or defaulted to AUTO. So, don't change things
  318. break;
  319. }
  320. }
  321. }, {
  322. key: 'render',
  323. value: function render() {
  324. var _props5 = this.props,
  325. value = _props5.value,
  326. format = _props5.format,
  327. children = _props5.children,
  328. style = _props5.style,
  329. className = _props5.className;
  330. var _getPositionInfo2 = this._getPositionInfo(),
  331. position = _getPositionInfo2.position,
  332. positionClassName = _getPositionInfo2.positionClassName;
  333. return _react2.default.createElement(
  334. 'div',
  335. {
  336. className: 'rv-hint ' + positionClassName + ' ' + className,
  337. style: _extends({}, style, position, {
  338. position: 'absolute'
  339. })
  340. },
  341. children ? children : _react2.default.createElement(
  342. 'div',
  343. { className: 'rv-hint__content', style: style.content },
  344. format(value).map(function (formattedProp, i) {
  345. return _react2.default.createElement(
  346. 'div',
  347. { key: 'rv-hint' + i, style: style.row },
  348. _react2.default.createElement(
  349. 'span',
  350. { className: 'rv-hint__title', style: style.title },
  351. formattedProp.title
  352. ),
  353. ': ',
  354. _react2.default.createElement(
  355. 'span',
  356. { className: 'rv-hint__value', style: style.value },
  357. formattedProp.value
  358. )
  359. );
  360. })
  361. )
  362. );
  363. }
  364. }], [{
  365. key: 'defaultProps',
  366. get: function get() {
  367. return {
  368. format: defaultFormat,
  369. align: {
  370. horizontal: ALIGN.AUTO,
  371. vertical: ALIGN.AUTO
  372. },
  373. style: {}
  374. };
  375. }
  376. }, {
  377. key: 'propTypes',
  378. get: function get() {
  379. return {
  380. marginTop: _propTypes2.default.number,
  381. marginLeft: _propTypes2.default.number,
  382. innerWidth: _propTypes2.default.number,
  383. innerHeight: _propTypes2.default.number,
  384. scales: _propTypes2.default.object,
  385. value: _propTypes2.default.object,
  386. format: _propTypes2.default.func,
  387. style: _propTypes2.default.object,
  388. className: _propTypes2.default.string,
  389. align: _propTypes2.default.shape({
  390. horizontal: _propTypes2.default.oneOf([ALIGN.AUTO, ALIGN.LEFT, ALIGN.RIGHT, ALIGN.LEFT_EDGE, ALIGN.RIGHT_EDGE]),
  391. vertical: _propTypes2.default.oneOf([ALIGN.AUTO, ALIGN.BOTTOM, ALIGN.TOP, ALIGN.BOTTOM_EDGE, ALIGN.TOP_EDGE])
  392. }),
  393. getAlignStyle: _propTypes2.default.func,
  394. orientation: _propTypes2.default.oneOf([ORIENTATION.BOTTOM_LEFT, ORIENTATION.BOTTOM_RIGHT, ORIENTATION.TOP_LEFT, ORIENTATION.TOP_RIGHT])
  395. };
  396. }
  397. }]);
  398. return Hint;
  399. }(_react.PureComponent);
  400. Hint.displayName = 'Hint';
  401. Hint.ORIENTATION = ORIENTATION;
  402. Hint.ALIGN = ALIGN;
  403. exports.default = Hint;