mirror of
https://github.com/ant-design/ant-design.git
synced 2026-02-13 04:49:21 +08:00
Compare commits
6 Commits
docs/theme
...
demo-debug
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c881c84f97 | ||
|
|
6e993d2ef8 | ||
|
|
a46cd9d8ba | ||
|
|
75819fc3a7 | ||
|
|
a900301eac | ||
|
|
06c9af5e98 |
@@ -255,7 +255,7 @@ function antdCodeAppend(docFileAbs: string, src: string): string {
|
||||
*
|
||||
* @param md - 原始 markdown 内容
|
||||
* @param docFileAbs - 文档文件的绝对路径,用于解析相对路径和检测语言
|
||||
* @param enablePickLocaleBlock - 是否启用多语言块提取,可以是布尔值或函数,默认为 true
|
||||
* @param codeAppend - 代码追加函数:在替换 <code src> 标签时,用于追加额外的内容(如 demo 描述信息)
|
||||
* @returns 替换后的 markdown 内容
|
||||
*/
|
||||
function replaceCodeSrcToMarkdown(
|
||||
@@ -556,7 +556,6 @@ function emitRawMd(api: IApi) {
|
||||
* 2. 在 HTML 文件导出阶段输出处理后的 raw markdown 文件
|
||||
*
|
||||
* @param api - Dumi API 实例
|
||||
* @param options - 插件配置选项
|
||||
*/
|
||||
export default function rawMdPlugin(api: IApi) {
|
||||
// 注册配置键,允许用户在配置中使用 rawMd 键
|
||||
|
||||
@@ -19,8 +19,8 @@ function extractSemantics(objContent: string): Record<string, string> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 _semantic*.tsx 文件中提取语义信息
|
||||
* @param semanticFile - _semantic*.tsx 文件的绝对路径
|
||||
* 从 _semantic*.tsx 文件内容中提取语义信息
|
||||
* @param content - _semantic*.tsx 文件的文件内容字符串
|
||||
* @returns 包含中文和英文语义描述的对象,失败返回 null
|
||||
*/
|
||||
function extractLocaleInfoFromContent(content: string): {
|
||||
|
||||
2
.github/workflows/pr-check-merge.yml
vendored
2
.github/workflows/pr-check-merge.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
if: (github.event.pull_request.head.ref == 'next' || github.event.pull_request.head.ref == 'feature' || github.event.pull_request.head.ref == 'master') && github.event.pull_request.head.user.login == 'ant-design'
|
||||
steps:
|
||||
- uses: actions-cool/issues-helper@e2ff99831a4f13625d35064e2b3dfe65c07a0396
|
||||
- uses: actions-cool/issues-helper@e361abf610221f09495ad510cb1e69328d839e1c
|
||||
with:
|
||||
actions: create-comment
|
||||
issue-number: ${{ github.event.number }}
|
||||
|
||||
@@ -27,8 +27,8 @@ const OTPInput = React.forwardRef<InputRef, OTPInputProps>((props, ref) => {
|
||||
React.useImperativeHandle(ref, () => inputRef.current!);
|
||||
|
||||
// ========================= Input ==========================
|
||||
const onInternalChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
|
||||
onChange(index, e.target.value);
|
||||
const onInternalChange: React.InputEventHandler<HTMLInputElement> = (e) => {
|
||||
onChange(index, (e.target as HTMLInputElement).value);
|
||||
};
|
||||
|
||||
// ========================= Focus ==========================
|
||||
|
||||
@@ -680,52 +680,56 @@ Array [
|
||||
class="ant-typography css-var-test-id"
|
||||
>
|
||||
Ant Design
|
||||
<button
|
||||
aria-describedby="test-id"
|
||||
aria-label="Copy"
|
||||
class="ant-typography-copy"
|
||||
type="button"
|
||||
<span
|
||||
class="ant-typography-actions"
|
||||
>
|
||||
<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>
|
||||
</button>
|
||||
<div
|
||||
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-tooltip-css-var css-var-test-id ant-tooltip-placement-top"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; right: auto; bottom: auto; box-sizing: border-box;"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-arrow"
|
||||
style="position: absolute; bottom: 0px; left: 0px;"
|
||||
<button
|
||||
aria-describedby="test-id"
|
||||
aria-label="Copy"
|
||||
class="ant-typography-copy"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-tooltip-arrow-content"
|
||||
/>
|
||||
</div>
|
||||
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>
|
||||
</button>
|
||||
<div
|
||||
class="ant-tooltip-container"
|
||||
id="test-id"
|
||||
role="tooltip"
|
||||
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-tooltip-css-var css-var-test-id ant-tooltip-placement-top"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; right: auto; bottom: auto; box-sizing: border-box;"
|
||||
>
|
||||
Copy
|
||||
<div
|
||||
class="ant-tooltip-arrow"
|
||||
style="position: absolute; bottom: 0px; left: 0px;"
|
||||
>
|
||||
<span
|
||||
class="ant-tooltip-arrow-content"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tooltip-container"
|
||||
id="test-id"
|
||||
role="tooltip"
|
||||
>
|
||||
Copy
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
class="ant-input-affix-wrapper ant-input-outlined css-var-test-id ant-input-css-var"
|
||||
|
||||
@@ -408,31 +408,35 @@ Array [
|
||||
class="ant-typography css-var-test-id"
|
||||
>
|
||||
Ant Design
|
||||
<button
|
||||
aria-label="Copy"
|
||||
class="ant-typography-copy"
|
||||
type="button"
|
||||
<span
|
||||
class="ant-typography-actions"
|
||||
>
|
||||
<span
|
||||
aria-label="copy"
|
||||
class="anticon anticon-copy"
|
||||
role="img"
|
||||
<button
|
||||
aria-label="Copy"
|
||||
class="ant-typography-copy"
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="copy"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
<span
|
||||
aria-label="copy"
|
||||
class="anticon anticon-copy"
|
||||
role="img"
|
||||
>
|
||||
<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>
|
||||
</button>
|
||||
<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>
|
||||
</button>
|
||||
</span>
|
||||
</span>,
|
||||
<span
|
||||
class="ant-input-affix-wrapper ant-input-outlined css-var-test-id ant-input-css-var"
|
||||
|
||||
@@ -1778,7 +1778,9 @@ Array [
|
||||
exports[`renders components/select/demo/custom-tag-render.tsx extend context correctly 2`] = `[]`;
|
||||
|
||||
exports[`renders components/select/demo/debug.tsx extend context correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
class="ant-flex css-var-test-id ant-flex-align-stretch ant-flex-gap-middle ant-flex-vertical"
|
||||
>
|
||||
<div
|
||||
class="ant-space ant-space-horizontal ant-space-align-center ant-space-gap-row-small ant-space-gap-col-small css-var-test-id"
|
||||
style="flex-wrap: wrap; width: 500px; position: relative; z-index: 1; border: 1px solid red; background-color: rgb(255, 255, 255);"
|
||||
@@ -2210,9 +2212,9 @@ Array [
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>,
|
||||
</div>
|
||||
<div
|
||||
style="width: 200px; margin-top: 24px;"
|
||||
style="width: 200px;"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-outlined css-var-test-id ant-select-css-var ant-select-multiple ant-select-show-arrow ant-select-show-search"
|
||||
@@ -2379,8 +2381,113 @@ Array [
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
</div>
|
||||
<div
|
||||
class="ant-select ant-select-outlined css-var-test-id ant-select-css-var ant-select-single ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
class="ant-select-content"
|
||||
title=""
|
||||
>
|
||||
<input
|
||||
aria-autocomplete="list"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="listbox"
|
||||
autocomplete="off"
|
||||
class="ant-select-input"
|
||||
id="test-id"
|
||||
readonly=""
|
||||
role="combobox"
|
||||
type="search"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-select-suffix"
|
||||
>
|
||||
<span
|
||||
aria-label="down"
|
||||
class="anticon anticon-down"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="down"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up css-var-test-id ant-select-css-var ant-select-dropdown-empty ant-select-dropdown-placement-bottomLeft"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; right: auto; bottom: auto; box-sizing: border-box;"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-item-empty"
|
||||
id="test-id_list"
|
||||
role="listbox"
|
||||
>
|
||||
<div
|
||||
class="css-var-test-id ant-empty ant-empty-normal ant-empty-small"
|
||||
>
|
||||
<div
|
||||
class="ant-empty-image"
|
||||
>
|
||||
<svg
|
||||
height="41"
|
||||
viewBox="0 0 64 41"
|
||||
width="64"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<title>
|
||||
No data
|
||||
</title>
|
||||
<g
|
||||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
transform="translate(0 1)"
|
||||
>
|
||||
<ellipse
|
||||
cx="32"
|
||||
cy="33"
|
||||
fill="#f5f5f5"
|
||||
rx="32"
|
||||
ry="7"
|
||||
/>
|
||||
<g
|
||||
fill-rule="nonzero"
|
||||
stroke="#d9d9d9"
|
||||
>
|
||||
<path
|
||||
d="M55 12.8 44.9 1.3Q44 0 42.9 0H21.1q-1.2 0-2 1.3L9 12.8V22h46z"
|
||||
/>
|
||||
<path
|
||||
d="M41.6 16c0-1.7 1-3 2.2-3H55v18.1c0 2.2-1.3 3.9-3 3.9H12c-1.7 0-3-1.7-3-3.9V13h11.2c1.2 0 2.2 1.3 2.2 3s1 2.9 2.2 2.9h14.8c1.2 0 2.2-1.4 2.2-3"
|
||||
fill="#fafafa"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
class="ant-empty-description"
|
||||
>
|
||||
No data
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders components/select/demo/debug.tsx extend context correctly 2`] = `[]`;
|
||||
|
||||
@@ -741,7 +741,9 @@ exports[`renders components/select/demo/custom-tag-render.tsx correctly 1`] = `
|
||||
`;
|
||||
|
||||
exports[`renders components/select/demo/debug.tsx correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
class="ant-flex css-var-test-id ant-flex-align-stretch ant-flex-gap-middle ant-flex-vertical"
|
||||
>
|
||||
<div
|
||||
class="ant-space ant-space-horizontal ant-space-align-center ant-space-gap-row-small ant-space-gap-col-small css-var-test-id"
|
||||
style="flex-wrap:wrap;width:500px;position:relative;z-index:1;border:1px solid red;background-color:#fff"
|
||||
@@ -924,9 +926,9 @@ Array [
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>,
|
||||
</div>
|
||||
<div
|
||||
style="width:200px;margin-top:24px"
|
||||
style="width:200px"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-outlined css-var-test-id ant-select-css-var ant-select-multiple ant-select-show-arrow ant-select-show-search"
|
||||
@@ -1018,8 +1020,52 @@ Array [
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
</div>
|
||||
<div
|
||||
class="ant-select ant-select-outlined css-var-test-id ant-select-css-var ant-select-single ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
class="ant-select-content"
|
||||
title=""
|
||||
>
|
||||
<input
|
||||
aria-autocomplete="list"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="listbox"
|
||||
autocomplete="off"
|
||||
class="ant-select-input"
|
||||
id="test-id"
|
||||
readonly=""
|
||||
role="combobox"
|
||||
type="search"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-select-suffix"
|
||||
>
|
||||
<span
|
||||
aria-label="down"
|
||||
class="anticon anticon-down"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="down"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders components/select/demo/debug-flip-shift.tsx correctly 1`] = `
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Button, Input, Select, Space } from 'antd';
|
||||
import { Button, Flex, Input, Select, Space } from 'antd';
|
||||
|
||||
const style: React.CSSProperties = {
|
||||
width: 500,
|
||||
@@ -14,7 +14,7 @@ const handleChange = (value: string | string[]) => {
|
||||
};
|
||||
|
||||
const App: React.FC = () => (
|
||||
<>
|
||||
<Flex vertical gap="middle">
|
||||
<Space style={style} wrap>
|
||||
<Input style={{ width: 100 }} value="222" />
|
||||
<Select
|
||||
@@ -48,7 +48,7 @@ const App: React.FC = () => (
|
||||
<span className="debug-align">AntDesign</span>
|
||||
<Button>222</Button>
|
||||
</Space>
|
||||
<div style={{ width: 200, marginTop: 24 }}>
|
||||
<div style={{ width: 200 }}>
|
||||
{/* https://github.com/ant-design/ant-design/issues/54179 */}
|
||||
<Select
|
||||
mode="multiple"
|
||||
@@ -62,7 +62,9 @@ const App: React.FC = () => (
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
|
||||
<Select defaultValue="" />
|
||||
</Flex>
|
||||
);
|
||||
|
||||
export default App;
|
||||
|
||||
@@ -280,6 +280,12 @@ export const genBaseStyle = (prefixCls: string, token: TreeToken): CSSObject =>
|
||||
.equal(),
|
||||
},
|
||||
|
||||
// >>> Checkbox
|
||||
// https://github.com/ant-design/ant-design/issues/56957
|
||||
[`${treeCls}-checkbox`]: {
|
||||
flexShrink: 0,
|
||||
},
|
||||
|
||||
// >>> Switcher
|
||||
[`${treeCls}-switcher`]: {
|
||||
...getSwitchStyle(prefixCls, token),
|
||||
|
||||
@@ -7,12 +7,15 @@ export interface EllipsisTooltipProps {
|
||||
tooltipProps?: TooltipProps;
|
||||
enableEllipsis: boolean;
|
||||
isEllipsis?: boolean;
|
||||
/** When true, show the ellipsis tooltip; when false, hide it. Fully controlled so tooltip re-opens when moving from copy button back to text. */
|
||||
open: boolean;
|
||||
children: React.ReactElement;
|
||||
}
|
||||
|
||||
const EllipsisTooltip: React.FC<EllipsisTooltipProps> = ({
|
||||
enableEllipsis,
|
||||
isEllipsis,
|
||||
open,
|
||||
children,
|
||||
tooltipProps,
|
||||
}) => {
|
||||
@@ -20,8 +23,9 @@ const EllipsisTooltip: React.FC<EllipsisTooltipProps> = ({
|
||||
return children;
|
||||
}
|
||||
|
||||
const mergedOpen = open && isEllipsis;
|
||||
return (
|
||||
<Tooltip open={isEllipsis ? undefined : false} {...tooltipProps}>
|
||||
<Tooltip open={mergedOpen} {...tooltipProps}>
|
||||
{children}
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
@@ -65,8 +65,9 @@ export interface EllipsisConfig {
|
||||
tooltip?: React.ReactNode | TooltipProps;
|
||||
}
|
||||
|
||||
export interface BlockProps<C extends keyof JSX.IntrinsicElements = keyof JSX.IntrinsicElements>
|
||||
extends TypographyProps<C> {
|
||||
export interface BlockProps<
|
||||
C extends keyof JSX.IntrinsicElements = keyof JSX.IntrinsicElements,
|
||||
> extends TypographyProps<C> {
|
||||
title?: string;
|
||||
editable?: boolean | EditConfig;
|
||||
copyable?: boolean | CopyConfig;
|
||||
@@ -133,6 +134,8 @@ const Base = React.forwardRef<HTMLElement, BlockProps>((props, ref) => {
|
||||
copyable,
|
||||
component,
|
||||
title,
|
||||
onMouseEnter,
|
||||
onMouseLeave,
|
||||
...restProps
|
||||
} = props;
|
||||
const { getPrefixCls, direction } = React.useContext(ConfigContext);
|
||||
@@ -262,6 +265,8 @@ const Base = React.forwardRef<HTMLElement, BlockProps>((props, ref) => {
|
||||
};
|
||||
|
||||
const [ellipsisWidth, setEllipsisWidth] = React.useState(0);
|
||||
const [isHoveringOperations, setIsHoveringOperations] = React.useState(false);
|
||||
const [isHoveringTypography, setIsHoveringTypography] = React.useState(false);
|
||||
const onResize = ({ offsetWidth }: { offsetWidth: number }) => {
|
||||
setEllipsisWidth(offsetWidth);
|
||||
};
|
||||
@@ -407,11 +412,28 @@ const Base = React.forwardRef<HTMLElement, BlockProps>((props, ref) => {
|
||||
);
|
||||
};
|
||||
|
||||
const renderOperations = (canEllipsis: boolean) => [
|
||||
canEllipsis && renderExpand(),
|
||||
renderEdit(),
|
||||
renderCopy(),
|
||||
];
|
||||
const renderOperations = (canEllipsis: boolean) => {
|
||||
const expandNode = canEllipsis && renderExpand();
|
||||
const editNode = renderEdit();
|
||||
const copyNode = renderCopy();
|
||||
|
||||
if (!expandNode && !editNode && !copyNode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<span
|
||||
key="operations"
|
||||
className={`${prefixCls}-actions`}
|
||||
onMouseEnter={() => setIsHoveringOperations(true)}
|
||||
onMouseLeave={() => setIsHoveringOperations(false)}
|
||||
>
|
||||
{expandNode}
|
||||
{editNode}
|
||||
{copyNode}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
const renderEllipsis = (canEllipsis: boolean) => [
|
||||
canEllipsis && !expanded && (
|
||||
@@ -430,8 +452,17 @@ const Base = React.forwardRef<HTMLElement, BlockProps>((props, ref) => {
|
||||
tooltipProps={tooltipProps}
|
||||
enableEllipsis={mergedEnableEllipsis}
|
||||
isEllipsis={isMergedEllipsis}
|
||||
open={isHoveringTypography && !isHoveringOperations}
|
||||
>
|
||||
<Typography
|
||||
onMouseEnter={(e) => {
|
||||
setIsHoveringTypography(true);
|
||||
onMouseEnter?.(e);
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
setIsHoveringTypography(false);
|
||||
onMouseLeave?.(e);
|
||||
}}
|
||||
className={clsx(
|
||||
{
|
||||
[`${prefixCls}-${type}`]: type,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -685,4 +685,51 @@ describe('Typography.Ellipsis', () => {
|
||||
expect(expandButtonCN).toHaveTextContent('展开');
|
||||
expect(expandButtonCN).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('copyable + ellipsis: ellipsis tooltip hides when hovering copy, shows when hovering text', async () => {
|
||||
offsetWidth = 50;
|
||||
scrollWidth = 100;
|
||||
|
||||
const ref = React.createRef<HTMLElement>();
|
||||
const { container, baseElement } = render(
|
||||
<Base ref={ref} component="p" copyable ellipsis={{ rows: 1, tooltip: true }}>
|
||||
{fullStr}
|
||||
</Base>,
|
||||
);
|
||||
|
||||
triggerResize(ref.current!);
|
||||
await waitFakeTimer();
|
||||
|
||||
const copyBtn = container.querySelector('.ant-typography-copy');
|
||||
const operationsWrapper = copyBtn?.parentElement;
|
||||
expect(operationsWrapper).toBeTruthy();
|
||||
|
||||
const typographyEl = ref.current!;
|
||||
|
||||
const getTooltipContent = () =>
|
||||
baseElement.querySelector('[role="tooltip"]')?.textContent?.trim();
|
||||
|
||||
fireEvent.mouseEnter(typographyEl);
|
||||
await waitFakeTimer();
|
||||
await waitFor(() => {
|
||||
expect(getTooltipContent()).toContain(fullStr);
|
||||
});
|
||||
|
||||
fireEvent.mouseEnter(operationsWrapper!);
|
||||
await waitFakeTimer();
|
||||
await waitFor(() => {
|
||||
const ellipsisTooltip = baseElement.querySelector('[role="tooltip"]');
|
||||
expect(ellipsisTooltip?.closest('.ant-tooltip')).toHaveClass('ant-tooltip-hidden');
|
||||
});
|
||||
|
||||
fireEvent.mouseLeave(operationsWrapper!);
|
||||
fireEvent.mouseEnter(typographyEl);
|
||||
await waitFakeTimer();
|
||||
await waitFor(() => {
|
||||
expect(getTooltipContent()).toContain(fullStr);
|
||||
});
|
||||
|
||||
fireEvent.mouseLeave(typographyEl);
|
||||
fireEvent.mouseLeave(operationsWrapper!);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
## zh-CN
|
||||
|
||||
多行文本省略。
|
||||
多行文本省略。页面底部包含「可复制 + 省略」时 tooltip 行为的调试区块,便于验证:悬停文字显示省略 tooltip,悬停复制按钮仅显示复制 tooltip,从复制按钮移回文字时省略 tooltip 再次出现。
|
||||
|
||||
## en-US
|
||||
|
||||
Multiple line ellipsis support.
|
||||
Multiple line ellipsis support. The bottom section is a debug block for copyable + ellipsis tooltip behavior: hover text for ellipsis tooltip, hover copy button for copy-only tooltip, then move back to text to confirm the ellipsis tooltip shows again.
|
||||
|
||||
@@ -108,6 +108,22 @@ const App: React.FC = () => {
|
||||
<Text style={{ width: 100, whiteSpace: 'nowrap' }} ellipsis copyable>
|
||||
{templateStr}
|
||||
</Text>
|
||||
|
||||
<div style={{ marginTop: 24 }}>
|
||||
<div style={{ marginBottom: 8, fontSize: 12, color: '#666' }}>
|
||||
<strong>Debug: copyable + ellipsis tooltips</strong>
|
||||
<br />
|
||||
1. Hover the text → ellipsis tooltip (full content) should show.
|
||||
<br />
|
||||
2. Hover the copy button → only "Copy" / "Copied" tooltip should show.
|
||||
<br />
|
||||
3. Move from copy button back to the text (without leaving the block) → ellipsis tooltip
|
||||
should show again.
|
||||
</div>
|
||||
<Text style={{ width: 280, display: 'block' }} ellipsis={{ tooltip: true }} copyable>
|
||||
{templateStr}
|
||||
</Text>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -107,6 +107,10 @@ const genTypographyStyle: GenerateStyle<TypographyToken> = (token) => {
|
||||
...getLinkStyles(token),
|
||||
|
||||
// Operation
|
||||
[`${componentCls}-actions`]: {
|
||||
display: 'inline',
|
||||
},
|
||||
|
||||
[`
|
||||
${componentCls}-expand,
|
||||
${componentCls}-collapse,
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
"@rc-component/rate": "~1.0.1",
|
||||
"@rc-component/resize-observer": "^1.1.1",
|
||||
"@rc-component/segmented": "~1.3.0",
|
||||
"@rc-component/select": "~1.6.5",
|
||||
"@rc-component/select": "~1.6.7",
|
||||
"@rc-component/slider": "~1.0.1",
|
||||
"@rc-component/steps": "~1.2.2",
|
||||
"@rc-component/switch": "~1.0.3",
|
||||
@@ -210,7 +210,7 @@
|
||||
"@types/pngjs": "^6.0.5",
|
||||
"@types/prismjs": "^1.26.5",
|
||||
"@types/progress": "^2.0.7",
|
||||
"@types/react": "19.2.9",
|
||||
"@types/react": "19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@types/react-highlight-words": "^0.20.0",
|
||||
"@types/semver": "^7.7.1",
|
||||
|
||||
Reference in New Issue
Block a user