|
| 1 | +import type { ComponentType } from 'react'; |
| 2 | +import { useEffect, useMemo, useState } from 'react'; |
| 3 | +import type { TooltipProps } from 'antd'; |
| 4 | +import { Tooltip } from 'antd'; |
| 5 | +import type { EllipsisConfig } from 'antd/es/typography/Base'; |
| 6 | +import type { ParagraphProps } from 'antd/es/typography/Paragraph'; |
| 7 | +import type { TextProps } from 'antd/es/typography/Text'; |
| 8 | +import type { TitleProps } from 'antd/es/typography/Title'; |
| 9 | + |
| 10 | +function withEllipsisTypography<T extends TextProps | ParagraphProps | TitleProps>( |
| 11 | + Component: ComponentType<MakeEllipsisTypographyProps<T>> |
| 12 | +) { |
| 13 | + return function EllipsisText(props: MakeEllipsisTypographyProps<T>) { |
| 14 | + const { ellipsis, text, ...rest } = props; |
| 15 | + const [isEllipsis, setIsEllipsis] = useState(false); |
| 16 | + const [dom, setDom] = useState<HTMLElement | null>(null); |
| 17 | + const isAutoEllipsis = useMemo(() => ellipsis === true, [ellipsis]); |
| 18 | + const isAutoTooltip = useMemo(() => typeof ellipsis === 'object' && ellipsis.tooltip === true, [ellipsis]); |
| 19 | + const isAutoTooltipTitle = useMemo( |
| 20 | + () => |
| 21 | + typeof ellipsis === 'object' && |
| 22 | + ellipsis.tooltip && |
| 23 | + typeof ellipsis.tooltip === 'object' && |
| 24 | + 'title' in ellipsis.tooltip && |
| 25 | + ellipsis.tooltip.title === true, |
| 26 | + [ellipsis] |
| 27 | + ); |
| 28 | + const isAuto = useMemo( |
| 29 | + () => isAutoEllipsis || isAutoTooltip || isAutoTooltipTitle, |
| 30 | + [isAutoEllipsis, isAutoTooltip, isAutoTooltipTitle] |
| 31 | + ); |
| 32 | + const tooltipTitle = useMemo(() => (isEllipsis ? text : undefined), [isEllipsis, text]); |
| 33 | + |
| 34 | + useEffect(() => { |
| 35 | + if (dom && isAuto) { |
| 36 | + Promise.resolve().then(() => { |
| 37 | + setIsEllipsis(dom.scrollWidth > dom.clientWidth || dom.scrollHeight > dom.clientHeight); |
| 38 | + }); |
| 39 | + } |
| 40 | + }, [text, isAuto, dom]); |
| 41 | + |
| 42 | + return ( |
| 43 | + <Tooltip title={tooltipTitle}> |
| 44 | + <Component |
| 45 | + ref={setDom} |
| 46 | + // eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 47 | + {...(rest as any)} |
| 48 | + ellipsis={ |
| 49 | + isAutoEllipsis |
| 50 | + ? { tooltip: undefined } |
| 51 | + : isAutoTooltip |
| 52 | + ? { |
| 53 | + ...(ellipsis as EllipsisConfig), |
| 54 | + tooltip: undefined, |
| 55 | + } |
| 56 | + : isAutoTooltipTitle |
| 57 | + ? { |
| 58 | + ...(ellipsis as EllipsisConfig), |
| 59 | + tooltip: { |
| 60 | + ...((ellipsis as EllipsisConfig)?.tooltip as TooltipProps), |
| 61 | + title: undefined, |
| 62 | + }, |
| 63 | + } |
| 64 | + : ellipsis |
| 65 | + } |
| 66 | + > |
| 67 | + {text} |
| 68 | + </Component> |
| 69 | + </Tooltip> |
| 70 | + ); |
| 71 | + }; |
| 72 | +} |
| 73 | + |
| 74 | +export type MakeEllipsisTypographyProps<T> = Omit<T, 'children'> & { |
| 75 | + text: string | undefined; |
| 76 | +}; |
| 77 | + |
| 78 | +export default withEllipsisTypography; |
0 commit comments