Text.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. "use strict";
  2. 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); }
  3. Object.defineProperty(exports, "__esModule", {
  4. value: true
  5. });
  6. exports.Text = void 0;
  7. var _react = _interopRequireWildcard(require("react"));
  8. var _isNil = _interopRequireDefault(require("lodash/isNil"));
  9. var _clsx = _interopRequireDefault(require("clsx"));
  10. var _DataUtils = require("../util/DataUtils");
  11. var _Global = require("../util/Global");
  12. var _ReactUtils = require("../util/ReactUtils");
  13. var _DOMUtils = require("../util/DOMUtils");
  14. var _ReduceCSSCalc = require("../util/ReduceCSSCalc");
  15. var _excluded = ["x", "y", "lineHeight", "capHeight", "scaleToFit", "textAnchor", "verticalAnchor", "fill"],
  16. _excluded2 = ["dx", "dy", "angle", "className", "breakAll"];
  17. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
  18. function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
  19. function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
  20. 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); }
  21. 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; }
  22. 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; }
  23. function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
  24. function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
  25. 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); }
  26. 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; }
  27. function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
  28. function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
  29. var BREAKING_SPACES = /[ \f\n\r\t\v\u2028\u2029]+/;
  30. var calculateWordWidths = function calculateWordWidths(_ref) {
  31. var children = _ref.children,
  32. breakAll = _ref.breakAll,
  33. style = _ref.style;
  34. try {
  35. var words = [];
  36. if (!(0, _isNil["default"])(children)) {
  37. if (breakAll) {
  38. words = children.toString().split('');
  39. } else {
  40. words = children.toString().split(BREAKING_SPACES);
  41. }
  42. }
  43. var wordsWithComputedWidth = words.map(function (word) {
  44. return {
  45. word: word,
  46. width: (0, _DOMUtils.getStringSize)(word, style).width
  47. };
  48. });
  49. var spaceWidth = breakAll ? 0 : (0, _DOMUtils.getStringSize)("\xA0", style).width;
  50. return {
  51. wordsWithComputedWidth: wordsWithComputedWidth,
  52. spaceWidth: spaceWidth
  53. };
  54. } catch (e) {
  55. return null;
  56. }
  57. };
  58. var calculateWordsByLines = function calculateWordsByLines(_ref2, initialWordsWithComputedWith, spaceWidth, lineWidth, scaleToFit) {
  59. var maxLines = _ref2.maxLines,
  60. children = _ref2.children,
  61. style = _ref2.style,
  62. breakAll = _ref2.breakAll;
  63. var shouldLimitLines = (0, _DataUtils.isNumber)(maxLines);
  64. var text = children;
  65. var calculate = function calculate() {
  66. var words = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  67. return words.reduce(function (result, _ref3) {
  68. var word = _ref3.word,
  69. width = _ref3.width;
  70. var currentLine = result[result.length - 1];
  71. if (currentLine && (lineWidth == null || scaleToFit || currentLine.width + width + spaceWidth < Number(lineWidth))) {
  72. // Word can be added to an existing line
  73. currentLine.words.push(word);
  74. currentLine.width += width + spaceWidth;
  75. } else {
  76. // Add first word to line or word is too long to scaleToFit on existing line
  77. var newLine = {
  78. words: [word],
  79. width: width
  80. };
  81. result.push(newLine);
  82. }
  83. return result;
  84. }, []);
  85. };
  86. var originalResult = calculate(initialWordsWithComputedWith);
  87. var findLongestLine = function findLongestLine(words) {
  88. return words.reduce(function (a, b) {
  89. return a.width > b.width ? a : b;
  90. });
  91. };
  92. if (!shouldLimitLines) {
  93. return originalResult;
  94. }
  95. var suffix = '…';
  96. var checkOverflow = function checkOverflow(index) {
  97. var tempText = text.slice(0, index);
  98. var words = calculateWordWidths({
  99. breakAll: breakAll,
  100. style: style,
  101. children: tempText + suffix
  102. }).wordsWithComputedWidth;
  103. var result = calculate(words);
  104. var doesOverflow = result.length > maxLines || findLongestLine(result).width > Number(lineWidth);
  105. return [doesOverflow, result];
  106. };
  107. var start = 0;
  108. var end = text.length - 1;
  109. var iterations = 0;
  110. var trimmedResult;
  111. while (start <= end && iterations <= text.length - 1) {
  112. var middle = Math.floor((start + end) / 2);
  113. var prev = middle - 1;
  114. var _checkOverflow = checkOverflow(prev),
  115. _checkOverflow2 = _slicedToArray(_checkOverflow, 2),
  116. doesPrevOverflow = _checkOverflow2[0],
  117. result = _checkOverflow2[1];
  118. var _checkOverflow3 = checkOverflow(middle),
  119. _checkOverflow4 = _slicedToArray(_checkOverflow3, 1),
  120. doesMiddleOverflow = _checkOverflow4[0];
  121. if (!doesPrevOverflow && !doesMiddleOverflow) {
  122. start = middle + 1;
  123. }
  124. if (doesPrevOverflow && doesMiddleOverflow) {
  125. end = middle - 1;
  126. }
  127. if (!doesPrevOverflow && doesMiddleOverflow) {
  128. trimmedResult = result;
  129. break;
  130. }
  131. iterations++;
  132. }
  133. // Fallback to originalResult (result without trimming) if we cannot find the
  134. // where to trim. This should not happen :tm:
  135. return trimmedResult || originalResult;
  136. };
  137. var getWordsWithoutCalculate = function getWordsWithoutCalculate(children) {
  138. var words = !(0, _isNil["default"])(children) ? children.toString().split(BREAKING_SPACES) : [];
  139. return [{
  140. words: words
  141. }];
  142. };
  143. var getWordsByLines = function getWordsByLines(_ref4) {
  144. var width = _ref4.width,
  145. scaleToFit = _ref4.scaleToFit,
  146. children = _ref4.children,
  147. style = _ref4.style,
  148. breakAll = _ref4.breakAll,
  149. maxLines = _ref4.maxLines;
  150. // Only perform calculations if using features that require them (multiline, scaleToFit)
  151. if ((width || scaleToFit) && !_Global.Global.isSsr) {
  152. var wordsWithComputedWidth, spaceWidth;
  153. var wordWidths = calculateWordWidths({
  154. breakAll: breakAll,
  155. children: children,
  156. style: style
  157. });
  158. if (wordWidths) {
  159. var wcw = wordWidths.wordsWithComputedWidth,
  160. sw = wordWidths.spaceWidth;
  161. wordsWithComputedWidth = wcw;
  162. spaceWidth = sw;
  163. } else {
  164. return getWordsWithoutCalculate(children);
  165. }
  166. return calculateWordsByLines({
  167. breakAll: breakAll,
  168. children: children,
  169. maxLines: maxLines,
  170. style: style
  171. }, wordsWithComputedWidth, spaceWidth, width, scaleToFit);
  172. }
  173. return getWordsWithoutCalculate(children);
  174. };
  175. var DEFAULT_FILL = '#808080';
  176. var Text = exports.Text = function Text(_ref5) {
  177. var _ref5$x = _ref5.x,
  178. propsX = _ref5$x === void 0 ? 0 : _ref5$x,
  179. _ref5$y = _ref5.y,
  180. propsY = _ref5$y === void 0 ? 0 : _ref5$y,
  181. _ref5$lineHeight = _ref5.lineHeight,
  182. lineHeight = _ref5$lineHeight === void 0 ? '1em' : _ref5$lineHeight,
  183. _ref5$capHeight = _ref5.capHeight,
  184. capHeight = _ref5$capHeight === void 0 ? '0.71em' : _ref5$capHeight,
  185. _ref5$scaleToFit = _ref5.scaleToFit,
  186. scaleToFit = _ref5$scaleToFit === void 0 ? false : _ref5$scaleToFit,
  187. _ref5$textAnchor = _ref5.textAnchor,
  188. textAnchor = _ref5$textAnchor === void 0 ? 'start' : _ref5$textAnchor,
  189. _ref5$verticalAnchor = _ref5.verticalAnchor,
  190. verticalAnchor = _ref5$verticalAnchor === void 0 ? 'end' : _ref5$verticalAnchor,
  191. _ref5$fill = _ref5.fill,
  192. fill = _ref5$fill === void 0 ? DEFAULT_FILL : _ref5$fill,
  193. props = _objectWithoutProperties(_ref5, _excluded);
  194. var wordsByLines = (0, _react.useMemo)(function () {
  195. return getWordsByLines({
  196. breakAll: props.breakAll,
  197. children: props.children,
  198. maxLines: props.maxLines,
  199. scaleToFit: scaleToFit,
  200. style: props.style,
  201. width: props.width
  202. });
  203. }, [props.breakAll, props.children, props.maxLines, scaleToFit, props.style, props.width]);
  204. var dx = props.dx,
  205. dy = props.dy,
  206. angle = props.angle,
  207. className = props.className,
  208. breakAll = props.breakAll,
  209. textProps = _objectWithoutProperties(props, _excluded2);
  210. if (!(0, _DataUtils.isNumOrStr)(propsX) || !(0, _DataUtils.isNumOrStr)(propsY)) {
  211. return null;
  212. }
  213. var x = propsX + ((0, _DataUtils.isNumber)(dx) ? dx : 0);
  214. var y = propsY + ((0, _DataUtils.isNumber)(dy) ? dy : 0);
  215. var startDy;
  216. switch (verticalAnchor) {
  217. case 'start':
  218. startDy = (0, _ReduceCSSCalc.reduceCSSCalc)("calc(".concat(capHeight, ")"));
  219. break;
  220. case 'middle':
  221. startDy = (0, _ReduceCSSCalc.reduceCSSCalc)("calc(".concat((wordsByLines.length - 1) / 2, " * -").concat(lineHeight, " + (").concat(capHeight, " / 2))"));
  222. break;
  223. default:
  224. startDy = (0, _ReduceCSSCalc.reduceCSSCalc)("calc(".concat(wordsByLines.length - 1, " * -").concat(lineHeight, ")"));
  225. break;
  226. }
  227. var transforms = [];
  228. if (scaleToFit) {
  229. var lineWidth = wordsByLines[0].width;
  230. var width = props.width;
  231. transforms.push("scale(".concat(((0, _DataUtils.isNumber)(width) ? width / lineWidth : 1) / lineWidth, ")"));
  232. }
  233. if (angle) {
  234. transforms.push("rotate(".concat(angle, ", ").concat(x, ", ").concat(y, ")"));
  235. }
  236. if (transforms.length) {
  237. textProps.transform = transforms.join(' ');
  238. }
  239. return /*#__PURE__*/_react["default"].createElement("text", _extends({}, (0, _ReactUtils.filterProps)(textProps, true), {
  240. x: x,
  241. y: y,
  242. className: (0, _clsx["default"])('recharts-text', className),
  243. textAnchor: textAnchor,
  244. fill: fill.includes('url') ? DEFAULT_FILL : fill
  245. }), wordsByLines.map(function (line, index) {
  246. var words = line.words.join(breakAll ? '' : ' ');
  247. return (
  248. /*#__PURE__*/
  249. // duplicate words will cause duplicate keys
  250. // eslint-disable-next-line react/no-array-index-key
  251. _react["default"].createElement("tspan", {
  252. x: x,
  253. dy: index === 0 ? startDy : lineHeight,
  254. key: "".concat(words, "-").concat(index)
  255. }, words)
  256. );
  257. }));
  258. };