CartesianGrid.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.CartesianGrid = CartesianGrid;
  6. var _react = _interopRequireDefault(require("react"));
  7. var _isFunction = _interopRequireDefault(require("lodash/isFunction"));
  8. var _LogUtils = require("../util/LogUtils");
  9. var _DataUtils = require("../util/DataUtils");
  10. var _ReactUtils = require("../util/ReactUtils");
  11. var _ChartUtils = require("../util/ChartUtils");
  12. var _getTicks = require("./getTicks");
  13. var _CartesianAxis = require("./CartesianAxis");
  14. var _chartLayoutContext = require("../context/chartLayoutContext");
  15. var _excluded = ["x1", "y1", "x2", "y2", "key"],
  16. _excluded2 = ["offset"];
  17. /**
  18. * @fileOverview Cartesian Grid
  19. */
  20. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
  21. function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
  22. function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
  23. function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
  24. function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  25. function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
  26. 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); }
  27. function _extends() { _extends = Object.assign ? Object.assign.bind() : 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); }
  28. function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
  29. function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } } return target; }
  30. /**
  31. * The <CartesianGrid horizontal
  32. */
  33. var Background = function Background(props) {
  34. var fill = props.fill;
  35. if (!fill || fill === 'none') {
  36. return null;
  37. }
  38. var fillOpacity = props.fillOpacity,
  39. x = props.x,
  40. y = props.y,
  41. width = props.width,
  42. height = props.height,
  43. ry = props.ry;
  44. return /*#__PURE__*/_react["default"].createElement("rect", {
  45. x: x,
  46. y: y,
  47. ry: ry,
  48. width: width,
  49. height: height,
  50. stroke: "none",
  51. fill: fill,
  52. fillOpacity: fillOpacity,
  53. className: "recharts-cartesian-grid-bg"
  54. });
  55. };
  56. function renderLineItem(option, props) {
  57. var lineItem;
  58. if ( /*#__PURE__*/_react["default"].isValidElement(option)) {
  59. // @ts-expect-error typescript does not see the props type when cloning an element
  60. lineItem = /*#__PURE__*/_react["default"].cloneElement(option, props);
  61. } else if ((0, _isFunction["default"])(option)) {
  62. lineItem = option(props);
  63. } else {
  64. var x1 = props.x1,
  65. y1 = props.y1,
  66. x2 = props.x2,
  67. y2 = props.y2,
  68. key = props.key,
  69. others = _objectWithoutProperties(props, _excluded);
  70. var _filterProps = (0, _ReactUtils.filterProps)(others, false),
  71. __ = _filterProps.offset,
  72. restOfFilteredProps = _objectWithoutProperties(_filterProps, _excluded2);
  73. lineItem = /*#__PURE__*/_react["default"].createElement("line", _extends({}, restOfFilteredProps, {
  74. x1: x1,
  75. y1: y1,
  76. x2: x2,
  77. y2: y2,
  78. fill: "none",
  79. key: key
  80. }));
  81. }
  82. return lineItem;
  83. }
  84. function HorizontalGridLines(props) {
  85. var x = props.x,
  86. width = props.width,
  87. _props$horizontal = props.horizontal,
  88. horizontal = _props$horizontal === void 0 ? true : _props$horizontal,
  89. horizontalPoints = props.horizontalPoints;
  90. if (!horizontal || !horizontalPoints || !horizontalPoints.length) {
  91. return null;
  92. }
  93. var items = horizontalPoints.map(function (entry, i) {
  94. var lineItemProps = _objectSpread(_objectSpread({}, props), {}, {
  95. x1: x,
  96. y1: entry,
  97. x2: x + width,
  98. y2: entry,
  99. key: "line-".concat(i),
  100. index: i
  101. });
  102. return renderLineItem(horizontal, lineItemProps);
  103. });
  104. return /*#__PURE__*/_react["default"].createElement("g", {
  105. className: "recharts-cartesian-grid-horizontal"
  106. }, items);
  107. }
  108. function VerticalGridLines(props) {
  109. var y = props.y,
  110. height = props.height,
  111. _props$vertical = props.vertical,
  112. vertical = _props$vertical === void 0 ? true : _props$vertical,
  113. verticalPoints = props.verticalPoints;
  114. if (!vertical || !verticalPoints || !verticalPoints.length) {
  115. return null;
  116. }
  117. var items = verticalPoints.map(function (entry, i) {
  118. var lineItemProps = _objectSpread(_objectSpread({}, props), {}, {
  119. x1: entry,
  120. y1: y,
  121. x2: entry,
  122. y2: y + height,
  123. key: "line-".concat(i),
  124. index: i
  125. });
  126. return renderLineItem(vertical, lineItemProps);
  127. });
  128. return /*#__PURE__*/_react["default"].createElement("g", {
  129. className: "recharts-cartesian-grid-vertical"
  130. }, items);
  131. }
  132. function HorizontalStripes(props) {
  133. var horizontalFill = props.horizontalFill,
  134. fillOpacity = props.fillOpacity,
  135. x = props.x,
  136. y = props.y,
  137. width = props.width,
  138. height = props.height,
  139. horizontalPoints = props.horizontalPoints,
  140. _props$horizontal2 = props.horizontal,
  141. horizontal = _props$horizontal2 === void 0 ? true : _props$horizontal2;
  142. if (!horizontal || !horizontalFill || !horizontalFill.length) {
  143. return null;
  144. }
  145. // Why =y -y? I was trying to find any difference that this makes, with floating point numbers and edge cases but ... nothing.
  146. var roundedSortedHorizontalPoints = horizontalPoints.map(function (e) {
  147. return Math.round(e + y - y);
  148. }).sort(function (a, b) {
  149. return a - b;
  150. });
  151. // Why is this condition `!==` instead of `<=` ?
  152. if (y !== roundedSortedHorizontalPoints[0]) {
  153. roundedSortedHorizontalPoints.unshift(0);
  154. }
  155. var items = roundedSortedHorizontalPoints.map(function (entry, i) {
  156. // Why do we strip only the last stripe if it is invisible, and not all invisible stripes?
  157. var lastStripe = !roundedSortedHorizontalPoints[i + 1];
  158. var lineHeight = lastStripe ? y + height - entry : roundedSortedHorizontalPoints[i + 1] - entry;
  159. if (lineHeight <= 0) {
  160. return null;
  161. }
  162. var colorIndex = i % horizontalFill.length;
  163. return /*#__PURE__*/_react["default"].createElement("rect", {
  164. key: "react-".concat(i) // eslint-disable-line react/no-array-index-key
  165. ,
  166. y: entry,
  167. x: x,
  168. height: lineHeight,
  169. width: width,
  170. stroke: "none",
  171. fill: horizontalFill[colorIndex],
  172. fillOpacity: fillOpacity,
  173. className: "recharts-cartesian-grid-bg"
  174. });
  175. });
  176. return /*#__PURE__*/_react["default"].createElement("g", {
  177. className: "recharts-cartesian-gridstripes-horizontal"
  178. }, items);
  179. }
  180. function VerticalStripes(props) {
  181. var _props$vertical2 = props.vertical,
  182. vertical = _props$vertical2 === void 0 ? true : _props$vertical2,
  183. verticalFill = props.verticalFill,
  184. fillOpacity = props.fillOpacity,
  185. x = props.x,
  186. y = props.y,
  187. width = props.width,
  188. height = props.height,
  189. verticalPoints = props.verticalPoints;
  190. if (!vertical || !verticalFill || !verticalFill.length) {
  191. return null;
  192. }
  193. var roundedSortedVerticalPoints = verticalPoints.map(function (e) {
  194. return Math.round(e + x - x);
  195. }).sort(function (a, b) {
  196. return a - b;
  197. });
  198. if (x !== roundedSortedVerticalPoints[0]) {
  199. roundedSortedVerticalPoints.unshift(0);
  200. }
  201. var items = roundedSortedVerticalPoints.map(function (entry, i) {
  202. var lastStripe = !roundedSortedVerticalPoints[i + 1];
  203. var lineWidth = lastStripe ? x + width - entry : roundedSortedVerticalPoints[i + 1] - entry;
  204. if (lineWidth <= 0) {
  205. return null;
  206. }
  207. var colorIndex = i % verticalFill.length;
  208. return /*#__PURE__*/_react["default"].createElement("rect", {
  209. key: "react-".concat(i) // eslint-disable-line react/no-array-index-key
  210. ,
  211. x: entry,
  212. y: y,
  213. width: lineWidth,
  214. height: height,
  215. stroke: "none",
  216. fill: verticalFill[colorIndex],
  217. fillOpacity: fillOpacity,
  218. className: "recharts-cartesian-grid-bg"
  219. });
  220. });
  221. return /*#__PURE__*/_react["default"].createElement("g", {
  222. className: "recharts-cartesian-gridstripes-vertical"
  223. }, items);
  224. }
  225. var defaultVerticalCoordinatesGenerator = function defaultVerticalCoordinatesGenerator(_ref, syncWithTicks) {
  226. var xAxis = _ref.xAxis,
  227. width = _ref.width,
  228. height = _ref.height,
  229. offset = _ref.offset;
  230. return (0, _ChartUtils.getCoordinatesOfGrid)((0, _getTicks.getTicks)(_objectSpread(_objectSpread(_objectSpread({}, _CartesianAxis.CartesianAxis.defaultProps), xAxis), {}, {
  231. ticks: (0, _ChartUtils.getTicksOfAxis)(xAxis, true),
  232. viewBox: {
  233. x: 0,
  234. y: 0,
  235. width: width,
  236. height: height
  237. }
  238. })), offset.left, offset.left + offset.width, syncWithTicks);
  239. };
  240. var defaultHorizontalCoordinatesGenerator = function defaultHorizontalCoordinatesGenerator(_ref2, syncWithTicks) {
  241. var yAxis = _ref2.yAxis,
  242. width = _ref2.width,
  243. height = _ref2.height,
  244. offset = _ref2.offset;
  245. return (0, _ChartUtils.getCoordinatesOfGrid)((0, _getTicks.getTicks)(_objectSpread(_objectSpread(_objectSpread({}, _CartesianAxis.CartesianAxis.defaultProps), yAxis), {}, {
  246. ticks: (0, _ChartUtils.getTicksOfAxis)(yAxis, true),
  247. viewBox: {
  248. x: 0,
  249. y: 0,
  250. width: width,
  251. height: height
  252. }
  253. })), offset.top, offset.top + offset.height, syncWithTicks);
  254. };
  255. var defaultProps = {
  256. horizontal: true,
  257. vertical: true,
  258. // The ordinates of horizontal grid lines
  259. horizontalPoints: [],
  260. // The abscissas of vertical grid lines
  261. verticalPoints: [],
  262. stroke: '#ccc',
  263. fill: 'none',
  264. // The fill of colors of grid lines
  265. verticalFill: [],
  266. horizontalFill: []
  267. };
  268. function CartesianGrid(props) {
  269. var _props$stroke, _props$fill, _props$horizontal3, _props$horizontalFill, _props$vertical3, _props$verticalFill;
  270. var chartWidth = (0, _chartLayoutContext.useChartWidth)();
  271. var chartHeight = (0, _chartLayoutContext.useChartHeight)();
  272. var offset = (0, _chartLayoutContext.useOffset)();
  273. var propsIncludingDefaults = _objectSpread(_objectSpread({}, props), {}, {
  274. stroke: (_props$stroke = props.stroke) !== null && _props$stroke !== void 0 ? _props$stroke : defaultProps.stroke,
  275. fill: (_props$fill = props.fill) !== null && _props$fill !== void 0 ? _props$fill : defaultProps.fill,
  276. horizontal: (_props$horizontal3 = props.horizontal) !== null && _props$horizontal3 !== void 0 ? _props$horizontal3 : defaultProps.horizontal,
  277. horizontalFill: (_props$horizontalFill = props.horizontalFill) !== null && _props$horizontalFill !== void 0 ? _props$horizontalFill : defaultProps.horizontalFill,
  278. vertical: (_props$vertical3 = props.vertical) !== null && _props$vertical3 !== void 0 ? _props$vertical3 : defaultProps.vertical,
  279. verticalFill: (_props$verticalFill = props.verticalFill) !== null && _props$verticalFill !== void 0 ? _props$verticalFill : defaultProps.verticalFill,
  280. x: (0, _DataUtils.isNumber)(props.x) ? props.x : offset.left,
  281. y: (0, _DataUtils.isNumber)(props.y) ? props.y : offset.top,
  282. width: (0, _DataUtils.isNumber)(props.width) ? props.width : offset.width,
  283. height: (0, _DataUtils.isNumber)(props.height) ? props.height : offset.height
  284. });
  285. var x = propsIncludingDefaults.x,
  286. y = propsIncludingDefaults.y,
  287. width = propsIncludingDefaults.width,
  288. height = propsIncludingDefaults.height,
  289. syncWithTicks = propsIncludingDefaults.syncWithTicks,
  290. horizontalValues = propsIncludingDefaults.horizontalValues,
  291. verticalValues = propsIncludingDefaults.verticalValues;
  292. // @ts-expect-error the scale prop is mixed up - we need to untagle this at some point
  293. var xAxis = (0, _chartLayoutContext.useArbitraryXAxis)();
  294. // @ts-expect-error the scale prop is mixed up - we need to untagle this at some point
  295. var yAxis = (0, _chartLayoutContext.useYAxisWithFiniteDomainOrRandom)();
  296. if (!(0, _DataUtils.isNumber)(width) || width <= 0 || !(0, _DataUtils.isNumber)(height) || height <= 0 || !(0, _DataUtils.isNumber)(x) || x !== +x || !(0, _DataUtils.isNumber)(y) || y !== +y) {
  297. return null;
  298. }
  299. /*
  300. * verticalCoordinatesGenerator and horizontalCoordinatesGenerator are defined
  301. * outside of the propsIncludingDefaults because they were never part of the original props
  302. * and they were never passed as a prop down to horizontal/vertical custom elements.
  303. * If we add these two to propsIncludingDefaults then we are changing public API.
  304. * Not a bad thing per se but also not necessary.
  305. */
  306. var verticalCoordinatesGenerator = propsIncludingDefaults.verticalCoordinatesGenerator || defaultVerticalCoordinatesGenerator;
  307. var horizontalCoordinatesGenerator = propsIncludingDefaults.horizontalCoordinatesGenerator || defaultHorizontalCoordinatesGenerator;
  308. var horizontalPoints = propsIncludingDefaults.horizontalPoints,
  309. verticalPoints = propsIncludingDefaults.verticalPoints;
  310. // No horizontal points are specified
  311. if ((!horizontalPoints || !horizontalPoints.length) && (0, _isFunction["default"])(horizontalCoordinatesGenerator)) {
  312. var isHorizontalValues = horizontalValues && horizontalValues.length;
  313. var generatorResult = horizontalCoordinatesGenerator({
  314. yAxis: yAxis ? _objectSpread(_objectSpread({}, yAxis), {}, {
  315. ticks: isHorizontalValues ? horizontalValues : yAxis.ticks
  316. }) : undefined,
  317. width: chartWidth,
  318. height: chartHeight,
  319. offset: offset
  320. }, isHorizontalValues ? true : syncWithTicks);
  321. (0, _LogUtils.warn)(Array.isArray(generatorResult), "horizontalCoordinatesGenerator should return Array but instead it returned [".concat(_typeof(generatorResult), "]"));
  322. if (Array.isArray(generatorResult)) {
  323. horizontalPoints = generatorResult;
  324. }
  325. }
  326. // No vertical points are specified
  327. if ((!verticalPoints || !verticalPoints.length) && (0, _isFunction["default"])(verticalCoordinatesGenerator)) {
  328. var isVerticalValues = verticalValues && verticalValues.length;
  329. var _generatorResult = verticalCoordinatesGenerator({
  330. xAxis: xAxis ? _objectSpread(_objectSpread({}, xAxis), {}, {
  331. ticks: isVerticalValues ? verticalValues : xAxis.ticks
  332. }) : undefined,
  333. width: chartWidth,
  334. height: chartHeight,
  335. offset: offset
  336. }, isVerticalValues ? true : syncWithTicks);
  337. (0, _LogUtils.warn)(Array.isArray(_generatorResult), "verticalCoordinatesGenerator should return Array but instead it returned [".concat(_typeof(_generatorResult), "]"));
  338. if (Array.isArray(_generatorResult)) {
  339. verticalPoints = _generatorResult;
  340. }
  341. }
  342. return /*#__PURE__*/_react["default"].createElement("g", {
  343. className: "recharts-cartesian-grid"
  344. }, /*#__PURE__*/_react["default"].createElement(Background, {
  345. fill: propsIncludingDefaults.fill,
  346. fillOpacity: propsIncludingDefaults.fillOpacity,
  347. x: propsIncludingDefaults.x,
  348. y: propsIncludingDefaults.y,
  349. width: propsIncludingDefaults.width,
  350. height: propsIncludingDefaults.height,
  351. ry: propsIncludingDefaults.ry
  352. }), /*#__PURE__*/_react["default"].createElement(HorizontalGridLines, _extends({}, propsIncludingDefaults, {
  353. offset: offset,
  354. horizontalPoints: horizontalPoints,
  355. xAxis: xAxis,
  356. yAxis: yAxis
  357. })), /*#__PURE__*/_react["default"].createElement(VerticalGridLines, _extends({}, propsIncludingDefaults, {
  358. offset: offset,
  359. verticalPoints: verticalPoints,
  360. xAxis: xAxis,
  361. yAxis: yAxis
  362. })), /*#__PURE__*/_react["default"].createElement(HorizontalStripes, _extends({}, propsIncludingDefaults, {
  363. horizontalPoints: horizontalPoints
  364. })), /*#__PURE__*/_react["default"].createElement(VerticalStripes, _extends({}, propsIncludingDefaults, {
  365. verticalPoints: verticalPoints
  366. })));
  367. }
  368. CartesianGrid.displayName = 'CartesianGrid';