mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-12-02 03:59:01 +08:00
refactor: Use native css for measure css line ellipsis (#47597)
* chore: init * chore: ellpsis check with native css * docs: all the lines * chore: move copied btn out * chore: add dpes * fix: logic order * fix: ellipsis event * test: update testcase * chore: use native way * chore: destructure * chore: fix lint * chore: fix lint * chore: fix lint
This commit is contained in:
parent
c06dc8e960
commit
72ee4517f0
@ -4593,22 +4593,6 @@ exports[`renders components/form/demo/label-debug.tsx correctly 1`] = `
|
||||
class="ant-typography ant-typography-ellipsis ant-typography-single-line"
|
||||
>
|
||||
longtextlongtextlongtextlongtextlongtextlongtextlongtext
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;word-break:keep-all;white-space:nowrap"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;width:0;white-space:normal;margin:0;padding:0"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
@ -4651,22 +4635,6 @@ exports[`renders components/form/demo/label-debug.tsx correctly 1`] = `
|
||||
class="ant-typography ant-typography-ellipsis ant-typography-single-line"
|
||||
>
|
||||
longtext longtext longtext longtext longtext longtext longtext
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;word-break:keep-all;white-space:nowrap"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;width:0;white-space:normal;margin:0;padding:0"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
@ -1826,22 +1826,6 @@ Array [
|
||||
class="ant-typography ant-typography-ellipsis ant-typography-single-line"
|
||||
>
|
||||
Ant Design, a design language for background applications, is refined by Ant UED Team
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;word-break:keep-all;white-space:nowrap"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;width:0;white-space:normal;margin:0;padding:0"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
|
50
components/typography/Base/CopyBtn.tsx
Normal file
50
components/typography/Base/CopyBtn.tsx
Normal file
@ -0,0 +1,50 @@
|
||||
import * as React from 'react';
|
||||
import CheckOutlined from '@ant-design/icons/CheckOutlined';
|
||||
import CopyOutlined from '@ant-design/icons/CopyOutlined';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import type { CopyConfig } from '.';
|
||||
import TransButton from '../../_util/transButton';
|
||||
import { type Locale } from '../../locale';
|
||||
import Tooltip from '../../tooltip';
|
||||
import { getNode, toList } from './util';
|
||||
|
||||
export interface CopyBtnProps extends CopyConfig {
|
||||
prefixCls: string;
|
||||
copied: boolean;
|
||||
locale: Locale['Text'];
|
||||
onCopy: React.MouseEventHandler<HTMLDivElement>;
|
||||
iconOnly: boolean;
|
||||
}
|
||||
|
||||
export default function CopyBtn(props: CopyBtnProps) {
|
||||
const { prefixCls, copied, locale = {}, onCopy, iconOnly, tooltips, icon } = props;
|
||||
|
||||
const tooltipNodes = toList(tooltips);
|
||||
const iconNodes = toList(icon);
|
||||
|
||||
const { copied: copiedText, copy: copyText } = locale;
|
||||
|
||||
const copyTitle = copied
|
||||
? getNode(tooltipNodes[1], copiedText)
|
||||
: getNode(tooltipNodes[0], copyText);
|
||||
const systemStr = copied ? copiedText : copyText;
|
||||
const ariaLabel = typeof copyTitle === 'string' ? copyTitle : systemStr;
|
||||
|
||||
return (
|
||||
<Tooltip key="copy" title={copyTitle}>
|
||||
<TransButton
|
||||
className={classNames(`${prefixCls}-copy`, {
|
||||
[`${prefixCls}-copy-success`]: copied,
|
||||
[`${prefixCls}-copy-icon-only`]: iconOnly,
|
||||
})}
|
||||
onClick={onCopy}
|
||||
aria-label={ariaLabel}
|
||||
>
|
||||
{copied
|
||||
? getNode(iconNodes[1], <CheckOutlined />, true)
|
||||
: getNode(iconNodes[0], <CopyOutlined />, true)}
|
||||
</TransButton>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
@ -1,17 +1,53 @@
|
||||
import * as React from 'react';
|
||||
import toArray from 'rc-util/lib/Children/toArray';
|
||||
import useIsomorphicLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect';
|
||||
import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect';
|
||||
|
||||
export interface EllipsisProps {
|
||||
enabledMeasure?: boolean;
|
||||
text?: React.ReactNode;
|
||||
width: number;
|
||||
fontSize: number;
|
||||
rows: number;
|
||||
children: (cutChildren: React.ReactNode[], needEllipsis: boolean) => React.ReactNode;
|
||||
onEllipsis: (isEllipsis: boolean) => void;
|
||||
interface MeasureTextProps {
|
||||
style?: React.CSSProperties;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
interface MeasureTextRef {
|
||||
isExceed: () => boolean;
|
||||
getHeight: () => number;
|
||||
}
|
||||
|
||||
const MeasureText = React.forwardRef<MeasureTextRef, MeasureTextProps>(
|
||||
({ style, children }, ref) => {
|
||||
const spanRef = React.useRef<HTMLSpanElement>(null);
|
||||
|
||||
React.useImperativeHandle(ref, () => ({
|
||||
isExceed: () => {
|
||||
const span = spanRef.current!;
|
||||
return span.scrollHeight > span.clientHeight;
|
||||
},
|
||||
getHeight: () => spanRef.current!.clientHeight,
|
||||
}));
|
||||
|
||||
return (
|
||||
<span
|
||||
aria-hidden
|
||||
ref={spanRef}
|
||||
style={{
|
||||
position: 'fixed',
|
||||
display: 'block',
|
||||
left: 0,
|
||||
top: 0,
|
||||
// zIndex: -9999,
|
||||
// visibility: 'hidden',
|
||||
pointerEvents: 'none',
|
||||
|
||||
backgroundColor: 'rgba(255, 0, 0, 0.65)',
|
||||
|
||||
...style,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
function cuttable(node: React.ReactElement) {
|
||||
const type = typeof node;
|
||||
return type === 'string' || type === 'number';
|
||||
@ -61,112 +97,141 @@ function sliceNodes(nodeList: React.ReactElement[], len: number) {
|
||||
return nodeList;
|
||||
}
|
||||
|
||||
const NONE = 0;
|
||||
const PREPARE = 1;
|
||||
const WALKING = 2;
|
||||
const DONE_WITH_ELLIPSIS = 3;
|
||||
const DONE_WITHOUT_ELLIPSIS = 4;
|
||||
export interface EllipsisProps {
|
||||
enabledMeasure?: boolean;
|
||||
text?: React.ReactNode;
|
||||
width: number;
|
||||
// fontSize: number;
|
||||
rows: number;
|
||||
children: (
|
||||
cutChildren: React.ReactNode[],
|
||||
/** Tell current `cutChildren` is in ellipsis */
|
||||
inEllipsis: boolean,
|
||||
/** Tell current `text` is exceed the `rows` which can be ellipsis */
|
||||
canEllipsis: boolean,
|
||||
) => React.ReactNode;
|
||||
onEllipsis: (isEllipsis: boolean) => void;
|
||||
/**
|
||||
* Mark for misc update. Which will not affect ellipsis content length.
|
||||
* e.g. tooltip content update.
|
||||
*/
|
||||
miscDeps: any[];
|
||||
}
|
||||
|
||||
type WalkingState =
|
||||
| typeof NONE
|
||||
| typeof PREPARE
|
||||
| typeof WALKING
|
||||
| typeof DONE_WITH_ELLIPSIS
|
||||
| typeof DONE_WITHOUT_ELLIPSIS;
|
||||
// Measure for the `text` is exceed the `rows` or not
|
||||
const STATUS_MEASURE_NONE = 0;
|
||||
const STATUS_MEASURE_START = 1;
|
||||
const STATUS_MEASURE_NEED_ELLIPSIS = 2;
|
||||
const STATUS_MEASURE_NO_NEED_ELLIPSIS = 3;
|
||||
|
||||
const Ellipsis: React.FC<EllipsisProps> = ({
|
||||
enabledMeasure,
|
||||
children,
|
||||
text,
|
||||
width,
|
||||
fontSize,
|
||||
rows,
|
||||
onEllipsis,
|
||||
}) => {
|
||||
const [[startLen, midLen, endLen], setCutLength] = React.useState<
|
||||
[startLen: number, midLen: number, endLen: number]
|
||||
>([0, 0, 0]);
|
||||
// record last done with ellipsis width
|
||||
const [lastLen, setLastLen] = React.useState(0);
|
||||
const [walkingState, setWalkingState] = React.useState<WalkingState>(NONE);
|
||||
const lineClipStyle: React.CSSProperties = {
|
||||
display: '-webkit-box',
|
||||
overflow: 'hidden',
|
||||
WebkitBoxOrient: 'vertical',
|
||||
};
|
||||
|
||||
const [singleRowHeight, setSingleRowHeight] = React.useState(0);
|
||||
|
||||
const singleRowRef = React.useRef<HTMLElement>(null);
|
||||
const midRowRef = React.useRef<HTMLElement>(null);
|
||||
export default function EllipsisMeasure(props: EllipsisProps) {
|
||||
const { enabledMeasure, width, text, children, rows, miscDeps, onEllipsis } = props;
|
||||
|
||||
const nodeList = React.useMemo(() => toArray(text), [text]);
|
||||
const totalLen = React.useMemo(() => getNodesLen(nodeList), [nodeList]);
|
||||
const nodeLen = React.useMemo(() => getNodesLen(nodeList), [text]);
|
||||
|
||||
const mergedChildren = React.useMemo(() => {
|
||||
if (!enabledMeasure || walkingState !== DONE_WITH_ELLIPSIS) {
|
||||
// if has lastLen, use it as temporary width to avoid lots of text to squeeze space.
|
||||
if (lastLen && walkingState !== DONE_WITHOUT_ELLIPSIS && enabledMeasure)
|
||||
return children(sliceNodes(nodeList, lastLen), lastLen < totalLen);
|
||||
// ========================= Full Content =========================
|
||||
const fullContent = React.useMemo(() => children(nodeList, false, false), [text]);
|
||||
|
||||
return children(nodeList, false);
|
||||
// ========================= Cut Content ==========================
|
||||
const [ellipsisCutIndex, setEllipsisCutIndex] = React.useState<[number, number] | null>(null);
|
||||
const cutMidRef = React.useRef<MeasureTextRef>(null);
|
||||
|
||||
// ========================= NeedEllipsis =========================
|
||||
const needEllipsisRef = React.useRef<MeasureTextRef>(null);
|
||||
|
||||
const [needEllipsis, setNeedEllipsis] = React.useState(STATUS_MEASURE_NONE);
|
||||
const [ellipsisHeight, setEllipsisHeight] = React.useState(0);
|
||||
|
||||
// Trigger start measure
|
||||
useLayoutEffect(() => {
|
||||
if (enabledMeasure && width && nodeLen) {
|
||||
setNeedEllipsis(STATUS_MEASURE_START);
|
||||
} else {
|
||||
setNeedEllipsis(STATUS_MEASURE_NONE);
|
||||
}
|
||||
}, [width, text, rows, enabledMeasure, nodeList]);
|
||||
|
||||
return children(sliceNodes(nodeList, midLen), midLen < totalLen);
|
||||
}, [enabledMeasure, walkingState, children, nodeList, midLen, totalLen]);
|
||||
// Measure process
|
||||
useLayoutEffect(() => {
|
||||
if (needEllipsis === STATUS_MEASURE_START) {
|
||||
const isOverflow = !!needEllipsisRef.current?.isExceed();
|
||||
|
||||
// ======================== Walk ========================
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
if (enabledMeasure && width && fontSize && totalLen) {
|
||||
setWalkingState(PREPARE);
|
||||
setCutLength([0, Math.ceil(totalLen / 2), totalLen]);
|
||||
setNeedEllipsis(isOverflow ? STATUS_MEASURE_NEED_ELLIPSIS : STATUS_MEASURE_NO_NEED_ELLIPSIS);
|
||||
setEllipsisCutIndex(isOverflow ? [0, nodeLen] : null);
|
||||
|
||||
// For the accuracy issue, we add 1px to the height
|
||||
setEllipsisHeight((needEllipsisRef.current?.getHeight() || 0) + 1);
|
||||
|
||||
onEllipsis(isOverflow);
|
||||
}
|
||||
}, [enabledMeasure, width, fontSize, text, totalLen, rows]);
|
||||
}, [needEllipsis]);
|
||||
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
if (walkingState === PREPARE) {
|
||||
setSingleRowHeight(singleRowRef.current?.offsetHeight || 0);
|
||||
}
|
||||
}, [walkingState]);
|
||||
// ========================= Cut Measure ==========================
|
||||
const cutMidIndex = ellipsisCutIndex
|
||||
? Math.ceil((ellipsisCutIndex[0] + ellipsisCutIndex[1]) / 2)
|
||||
: 0;
|
||||
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
if (singleRowHeight) {
|
||||
if (walkingState === PREPARE) {
|
||||
// Ignore if position is enough
|
||||
const midHeight = midRowRef.current?.offsetHeight || 0;
|
||||
const maxHeight = rows * singleRowHeight;
|
||||
useLayoutEffect(() => {
|
||||
const [minIndex, maxIndex] = ellipsisCutIndex || [0, 0];
|
||||
if (minIndex !== maxIndex) {
|
||||
const midHeight = cutMidRef.current?.getHeight() || 0;
|
||||
|
||||
if (midHeight <= maxHeight) {
|
||||
setWalkingState(DONE_WITHOUT_ELLIPSIS);
|
||||
onEllipsis(false);
|
||||
} else {
|
||||
setWalkingState(WALKING);
|
||||
}
|
||||
} else if (walkingState === WALKING) {
|
||||
if (startLen !== endLen) {
|
||||
const midHeight = midRowRef.current?.offsetHeight || 0;
|
||||
const maxHeight = rows * singleRowHeight;
|
||||
const isOverflow = midHeight > ellipsisHeight;
|
||||
let targetMidIndex = cutMidIndex;
|
||||
|
||||
let nextStartLen = startLen;
|
||||
let nextEndLen = endLen;
|
||||
if (maxIndex - minIndex === 1) {
|
||||
targetMidIndex = isOverflow ? minIndex : maxIndex;
|
||||
}
|
||||
|
||||
// We reach the last round
|
||||
if (startLen === endLen - 1) {
|
||||
nextEndLen = startLen;
|
||||
} else if (midHeight <= maxHeight) {
|
||||
nextStartLen = midLen;
|
||||
} else {
|
||||
nextEndLen = midLen;
|
||||
}
|
||||
|
||||
const nextMidLen = Math.ceil((nextStartLen + nextEndLen) / 2);
|
||||
|
||||
setCutLength([nextStartLen, nextMidLen, nextEndLen]);
|
||||
} else {
|
||||
setWalkingState(DONE_WITH_ELLIPSIS);
|
||||
setLastLen(midLen);
|
||||
onEllipsis(true);
|
||||
}
|
||||
if (isOverflow) {
|
||||
setEllipsisCutIndex([minIndex, targetMidIndex]);
|
||||
} else {
|
||||
setEllipsisCutIndex([targetMidIndex, maxIndex]);
|
||||
}
|
||||
}
|
||||
}, [walkingState, startLen, endLen, rows, singleRowHeight]);
|
||||
}, [ellipsisCutIndex, cutMidIndex]);
|
||||
|
||||
// ======================= Render =======================
|
||||
// ========================= Text Content =========================
|
||||
const finalContent = React.useMemo(() => {
|
||||
if (
|
||||
needEllipsis !== STATUS_MEASURE_NEED_ELLIPSIS ||
|
||||
!ellipsisCutIndex ||
|
||||
ellipsisCutIndex[0] !== ellipsisCutIndex[1]
|
||||
) {
|
||||
const content = children(nodeList, false, false);
|
||||
|
||||
// Limit the max line count to avoid scrollbar blink
|
||||
// https://github.com/ant-design/ant-design/issues/42958
|
||||
if (
|
||||
needEllipsis !== STATUS_MEASURE_NO_NEED_ELLIPSIS &&
|
||||
needEllipsis !== STATUS_MEASURE_NONE
|
||||
) {
|
||||
return (
|
||||
<span
|
||||
style={{
|
||||
...lineClipStyle,
|
||||
WebkitLineClamp: rows,
|
||||
}}
|
||||
>
|
||||
{content}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
return children(sliceNodes(nodeList, ellipsisCutIndex[0]), true, true);
|
||||
}, [needEllipsis, ellipsisCutIndex, nodeList, ...miscDeps]);
|
||||
|
||||
// ============================ Render ============================
|
||||
const measureStyle: React.CSSProperties = {
|
||||
width,
|
||||
whiteSpace: 'normal',
|
||||
@ -174,58 +239,39 @@ const Ellipsis: React.FC<EllipsisProps> = ({
|
||||
padding: 0,
|
||||
};
|
||||
|
||||
const renderMeasure = (
|
||||
content: React.ReactNode,
|
||||
ref: React.Ref<HTMLElement>,
|
||||
style: React.CSSProperties,
|
||||
) => (
|
||||
<span
|
||||
aria-hidden
|
||||
ref={ref}
|
||||
style={{
|
||||
position: 'fixed',
|
||||
display: 'block',
|
||||
left: 0,
|
||||
top: 0,
|
||||
zIndex: -9999,
|
||||
visibility: 'hidden',
|
||||
pointerEvents: 'none',
|
||||
fontSize: Math.ceil(fontSize / 2) * 2,
|
||||
...style,
|
||||
}}
|
||||
>
|
||||
{content}
|
||||
</span>
|
||||
);
|
||||
|
||||
const renderMeasureSlice = (len: number, ref: React.Ref<HTMLElement>) => {
|
||||
const sliceNodeList = sliceNodes(nodeList, len);
|
||||
|
||||
return renderMeasure(children(sliceNodeList, true), ref, measureStyle);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{mergedChildren}
|
||||
{/* Measure usage */}
|
||||
{enabledMeasure &&
|
||||
walkingState !== DONE_WITH_ELLIPSIS &&
|
||||
walkingState !== DONE_WITHOUT_ELLIPSIS && (
|
||||
<>
|
||||
{/* `l` for top & `g` for bottom measure */}
|
||||
{renderMeasure('lg', singleRowRef, { wordBreak: 'keep-all', whiteSpace: 'nowrap' })}
|
||||
{/* {renderMeasureSlice(midLen, midRowRef)} */}
|
||||
{walkingState === PREPARE
|
||||
? renderMeasure(children(nodeList, false), midRowRef, measureStyle)
|
||||
: renderMeasureSlice(midLen, midRowRef)}
|
||||
</>
|
||||
{/* Final show content */}
|
||||
{finalContent}
|
||||
|
||||
{/* Measure if current content is exceed the rows */}
|
||||
{needEllipsis === STATUS_MEASURE_START && (
|
||||
<MeasureText
|
||||
style={{
|
||||
...measureStyle,
|
||||
...lineClipStyle,
|
||||
WebkitLineClamp: rows,
|
||||
}}
|
||||
ref={needEllipsisRef}
|
||||
>
|
||||
{fullContent}
|
||||
</MeasureText>
|
||||
)}
|
||||
|
||||
{/* Real size overflow measure */}
|
||||
{needEllipsis === STATUS_MEASURE_NEED_ELLIPSIS &&
|
||||
ellipsisCutIndex &&
|
||||
ellipsisCutIndex[0] !== ellipsisCutIndex[1] && (
|
||||
<MeasureText
|
||||
style={{
|
||||
...measureStyle,
|
||||
top: 400,
|
||||
}}
|
||||
ref={cutMidRef}
|
||||
>
|
||||
{children(sliceNodes(nodeList, cutMidIndex), true, true)}
|
||||
</MeasureText>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
Ellipsis.displayName = 'Ellipsis';
|
||||
}
|
||||
|
||||
export default Ellipsis;
|
||||
|
@ -1,6 +1,4 @@
|
||||
import * as React from 'react';
|
||||
import CheckOutlined from '@ant-design/icons/CheckOutlined';
|
||||
import CopyOutlined from '@ant-design/icons/CopyOutlined';
|
||||
import EditOutlined from '@ant-design/icons/EditOutlined';
|
||||
import classNames from 'classnames';
|
||||
import copy from 'copy-to-clipboard';
|
||||
@ -23,12 +21,13 @@ import useMergedConfig from '../hooks/useMergedConfig';
|
||||
import useUpdatedEffect from '../hooks/useUpdatedEffect';
|
||||
import type { TypographyProps } from '../Typography';
|
||||
import Typography from '../Typography';
|
||||
import CopyBtn from './CopyBtn';
|
||||
import Ellipsis from './Ellipsis';
|
||||
import EllipsisTooltip from './EllipsisTooltip';
|
||||
|
||||
export type BaseType = 'secondary' | 'success' | 'warning' | 'danger';
|
||||
|
||||
interface CopyConfig {
|
||||
export interface CopyConfig {
|
||||
text?: string;
|
||||
onCopy?: (event?: React.MouseEvent<HTMLDivElement>) => void;
|
||||
icon?: React.ReactNode;
|
||||
@ -104,20 +103,6 @@ function wrapperDecorations(
|
||||
return currentContent;
|
||||
}
|
||||
|
||||
function getNode(dom: React.ReactNode, defaultNode: React.ReactNode, needDom?: boolean) {
|
||||
if (dom === true || dom === undefined) {
|
||||
return defaultNode;
|
||||
}
|
||||
return dom || (needDom && defaultNode);
|
||||
}
|
||||
|
||||
function toList<T extends any>(val: T | T[]): T[] {
|
||||
if (val === false) {
|
||||
return [false, false] as T[];
|
||||
}
|
||||
return Array.isArray(val) ? val : [val];
|
||||
}
|
||||
|
||||
const ELLIPSIS_STR = '...';
|
||||
|
||||
const Base = React.forwardRef<HTMLElement, BlockProps>((props, ref) => {
|
||||
@ -288,10 +273,8 @@ const Base = React.forwardRef<HTMLElement, BlockProps>((props, ref) => {
|
||||
};
|
||||
|
||||
const [ellipsisWidth, setEllipsisWidth] = React.useState(0);
|
||||
const [ellipsisFontSize, setEllipsisFontSize] = React.useState(0);
|
||||
const onResize = ({ offsetWidth }: { offsetWidth: number }, element: HTMLElement) => {
|
||||
const onResize = ({ offsetWidth }: { offsetWidth: number }) => {
|
||||
setEllipsisWidth(offsetWidth);
|
||||
setEllipsisFontSize(parseInt(window.getComputedStyle?.(element).fontSize, 10) || 0);
|
||||
};
|
||||
|
||||
// >>>>> JS Ellipsis
|
||||
@ -455,32 +438,16 @@ const Base = React.forwardRef<HTMLElement, BlockProps>((props, ref) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { tooltips, icon } = copyConfig;
|
||||
|
||||
const tooltipNodes = toList(tooltips);
|
||||
const iconNodes = toList(icon);
|
||||
|
||||
const copyTitle = copied
|
||||
? getNode(tooltipNodes[1], textLocale?.copied)
|
||||
: getNode(tooltipNodes[0], textLocale?.copy);
|
||||
const systemStr = copied ? textLocale?.copied : textLocale?.copy;
|
||||
const ariaLabel = typeof copyTitle === 'string' ? copyTitle : systemStr;
|
||||
|
||||
return (
|
||||
<Tooltip key="copy" title={copyTitle}>
|
||||
<TransButton
|
||||
className={classNames(`${prefixCls}-copy`, {
|
||||
[`${prefixCls}-copy-success`]: copied,
|
||||
[`${prefixCls}-copy-icon-only`]: children === null || children === undefined,
|
||||
})}
|
||||
onClick={onCopyClick}
|
||||
aria-label={ariaLabel}
|
||||
>
|
||||
{copied
|
||||
? getNode(iconNodes[1], <CheckOutlined />, true)
|
||||
: getNode(iconNodes[0], <CopyOutlined />, true)}
|
||||
</TransButton>
|
||||
</Tooltip>
|
||||
<CopyBtn
|
||||
key="copy"
|
||||
{...copyConfig}
|
||||
prefixCls={prefixCls}
|
||||
copied={copied}
|
||||
locale={textLocale}
|
||||
onCopy={onCopyClick}
|
||||
iconOnly={children === null || children === undefined}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -538,8 +505,8 @@ const Base = React.forwardRef<HTMLElement, BlockProps>((props, ref) => {
|
||||
text={children}
|
||||
rows={rows}
|
||||
width={ellipsisWidth}
|
||||
fontSize={ellipsisFontSize}
|
||||
onEllipsis={onJsEllipsis}
|
||||
miscDeps={[copied, expanded]}
|
||||
>
|
||||
{(node, needEllipsis) => {
|
||||
let renderNode: React.ReactNode = node;
|
||||
|
13
components/typography/Base/util.ts
Normal file
13
components/typography/Base/util.ts
Normal file
@ -0,0 +1,13 @@
|
||||
export function toList<T extends any>(val: T | T[]): T[] {
|
||||
if (val === false) {
|
||||
return [false, false] as T[];
|
||||
}
|
||||
return Array.isArray(val) ? val : [val];
|
||||
}
|
||||
|
||||
export function getNode(dom: React.ReactNode, defaultNode: React.ReactNode, needDom?: boolean) {
|
||||
if (dom === true || dom === undefined) {
|
||||
return defaultNode;
|
||||
}
|
||||
return dom || (needDom && defaultNode);
|
||||
}
|
@ -797,69 +797,6 @@ Array [
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position: fixed; display: block; left: 0px; top: 0px; z-index: -9999; visibility: hidden; pointer-events: none; font-size: 0px; word-break: keep-all; white-space: nowrap;"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position: fixed; display: block; left: 0px; top: 0px; z-index: -9999; visibility: hidden; pointer-events: none; font-size: 0px; width: 0px; white-space: normal; margin: 0px; padding: 0px;"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
with suffix.
|
||||
<div
|
||||
aria-label="Edit"
|
||||
class="ant-typography-edit"
|
||||
role="button"
|
||||
style="border: 0px; background: transparent; padding: 0px; line-height: inherit; display: inline-block;"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
aria-label="edit"
|
||||
class="anticon anticon-edit"
|
||||
role="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="edit"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M257.7 752c2 0 4-.2 6-.5L431.9 722c2-.4 3.9-1.3 5.3-2.8l423.9-423.9a9.96 9.96 0 000-14.1L694.9 114.9c-1.9-1.9-4.4-2.9-7.1-2.9s-5.2 1-7.1 2.9L256.8 538.8c-1.5 1.5-2.4 3.3-2.8 5.3l-29.5 168.2a33.5 33.5 0 009.4 29.8c6.6 6.4 14.9 9.9 23.8 9.9zm67.4-174.4L687.8 215l73.3 73.3-362.7 362.6-88.9 15.7 15.6-89zM880 836H144c-17.7 0-32 14.3-32 32v36c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-36c0-17.7-14.3-32-32-32z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-tooltip-placement-top"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-arrow"
|
||||
style="position: absolute; bottom: 0px; left: 0px;"
|
||||
/>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-inner"
|
||||
role="tooltip"
|
||||
>
|
||||
Edit
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-typography"
|
||||
@ -1525,28 +1462,6 @@ Array [
|
||||
class="ant-typography ant-typography-ellipsis"
|
||||
>
|
||||
Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team.
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position: fixed; display: block; left: 0px; top: 0px; z-index: -9999; visibility: hidden; pointer-events: none; font-size: 0px; word-break: keep-all; white-space: nowrap;"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position: fixed; display: block; left: 0px; top: 0px; z-index: -9999; visibility: hidden; pointer-events: none; font-size: 0px; width: 0px; white-space: normal; margin: 0px; padding: 0px;"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
<a
|
||||
aria-label="Expand"
|
||||
class="ant-typography-expand"
|
||||
>
|
||||
more
|
||||
</a>
|
||||
</span>
|
||||
</div>,
|
||||
<span
|
||||
class="ant-typography ant-typography-ellipsis ant-typography-single-line ant-typography-ellipsis-single-line"
|
||||
@ -1802,68 +1717,6 @@ Array [
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position: fixed; display: block; left: 0px; top: 0px; z-index: -9999; visibility: hidden; pointer-events: none; font-size: 0px; word-break: keep-all; white-space: nowrap;"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position: fixed; display: block; left: 0px; top: 0px; z-index: -9999; visibility: hidden; pointer-events: none; font-size: 0px; width: 0px; white-space: normal; margin: 0px; padding: 0px;"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="ant-typography-copy"
|
||||
role="button"
|
||||
style="border: 0px; background: transparent; padding: 0px; line-height: inherit; display: inline-block;"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
aria-label="copy"
|
||||
class="anticon anticon-copy"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="copy"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-tooltip-placement-top"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-arrow"
|
||||
style="position: absolute; bottom: 0px; left: 0px;"
|
||||
/>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-inner"
|
||||
role="tooltip"
|
||||
>
|
||||
Copy
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</span>,
|
||||
<br />,
|
||||
<span
|
||||
@ -1918,68 +1771,6 @@ Array [
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position: fixed; display: block; left: 0px; top: 0px; z-index: -9999; visibility: hidden; pointer-events: none; font-size: 0px; word-break: keep-all; white-space: nowrap;"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position: fixed; display: block; left: 0px; top: 0px; z-index: -9999; visibility: hidden; pointer-events: none; font-size: 0px; width: 0px; white-space: normal; margin: 0px; padding: 0px;"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="ant-typography-copy"
|
||||
role="button"
|
||||
style="border: 0px; background: transparent; padding: 0px; line-height: inherit; display: inline-block;"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
aria-label="copy"
|
||||
class="anticon anticon-copy"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="copy"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-tooltip-placement-top"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-arrow"
|
||||
style="position: absolute; bottom: 0px; left: 0px;"
|
||||
/>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-inner"
|
||||
role="tooltip"
|
||||
>
|
||||
Copy
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</span>,
|
||||
<br />,
|
||||
<span
|
||||
@ -2034,68 +1825,6 @@ Array [
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position: fixed; display: block; left: 0px; top: 0px; z-index: -9999; visibility: hidden; pointer-events: none; font-size: 0px; word-break: keep-all; white-space: nowrap;"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position: fixed; display: block; left: 0px; top: 0px; z-index: -9999; visibility: hidden; pointer-events: none; font-size: 0px; width: 0px; white-space: normal; margin: 0px; padding: 0px;"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="ant-typography-copy"
|
||||
role="button"
|
||||
style="border: 0px; background: transparent; padding: 0px; line-height: inherit; display: inline-block;"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
aria-label="copy"
|
||||
class="anticon anticon-copy"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="copy"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-tooltip-placement-top"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-arrow"
|
||||
style="position: absolute; bottom: 0px; left: 0px;"
|
||||
/>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-inner"
|
||||
role="tooltip"
|
||||
>
|
||||
Copy
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</span>,
|
||||
<br />,
|
||||
<span
|
||||
@ -2150,68 +1879,6 @@ Array [
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position: fixed; display: block; left: 0px; top: 0px; z-index: -9999; visibility: hidden; pointer-events: none; font-size: 0px; word-break: keep-all; white-space: nowrap;"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position: fixed; display: block; left: 0px; top: 0px; z-index: -9999; visibility: hidden; pointer-events: none; font-size: 0px; width: 0px; white-space: normal; margin: 0px; padding: 0px;"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="ant-typography-copy"
|
||||
role="button"
|
||||
style="border: 0px; background: transparent; padding: 0px; line-height: inherit; display: inline-block;"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
aria-label="copy"
|
||||
class="anticon anticon-copy"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="copy"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-tooltip-placement-top"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-arrow"
|
||||
style="position: absolute; bottom: 0px; left: 0px;"
|
||||
/>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-inner"
|
||||
role="tooltip"
|
||||
>
|
||||
Copy
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</span>,
|
||||
<p>
|
||||
[Before]
|
||||
@ -2251,6 +1918,18 @@ Array [
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-typography ant-typography-ellipsis ant-typography-ellipsis-multiple-line"
|
||||
style="width: 300px;"
|
||||
>
|
||||
In the process of internal desktop applications development,
|
||||
<span
|
||||
style="font-size: 5em;"
|
||||
>
|
||||
ANTD
|
||||
</span>
|
||||
many different design specs and implementations would be involved, which might cause designers and developers difficulties and duplication and reduce the efficiency of development.
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
@ -2258,28 +1937,11 @@ exports[`renders components/typography/demo/ellipsis-debug.tsx extend context co
|
||||
|
||||
exports[`renders components/typography/demo/ellipsis-middle.tsx extend context correctly 1`] = `
|
||||
<span
|
||||
aria-label="In the process of internal desktop applications development, many different design specs and implementations would be involved, which might cause designers and developers difficulties and duplication and reduce the efficiency of"
|
||||
aria-label="In the process of internal desktop applications development, many different design specs and implementations would be involved, which might cause designers and developers difficulties and duplication and reduce the efficiency of "
|
||||
class="ant-typography ant-typography-ellipsis ant-typography-single-line"
|
||||
style="max-width: 100%;"
|
||||
>
|
||||
In the process of internal desktop applications development, many different design specs and implementations would be involved, which might cause designers and developers difficulties and duplication and reduce the efficiency ofdevelopment.
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position: fixed; display: block; left: 0px; top: 0px; z-index: -9999; visibility: hidden; pointer-events: none; font-size: 0px; word-break: keep-all; white-space: nowrap;"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position: fixed; display: block; left: 0px; top: 0px; z-index: -9999; visibility: hidden; pointer-events: none; font-size: 0px; width: 0px; white-space: normal; margin: 0px; padding: 0px;"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
development.
|
||||
</span>
|
||||
In the process of internal desktop applications development, many different design specs and implementations would be involved, which might cause designers and developers difficulties and duplication and reduce the efficiency of development.
|
||||
</span>
|
||||
`;
|
||||
|
||||
@ -2540,29 +2202,6 @@ Array [
|
||||
title="To be, or not to be, that is a question: Whether it is nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them? To die: to sleep; No more; and by a sleep to say we end The heart-ache and the thousand natural shocks That flesh is heir to, 'tis a consummation Devoutly to be wish'd. To die, to sleep To sleep- perchance to dream: ay, there's the rub! For in that sleep of death what dreams may come When we have shuffled off this mortal coil, Must give us pause. There 's the respect That makes calamity of so long life--William Shakespeare"
|
||||
>
|
||||
To be, or not to be, that is a question: Whether it is nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them? To die: to sleep; No more; and by a sleep to say we end The heart-ache and the thousand natural shocks That flesh is heir to, 'tis a consummation Devoutly to be wish'd. To die, to sleep To sleep- perchance to dream: ay, there's the rub! For in that sleep of death what dreams may come When we have shuffled off this mortal coil, Must give us pause. There 's the respect That makes calamity of so long life--William Shakespeare
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position: fixed; display: block; left: 0px; top: 0px; z-index: -9999; visibility: hidden; pointer-events: none; font-size: 0px; word-break: keep-all; white-space: nowrap;"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position: fixed; display: block; left: 0px; top: 0px; z-index: -9999; visibility: hidden; pointer-events: none; font-size: 0px; width: 0px; white-space: normal; margin: 0px; padding: 0px;"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
--William Shakespeare
|
||||
<a
|
||||
aria-label="Expand"
|
||||
class="ant-typography-expand"
|
||||
>
|
||||
Expand
|
||||
</a>
|
||||
</span>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
@ -664,50 +664,6 @@ Array [
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;word-break:keep-all;white-space:nowrap"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;width:0;white-space:normal;margin:0;padding:0"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
with suffix.
|
||||
<div
|
||||
aria-label="Edit"
|
||||
class="ant-typography-edit"
|
||||
role="button"
|
||||
style="border:0;background:transparent;padding:0;line-height:inherit;display:inline-block"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
aria-label="edit"
|
||||
class="anticon anticon-edit"
|
||||
role="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="edit"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M257.7 752c2 0 4-.2 6-.5L431.9 722c2-.4 3.9-1.3 5.3-2.8l423.9-423.9a9.96 9.96 0 000-14.1L694.9 114.9c-1.9-1.9-4.4-2.9-7.1-2.9s-5.2 1-7.1 2.9L256.8 538.8c-1.5 1.5-2.4 3.3-2.8 5.3l-29.5 168.2a33.5 33.5 0 009.4 29.8c6.6 6.4 14.9 9.9 23.8 9.9zm67.4-174.4L687.8 215l73.3 73.3-362.7 362.6-88.9 15.7 15.6-89zM880 836H144c-17.7 0-32 14.3-32 32v36c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-36c0-17.7-14.3-32-32-32z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-typography"
|
||||
@ -1161,50 +1117,12 @@ Array [
|
||||
class="ant-typography ant-typography-ellipsis ant-typography-single-line"
|
||||
>
|
||||
Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team.
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;word-break:keep-all;white-space:nowrap"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;width:0;white-space:normal;margin:0;padding:0"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
</span>
|
||||
</div>,
|
||||
<div
|
||||
aria-label="Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team."
|
||||
class="ant-typography ant-typography-ellipsis"
|
||||
>
|
||||
Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team. Ant Design, a design language for background applications, is refined by Ant UED Team.
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;word-break:keep-all;white-space:nowrap"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;width:0;white-space:normal;margin:0;padding:0"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
<a
|
||||
aria-label="Expand"
|
||||
class="ant-typography-expand"
|
||||
>
|
||||
more
|
||||
</a>
|
||||
</span>
|
||||
</div>,
|
||||
<span
|
||||
aria-label="Ant Design, a design language for background applications, is refined by Ant UED Team."
|
||||
@ -1212,22 +1130,6 @@ Array [
|
||||
style="width:200px"
|
||||
>
|
||||
Ant Design, a design language for background applications, is refined by Ant UED Team.
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;word-break:keep-all;white-space:nowrap"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;width:0;white-space:normal;margin:0;padding:0"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
aria-label="Ant Design, a design language for background applications, is refined by Ant UED Team."
|
||||
@ -1237,24 +1139,6 @@ Array [
|
||||
<code>
|
||||
Ant Design, a design language for background applications, is refined by Ant UED Team.
|
||||
</code>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;word-break:keep-all;white-space:nowrap"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;width:0;white-space:normal;margin:0;padding:0"
|
||||
>
|
||||
<code>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
</code>
|
||||
</span>
|
||||
</span>,
|
||||
]
|
||||
`;
|
||||
@ -1386,22 +1270,6 @@ Array [
|
||||
</span>
|
||||
<!-- -->
|
||||
case. Bnt Design, a design language for background applications, is refined by Ant UED Team. Cnt Design, a design language for background applications, is refined by Ant UED Team. Dnt Design, a design language for background applications, is refined by Ant UED Team. Ent Design, a design language for background applications, is refined by Ant UED Team.
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;word-break:keep-all;white-space:nowrap"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;width:0;white-space:normal;margin:0;padding:0"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
</span>
|
||||
</div>,
|
||||
<span
|
||||
aria-label="In the process of internal desktop applications development, many different design specs and implementations would be involved, which might cause designers and developers difficulties and duplication and reduce the efficiency of development."
|
||||
@ -1436,49 +1304,6 @@ Array [
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;word-break:keep-all;white-space:nowrap"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;width:0;white-space:normal;margin:0;padding:0"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="ant-typography-copy"
|
||||
role="button"
|
||||
style="border:0;background:transparent;padding:0;line-height:inherit;display:inline-block"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
aria-label="copy"
|
||||
class="anticon anticon-copy"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="copy"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</span>,
|
||||
<br />,
|
||||
<span
|
||||
@ -1514,49 +1339,6 @@ Array [
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;word-break:keep-all;white-space:nowrap"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;width:0;white-space:normal;margin:0;padding:0"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="ant-typography-copy"
|
||||
role="button"
|
||||
style="border:0;background:transparent;padding:0;line-height:inherit;display:inline-block"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
aria-label="copy"
|
||||
class="anticon anticon-copy"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="copy"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</span>,
|
||||
<br />,
|
||||
<span
|
||||
@ -1592,49 +1374,6 @@ Array [
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;word-break:keep-all;white-space:nowrap"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;width:0;white-space:normal;margin:0;padding:0"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="ant-typography-copy"
|
||||
role="button"
|
||||
style="border:0;background:transparent;padding:0;line-height:inherit;display:inline-block"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
aria-label="copy"
|
||||
class="anticon anticon-copy"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="copy"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</span>,
|
||||
<br />,
|
||||
<span
|
||||
@ -1670,49 +1409,6 @@ Array [
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;word-break:keep-all;white-space:nowrap"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;width:0;white-space:normal;margin:0;padding:0"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="ant-typography-copy"
|
||||
role="button"
|
||||
style="border:0;background:transparent;padding:0;line-height:inherit;display:inline-block"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
aria-label="copy"
|
||||
class="anticon anticon-copy"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="copy"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</span>,
|
||||
<p>
|
||||
[Before]
|
||||
@ -1721,22 +1417,6 @@ Array [
|
||||
class="ant-typography ant-typography-ellipsis ant-typography-single-line"
|
||||
>
|
||||
not ellipsis
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;word-break:keep-all;white-space:nowrap"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;width:0;white-space:normal;margin:0;padding:0"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
[After]
|
||||
</p>,
|
||||
@ -1749,53 +1429,32 @@ Array [
|
||||
style="width:100px"
|
||||
>
|
||||
默认display none 样式的超长文字, 悬停tooltip失效了
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;word-break:keep-all;white-space:nowrap"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;width:0;white-space:normal;margin:0;padding:0"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-typography ant-typography-ellipsis"
|
||||
style="width:300px"
|
||||
>
|
||||
In the process of internal desktop applications development,
|
||||
<span
|
||||
style="font-size:5em"
|
||||
>
|
||||
ANTD
|
||||
</span>
|
||||
many different design specs and implementations would be involved, which might cause designers and developers difficulties and duplication and reduce the efficiency of development.
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders components/typography/demo/ellipsis-middle.tsx correctly 1`] = `
|
||||
<span
|
||||
aria-label="In the process of internal desktop applications development, many different design specs and implementations would be involved, which might cause designers and developers difficulties and duplication and reduce the efficiency of"
|
||||
aria-label="In the process of internal desktop applications development, many different design specs and implementations would be involved, which might cause designers and developers difficulties and duplication and reduce the efficiency of "
|
||||
class="ant-typography ant-typography-ellipsis ant-typography-single-line"
|
||||
style="max-width:100%"
|
||||
>
|
||||
In the process of internal desktop applications development, many different design specs and implementations would be involved, which might cause designers and developers difficulties and duplication and reduce the efficiency of
|
||||
<!-- -->
|
||||
development.
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;word-break:keep-all;white-space:nowrap"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;width:0;white-space:normal;margin:0;padding:0"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
development.
|
||||
</span>
|
||||
</span>
|
||||
`;
|
||||
|
||||
@ -2035,29 +1694,6 @@ Array [
|
||||
To be, or not to be, that is a question: Whether it is nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them? To die: to sleep; No more; and by a sleep to say we end The heart-ache and the thousand natural shocks That flesh is heir to, 'tis a consummation Devoutly to be wish'd. To die, to sleep To sleep- perchance to dream: ay, there's the rub! For in that sleep of death what dreams may come When we have shuffled off this mortal coil, Must give us pause. There 's the respect That makes calamity of so long life
|
||||
<!-- -->
|
||||
--William Shakespeare
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;word-break:keep-all;white-space:nowrap"
|
||||
>
|
||||
lg
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
style="position:fixed;display:block;left:0;top:0;z-index:-9999;visibility:hidden;pointer-events:none;font-size:0;width:0;white-space:normal;margin:0;padding:0"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
--William Shakespeare
|
||||
<a
|
||||
aria-label="Expand"
|
||||
class="ant-typography-expand"
|
||||
>
|
||||
Expand
|
||||
</a>
|
||||
</span>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
@ -14,38 +14,39 @@ jest.mock('../../_util/styleChecker', () => ({
|
||||
|
||||
describe('Typography.Ellipsis', () => {
|
||||
const LINE_STR_COUNT = 20;
|
||||
const LINE_HEIGHT = 16;
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
let mockRectSpy: ReturnType<typeof spyElementPrototypes>;
|
||||
let getWidthTimes = 0;
|
||||
let computeSpy: jest.SpyInstance<CSSStyleDeclaration>;
|
||||
let offsetWidth: number;
|
||||
let scrollWidth: number;
|
||||
|
||||
function getContentHeight(elem?: HTMLElement) {
|
||||
const regex = /<[^>]*>/g;
|
||||
|
||||
let html = (elem || this).innerHTML;
|
||||
html = html.replace(regex, '');
|
||||
const lines = Math.ceil(html.length / LINE_STR_COUNT);
|
||||
return lines * LINE_HEIGHT;
|
||||
}
|
||||
|
||||
beforeAll(() => {
|
||||
jest.useFakeTimers();
|
||||
mockRectSpy = spyElementPrototypes(HTMLElement, {
|
||||
offsetHeight: {
|
||||
get() {
|
||||
let html = this.innerHTML;
|
||||
html = html.replace(/<[^>]*>/g, '');
|
||||
const lines = Math.ceil(html.length / LINE_STR_COUNT);
|
||||
return lines * 16;
|
||||
},
|
||||
},
|
||||
offsetWidth: {
|
||||
get: () => {
|
||||
getWidthTimes += 1;
|
||||
return offsetWidth;
|
||||
},
|
||||
},
|
||||
scrollWidth: {
|
||||
get: () => scrollWidth,
|
||||
},
|
||||
getBoundingClientRect() {
|
||||
let html = this.innerHTML;
|
||||
html = html.replace(/<[^>]*>/g, '');
|
||||
const lines = Math.ceil(html.length / LINE_STR_COUNT);
|
||||
return { height: lines * 16 };
|
||||
offsetWidth: {
|
||||
get: () => offsetWidth,
|
||||
},
|
||||
scrollHeight: {
|
||||
get: getContentHeight,
|
||||
},
|
||||
clientHeight: {
|
||||
get() {
|
||||
const { WebkitLineClamp } = this.style;
|
||||
return WebkitLineClamp ? Number(WebkitLineClamp) * LINE_HEIGHT : getContentHeight(this);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -61,7 +62,6 @@ describe('Typography.Ellipsis', () => {
|
||||
|
||||
afterEach(() => {
|
||||
errorSpy.mockReset();
|
||||
getWidthTimes = 0;
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
@ -234,24 +234,33 @@ describe('Typography.Ellipsis', () => {
|
||||
|
||||
it('should expandable work', async () => {
|
||||
const onExpand = jest.fn();
|
||||
const { container: wrapper } = render(
|
||||
<Base ellipsis={{ expandable: true, onExpand }} component="p" copyable editable>
|
||||
const ref = React.createRef<HTMLElement>();
|
||||
const { container } = render(
|
||||
<Base ellipsis={{ expandable: true, onExpand }} component="p" copyable editable ref={ref}>
|
||||
{fullStr}
|
||||
</Base>,
|
||||
);
|
||||
|
||||
fireEvent.click(wrapper.querySelector('.ant-typography-expand')!);
|
||||
triggerResize(ref.current!);
|
||||
await waitFakeTimer();
|
||||
|
||||
fireEvent.click(container.querySelector('.ant-typography-expand')!);
|
||||
expect(onExpand).toHaveBeenCalled();
|
||||
expect(wrapper.querySelector('p')?.textContent).toEqual(fullStr);
|
||||
expect(container.querySelector('p')?.textContent).toEqual(fullStr);
|
||||
});
|
||||
|
||||
it('should have custom expand style', async () => {
|
||||
const ref = React.createRef<HTMLElement>();
|
||||
const symbol = 'more';
|
||||
const { container } = render(
|
||||
<Base ellipsis={{ expandable: true, symbol }} component="p">
|
||||
<Base ellipsis={{ expandable: true, symbol }} component="p" ref={ref}>
|
||||
{fullStr}
|
||||
</Base>,
|
||||
);
|
||||
|
||||
triggerResize(ref.current!);
|
||||
await waitFakeTimer();
|
||||
|
||||
expect(container.querySelector('.ant-typography-expand')?.textContent).toEqual('more');
|
||||
});
|
||||
|
||||
@ -289,15 +298,18 @@ describe('Typography.Ellipsis', () => {
|
||||
});
|
||||
|
||||
// Trigger visible should trigger recheck
|
||||
getWidthTimes = 0;
|
||||
let getOffsetParent = false;
|
||||
Object.defineProperty(container.querySelector('.ant-typography'), 'offsetParent', {
|
||||
get: () => document.body,
|
||||
get: () => {
|
||||
getOffsetParent = true;
|
||||
return document.body;
|
||||
},
|
||||
});
|
||||
act(() => {
|
||||
elementChangeCallback?.();
|
||||
});
|
||||
|
||||
expect(getWidthTimes).toBeGreaterThan(0);
|
||||
expect(getOffsetParent).toBeTruthy();
|
||||
|
||||
unmount();
|
||||
expect(disconnectFn).toHaveBeenCalled();
|
||||
@ -445,80 +457,6 @@ describe('Typography.Ellipsis', () => {
|
||||
mockRectSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('should not throw default dom nodes', async () => {
|
||||
let currentWidth = 100;
|
||||
// string count is different with different width
|
||||
const getLineStrCount = (width: number) => {
|
||||
const res = width === 100 ? 20 : 17;
|
||||
return res;
|
||||
};
|
||||
|
||||
const ref = React.createRef<HTMLElement>();
|
||||
const resize = (width: number) => {
|
||||
currentWidth = width;
|
||||
if (ref.current) triggerResize(ref.current);
|
||||
};
|
||||
|
||||
mockRectSpy = spyElementPrototypes(HTMLElement, {
|
||||
offsetHeight: {
|
||||
get() {
|
||||
let html = this.innerHTML;
|
||||
html = html.replace(/<[^>]*>/g, '');
|
||||
const lines = Math.ceil(html.length / getLineStrCount(currentWidth));
|
||||
|
||||
return lines * 16;
|
||||
},
|
||||
},
|
||||
offsetWidth: {
|
||||
get: () => currentWidth,
|
||||
},
|
||||
getBoundingClientRect() {
|
||||
let html = this.innerHTML;
|
||||
html = html.replace(/<[^>]*>/g, '');
|
||||
const lines = Math.ceil(html.length / getLineStrCount(currentWidth));
|
||||
return { height: lines * 16 };
|
||||
},
|
||||
});
|
||||
|
||||
const { container } = render(
|
||||
<Base
|
||||
ellipsis={{
|
||||
rows: 2,
|
||||
}}
|
||||
ref={ref}
|
||||
editable
|
||||
component="p"
|
||||
>
|
||||
{fullStr}
|
||||
</Base>,
|
||||
);
|
||||
|
||||
// hijackings Math.ceil
|
||||
const originalCeil = Math.ceil;
|
||||
let hasDefaultStr = false;
|
||||
|
||||
// Math.ceil will be used for ellipsis's calculations;
|
||||
Math.ceil = (value) => {
|
||||
const text = container.querySelector('p')?.innerHTML.replace(/<[^>]*>/g, '');
|
||||
if (text && !text.includes('...')) {
|
||||
hasDefaultStr = true;
|
||||
}
|
||||
return originalCeil.call(Math, value);
|
||||
};
|
||||
|
||||
resize(50);
|
||||
await waitFakeTimer(20, 1);
|
||||
// ignore last result
|
||||
hasDefaultStr = false;
|
||||
resize(100);
|
||||
await waitFakeTimer();
|
||||
|
||||
expect(hasDefaultStr).not.toBeTruthy();
|
||||
// reset
|
||||
mockRectSpy.mockRestore();
|
||||
Math.ceil = originalCeil;
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/46580
|
||||
it('dynamic to be ellipsis should show tooltip', async () => {
|
||||
const ref = React.createRef<HTMLElement>();
|
||||
|
@ -3,6 +3,9 @@ import { Slider, Switch, Typography } from 'antd';
|
||||
|
||||
const { Text, Paragraph } = Typography;
|
||||
|
||||
const templateStr =
|
||||
'In the process of internal desktop applications development, many different design specs and implementations would be involved, which might cause designers and developers difficulties and duplication and reduce the efficiency of development.';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [rows, setRows] = useState(1);
|
||||
const [longText, setLongText] = useState(true);
|
||||
@ -44,25 +47,19 @@ const App: React.FC = () => {
|
||||
)}
|
||||
|
||||
<Text style={{ maxWidth: 400, fontSize: 24 }} copyable ellipsis>
|
||||
In the process of internal desktop applications development, many different design specs and
|
||||
implementations would be involved, which might cause designers and developers difficulties
|
||||
and duplication and reduce the efficiency of development.
|
||||
{templateStr}
|
||||
</Text>
|
||||
|
||||
<br />
|
||||
|
||||
<Text style={{ maxWidth: 400, fontSize: 12 }} copyable ellipsis>
|
||||
In the process of internal desktop applications development, many different design specs and
|
||||
implementations would be involved, which might cause designers and developers difficulties
|
||||
and duplication and reduce the efficiency of development.
|
||||
{templateStr}
|
||||
</Text>
|
||||
|
||||
<br />
|
||||
|
||||
<Text style={{ width: 400, fontSize: 24 }} copyable ellipsis>
|
||||
In the process of internal desktop applications development, many different design specs and
|
||||
implementations would be involved, which might cause designers and developers difficulties
|
||||
and duplication and reduce the efficiency of development.
|
||||
{templateStr}
|
||||
</Text>
|
||||
|
||||
<br />
|
||||
@ -80,6 +77,12 @@ const App: React.FC = () => {
|
||||
默认display none 样式的超长文字, 悬停tooltip失效了
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<Typography.Paragraph style={{ width: 300 }} ellipsis={{ rows: 3 }}>
|
||||
{templateStr.slice(0, 60)}
|
||||
<span style={{ fontSize: '5em' }}>ANTD</span>
|
||||
{templateStr.slice(60)}
|
||||
</Typography.Paragraph>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ const EllipsisMiddle: React.FC<{ suffixCount: number; children: string }> = ({
|
||||
suffixCount,
|
||||
children,
|
||||
}) => {
|
||||
const start = children.slice(0, children.length - suffixCount).trim();
|
||||
const start = children.slice(0, children.length - suffixCount);
|
||||
const suffix = children.slice(-suffixCount).trim();
|
||||
return (
|
||||
<Text style={{ maxWidth: '100%' }} ellipsis={{ suffix }}>
|
||||
|
@ -25,6 +25,7 @@ if (process.env.LIB_DIR === 'dist') {
|
||||
|
||||
$('{es,lib}/typography/Base/*.js')
|
||||
.isFile()
|
||||
.filter((filename) => !filename.endsWith('/util.js'))
|
||||
.assert('contain use client', (filename) => includeUseClient(filename));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user