@nutui/nutui-react
Version:
京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序
194 lines (193 loc) • 7.98 kB
JavaScript
import { _ as _define_property } from "@swc/helpers/_/_define_property";
import { _ as _object_spread } from "@swc/helpers/_/_object_spread";
import { _ as _object_spread_props } from "@swc/helpers/_/_object_spread_props";
import { _ as _object_without_properties } from "@swc/helpers/_/_object_without_properties";
import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array";
import React, { useState, useRef } from "react";
import classNames from "classnames";
import { ComponentDefaults } from "../../utils/typings";
import { useIsomorphicLayoutEffect } from "../../hooks/use-isomprphic-layout-effect";
import { useRtl } from "../configprovider";
var defaultProps = _object_spread_props(_object_spread({}, ComponentDefaults), {
content: '',
direction: 'end',
rows: 1,
expandText: '',
collapseText: '',
symbol: '...',
lineHeight: '20'
});
var classPrefix = "nut-ellipsis";
export var Ellipsis = function(props) {
var _ellipsis_current, _ellipsis_current1;
var _ref = _object_spread({}, defaultProps, props), children = _ref.children, content = _ref.content, className = _ref.className, direction = _ref.direction, rows = _ref.rows, expandText = _ref.expandText, collapseText = _ref.collapseText, symbol = _ref.symbol, lineHeight = _ref.lineHeight, onClick = _ref.onClick, onChange = _ref.onChange, rest = _object_without_properties(_ref, [
"children",
"content",
"className",
"direction",
"rows",
"expandText",
"collapseText",
"symbol",
"lineHeight",
"onClick",
"onChange"
]);
var rtl = useRtl();
var container = null;
var maxHeight = 0;
var _useState = _sliced_to_array(useState(false), 2), exceeded = _useState[0], setExceeded = _useState[1];
var _useState1 = _sliced_to_array(useState(false), 2), expanded = _useState1[0], setExpanded = _useState1[1];
var ellipsis = useRef();
var root = useRef(null);
var rtlClasses = classNames(_define_property({}, "".concat(classPrefix, "-rtl"), rtl));
var classes = classNames(classPrefix, rtlClasses, className);
useIsomorphicLayoutEffect(function() {
if (content) {
createContainer();
}
}, [
content
]);
// 创建虚拟 container,内容为 contant 的内容
var createContainer = function() {
if (!root.current) return;
var originStyle = window.getComputedStyle(root.current);
container = document.createElement('div');
var styleNames = Array.prototype.slice.apply(originStyle);
styleNames.forEach(function(name) {
container.style.setProperty(name, originStyle.getPropertyValue(name));
});
container.style.position = 'fixed';
container.style.left = '999999px';
container.style.top = '999999px';
container.style.zIndex = '-1000';
container.style.height = 'auto';
container.style.minHeight = 'auto';
container.style.maxHeight = 'auto';
container.style.textOverflow = 'clip';
container.style.whiteSpace = 'normal';
container.style.webkitLineClamp = 'unset';
container.style.display = 'block';
var lineH = pxToNumber(originStyle.lineHeight === 'normal' ? lineHeight : originStyle.lineHeight);
maxHeight = Math.floor(lineH * (Number(rows) + 0.5) + pxToNumber(originStyle.paddingTop) + pxToNumber(originStyle.paddingBottom));
container.innerText = content;
document.body.appendChild(container);
calcEllipse();
document.body.removeChild(container);
};
// 计算省略号的位置
var calcEllipse = function() {
if (container.offsetHeight <= maxHeight) {
setExceeded(false);
} else {
setExceeded(true);
var end = content.length;
var middle = Math.floor((0 + end) / 2);
var ellipsised = direction === 'middle' ? tailorMiddle([
0,
middle
], [
middle,
end
]) : tailor(0, end);
ellipsis.current = ellipsised;
}
};
// 计算 start/end 省略
var tailor = function(left, right) {
var actionText = expanded ? collapseText : expandText;
var end = content.length;
if (right - left <= 1) {
if (direction === 'end') {
return {
leading: content.slice(0, left) + symbol
};
}
return {
tailing: symbol + content.slice(right, end)
};
}
var middle = Math.round((left + right) / 2);
if (direction === 'end') {
container.innerText = content.slice(0, middle) + symbol + actionText;
} else {
container.innerText = actionText + symbol + content.slice(middle, end);
}
if (container.offsetHeight <= maxHeight) {
if (direction === 'end') {
return tailor(middle, right);
}
return tailor(left, middle);
}
if (direction === 'end') {
return tailor(left, middle);
}
return tailor(middle, right);
};
// 计算 middle 省略
var tailorMiddle = function(leftPart, rightPart) {
var actionText = expanded ? collapseText : expandText;
var end = content.length;
if (leftPart[1] - leftPart[0] <= 1 && rightPart[1] - rightPart[0] <= 1) {
return {
leading: content.slice(0, leftPart[0]) + symbol,
tailing: symbol + content.slice(rightPart[1], end)
};
}
var leftPartMiddle = Math.floor((leftPart[0] + leftPart[1]) / 2);
var rightPartMiddle = Math.ceil((rightPart[0] + rightPart[1]) / 2);
container.innerText = content.slice(0, leftPartMiddle) + symbol + actionText + symbol + content.slice(rightPartMiddle, end);
if (container.offsetHeight <= maxHeight) {
return tailorMiddle([
leftPartMiddle,
leftPart[1]
], [
rightPart[0],
rightPartMiddle
]);
}
return tailorMiddle([
leftPart[0],
leftPartMiddle
], [
rightPartMiddle,
rightPart[1]
]);
};
var pxToNumber = function(value) {
if (!value) return 0;
var match = value.match(/^\d*(\.\d*)?/);
return match ? Number(match[0]) : 0;
};
var clickHandle = function(type) {
if (type === 1) {
setExpanded(true);
onChange && onChange('expand');
} else {
setExpanded(false);
onChange && onChange('collapse');
}
};
var handleClick = function() {
onClick && onClick();
};
return /*#__PURE__*/ React.createElement("div", _object_spread({
className: classes,
onClick: handleClick,
ref: root
}, rest), !exceeded ? content : null, exceeded && !expanded ? /*#__PURE__*/ React.createElement("span", null, (_ellipsis_current = ellipsis.current) === null || _ellipsis_current === void 0 ? void 0 : _ellipsis_current.leading, expandText ? /*#__PURE__*/ React.createElement("span", {
className: "nut-ellipsis-text",
onClick: function(e) {
e.stopPropagation();
clickHandle(1);
}
}, expandText) : null, (_ellipsis_current1 = ellipsis.current) === null || _ellipsis_current1 === void 0 ? void 0 : _ellipsis_current1.tailing) : null, exceeded && expanded ? /*#__PURE__*/ React.createElement("span", null, content, expandText ? /*#__PURE__*/ React.createElement("span", {
className: "nut-ellipsis-text",
onClick: function(e) {
e.stopPropagation();
clickHandle(2);
}
}, collapseText) : null) : null);
};
Ellipsis.displayName = 'NutEllipsis';