react-text-ellipsis-tool
Version:
react-text-ellipsis tool , react version , button click event
100 lines (96 loc) • 3.95 kB
JavaScript
;
var jsxRuntime = require('react/jsx-runtime');
var react = require('react');
const TextEllipsis = react.forwardRef(({ content, rows = 2, dots = '...', expandText = 'More', collapseText = '', onClickAction, }, ref) => {
const [text, setText] = react.useState(content);
const [expanded, setExpanded] = react.useState(false);
const [hasAction, setHasAction] = react.useState(false);
const rootRef = react.useRef(null);
const actionRef = react.useRef(null);
const actionText = expanded ? collapseText : expandText;
const pxToNum = (value) => {
if (!value)
return 0;
const match = value.match(/^\d*(\.\d*)?/);
return match ? Number(match[0]) : 0;
};
// 复制容器
const cloneContainer = () => {
if (!rootRef.current || !rootRef.current.isConnected)
return;
const originStyle = window.getComputedStyle(rootRef.current);
const container = document.createElement('div');
const styleNames = Array.from(originStyle);
styleNames.forEach((name) => {
container.style.setProperty(name, originStyle.getPropertyValue(name));
});
container.style.position = 'fixed';
container.style.zIndex = '-9999';
container.style.top = '-9999px';
container.style.height = 'auto';
container.style.minHeight = 'auto';
container.style.maxHeight = 'auto';
container.innerText = content;
document.body.appendChild(container);
return container;
};
// 计算省略的文字
const calcEllipsisText = (container, maxHeight) => {
const end = content.length;
const actionHTML = expandText;
const calcEllipse = () => {
// calculate the former or later content
const tail = (left, right) => {
if (right - left <= 1) {
return content.slice(0, left) + dots;
}
const middle = Math.round((left + right) / 2);
// Set the interception location
container.innerText = content.slice(0, middle) + dots;
container.innerHTML += actionHTML;
// The height after interception still does not match the rquired height
if (container.offsetHeight > maxHeight) {
return tail(left, middle);
}
return tail(middle, right);
};
return tail(0, end);
};
return calcEllipse();
};
const calcEllipsis = () => {
const container = cloneContainer();
const { paddingBottom, paddingTop, lineHeight } = container.style;
const maxHeight = Math.ceil((Number(rows) + 0.5) * pxToNum(lineHeight) + pxToNum(paddingTop) + pxToNum(paddingBottom));
if (maxHeight < container.offsetHeight) {
setHasAction(true);
setText(calcEllipsisText(container, maxHeight));
}
else {
setHasAction(false);
setText(content);
}
document.body.removeChild(container);
};
const toggle = () => {
setExpanded(!expanded);
};
const onClickActionHandler = (event) => {
toggle();
onClickAction(event);
};
const renderAction = () => (jsxRuntime.jsx("span", { ref: actionRef, onClick: onClickActionHandler, children: actionText }));
react.useEffect(() => {
calcEllipsis();
window.addEventListener('resize', calcEllipsis);
return () => {
window.removeEventListener('resize', calcEllipsis);
};
}, [content, rows]);
react.useImperativeHandle(ref, () => ({
toggle,
}));
return (jsxRuntime.jsxs("div", { ref: rootRef, className: "text-ellipsis w-full", children: [expanded ? content : text, hasAction && renderAction()] }));
});
module.exports = TextEllipsis;
//# sourceMappingURL=index.cjs.js.map