UNPKG

antd-mobile

Version:
112 lines (111 loc) 5.13 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = useMeasure; var _rcUtil = require("rc-util"); var _react = _interopRequireDefault(require("react")); var _reactDom = require("react-dom"); var _runes = _interopRequireDefault(require("runes2")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const ELLIPSIS_TEXT = '...'; const measureStyle = { visibility: 'hidden', whiteSpace: 'inherit', lineHeight: 'inherit', fontSize: 'inherit' }; function useMeasure(containerRef, content, rows, direction, expanded, expandNode, collapseNode) { const contentChars = _react.default.useMemo(() => (0, _runes.default)(content), [content]); const [maxHeight, setMaxHeight] = _react.default.useState(0); const [walkingIndexes, setWalkingIndexes] = _react.default.useState([0, 0]); const midIndex = Math.ceil((walkingIndexes[0] + walkingIndexes[1]) / 2); const [status, setStatus] = _react.default.useState(100 /* STABLE_NO_ELLIPSIS */); // ============================ Refs ============================ const singleRowMeasureRef = _react.default.useRef(null); const fullMeasureRef = _react.default.useRef(null); const midMeasureRef = _react.default.useRef(null); const startMeasure = (0, _rcUtil.useEvent)(() => { // use batch update to avoid async update trigger 2 render (0, _reactDom.unstable_batchedUpdates)(() => { setStatus(1 /* PREPARE */); setWalkingIndexes([0, direction === 'middle' ? Math.ceil(contentChars.length / 2) : contentChars.length]); }); }); // Initialize _react.default.useLayoutEffect(() => { startMeasure(); }, [contentChars, rows]); // Measure element height _react.default.useLayoutEffect(() => { var _a, _b; if (status === 1 /* PREPARE */) { const fullMeasureHeight = ((_a = fullMeasureRef.current) === null || _a === void 0 ? void 0 : _a.offsetHeight) || 0; const singleRowMeasureHeight = ((_b = singleRowMeasureRef.current) === null || _b === void 0 ? void 0 : _b.offsetHeight) || 0; const rowMeasureHeight = singleRowMeasureHeight * (rows + 0.5); if (fullMeasureHeight <= rowMeasureHeight) { setStatus(100 /* STABLE_NO_ELLIPSIS */); } else { setMaxHeight(rowMeasureHeight); setStatus(2 /* MEASURE_WALKING */); } } }, [status]); // Walking measure _react.default.useLayoutEffect(() => { var _a; if (status === 2 /* MEASURE_WALKING */) { const diff = walkingIndexes[1] - walkingIndexes[0]; const midHeight = ((_a = midMeasureRef.current) === null || _a === void 0 ? void 0 : _a.offsetHeight) || 0; if (diff > 1) { if (midHeight > maxHeight) { setWalkingIndexes([walkingIndexes[0], midIndex]); } else { setWalkingIndexes([midIndex, walkingIndexes[1]]); } } else { if (midHeight > maxHeight) { setWalkingIndexes([walkingIndexes[0], walkingIndexes[0]]); } else { setWalkingIndexes([walkingIndexes[1], walkingIndexes[1]]); } setStatus(99 /* STABLE_ELLIPSIS */); } } }, [status, walkingIndexes]); // =========================== Render =========================== /** Render by cut index */ const renderContent = index => { const prefixContent = contentChars.slice(0, index); const suffixContent = contentChars.slice(contentChars.length - index); return _react.default.createElement(_react.default.Fragment, null, direction === 'start' && _react.default.createElement(_react.default.Fragment, null, expandNode, ELLIPSIS_TEXT), direction !== 'start' && prefixContent.join(''), direction === 'middle' && _react.default.createElement(_react.default.Fragment, null, ELLIPSIS_TEXT, expandNode, ELLIPSIS_TEXT), direction !== 'end' && suffixContent.join(''), direction === 'end' && _react.default.createElement(_react.default.Fragment, null, ELLIPSIS_TEXT, expandNode)); }; const finalContent = _react.default.useMemo(() => { if (expanded || status === 100 /* STABLE_NO_ELLIPSIS */) { return _react.default.createElement(_react.default.Fragment, { key: 'display' }, content, status === 99 /* STABLE_ELLIPSIS */ && collapseNode); } if (status === 99 /* STABLE_ELLIPSIS */) { return renderContent(midIndex); } return null; }, [expanded, status, content, collapseNode, midIndex]); const allNodes = _react.default.createElement(_react.default.Fragment, null, status === 1 /* PREPARE */ && _react.default.createElement("div", { key: 'full', "aria-hidden": true, ref: fullMeasureRef, style: measureStyle }, content, expandNode), status === 1 /* PREPARE */ && _react.default.createElement("div", { key: 'stable', "aria-hidden": true, ref: singleRowMeasureRef, style: measureStyle }, '\u00A0'), status === 2 /* MEASURE_WALKING */ && _react.default.createElement("div", { key: 'walking-mid', "aria-hidden": true, ref: midMeasureRef, style: measureStyle }, renderContent(midIndex)), finalContent); return [allNodes, startMeasure]; }