ChartUtils.js 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061
  1. 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); }
  2. function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
  3. function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
  4. function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
  5. function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
  6. function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
  7. function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
  8. 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; }
  9. 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; }
  10. 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; }
  11. function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
  12. 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); }
  13. import * as d3Scales from 'victory-vendor/d3-scale';
  14. import { stack as shapeStack, stackOffsetExpand, stackOffsetNone, stackOffsetSilhouette, stackOffsetWiggle, stackOrderNone } from 'victory-vendor/d3-shape';
  15. import max from 'lodash/max';
  16. import min from 'lodash/min';
  17. import isNil from 'lodash/isNil';
  18. import isFunction from 'lodash/isFunction';
  19. import isString from 'lodash/isString';
  20. import get from 'lodash/get';
  21. import flatMap from 'lodash/flatMap';
  22. import isNan from 'lodash/isNaN';
  23. import upperFirst from 'lodash/upperFirst';
  24. import isEqual from 'lodash/isEqual';
  25. import sortBy from 'lodash/sortBy';
  26. import { getNiceTickValues, getTickValuesFixedDomain } from 'recharts-scale';
  27. import { ErrorBar } from '../cartesian/ErrorBar';
  28. import { findEntryInArray, getPercentValue, isNumber, isNumOrStr, mathSign, uniqueId } from './DataUtils';
  29. import { filterProps, findAllByType, getDisplayName } from './ReactUtils';
  30. // TODO: Cause of circular dependency. Needs refactor.
  31. // import { RadiusAxisProps, AngleAxisProps } from '../polar/types';
  32. import { getLegendProps } from './getLegendProps';
  33. // Exported for backwards compatibility
  34. export { getLegendProps };
  35. export function getValueByDataKey(obj, dataKey, defaultValue) {
  36. if (isNil(obj) || isNil(dataKey)) {
  37. return defaultValue;
  38. }
  39. if (isNumOrStr(dataKey)) {
  40. return get(obj, dataKey, defaultValue);
  41. }
  42. if (isFunction(dataKey)) {
  43. return dataKey(obj);
  44. }
  45. return defaultValue;
  46. }
  47. /**
  48. * Get domain of data by key.
  49. * @param {Array} data The data displayed in the chart
  50. * @param {String} key The unique key of a group of data
  51. * @param {String} type The type of axis
  52. * @param {Boolean} filterNil Whether or not filter nil values
  53. * @return {Array} Domain of data
  54. */
  55. export function getDomainOfDataByKey(data, key, type, filterNil) {
  56. var flattenData = flatMap(data, function (entry) {
  57. return getValueByDataKey(entry, key);
  58. });
  59. if (type === 'number') {
  60. // @ts-expect-error parseFloat type only accepts strings
  61. var domain = flattenData.filter(function (entry) {
  62. return isNumber(entry) || parseFloat(entry);
  63. });
  64. return domain.length ? [min(domain), max(domain)] : [Infinity, -Infinity];
  65. }
  66. var validateData = filterNil ? flattenData.filter(function (entry) {
  67. return !isNil(entry);
  68. }) : flattenData;
  69. // Supports x-axis of Date type
  70. return validateData.map(function (entry) {
  71. return isNumOrStr(entry) || entry instanceof Date ? entry : '';
  72. });
  73. }
  74. export var calculateActiveTickIndex = function calculateActiveTickIndex(coordinate) {
  75. var _ticks$length;
  76. var ticks = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  77. var unsortedTicks = arguments.length > 2 ? arguments[2] : undefined;
  78. var axis = arguments.length > 3 ? arguments[3] : undefined;
  79. var index = -1;
  80. var len = (_ticks$length = ticks === null || ticks === void 0 ? void 0 : ticks.length) !== null && _ticks$length !== void 0 ? _ticks$length : 0;
  81. // if there are 1 or less ticks ticks then the active tick is at index 0
  82. if (len <= 1) {
  83. return 0;
  84. }
  85. if (axis && axis.axisType === 'angleAxis' && Math.abs(Math.abs(axis.range[1] - axis.range[0]) - 360) <= 1e-6) {
  86. var range = axis.range;
  87. // ticks are distributed in a circle
  88. for (var i = 0; i < len; i++) {
  89. var before = i > 0 ? unsortedTicks[i - 1].coordinate : unsortedTicks[len - 1].coordinate;
  90. var cur = unsortedTicks[i].coordinate;
  91. var after = i >= len - 1 ? unsortedTicks[0].coordinate : unsortedTicks[i + 1].coordinate;
  92. var sameDirectionCoord = void 0;
  93. if (mathSign(cur - before) !== mathSign(after - cur)) {
  94. var diffInterval = [];
  95. if (mathSign(after - cur) === mathSign(range[1] - range[0])) {
  96. sameDirectionCoord = after;
  97. var curInRange = cur + range[1] - range[0];
  98. diffInterval[0] = Math.min(curInRange, (curInRange + before) / 2);
  99. diffInterval[1] = Math.max(curInRange, (curInRange + before) / 2);
  100. } else {
  101. sameDirectionCoord = before;
  102. var afterInRange = after + range[1] - range[0];
  103. diffInterval[0] = Math.min(cur, (afterInRange + cur) / 2);
  104. diffInterval[1] = Math.max(cur, (afterInRange + cur) / 2);
  105. }
  106. var sameInterval = [Math.min(cur, (sameDirectionCoord + cur) / 2), Math.max(cur, (sameDirectionCoord + cur) / 2)];
  107. if (coordinate > sameInterval[0] && coordinate <= sameInterval[1] || coordinate >= diffInterval[0] && coordinate <= diffInterval[1]) {
  108. index = unsortedTicks[i].index;
  109. break;
  110. }
  111. } else {
  112. var minValue = Math.min(before, after);
  113. var maxValue = Math.max(before, after);
  114. if (coordinate > (minValue + cur) / 2 && coordinate <= (maxValue + cur) / 2) {
  115. index = unsortedTicks[i].index;
  116. break;
  117. }
  118. }
  119. }
  120. } else {
  121. // ticks are distributed in a single direction
  122. for (var _i = 0; _i < len; _i++) {
  123. if (_i === 0 && coordinate <= (ticks[_i].coordinate + ticks[_i + 1].coordinate) / 2 || _i > 0 && _i < len - 1 && coordinate > (ticks[_i].coordinate + ticks[_i - 1].coordinate) / 2 && coordinate <= (ticks[_i].coordinate + ticks[_i + 1].coordinate) / 2 || _i === len - 1 && coordinate > (ticks[_i].coordinate + ticks[_i - 1].coordinate) / 2) {
  124. index = ticks[_i].index;
  125. break;
  126. }
  127. }
  128. }
  129. return index;
  130. };
  131. /**
  132. * Get the main color of each graphic item
  133. * @param {ReactElement} item A graphic item
  134. * @return {String} Color
  135. */
  136. export var getMainColorOfGraphicItem = function getMainColorOfGraphicItem(item) {
  137. var _item$type;
  138. var _ref = item,
  139. displayName = _ref.type.displayName; // TODO: check if displayName is valid.
  140. var defaultedProps = (_item$type = item.type) !== null && _item$type !== void 0 && _item$type.defaultProps ? _objectSpread(_objectSpread({}, item.type.defaultProps), item.props) : item.props;
  141. var stroke = defaultedProps.stroke,
  142. fill = defaultedProps.fill;
  143. var result;
  144. switch (displayName) {
  145. case 'Line':
  146. result = stroke;
  147. break;
  148. case 'Area':
  149. case 'Radar':
  150. result = stroke && stroke !== 'none' ? stroke : fill;
  151. break;
  152. default:
  153. result = fill;
  154. break;
  155. }
  156. return result;
  157. };
  158. /**
  159. * Calculate the size of all groups for stacked bar graph
  160. * @param {Object} stackGroups The items grouped by axisId and stackId
  161. * @return {Object} The size of all groups
  162. */
  163. export var getBarSizeList = function getBarSizeList(_ref2) {
  164. var globalSize = _ref2.barSize,
  165. totalSize = _ref2.totalSize,
  166. _ref2$stackGroups = _ref2.stackGroups,
  167. stackGroups = _ref2$stackGroups === void 0 ? {} : _ref2$stackGroups;
  168. if (!stackGroups) {
  169. return {};
  170. }
  171. var result = {};
  172. var numericAxisIds = Object.keys(stackGroups);
  173. for (var i = 0, len = numericAxisIds.length; i < len; i++) {
  174. var sgs = stackGroups[numericAxisIds[i]].stackGroups;
  175. var stackIds = Object.keys(sgs);
  176. for (var j = 0, sLen = stackIds.length; j < sLen; j++) {
  177. var _sgs$stackIds$j = sgs[stackIds[j]],
  178. items = _sgs$stackIds$j.items,
  179. cateAxisId = _sgs$stackIds$j.cateAxisId;
  180. var barItems = items.filter(function (item) {
  181. return getDisplayName(item.type).indexOf('Bar') >= 0;
  182. });
  183. if (barItems && barItems.length) {
  184. var barItemDefaultProps = barItems[0].type.defaultProps;
  185. var barItemProps = barItemDefaultProps !== undefined ? _objectSpread(_objectSpread({}, barItemDefaultProps), barItems[0].props) : barItems[0].props;
  186. var selfSize = barItemProps.barSize;
  187. var cateId = barItemProps[cateAxisId];
  188. if (!result[cateId]) {
  189. result[cateId] = [];
  190. }
  191. var barSize = isNil(selfSize) ? globalSize : selfSize;
  192. result[cateId].push({
  193. item: barItems[0],
  194. stackList: barItems.slice(1),
  195. barSize: isNil(barSize) ? undefined : getPercentValue(barSize, totalSize, 0)
  196. });
  197. }
  198. }
  199. }
  200. return result;
  201. };
  202. /**
  203. * Calculate the size of each bar and offset between start of band and the bar
  204. *
  205. * @param {number} bandSize is the size of area where bars can render
  206. * @param {number | string} barGap is the gap size, as a percentage of `bandSize`.
  207. * Can be defined as number or percent string
  208. * @param {number | string} barCategoryGap is the gap size, as a percentage of `bandSize`.
  209. * Can be defined as number or percent string
  210. * @param {Array<object>} sizeList Sizes of all groups
  211. * @param {number} maxBarSize The maximum size of each bar
  212. * @return {Array<object>} The size and offset of each bar
  213. */
  214. export var getBarPosition = function getBarPosition(_ref3) {
  215. var barGap = _ref3.barGap,
  216. barCategoryGap = _ref3.barCategoryGap,
  217. bandSize = _ref3.bandSize,
  218. _ref3$sizeList = _ref3.sizeList,
  219. sizeList = _ref3$sizeList === void 0 ? [] : _ref3$sizeList,
  220. maxBarSize = _ref3.maxBarSize;
  221. var len = sizeList.length;
  222. if (len < 1) return null;
  223. var realBarGap = getPercentValue(barGap, bandSize, 0, true);
  224. var result;
  225. var initialValue = [];
  226. // whether or not is barSize setted by user
  227. if (sizeList[0].barSize === +sizeList[0].barSize) {
  228. var useFull = false;
  229. var fullBarSize = bandSize / len;
  230. // @ts-expect-error the type check above does not check for type number explicitly
  231. var sum = sizeList.reduce(function (res, entry) {
  232. return res + entry.barSize || 0;
  233. }, 0);
  234. sum += (len - 1) * realBarGap;
  235. if (sum >= bandSize) {
  236. sum -= (len - 1) * realBarGap;
  237. realBarGap = 0;
  238. }
  239. if (sum >= bandSize && fullBarSize > 0) {
  240. useFull = true;
  241. fullBarSize *= 0.9;
  242. sum = len * fullBarSize;
  243. }
  244. var offset = (bandSize - sum) / 2 >> 0;
  245. var prev = {
  246. offset: offset - realBarGap,
  247. size: 0
  248. };
  249. result = sizeList.reduce(function (res, entry) {
  250. var newPosition = {
  251. item: entry.item,
  252. position: {
  253. offset: prev.offset + prev.size + realBarGap,
  254. // @ts-expect-error the type check above does not check for type number explicitly
  255. size: useFull ? fullBarSize : entry.barSize
  256. }
  257. };
  258. var newRes = [].concat(_toConsumableArray(res), [newPosition]);
  259. prev = newRes[newRes.length - 1].position;
  260. if (entry.stackList && entry.stackList.length) {
  261. entry.stackList.forEach(function (item) {
  262. newRes.push({
  263. item: item,
  264. position: prev
  265. });
  266. });
  267. }
  268. return newRes;
  269. }, initialValue);
  270. } else {
  271. var _offset = getPercentValue(barCategoryGap, bandSize, 0, true);
  272. if (bandSize - 2 * _offset - (len - 1) * realBarGap <= 0) {
  273. realBarGap = 0;
  274. }
  275. var originalSize = (bandSize - 2 * _offset - (len - 1) * realBarGap) / len;
  276. if (originalSize > 1) {
  277. originalSize >>= 0;
  278. }
  279. var size = maxBarSize === +maxBarSize ? Math.min(originalSize, maxBarSize) : originalSize;
  280. result = sizeList.reduce(function (res, entry, i) {
  281. var newRes = [].concat(_toConsumableArray(res), [{
  282. item: entry.item,
  283. position: {
  284. offset: _offset + (originalSize + realBarGap) * i + (originalSize - size) / 2,
  285. size: size
  286. }
  287. }]);
  288. if (entry.stackList && entry.stackList.length) {
  289. entry.stackList.forEach(function (item) {
  290. newRes.push({
  291. item: item,
  292. position: newRes[newRes.length - 1].position
  293. });
  294. });
  295. }
  296. return newRes;
  297. }, initialValue);
  298. }
  299. return result;
  300. };
  301. export var appendOffsetOfLegend = function appendOffsetOfLegend(offset, _unused, props, legendBox) {
  302. var children = props.children,
  303. width = props.width,
  304. margin = props.margin;
  305. var legendWidth = width - (margin.left || 0) - (margin.right || 0);
  306. var legendProps = getLegendProps({
  307. children: children,
  308. legendWidth: legendWidth
  309. });
  310. if (legendProps) {
  311. var _ref4 = legendBox || {},
  312. boxWidth = _ref4.width,
  313. boxHeight = _ref4.height;
  314. var align = legendProps.align,
  315. verticalAlign = legendProps.verticalAlign,
  316. layout = legendProps.layout;
  317. if ((layout === 'vertical' || layout === 'horizontal' && verticalAlign === 'middle') && align !== 'center' && isNumber(offset[align])) {
  318. return _objectSpread(_objectSpread({}, offset), {}, _defineProperty({}, align, offset[align] + (boxWidth || 0)));
  319. }
  320. if ((layout === 'horizontal' || layout === 'vertical' && align === 'center') && verticalAlign !== 'middle' && isNumber(offset[verticalAlign])) {
  321. return _objectSpread(_objectSpread({}, offset), {}, _defineProperty({}, verticalAlign, offset[verticalAlign] + (boxHeight || 0)));
  322. }
  323. }
  324. return offset;
  325. };
  326. var isErrorBarRelevantForAxis = function isErrorBarRelevantForAxis(layout, axisType, direction) {
  327. if (isNil(axisType)) {
  328. return true;
  329. }
  330. if (layout === 'horizontal') {
  331. return axisType === 'yAxis';
  332. }
  333. if (layout === 'vertical') {
  334. return axisType === 'xAxis';
  335. }
  336. if (direction === 'x') {
  337. return axisType === 'xAxis';
  338. }
  339. if (direction === 'y') {
  340. return axisType === 'yAxis';
  341. }
  342. return true;
  343. };
  344. export var getDomainOfErrorBars = function getDomainOfErrorBars(data, item, dataKey, layout, axisType) {
  345. var children = item.props.children;
  346. var errorBars = findAllByType(children, ErrorBar).filter(function (errorBarChild) {
  347. return isErrorBarRelevantForAxis(layout, axisType, errorBarChild.props.direction);
  348. });
  349. if (errorBars && errorBars.length) {
  350. var keys = errorBars.map(function (errorBarChild) {
  351. return errorBarChild.props.dataKey;
  352. });
  353. return data.reduce(function (result, entry) {
  354. var entryValue = getValueByDataKey(entry, dataKey);
  355. if (isNil(entryValue)) return result;
  356. var mainValue = Array.isArray(entryValue) ? [min(entryValue), max(entryValue)] : [entryValue, entryValue];
  357. var errorDomain = keys.reduce(function (prevErrorArr, k) {
  358. var errorValue = getValueByDataKey(entry, k, 0);
  359. var lowerValue = mainValue[0] - Math.abs(Array.isArray(errorValue) ? errorValue[0] : errorValue);
  360. var upperValue = mainValue[1] + Math.abs(Array.isArray(errorValue) ? errorValue[1] : errorValue);
  361. return [Math.min(lowerValue, prevErrorArr[0]), Math.max(upperValue, prevErrorArr[1])];
  362. }, [Infinity, -Infinity]);
  363. return [Math.min(errorDomain[0], result[0]), Math.max(errorDomain[1], result[1])];
  364. }, [Infinity, -Infinity]);
  365. }
  366. return null;
  367. };
  368. export var parseErrorBarsOfAxis = function parseErrorBarsOfAxis(data, items, dataKey, axisType, layout) {
  369. var domains = items.map(function (item) {
  370. return getDomainOfErrorBars(data, item, dataKey, layout, axisType);
  371. }).filter(function (entry) {
  372. return !isNil(entry);
  373. });
  374. if (domains && domains.length) {
  375. return domains.reduce(function (result, entry) {
  376. return [Math.min(result[0], entry[0]), Math.max(result[1], entry[1])];
  377. }, [Infinity, -Infinity]);
  378. }
  379. return null;
  380. };
  381. /**
  382. * Get domain of data by the configuration of item element
  383. * @param {Array} data The data displayed in the chart
  384. * @param {Array} items The instances of item
  385. * @param {String} type The type of axis, number - Number Axis, category - Category Axis
  386. * @param {LayoutType} layout The type of layout
  387. * @param {Boolean} filterNil Whether or not filter nil values
  388. * @return {Array} Domain
  389. */
  390. export var getDomainOfItemsWithSameAxis = function getDomainOfItemsWithSameAxis(data, items, type, layout, filterNil) {
  391. var domains = items.map(function (item) {
  392. var dataKey = item.props.dataKey;
  393. if (type === 'number' && dataKey) {
  394. return getDomainOfErrorBars(data, item, dataKey, layout) || getDomainOfDataByKey(data, dataKey, type, filterNil);
  395. }
  396. return getDomainOfDataByKey(data, dataKey, type, filterNil);
  397. });
  398. if (type === 'number') {
  399. // Calculate the domain of number axis
  400. return domains.reduce(
  401. // @ts-expect-error if (type === number) means that the domain is numerical type
  402. // - but this link is missing in the type definition
  403. function (result, entry) {
  404. return [Math.min(result[0], entry[0]), Math.max(result[1], entry[1])];
  405. }, [Infinity, -Infinity]);
  406. }
  407. var tag = {};
  408. // Get the union set of category axis
  409. return domains.reduce(function (result, entry) {
  410. for (var i = 0, len = entry.length; i < len; i++) {
  411. // @ts-expect-error Date cannot index an object
  412. if (!tag[entry[i]]) {
  413. // @ts-expect-error Date cannot index an object
  414. tag[entry[i]] = true;
  415. // @ts-expect-error Date cannot index an object
  416. result.push(entry[i]);
  417. }
  418. }
  419. return result;
  420. }, []);
  421. };
  422. export var isCategoricalAxis = function isCategoricalAxis(layout, axisType) {
  423. return layout === 'horizontal' && axisType === 'xAxis' || layout === 'vertical' && axisType === 'yAxis' || layout === 'centric' && axisType === 'angleAxis' || layout === 'radial' && axisType === 'radiusAxis';
  424. };
  425. /**
  426. * Calculate the Coordinates of grid
  427. * @param {Array} ticks The ticks in axis
  428. * @param {Number} minValue The minimun value of axis
  429. * @param {Number} maxValue The maximun value of axis
  430. * @param {boolean} syncWithTicks Synchronize grid lines with ticks or not
  431. * @return {Array} Coordinates
  432. */
  433. export var getCoordinatesOfGrid = function getCoordinatesOfGrid(ticks, minValue, maxValue, syncWithTicks) {
  434. if (syncWithTicks) {
  435. return ticks.map(function (entry) {
  436. return entry.coordinate;
  437. });
  438. }
  439. var hasMin, hasMax;
  440. var values = ticks.map(function (entry) {
  441. if (entry.coordinate === minValue) {
  442. hasMin = true;
  443. }
  444. if (entry.coordinate === maxValue) {
  445. hasMax = true;
  446. }
  447. return entry.coordinate;
  448. });
  449. if (!hasMin) {
  450. values.push(minValue);
  451. }
  452. if (!hasMax) {
  453. values.push(maxValue);
  454. }
  455. return values;
  456. };
  457. /**
  458. * Get the ticks of an axis
  459. * @param {Object} axis The configuration of an axis
  460. * @param {Boolean} isGrid Whether or not are the ticks in grid
  461. * @param {Boolean} isAll Return the ticks of all the points or not
  462. * @return {Array} Ticks
  463. */
  464. export var getTicksOfAxis = function getTicksOfAxis(axis, isGrid, isAll) {
  465. if (!axis) return null;
  466. var scale = axis.scale;
  467. var duplicateDomain = axis.duplicateDomain,
  468. type = axis.type,
  469. range = axis.range;
  470. var offsetForBand = axis.realScaleType === 'scaleBand' ? scale.bandwidth() / 2 : 2;
  471. var offset = (isGrid || isAll) && type === 'category' && scale.bandwidth ? scale.bandwidth() / offsetForBand : 0;
  472. offset = axis.axisType === 'angleAxis' && (range === null || range === void 0 ? void 0 : range.length) >= 2 ? mathSign(range[0] - range[1]) * 2 * offset : offset;
  473. // The ticks set by user should only affect the ticks adjacent to axis line
  474. if (isGrid && (axis.ticks || axis.niceTicks)) {
  475. var result = (axis.ticks || axis.niceTicks).map(function (entry) {
  476. var scaleContent = duplicateDomain ? duplicateDomain.indexOf(entry) : entry;
  477. return {
  478. // If the scaleContent is not a number, the coordinate will be NaN.
  479. // That could be the case for example with a PointScale and a string as domain.
  480. coordinate: scale(scaleContent) + offset,
  481. value: entry,
  482. offset: offset
  483. };
  484. });
  485. return result.filter(function (row) {
  486. return !isNan(row.coordinate);
  487. });
  488. }
  489. // When axis is a categorial axis, but the type of axis is number or the scale of axis is not "auto"
  490. if (axis.isCategorical && axis.categoricalDomain) {
  491. return axis.categoricalDomain.map(function (entry, index) {
  492. return {
  493. coordinate: scale(entry) + offset,
  494. value: entry,
  495. index: index,
  496. offset: offset
  497. };
  498. });
  499. }
  500. if (scale.ticks && !isAll) {
  501. return scale.ticks(axis.tickCount).map(function (entry) {
  502. return {
  503. coordinate: scale(entry) + offset,
  504. value: entry,
  505. offset: offset
  506. };
  507. });
  508. }
  509. // When axis has duplicated text, serial numbers are used to generate scale
  510. return scale.domain().map(function (entry, index) {
  511. return {
  512. coordinate: scale(entry) + offset,
  513. value: duplicateDomain ? duplicateDomain[entry] : entry,
  514. index: index,
  515. offset: offset
  516. };
  517. });
  518. };
  519. /**
  520. * combine the handlers
  521. * @param {Function} defaultHandler Internal private handler
  522. * @param {Function} childHandler Handler function specified in child component
  523. * @return {Function} The combined handler
  524. */
  525. var handlerWeakMap = new WeakMap();
  526. export var combineEventHandlers = function combineEventHandlers(defaultHandler, childHandler) {
  527. if (typeof childHandler !== 'function') {
  528. return defaultHandler;
  529. }
  530. if (!handlerWeakMap.has(defaultHandler)) {
  531. handlerWeakMap.set(defaultHandler, new WeakMap());
  532. }
  533. var childWeakMap = handlerWeakMap.get(defaultHandler);
  534. if (childWeakMap.has(childHandler)) {
  535. return childWeakMap.get(childHandler);
  536. }
  537. var combineHandler = function combineHandler() {
  538. defaultHandler.apply(void 0, arguments);
  539. childHandler.apply(void 0, arguments);
  540. };
  541. childWeakMap.set(childHandler, combineHandler);
  542. return combineHandler;
  543. };
  544. /**
  545. * Parse the scale function of axis
  546. * @param {Object} axis The option of axis
  547. * @param {String} chartType The displayName of chart
  548. * @param {Boolean} hasBar if it has a bar
  549. * @return {object} The scale function and resolved name
  550. */
  551. export var parseScale = function parseScale(axis, chartType, hasBar) {
  552. var scale = axis.scale,
  553. type = axis.type,
  554. layout = axis.layout,
  555. axisType = axis.axisType;
  556. if (scale === 'auto') {
  557. if (layout === 'radial' && axisType === 'radiusAxis') {
  558. return {
  559. scale: d3Scales.scaleBand(),
  560. realScaleType: 'band'
  561. };
  562. }
  563. if (layout === 'radial' && axisType === 'angleAxis') {
  564. return {
  565. scale: d3Scales.scaleLinear(),
  566. realScaleType: 'linear'
  567. };
  568. }
  569. if (type === 'category' && chartType && (chartType.indexOf('LineChart') >= 0 || chartType.indexOf('AreaChart') >= 0 || chartType.indexOf('ComposedChart') >= 0 && !hasBar)) {
  570. return {
  571. scale: d3Scales.scalePoint(),
  572. realScaleType: 'point'
  573. };
  574. }
  575. if (type === 'category') {
  576. return {
  577. scale: d3Scales.scaleBand(),
  578. realScaleType: 'band'
  579. };
  580. }
  581. return {
  582. scale: d3Scales.scaleLinear(),
  583. realScaleType: 'linear'
  584. };
  585. }
  586. if (isString(scale)) {
  587. var name = "scale".concat(upperFirst(scale));
  588. return {
  589. scale: (d3Scales[name] || d3Scales.scalePoint)(),
  590. realScaleType: d3Scales[name] ? name : 'point'
  591. };
  592. }
  593. return isFunction(scale) ? {
  594. scale: scale
  595. } : {
  596. scale: d3Scales.scalePoint(),
  597. realScaleType: 'point'
  598. };
  599. };
  600. var EPS = 1e-4;
  601. export var checkDomainOfScale = function checkDomainOfScale(scale) {
  602. var domain = scale.domain();
  603. if (!domain || domain.length <= 2) {
  604. return;
  605. }
  606. var len = domain.length;
  607. var range = scale.range();
  608. var minValue = Math.min(range[0], range[1]) - EPS;
  609. var maxValue = Math.max(range[0], range[1]) + EPS;
  610. var first = scale(domain[0]);
  611. var last = scale(domain[len - 1]);
  612. if (first < minValue || first > maxValue || last < minValue || last > maxValue) {
  613. scale.domain([domain[0], domain[len - 1]]);
  614. }
  615. };
  616. export var findPositionOfBar = function findPositionOfBar(barPosition, child) {
  617. if (!barPosition) {
  618. return null;
  619. }
  620. for (var i = 0, len = barPosition.length; i < len; i++) {
  621. if (barPosition[i].item === child) {
  622. return barPosition[i].position;
  623. }
  624. }
  625. return null;
  626. };
  627. /**
  628. * Both value and domain are tuples of two numbers
  629. * - but the type stays as array of numbers until we have better support in rest of the app
  630. * @param {Array} value input that will be truncated
  631. * @param {Array} domain boundaries
  632. * @returns {Array} tuple of two numbers
  633. */
  634. export var truncateByDomain = function truncateByDomain(value, domain) {
  635. if (!domain || domain.length !== 2 || !isNumber(domain[0]) || !isNumber(domain[1])) {
  636. return value;
  637. }
  638. var minValue = Math.min(domain[0], domain[1]);
  639. var maxValue = Math.max(domain[0], domain[1]);
  640. var result = [value[0], value[1]];
  641. if (!isNumber(value[0]) || value[0] < minValue) {
  642. result[0] = minValue;
  643. }
  644. if (!isNumber(value[1]) || value[1] > maxValue) {
  645. result[1] = maxValue;
  646. }
  647. if (result[0] > maxValue) {
  648. result[0] = maxValue;
  649. }
  650. if (result[1] < minValue) {
  651. result[1] = minValue;
  652. }
  653. return result;
  654. };
  655. /**
  656. * Stacks all positive numbers above zero and all negative numbers below zero.
  657. *
  658. * If all values in the series are positive then this behaves the same as 'none' stacker.
  659. *
  660. * @param {Array} series from d3-shape Stack
  661. * @return {Array} series with applied offset
  662. */
  663. export var offsetSign = function offsetSign(series) {
  664. var n = series.length;
  665. if (n <= 0) {
  666. return;
  667. }
  668. for (var j = 0, m = series[0].length; j < m; ++j) {
  669. var positive = 0;
  670. var negative = 0;
  671. for (var i = 0; i < n; ++i) {
  672. var value = isNan(series[i][j][1]) ? series[i][j][0] : series[i][j][1];
  673. /* eslint-disable prefer-destructuring, no-param-reassign */
  674. if (value >= 0) {
  675. series[i][j][0] = positive;
  676. series[i][j][1] = positive + value;
  677. positive = series[i][j][1];
  678. } else {
  679. series[i][j][0] = negative;
  680. series[i][j][1] = negative + value;
  681. negative = series[i][j][1];
  682. }
  683. /* eslint-enable prefer-destructuring, no-param-reassign */
  684. }
  685. }
  686. };
  687. /**
  688. * Replaces all negative values with zero when stacking data.
  689. *
  690. * If all values in the series are positive then this behaves the same as 'none' stacker.
  691. *
  692. * @param {Array} series from d3-shape Stack
  693. * @return {Array} series with applied offset
  694. */
  695. export var offsetPositive = function offsetPositive(series) {
  696. var n = series.length;
  697. if (n <= 0) {
  698. return;
  699. }
  700. for (var j = 0, m = series[0].length; j < m; ++j) {
  701. var positive = 0;
  702. for (var i = 0; i < n; ++i) {
  703. var value = isNan(series[i][j][1]) ? series[i][j][0] : series[i][j][1];
  704. /* eslint-disable prefer-destructuring, no-param-reassign */
  705. if (value >= 0) {
  706. series[i][j][0] = positive;
  707. series[i][j][1] = positive + value;
  708. positive = series[i][j][1];
  709. } else {
  710. series[i][j][0] = 0;
  711. series[i][j][1] = 0;
  712. }
  713. /* eslint-enable prefer-destructuring, no-param-reassign */
  714. }
  715. }
  716. };
  717. /**
  718. * Function type to compute offset for stacked data.
  719. *
  720. * d3-shape has something fishy going on with its types.
  721. * In @definitelytyped/d3-shape, this function (the offset accessor) is typed as Series<> => void.
  722. * However! When I actually open the storybook I can see that the offset accessor actually receives Array<Series<>>.
  723. * The same I can see in the source code itself:
  724. * https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/66042
  725. * That one unfortunately has no types but we can tell it passes three-dimensional array.
  726. *
  727. * Which leads me to believe that definitelytyped is wrong on this one.
  728. * There's open discussion on this topic without much attention:
  729. * https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/66042
  730. */
  731. var STACK_OFFSET_MAP = {
  732. sign: offsetSign,
  733. // @ts-expect-error definitelytyped types are incorrect
  734. expand: stackOffsetExpand,
  735. // @ts-expect-error definitelytyped types are incorrect
  736. none: stackOffsetNone,
  737. // @ts-expect-error definitelytyped types are incorrect
  738. silhouette: stackOffsetSilhouette,
  739. // @ts-expect-error definitelytyped types are incorrect
  740. wiggle: stackOffsetWiggle,
  741. positive: offsetPositive
  742. };
  743. export var getStackedData = function getStackedData(data, stackItems, offsetType) {
  744. var dataKeys = stackItems.map(function (item) {
  745. return item.props.dataKey;
  746. });
  747. var offsetAccessor = STACK_OFFSET_MAP[offsetType];
  748. var stack = shapeStack()
  749. // @ts-expect-error stack.keys type wants an array of strings, but we provide array of DataKeys
  750. .keys(dataKeys).value(function (d, key) {
  751. return +getValueByDataKey(d, key, 0);
  752. }).order(stackOrderNone)
  753. // @ts-expect-error definitelytyped types are incorrect
  754. .offset(offsetAccessor);
  755. return stack(data);
  756. };
  757. export var getStackGroupsByAxisId = function getStackGroupsByAxisId(data, _items, numericAxisId, cateAxisId, offsetType, reverseStackOrder) {
  758. if (!data) {
  759. return null;
  760. }
  761. // reversing items to affect render order (for layering)
  762. var items = reverseStackOrder ? _items.reverse() : _items;
  763. var parentStackGroupsInitialValue = {};
  764. var stackGroups = items.reduce(function (result, item) {
  765. var _item$type2;
  766. var defaultedProps = (_item$type2 = item.type) !== null && _item$type2 !== void 0 && _item$type2.defaultProps ? _objectSpread(_objectSpread({}, item.type.defaultProps), item.props) : item.props;
  767. var stackId = defaultedProps.stackId,
  768. hide = defaultedProps.hide;
  769. if (hide) {
  770. return result;
  771. }
  772. var axisId = defaultedProps[numericAxisId];
  773. var parentGroup = result[axisId] || {
  774. hasStack: false,
  775. stackGroups: {}
  776. };
  777. if (isNumOrStr(stackId)) {
  778. var childGroup = parentGroup.stackGroups[stackId] || {
  779. numericAxisId: numericAxisId,
  780. cateAxisId: cateAxisId,
  781. items: []
  782. };
  783. childGroup.items.push(item);
  784. parentGroup.hasStack = true;
  785. parentGroup.stackGroups[stackId] = childGroup;
  786. } else {
  787. parentGroup.stackGroups[uniqueId('_stackId_')] = {
  788. numericAxisId: numericAxisId,
  789. cateAxisId: cateAxisId,
  790. items: [item]
  791. };
  792. }
  793. return _objectSpread(_objectSpread({}, result), {}, _defineProperty({}, axisId, parentGroup));
  794. }, parentStackGroupsInitialValue);
  795. var axisStackGroupsInitialValue = {};
  796. return Object.keys(stackGroups).reduce(function (result, axisId) {
  797. var group = stackGroups[axisId];
  798. if (group.hasStack) {
  799. var stackGroupsInitialValue = {};
  800. group.stackGroups = Object.keys(group.stackGroups).reduce(function (res, stackId) {
  801. var g = group.stackGroups[stackId];
  802. return _objectSpread(_objectSpread({}, res), {}, _defineProperty({}, stackId, {
  803. numericAxisId: numericAxisId,
  804. cateAxisId: cateAxisId,
  805. items: g.items,
  806. stackedData: getStackedData(data, g.items, offsetType)
  807. }));
  808. }, stackGroupsInitialValue);
  809. }
  810. return _objectSpread(_objectSpread({}, result), {}, _defineProperty({}, axisId, group));
  811. }, axisStackGroupsInitialValue);
  812. };
  813. /**
  814. * Configure the scale function of axis
  815. * @param {Object} scale The scale function
  816. * @param {Object} opts The configuration of axis
  817. * @return {Object} null
  818. */
  819. export var getTicksOfScale = function getTicksOfScale(scale, opts) {
  820. var realScaleType = opts.realScaleType,
  821. type = opts.type,
  822. tickCount = opts.tickCount,
  823. originalDomain = opts.originalDomain,
  824. allowDecimals = opts.allowDecimals;
  825. var scaleType = realScaleType || opts.scale;
  826. if (scaleType !== 'auto' && scaleType !== 'linear') {
  827. return null;
  828. }
  829. if (tickCount && type === 'number' && originalDomain && (originalDomain[0] === 'auto' || originalDomain[1] === 'auto')) {
  830. // Calculate the ticks by the number of grid when the axis is a number axis
  831. var domain = scale.domain();
  832. if (!domain.length) {
  833. return null;
  834. }
  835. var tickValues = getNiceTickValues(domain, tickCount, allowDecimals);
  836. scale.domain([min(tickValues), max(tickValues)]);
  837. return {
  838. niceTicks: tickValues
  839. };
  840. }
  841. if (tickCount && type === 'number') {
  842. var _domain = scale.domain();
  843. var _tickValues = getTickValuesFixedDomain(_domain, tickCount, allowDecimals);
  844. return {
  845. niceTicks: _tickValues
  846. };
  847. }
  848. return null;
  849. };
  850. export function getCateCoordinateOfLine(_ref5) {
  851. var axis = _ref5.axis,
  852. ticks = _ref5.ticks,
  853. bandSize = _ref5.bandSize,
  854. entry = _ref5.entry,
  855. index = _ref5.index,
  856. dataKey = _ref5.dataKey;
  857. if (axis.type === 'category') {
  858. // find coordinate of category axis by the value of category
  859. // @ts-expect-error why does this use direct object access instead of getValueByDataKey?
  860. if (!axis.allowDuplicatedCategory && axis.dataKey && !isNil(entry[axis.dataKey])) {
  861. // @ts-expect-error why does this use direct object access instead of getValueByDataKey?
  862. var matchedTick = findEntryInArray(ticks, 'value', entry[axis.dataKey]);
  863. if (matchedTick) {
  864. return matchedTick.coordinate + bandSize / 2;
  865. }
  866. }
  867. return ticks[index] ? ticks[index].coordinate + bandSize / 2 : null;
  868. }
  869. var value = getValueByDataKey(entry, !isNil(dataKey) ? dataKey : axis.dataKey);
  870. return !isNil(value) ? axis.scale(value) : null;
  871. }
  872. export var getCateCoordinateOfBar = function getCateCoordinateOfBar(_ref6) {
  873. var axis = _ref6.axis,
  874. ticks = _ref6.ticks,
  875. offset = _ref6.offset,
  876. bandSize = _ref6.bandSize,
  877. entry = _ref6.entry,
  878. index = _ref6.index;
  879. if (axis.type === 'category') {
  880. return ticks[index] ? ticks[index].coordinate + offset : null;
  881. }
  882. var value = getValueByDataKey(entry, axis.dataKey, axis.domain[index]);
  883. return !isNil(value) ? axis.scale(value) - bandSize / 2 + offset : null;
  884. };
  885. export var getBaseValueOfBar = function getBaseValueOfBar(_ref7) {
  886. var numericAxis = _ref7.numericAxis;
  887. var domain = numericAxis.scale.domain();
  888. if (numericAxis.type === 'number') {
  889. var minValue = Math.min(domain[0], domain[1]);
  890. var maxValue = Math.max(domain[0], domain[1]);
  891. if (minValue <= 0 && maxValue >= 0) {
  892. return 0;
  893. }
  894. if (maxValue < 0) {
  895. return maxValue;
  896. }
  897. return minValue;
  898. }
  899. return domain[0];
  900. };
  901. export var getStackedDataOfItem = function getStackedDataOfItem(item, stackGroups) {
  902. var _item$type3;
  903. var defaultedProps = (_item$type3 = item.type) !== null && _item$type3 !== void 0 && _item$type3.defaultProps ? _objectSpread(_objectSpread({}, item.type.defaultProps), item.props) : item.props;
  904. var stackId = defaultedProps.stackId;
  905. if (isNumOrStr(stackId)) {
  906. var group = stackGroups[stackId];
  907. if (group) {
  908. var itemIndex = group.items.indexOf(item);
  909. return itemIndex >= 0 ? group.stackedData[itemIndex] : null;
  910. }
  911. }
  912. return null;
  913. };
  914. var getDomainOfSingle = function getDomainOfSingle(data) {
  915. return data.reduce(function (result, entry) {
  916. return [min(entry.concat([result[0]]).filter(isNumber)), max(entry.concat([result[1]]).filter(isNumber))];
  917. }, [Infinity, -Infinity]);
  918. };
  919. export var getDomainOfStackGroups = function getDomainOfStackGroups(stackGroups, startIndex, endIndex) {
  920. return Object.keys(stackGroups).reduce(function (result, stackId) {
  921. var group = stackGroups[stackId];
  922. var stackedData = group.stackedData;
  923. var domain = stackedData.reduce(function (res, entry) {
  924. var s = getDomainOfSingle(entry.slice(startIndex, endIndex + 1));
  925. return [Math.min(res[0], s[0]), Math.max(res[1], s[1])];
  926. }, [Infinity, -Infinity]);
  927. return [Math.min(domain[0], result[0]), Math.max(domain[1], result[1])];
  928. }, [Infinity, -Infinity]).map(function (result) {
  929. return result === Infinity || result === -Infinity ? 0 : result;
  930. });
  931. };
  932. export var MIN_VALUE_REG = /^dataMin[\s]*-[\s]*([0-9]+([.]{1}[0-9]+){0,1})$/;
  933. export var MAX_VALUE_REG = /^dataMax[\s]*\+[\s]*([0-9]+([.]{1}[0-9]+){0,1})$/;
  934. export var parseSpecifiedDomain = function parseSpecifiedDomain(specifiedDomain, dataDomain, allowDataOverflow) {
  935. if (isFunction(specifiedDomain)) {
  936. return specifiedDomain(dataDomain, allowDataOverflow);
  937. }
  938. if (!Array.isArray(specifiedDomain)) {
  939. return dataDomain;
  940. }
  941. var domain = [];
  942. /* eslint-disable prefer-destructuring */
  943. if (isNumber(specifiedDomain[0])) {
  944. domain[0] = allowDataOverflow ? specifiedDomain[0] : Math.min(specifiedDomain[0], dataDomain[0]);
  945. } else if (MIN_VALUE_REG.test(specifiedDomain[0])) {
  946. var value = +MIN_VALUE_REG.exec(specifiedDomain[0])[1];
  947. domain[0] = dataDomain[0] - value;
  948. } else if (isFunction(specifiedDomain[0])) {
  949. domain[0] = specifiedDomain[0](dataDomain[0]);
  950. } else {
  951. domain[0] = dataDomain[0];
  952. }
  953. if (isNumber(specifiedDomain[1])) {
  954. domain[1] = allowDataOverflow ? specifiedDomain[1] : Math.max(specifiedDomain[1], dataDomain[1]);
  955. } else if (MAX_VALUE_REG.test(specifiedDomain[1])) {
  956. var _value = +MAX_VALUE_REG.exec(specifiedDomain[1])[1];
  957. domain[1] = dataDomain[1] + _value;
  958. } else if (isFunction(specifiedDomain[1])) {
  959. domain[1] = specifiedDomain[1](dataDomain[1]);
  960. } else {
  961. domain[1] = dataDomain[1];
  962. }
  963. /* eslint-enable prefer-destructuring */
  964. return domain;
  965. };
  966. /**
  967. * Calculate the size between two category
  968. * @param {Object} axis The options of axis
  969. * @param {Array} ticks The ticks of axis
  970. * @param {Boolean} isBar if items in axis are bars
  971. * @return {Number} Size
  972. */
  973. export var getBandSizeOfAxis = function getBandSizeOfAxis(axis, ticks, isBar) {
  974. // @ts-expect-error we need to rethink scale type
  975. if (axis && axis.scale && axis.scale.bandwidth) {
  976. // @ts-expect-error we need to rethink scale type
  977. var bandWidth = axis.scale.bandwidth();
  978. if (!isBar || bandWidth > 0) {
  979. return bandWidth;
  980. }
  981. }
  982. if (axis && ticks && ticks.length >= 2) {
  983. var orderedTicks = sortBy(ticks, function (o) {
  984. return o.coordinate;
  985. });
  986. var bandSize = Infinity;
  987. for (var i = 1, len = orderedTicks.length; i < len; i++) {
  988. var cur = orderedTicks[i];
  989. var prev = orderedTicks[i - 1];
  990. bandSize = Math.min((cur.coordinate || 0) - (prev.coordinate || 0), bandSize);
  991. }
  992. return bandSize === Infinity ? 0 : bandSize;
  993. }
  994. return isBar ? undefined : 0;
  995. };
  996. /**
  997. * parse the domain of a category axis when a domain is specified
  998. * @param {Array} specifiedDomain The domain specified by users
  999. * @param {Array} calculatedDomain The domain calculated by dateKey
  1000. * @param {ReactElement} axisChild The axis ReactElement
  1001. * @returns {Array} domains
  1002. */
  1003. export var parseDomainOfCategoryAxis = function parseDomainOfCategoryAxis(specifiedDomain, calculatedDomain, axisChild) {
  1004. if (!specifiedDomain || !specifiedDomain.length) {
  1005. return calculatedDomain;
  1006. }
  1007. if (isEqual(specifiedDomain, get(axisChild, 'type.defaultProps.domain'))) {
  1008. return calculatedDomain;
  1009. }
  1010. return specifiedDomain;
  1011. };
  1012. export var getTooltipItem = function getTooltipItem(graphicalItem, payload) {
  1013. var defaultedProps = graphicalItem.type.defaultProps ? _objectSpread(_objectSpread({}, graphicalItem.type.defaultProps), graphicalItem.props) : graphicalItem.props;
  1014. var dataKey = defaultedProps.dataKey,
  1015. name = defaultedProps.name,
  1016. unit = defaultedProps.unit,
  1017. formatter = defaultedProps.formatter,
  1018. tooltipType = defaultedProps.tooltipType,
  1019. chartType = defaultedProps.chartType,
  1020. hide = defaultedProps.hide;
  1021. return _objectSpread(_objectSpread({}, filterProps(graphicalItem, false)), {}, {
  1022. dataKey: dataKey,
  1023. unit: unit,
  1024. formatter: formatter,
  1025. name: name || dataKey,
  1026. color: getMainColorOfGraphicItem(graphicalItem),
  1027. value: getValueByDataKey(payload, dataKey),
  1028. type: tooltipType,
  1029. payload: payload,
  1030. chartType: chartType,
  1031. hide: hide
  1032. });
  1033. };