mirror of
https://github.com/kremalicious/umami.git
synced 2024-11-15 09:45:04 +01:00
67 lines
1.7 KiB
JavaScript
67 lines
1.7 KiB
JavaScript
import PropTypes from 'prop-types';
|
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
import ReactTooltip from 'react-tooltip';
|
|
|
|
import styles from './OverflowText.module.css';
|
|
|
|
const OverflowText = ({ children, tooltipId }) => {
|
|
const measureEl = useRef();
|
|
const [isOverflown, setIsOverflown] = useState(false);
|
|
|
|
const measure = useCallback(
|
|
el => {
|
|
if (!el) return;
|
|
setIsOverflown(el.scrollWidth > el.clientWidth);
|
|
},
|
|
[setIsOverflown],
|
|
);
|
|
|
|
// Do one measure on mount
|
|
useEffect(() => {
|
|
measure(measureEl.current);
|
|
}, [measure]);
|
|
|
|
// Set up resize listener for subsequent measures
|
|
useEffect(() => {
|
|
if (!measureEl.current) return;
|
|
|
|
// Destructure ref in case it changes out from under us
|
|
const el = measureEl.current;
|
|
|
|
if ('ResizeObserver' in global) {
|
|
// Ideally, we have access to ResizeObservers
|
|
const observer = new ResizeObserver(() => {
|
|
measure(el);
|
|
});
|
|
observer.observe(el);
|
|
return () => observer.unobserve(el);
|
|
} else {
|
|
// Otherwise, fall back to measuring on window resizes
|
|
const handler = () => measure(el);
|
|
|
|
window.addEventListener('resize', handler, { passive: true });
|
|
return () => window.removeEventListener('resize', handler, { passive: true });
|
|
}
|
|
});
|
|
|
|
return (
|
|
<span
|
|
ref={measureEl}
|
|
data-tip={children.toString()}
|
|
data-effect="solid"
|
|
data-for={tooltipId}
|
|
className={styles.root}
|
|
>
|
|
{children}
|
|
{isOverflown && <ReactTooltip id={tooltipId}>{children}</ReactTooltip>}
|
|
</span>
|
|
);
|
|
};
|
|
|
|
OverflowText.propTypes = {
|
|
children: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
|
|
tooltipId: PropTypes.string.isRequired,
|
|
};
|
|
|
|
export default OverflowText;
|