UNPKG

antd

Version:

An enterprise-class UI design language and React components implementation

172 lines 6.34 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray"; import _typeof from "@babel/runtime/helpers/esm/typeof"; import toArray from "rc-util/es/Children/toArray"; import useIsomorphicLayoutEffect from "rc-util/es/hooks/useLayoutEffect"; import * as React from 'react'; function cuttable(node) { var type = _typeof(node); return type === 'string' || type === 'number'; } function getNodesLen(nodeList) { var totalLen = 0; nodeList.forEach(function (node) { if (cuttable(node)) { totalLen += String(node).length; } else { totalLen += 1; } }); return totalLen; } function sliceNodes(nodeList, len) { var currLen = 0; var currentNodeList = []; for (var i = 0; i < nodeList.length; i += 1) { // Match to return if (currLen === len) { return currentNodeList; } var node = nodeList[i]; var canCut = cuttable(node); var nodeLen = canCut ? String(node).length : 1; var nextLen = currLen + nodeLen; // Exceed but current not which means we need cut this // This will not happen on validate ReactElement if (nextLen > len) { var restLen = len - currLen; currentNodeList.push(String(node).slice(0, restLen)); return currentNodeList; } currentNodeList.push(node); currLen = nextLen; } return nodeList; } var NONE = 0; var PREPARE = 1; var WALKING = 2; var DONE_WITH_ELLIPSIS = 3; var DONE_WITHOUT_ELLIPSIS = 4; var Ellipsis = function Ellipsis(_ref) { var enabledMeasure = _ref.enabledMeasure, children = _ref.children, text = _ref.text, width = _ref.width, fontSize = _ref.fontSize, rows = _ref.rows, onEllipsis = _ref.onEllipsis; var _React$useState = React.useState([0, 0, 0]), _React$useState2 = _slicedToArray(_React$useState, 2), _React$useState2$ = _slicedToArray(_React$useState2[0], 3), startLen = _React$useState2$[0], midLen = _React$useState2$[1], endLen = _React$useState2$[2], setCutLength = _React$useState2[1]; var _React$useState3 = React.useState(NONE), _React$useState4 = _slicedToArray(_React$useState3, 2), walkingState = _React$useState4[0], setWalkingState = _React$useState4[1]; var _React$useState5 = React.useState(0), _React$useState6 = _slicedToArray(_React$useState5, 2), singleRowHeight = _React$useState6[0], setSingleRowHeight = _React$useState6[1]; var singleRowRef = React.useRef(null); var midRowRef = React.useRef(null); var nodeList = React.useMemo(function () { return toArray(text); }, [text]); var totalLen = React.useMemo(function () { return getNodesLen(nodeList); }, [nodeList]); var mergedChildren = React.useMemo(function () { if (!enabledMeasure || walkingState !== DONE_WITH_ELLIPSIS) { return children(nodeList, false); } return children(sliceNodes(nodeList, midLen), midLen < totalLen); }, [enabledMeasure, walkingState, children, nodeList, midLen, totalLen]); // ======================== Walk ======================== useIsomorphicLayoutEffect(function () { if (enabledMeasure && width && fontSize && totalLen) { setWalkingState(PREPARE); setCutLength([0, Math.ceil(totalLen / 2), totalLen]); } }, [enabledMeasure, width, fontSize, text, totalLen, rows]); useIsomorphicLayoutEffect(function () { var _a; if (walkingState === PREPARE) { setSingleRowHeight(((_a = singleRowRef.current) === null || _a === void 0 ? void 0 : _a.offsetHeight) || 0); } }, [walkingState]); useIsomorphicLayoutEffect(function () { var _a, _b; if (singleRowHeight) { if (walkingState === PREPARE) { // Ignore if position is enough var midHeight = ((_a = midRowRef.current) === null || _a === void 0 ? void 0 : _a.offsetHeight) || 0; var maxHeight = rows * singleRowHeight; if (midHeight <= maxHeight) { setWalkingState(DONE_WITHOUT_ELLIPSIS); onEllipsis(false); } else { setWalkingState(WALKING); } } else if (walkingState === WALKING) { if (startLen !== endLen) { var _midHeight = ((_b = midRowRef.current) === null || _b === void 0 ? void 0 : _b.offsetHeight) || 0; var _maxHeight = rows * singleRowHeight; var nextStartLen = startLen; var nextEndLen = endLen; // We reach the last round if (startLen === endLen - 1) { nextEndLen = startLen; } else if (_midHeight <= _maxHeight) { nextStartLen = midLen; } else { nextEndLen = midLen; } var nextMidLen = Math.ceil((nextStartLen + nextEndLen) / 2); setCutLength([nextStartLen, nextMidLen, nextEndLen]); } else { setWalkingState(DONE_WITH_ELLIPSIS); onEllipsis(true); } } } }, [walkingState, startLen, endLen, rows, singleRowHeight]); // ======================= Render ======================= var measureStyle = { width: width, whiteSpace: 'normal', margin: 0, padding: 0 }; var renderMeasure = function renderMeasure(content, ref, style) { return /*#__PURE__*/React.createElement("span", { "aria-hidden": true, ref: ref, style: _extends({ position: 'fixed', display: 'block', left: 0, top: 0, zIndex: -9999, visibility: 'hidden', pointerEvents: 'none', fontSize: Math.floor(fontSize / 2) * 2 }, style) }, content); }; var renderMeasureSlice = function renderMeasureSlice(len, ref) { var sliceNodeList = sliceNodes(nodeList, len); return renderMeasure(children(sliceNodeList, true), ref, measureStyle); }; return /*#__PURE__*/React.createElement(React.Fragment, null, mergedChildren, enabledMeasure && walkingState !== DONE_WITH_ELLIPSIS && walkingState !== DONE_WITHOUT_ELLIPSIS && /*#__PURE__*/React.createElement(React.Fragment, null, renderMeasure('lg', singleRowRef, { wordBreak: 'keep-all', whiteSpace: 'nowrap' }), walkingState === PREPARE ? renderMeasure(children(nodeList, false), midRowRef, measureStyle) : renderMeasureSlice(midLen, midRowRef))); }; if (process.env.NODE_ENV !== 'production') { Ellipsis.displayName = 'Ellipsis'; } export default Ellipsis;