UNPKG

@visx/text

Version:
113 lines (111 loc) 3.93 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = useText; var _react = require("react"); var _reduceCssCalc = _interopRequireDefault(require("reduce-css-calc")); var _getStringWidth = _interopRequireDefault(require("../util/getStringWidth")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function isNumber(val) { return typeof val === 'number'; } function isXOrYInValid(xOrY) { return ( // number that is not NaN or Infinity typeof xOrY === 'number' && Number.isFinite(xOrY) || // for percentage typeof xOrY === 'string' ); } function useText(props) { const { verticalAnchor = 'end', scaleToFit = false, angle, width, lineHeight = '1em', capHeight = '0.71em', // Magic number from d3 children, style, ...textProps } = props; const { x = 0, y = 0 } = textProps; const isXOrYNotValid = !isXOrYInValid(x) || !isXOrYInValid(y); const { wordsWithWidth, spaceWidth } = (0, _react.useMemo)(() => { const words = children == null ? [] : children.toString().split(/(?:(?!\u00A0+)\s+)/); return { wordsWithWidth: words.map(word => ({ word, wordWidth: (0, _getStringWidth.default)(word, style) || 0 })), spaceWidth: (0, _getStringWidth.default)('\u00A0', style) || 0 }; }, [children, style]); const wordsByLines = (0, _react.useMemo)(() => { if (isXOrYNotValid) { return []; } // Only perform calculations if using features that require them (multiline, scaleToFit) if (width || scaleToFit) { return wordsWithWidth.reduce((result, _ref) => { let { word, wordWidth } = _ref; const currentLine = result[result.length - 1]; if (currentLine && (width == null || scaleToFit || (currentLine.width || 0) + wordWidth + spaceWidth < width)) { // Word can be added to an existing line currentLine.words.push(word); currentLine.width = currentLine.width || 0; currentLine.width += wordWidth + spaceWidth; } else { // Add first word to line or word is too long to scaleToFit on existing line const newLine = { words: [word], width: wordWidth }; result.push(newLine); } return result; }, []); } return [{ words: children == null ? [] : children.toString().split(/(?:(?!\u00A0+)\s+)/) }]; }, [isXOrYNotValid, width, scaleToFit, children, wordsWithWidth, spaceWidth]); const startDy = (0, _react.useMemo)(() => { const startDyStr = isXOrYNotValid ? '' : verticalAnchor === 'start' ? (0, _reduceCssCalc.default)(`calc(${capHeight})`) : verticalAnchor === 'middle' ? (0, _reduceCssCalc.default)(`calc(${(wordsByLines.length - 1) / 2} * -${lineHeight} + (${capHeight} / 2))`) : (0, _reduceCssCalc.default)(`calc(${wordsByLines.length - 1} * -${lineHeight})`); return startDyStr; }, [isXOrYNotValid, verticalAnchor, capHeight, wordsByLines.length, lineHeight]); const transform = (0, _react.useMemo)(() => { const transforms = []; if (isXOrYNotValid) { return ''; } if (isNumber(x) && isNumber(y) && isNumber(width) && scaleToFit && wordsByLines.length > 0) { const lineWidth = wordsByLines[0].width || 1; const sx = scaleToFit === 'shrink-only' ? Math.min(width / lineWidth, 1) : width / lineWidth; const sy = sx; const originX = x - sx * x; const originY = y - sy * y; transforms.push(`matrix(${sx}, 0, 0, ${sy}, ${originX}, ${originY})`); } if (angle) { transforms.push(`rotate(${angle}, ${x}, ${y})`); } return transforms.length > 0 ? transforms.join(' ') : ''; }, [isXOrYNotValid, x, y, width, scaleToFit, wordsByLines, angle]); return { wordsByLines, startDy, transform }; }