react-text-ellipsis-tool
Version:
react-text-ellipsis tool , react version , button click event
98 lines (95 loc) • 3.93 kB
JavaScript
import { jsxs, jsx } from 'react/jsx-runtime';
import { forwardRef, useState, useRef, useEffect, useImperativeHandle } from 'react';
const TextEllipsis = forwardRef(({ content, rows = 2, dots = '...', expandText = 'More', collapseText = '', onClickAction, }, ref) => {
const [text, setText] = useState(content);
const [expanded, setExpanded] = useState(false);
const [hasAction, setHasAction] = useState(false);
const rootRef = useRef(null);
const actionRef = 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 = () => (jsx("span", { ref: actionRef, onClick: onClickActionHandler, children: actionText }));
useEffect(() => {
calcEllipsis();
window.addEventListener('resize', calcEllipsis);
return () => {
window.removeEventListener('resize', calcEllipsis);
};
}, [content, rows]);
useImperativeHandle(ref, () => ({
toggle,
}));
return (jsxs("div", { ref: rootRef, className: "text-ellipsis w-full", children: [expanded ? content : text, hasAction && renderAction()] }));
});
export { TextEllipsis as default };
//# sourceMappingURL=index.esm.js.map