Merge pull request #47625 from ant-design/master-merge-feature

chore: merge master into feature
This commit is contained in:
lijianan 2024-02-28 14:10:05 +08:00 committed by GitHub
commit 52255ba84b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 442 additions and 1140 deletions

View File

@ -53,6 +53,7 @@ const useStyle = createStyles(({ token, css, cx }) => {
column-gap: ${token.paddingMD * 2}px;
align-items: stretch;
text-align: start;
min-height: 178px;
> * {
width: calc((100% - ${token.marginXXL * 2}px) / 3);
}

View File

@ -55,7 +55,7 @@ Common props ref[Common props](/docs/react/common-props)
| popupClassName | The className of dropdown menu | string | - | 4.23.0 |
| dropdownMatchSelectWidth | Determine whether the dropdown menu and the select input are the same width. Default set `min-width` same as input. Will ignore when value less than select width. `false` will disable virtual scroll | boolean \| number | true | |
| filterOption | If true, filter options by input, if function, filter options against it. The function will receive two arguments, `inputValue` and `option`, if the function returns true, the option will be included in the filtered set; Otherwise, it will be excluded | boolean \| function(inputValue, option) | true | |
| notFoundContent | Specify content to show when no result matches | string | `Not Found` | |
| notFoundContent | Specify content to show when no result matches | ReactNode | - | |
| open | Controlled open state of dropdown | boolean | - | |
| options | Select options. Will get better perf than jsx definition | { label, value }\[] | - | |
| placeholder | The placeholder of input | string | - | |

View File

@ -95,11 +95,11 @@ import { Link } from 'react-router';
const items = [
{
path: 'index',
path: '/index',
title: 'home',
},
{
path: 'first',
path: '/first',
title: 'first',
children: [
{
@ -117,13 +117,19 @@ const items = [
],
},
{
path: 'second',
path: '/second',
title: 'second',
},
];
function itemRender(route, params, items, paths) {
const last = items.indexOf(item) === items.length - 1;
return last ? <span>{item.title}</span> : <Link to={paths.join('/')}>{item.title}</Link>;
function itemRender(currentRoute, params, items, paths) {
const isLast = currentRoute?.path === items[items.length - 1]?.path;
return isLast ? (
<span>{currentRoute.title}</span>
) : (
<Link to={`/${paths.join("/")}`}>{currentRoute.title}</Link>
);
}
return <Breadcrumb itemRender={itemRender} items={items} />;

View File

@ -96,11 +96,11 @@ import { Link } from 'react-router';
const items = [
{
path: 'index',
path: '/index',
title: 'home',
},
{
path: 'first',
path: '/first',
title: 'first',
children: [
{
@ -118,13 +118,19 @@ const items = [
],
},
{
path: 'second',
path: '/second',
title: 'second',
},
];
function itemRender(item, params, items, paths) {
const last = items.indexOf(item) === items.length - 1;
return last ? <span>{item.title}</span> : <Link to={paths.join('/')}>{item.title}</Link>;
function itemRender(currentRoute, params, items, paths) {
const isLast = currentRoute?.path === items[items.length - 1]?.path;
return isLast ? (
<span>{currentRoute.title}</span>
) : (
<Link to={`/${paths.join("/")}`}>{currentRoute.title}</Link>
);
}
return <Breadcrumb itemRender={itemRender} items={items} />;

View File

@ -1,7 +1,8 @@
import React, { Suspense, useRef, useState } from 'react';
import { SearchOutlined } from '@ant-design/icons';
import { resetWarned } from 'rc-util/lib/warning';
import React, { Suspense, useRef, useState } from 'react';
import { act } from 'react-dom/test-utils';
import Button from '..';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
@ -434,4 +435,10 @@ describe('Button', () => {
const { container } = render(<Button loading={{ delay: 0 }}>Button</Button>);
expect(container.querySelectorAll('.ant-btn-loading').length).toBe(1);
});
// https://github.com/ant-design/ant-design/issues/47605
it('Compatible with original `type` behavior', async () => {
const { container } = render(<Button type={'' as any} />);
expect(container.querySelector('.ant-btn-default')).toBeTruthy();
});
});

View File

@ -96,7 +96,7 @@ const InternalButton: React.ForwardRefRenderFunction<
const {
loading = false,
prefixCls: customizePrefixCls,
type = 'default',
type,
danger,
shape = 'default',
size: customizeSize,
@ -115,6 +115,10 @@ const InternalButton: React.ForwardRefRenderFunction<
...rest
} = props;
// https://github.com/ant-design/ant-design/issues/47605
// Compatible with original `type` behavior
const mergedType = type || 'default';
const { getPrefixCls, autoInsertSpaceInButton, direction, button } = useContext(ConfigContext);
const prefixCls = getPrefixCls('btn', customizePrefixCls);
@ -135,7 +139,8 @@ const InternalButton: React.ForwardRefRenderFunction<
const buttonRef = composeRef(ref, internalRef);
const needInserted = Children.count(children) === 1 && !icon && !isUnBorderedButtonType(type);
const needInserted =
Children.count(children) === 1 && !icon && !isUnBorderedButtonType(mergedType);
useEffect(() => {
let delayTimer: ReturnType<typeof setTimeout> | null = null;
@ -193,7 +198,7 @@ const InternalButton: React.ForwardRefRenderFunction<
);
warning(
!(ghost && isUnBorderedButtonType(type)),
!(ghost && isUnBorderedButtonType(mergedType)),
'usage',
"`link` or `text` button can't be a `ghost` button.",
);
@ -218,10 +223,10 @@ const InternalButton: React.ForwardRefRenderFunction<
cssVarCls,
{
[`${prefixCls}-${shape}`]: shape !== 'default' && shape,
[`${prefixCls}-${type}`]: type,
[`${prefixCls}-${mergedType}`]: mergedType,
[`${prefixCls}-${sizeCls}`]: sizeCls,
[`${prefixCls}-icon-only`]: !children && children !== 0 && !!iconType,
[`${prefixCls}-background-ghost`]: ghost && !isUnBorderedButtonType(type),
[`${prefixCls}-background-ghost`]: ghost && !isUnBorderedButtonType(mergedType),
[`${prefixCls}-loading`]: innerLoading,
[`${prefixCls}-two-chinese-chars`]: hasTwoCNChar && autoInsertSpace && !innerLoading,
[`${prefixCls}-block`]: block,
@ -291,7 +296,7 @@ const InternalButton: React.ForwardRefRenderFunction<
</button>
);
if (!isUnBorderedButtonType(type)) {
if (!isUnBorderedButtonType(mergedType)) {
buttonNode = (
<Wave component="Button" disabled={!!innerLoading}>
{buttonNode}

View File

@ -128,10 +128,7 @@ export type PaginationConfig = ComponentStyleConfig & Pick<PaginationProps, 'sho
export type SelectConfig = ComponentStyleConfig & Pick<SelectProps, 'showSearch'>;
export type SpaceConfig = Pick<
SpaceProps,
'size' | 'className' | 'classNames' | 'style' | 'styles'
>;
export type SpaceConfig = ComponentStyleConfig & Pick<SpaceProps, 'size' | 'classNames' | 'styles'>;
export type PopupOverflow = 'viewport' | 'scroll';

View File

@ -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>

View File

@ -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>

View 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>
);
}

View File

@ -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;

View File

@ -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;

View 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);
}

View File

@ -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>,
]
`;

View File

@ -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>,
]
`;

View File

@ -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>();

View File

@ -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>
</>
);
};

View File

@ -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 }}>

17
docs/blog/v4-ood.en-US.md Normal file
View File

@ -0,0 +1,17 @@
---
title: 📢 v4 surpassed maintenance period
date: 2024-02-28
author: zombieJ
---
For our release schedule, the maintenance period for Ant Design v4 has officially ended at the end of 2023. This means that we will not release any new updates or patches for v4 unless significant defects or other serious issues are discovered. We strongly recommend that users upgrade to Ant Design v5 as soon as possible.
You will get a series of benefits from upgrading to v5, including more powerful design system theme capabilities, richer component functionality, performance optimization, and more. In addition, v5 also includes many issue fixes and user experience improvements based on community feedback. We will continue to provide continuous support and updates on v5 to ensure that developers can get the best user experience.
For a smooth transition to v5, we provide detailed upgrade guides and documentation. We understand that the upgrade process may involve a lot of work, so our team is also working hard to make this process as seamless and simple as possible. If you encounter any problems during the upgrade process, please feel free to submit an issue on GitHub.
Please visit our official website or view the v5 upgrade documentation directly to start your upgrade journey and enjoy the latest Ant Design experience.
- [v4 to v5](https://ant.design/docs/react/migration-v5)
- [Less variables to Component Token](https://ant.design/docs/react/migrate-less-variables)
- [CSS Compatible](https://ant.design/docs/react/compatible-style)

17
docs/blog/v4-ood.zh-CN.md Normal file
View File

@ -0,0 +1,17 @@
---
title: 📢 v4 维护周期截止
date: 2024-02-28
author: zombieJ
---
根据我们的发布时间表Ant Design v4 版本的维护期已于 2023 年年底正式结束。这意味着,除非发现了重大的缺陷或其他严重问题,我们不会再为 v4 推出任何新的更新或补丁版本。我们强烈建议用户尽快升级到 Ant Design v5 版本。
升级至 v5 将为您带来一系列的好处包括对更强大的设计系统主题能力、更为丰富的组件功能、性能优化等等。此外v5 还包含了许多社区反馈的问题修复和用户体验的改进。我们将继续在 v5 上提供持续的支持和更新,确保开发者可以获得最佳的使用体验。
为了帮助您平滑迁移到 v5我们提供了详尽的升级指南和文档。我们了解升级过程可能会涉及到不少工作量因此我们的团队也在努力使这个过程尽可能无缝和简便。如果你在升级过程中遇到任何问题欢迎在 GitHub 中提交 issue 反馈。
请访问我们的官方网站或直接查看 v5 的升级文档,开始您的升级之旅,享受最新的 Ant Design 体验。
- [从 v4 到 v5](https://ant.design/docs/react/migration-v5-cn)
- [从 Less 变量到 Design Token](https://ant.design/docs/react/migrate-less-variables-cn)
- [样式兼容](https://ant.design/docs/react/compatible-style-cn)

View File

@ -14,7 +14,7 @@ tag: Updated
<InstallDependencies npm='$ npx create-next-app antd-demo' yarn='$ yarn create next-app antd-demo' pnpm='$ pnpm create next-app antd-demo'></InstallDependencies>
工具会自动初始化一个脚手架并安装项目的各种必要依赖,在安装过程中,有一些配置项需要自行选择,如果在过程中出现网络问题,请尝试配置代理,或使用其他 npm registry。
工具会自动初始化一个脚手架并安装项目的各种必要依赖,在安装过程中,有一些配置项需要自行选择,如果在过程中出现网络问题,请尝试配置代理,或使用其他 npm registry,例如,你可以切换到淘宝镜像源:`npm config set registry https://registry.npmmirror.com`
初始化完成后,我们进入项目并启动。

View File

@ -119,6 +119,7 @@
"@ant-design/cssinjs": "^1.18.4",
"@ant-design/icons": "^5.3.0",
"@ant-design/react-slick": "~1.0.2",
"@babel/runtime": "^7.23.9",
"@ctrl/tinycolor": "^3.6.1",
"@rc-component/color-picker": "~1.5.2",
"@rc-component/mutate-observer": "^1.1.0",
@ -143,7 +144,7 @@
"rc-motion": "^2.9.0",
"rc-notification": "~5.3.0",
"rc-pagination": "~4.0.4",
"rc-picker": "~4.1.4",
"rc-picker": "~4.1.5",
"rc-progress": "~3.5.1",
"rc-rate": "~2.12.0",
"rc-resize-observer": "^1.4.0",
@ -170,7 +171,7 @@
"@antv/g6": "^4.8.24",
"@babel/eslint-plugin": "^7.23.5",
"@biomejs/biome": "^1.5.3",
"@codesandbox/sandpack-react": "^2.13.0",
"@codesandbox/sandpack-react": "^2.13.2",
"@dnd-kit/core": "^6.1.0",
"@dnd-kit/modifiers": "^7.0.0",
"@dnd-kit/sortable": "^8.0.0",
@ -207,17 +208,17 @@
"@types/prismjs": "^1.26.3",
"@types/progress": "^2.0.7",
"@types/qs": "^6.9.11",
"@types/react": "^18.2.58",
"@types/react": "^18.2.60",
"@types/react-copy-to-clipboard": "^5.0.7",
"@types/react-dom": "^18.2.19",
"@types/react-highlight-words": "^0.16.7",
"@types/react-resizable": "^3.0.7",
"@types/semver": "^7.5.7",
"@types/semver": "^7.5.8",
"@types/tar": "^6.1.11",
"@types/throttle-debounce": "^5.0.2",
"@types/warning": "^3.0.3",
"@typescript-eslint/eslint-plugin": "^7.0.2",
"@typescript-eslint/parser": "^7.0.2",
"@typescript-eslint/eslint-plugin": "^7.1.0",
"@typescript-eslint/parser": "^7.1.0",
"ali-oss": "^6.20.0",
"antd-img-crop": "^4.21.0",
"antd-style": "^3.6.1",
@ -232,7 +233,7 @@
"dumi": "^2.3.0-beta.7",
"dumi-plugin-color-chunk": "^1.1.0",
"esbuild-loader": "^4.0.3",
"eslint": "^8.56.0",
"eslint": "^8.57.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.1",
@ -278,7 +279,7 @@
"node-fetch": "^3.3.2",
"node-notifier": "^10.0.1",
"nprogress": "^0.2.0",
"open": "^10.0.3",
"open": "^10.0.4",
"pixelmatch": "^5.3.0",
"pngjs": "^7.0.0",
"prettier": "^3.2.5",
@ -286,7 +287,7 @@
"pretty-format": "^29.7.0",
"prismjs": "^1.29.0",
"progress": "^2.0.3",
"puppeteer": "^22.2.0",
"puppeteer": "^22.3.0",
"qs": "^6.11.2",
"rc-footer": "^0.6.8",
"rc-tween-one": "^3.0.6",
@ -323,9 +324,9 @@
"sylvanas": "^0.6.1",
"tar": "^6.2.0",
"tar-fs": "^3.0.5",
"terser": "^5.28.0",
"terser": "^5.28.1",
"tsx": "^4.7.1",
"typedoc": "^0.25.8",
"typedoc": "^0.25.9",
"typescript": "~5.3.3",
"vanilla-jsoneditor": "^0.21.6",
"vanilla-tilt": "^1.8.1",

View File

@ -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));
}