choerodon-ui
Version:
An enterprise-class UI design language and React-based implementation
212 lines (173 loc) • 6.96 kB
JavaScript
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard")["default"];
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
var _react = _interopRequireWildcard(require("react"));
var _utils = require("../../mentions/utils");
function cuttable(node) {
var type = (0, _typeof2["default"])(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) {
// 匹配返回
if (currLen === len) {
return currentNodeList;
}
var node = nodeList[i];
var canCut = cuttable(node);
var nodeLen = canCut ? String(node).length : 1;
var nextLen = currLen + nodeLen; // 超过但不是当前的长度,需要削减
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,
rows = _ref.rows,
onEllipsis = _ref.onEllipsis;
var _useState = (0, _react.useState)([0, 0, 0]),
_useState2 = (0, _slicedToArray2["default"])(_useState, 2),
cutLength = _useState2[0],
setCutLength = _useState2[1];
var _useState3 = (0, _react.useState)(NONE),
_useState4 = (0, _slicedToArray2["default"])(_useState3, 2),
walkingState = _useState4[0],
setWalkingState = _useState4[1];
var _cutLength = (0, _slicedToArray2["default"])(cutLength, 3),
startLen = _cutLength[0],
midLen = _cutLength[1],
endLen = _cutLength[2];
var _useState5 = (0, _react.useState)(0),
_useState6 = (0, _slicedToArray2["default"])(_useState5, 2),
singleRowHeight = _useState6[0],
setSingleRowHeight = _useState6[1];
var singleRowRef = (0, _react.useRef)(null);
var midRowRef = (0, _react.useRef)(null);
var nodeList = (0, _react.useMemo)(function () {
return (0, _utils.toArray)(text);
}, [text]);
var totalLen = (0, _react.useMemo)(function () {
return getNodesLen(nodeList);
}, [nodeList]);
var mergedChildren = (0, _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 ========================
(0, _react.useLayoutEffect)(function () {
if (enabledMeasure && width && totalLen) {
setWalkingState(PREPARE);
setCutLength([0, Math.ceil(totalLen / 2), totalLen]);
}
}, [enabledMeasure, width, text, totalLen, rows]);
(0, _react.useLayoutEffect)(function () {
if (walkingState === PREPARE) {
var _singleRowRef$current;
setSingleRowHeight(((_singleRowRef$current = singleRowRef.current) === null || _singleRowRef$current === void 0 ? void 0 : _singleRowRef$current.offsetHeight) || 0);
}
}, [walkingState]);
(0, _react.useLayoutEffect)(function () {
if (singleRowHeight) {
if (walkingState === PREPARE) {
var _midRowRef$current;
// 忽略位置是否足够
var midHeight = ((_midRowRef$current = midRowRef.current) === null || _midRowRef$current === void 0 ? void 0 : _midRowRef$current.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 _midRowRef$current2;
var _midHeight = ((_midRowRef$current2 = midRowRef.current) === null || _midRowRef$current2 === void 0 ? void 0 : _midRowRef$current2.offsetHeight) || 0;
var _maxHeight = rows * singleRowHeight;
var nextStartLen = startLen;
var nextEndLen = endLen; // 当等于最后的时候
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["default"].createElement("span", {
"aria-hidden": true,
ref: ref,
style: (0, _objectSpread2["default"])({
position: 'fixed',
display: 'block',
left: 0,
top: 0,
zIndex: -9999,
visibility: 'hidden',
pointerEvents: 'none'
}, style)
}, content);
};
var renderMeasureSlice = function renderMeasureSlice(len, ref) {
var sliceNodeList = sliceNodes(nodeList, len);
return renderMeasure(children(sliceNodeList, true), ref, measureStyle);
};
return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, mergedChildren, enabledMeasure && walkingState !== DONE_WITH_ELLIPSIS && walkingState !== DONE_WITHOUT_ELLIPSIS && /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, renderMeasure('lg', singleRowRef, {
wordBreak: 'keep-all',
whiteSpace: 'nowrap'
}), walkingState === PREPARE ? renderMeasure(children(nodeList, false), midRowRef, measureStyle) : renderMeasureSlice(midLen, midRowRef)));
};
Ellipsis.displayName = 'Ellipsis';
var _default = Ellipsis;
exports["default"] = _default;
//# sourceMappingURL=Ellipsis.js.map
;