mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-07 09:26:06 +08:00
chore: merge next
This commit is contained in:
commit
432570d252
116
.dumi/global.css
116
.dumi/global.css
@ -18,3 +18,119 @@ html {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: #eaeaea transparent;
|
||||
}
|
||||
|
||||
.rc-footer {
|
||||
position: relative;
|
||||
clear: both;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
background-color: #000;
|
||||
}
|
||||
.rc-footer a {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
text-decoration: none;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.rc-footer a:hover {
|
||||
color: #40a9ff;
|
||||
}
|
||||
.rc-footer-container {
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
margin: auto;
|
||||
padding: 80px 0 20px;
|
||||
}
|
||||
.rc-footer-columns {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
.rc-footer-column {
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
.rc-footer-column h2 {
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
}
|
||||
.rc-footer-column-icon {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
display: inline-block;
|
||||
width: 22px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
margin-inline-end: 0.5em;
|
||||
}
|
||||
.rc-footer-column-icon > span,
|
||||
.rc-footer-column-icon > svg,
|
||||
.rc-footer-column-icon img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
.rc-footer-item {
|
||||
margin: 12px 0;
|
||||
}
|
||||
.rc-footer-item-icon {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
margin-inline-end: 0.4em;
|
||||
}
|
||||
.rc-footer-item-icon > span,
|
||||
.rc-footer-item-icon > svg,
|
||||
.rc-footer-item-icon img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
.rc-footer-item-separator {
|
||||
margin: 0 0.3em;
|
||||
}
|
||||
.rc-footer-bottom-container {
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 16px 0;
|
||||
font-size: 16px;
|
||||
line-height: 32px;
|
||||
text-align: center;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
.rc-footer-light {
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
background-color: transparent;
|
||||
}
|
||||
.rc-footer-light h2,
|
||||
.rc-footer-light a {
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
}
|
||||
.rc-footer-light .rc-footer-bottom-container {
|
||||
border-top-color: #e8e8e8;
|
||||
}
|
||||
.rc-footer-light .rc-footer-item-separator,
|
||||
.rc-footer-light .rc-footer-item-description {
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
@media only screen and (max-width: 767.99px) {
|
||||
.rc-footer {
|
||||
text-align: center;
|
||||
}
|
||||
.rc-footer-container {
|
||||
padding: 40px 0;
|
||||
}
|
||||
.rc-footer-columns {
|
||||
display: block;
|
||||
}
|
||||
.rc-footer-column {
|
||||
display: block;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
.rc-footer-column:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
89
.dumi/rehypeChangelog.ts
Normal file
89
.dumi/rehypeChangelog.ts
Normal file
@ -0,0 +1,89 @@
|
||||
import type { UnifiedTransformer } from 'dumi';
|
||||
import { unistUtilVisit } from 'dumi';
|
||||
import set from 'lodash/set';
|
||||
let hastToString: typeof import('hast-util-to-string').toString;
|
||||
|
||||
// workaround to import pure esm module
|
||||
(async () => {
|
||||
({ toString: hastToString } = await import('hast-util-to-string'));
|
||||
})();
|
||||
|
||||
const COMPONENT_NAME = 'RefinedChangelog';
|
||||
|
||||
function rehypeChangelog(): UnifiedTransformer<any> {
|
||||
return (tree, vFile) => {
|
||||
const { filename } = vFile.data.frontmatter as any;
|
||||
|
||||
// 只处理 changelog 文件
|
||||
if (!/^changelog\.\S+\.md$/i.test(filename)) return;
|
||||
|
||||
const nodesToWrap: { parent: any; startIdx: number }[] = [];
|
||||
const WRAPPER_FLAG = 'data-changelog-wrapped'; // 包裹容器唯一标识
|
||||
|
||||
unistUtilVisit.visit(tree, 'element', (node, idx, parent) => {
|
||||
if (node.properties?.[WRAPPER_FLAG]) return unistUtilVisit.SKIP;
|
||||
|
||||
if (
|
||||
idx !== undefined &&
|
||||
parent &&
|
||||
idx! + 2 < parent.children.length &&
|
||||
node.tagName === 'h2' &&
|
||||
parent.children[idx! + 1].tagName === 'p' &&
|
||||
parent.children[idx! + 2].tagName === 'ul'
|
||||
) {
|
||||
nodesToWrap.push({ parent, startIdx: idx! });
|
||||
}
|
||||
});
|
||||
|
||||
nodesToWrap.reverse().forEach(({ parent, startIdx }) => {
|
||||
const [heading, date, list] = parent.children.splice(startIdx, 3);
|
||||
|
||||
const version = hastToString(heading);
|
||||
const dateStr = hastToString(date);
|
||||
|
||||
const headingWrap = {
|
||||
type: 'element',
|
||||
tagName: `${COMPONENT_NAME}.Version`,
|
||||
// 为标签添加语义化 className (下面同理)
|
||||
children: [set(heading, 'properties.className', 'changelog-version')],
|
||||
};
|
||||
|
||||
const dateWrap = {
|
||||
type: 'element',
|
||||
tagName: `${COMPONENT_NAME}.Date`,
|
||||
children: [set(date, 'properties.className', 'changelog-date')],
|
||||
};
|
||||
|
||||
const listWrap = {
|
||||
type: 'element',
|
||||
tagName: `${COMPONENT_NAME}.Details`,
|
||||
children: [set(list, 'properties.className', 'changelog-details')],
|
||||
};
|
||||
|
||||
const wrapper = {
|
||||
type: 'element',
|
||||
tagName: COMPONENT_NAME,
|
||||
properties: {
|
||||
[WRAPPER_FLAG]: true,
|
||||
},
|
||||
JSXAttributes: [
|
||||
{
|
||||
type: 'JSXAttribute',
|
||||
name: 'version',
|
||||
value: JSON.stringify(version),
|
||||
},
|
||||
{
|
||||
type: 'JSXAttribute',
|
||||
name: 'date',
|
||||
value: JSON.stringify(dateStr),
|
||||
},
|
||||
],
|
||||
children: [headingWrap, dateWrap, listWrap],
|
||||
};
|
||||
|
||||
parent.children.splice(startIdx, 0, wrapper);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export default rehypeChangelog;
|
@ -1,176 +0,0 @@
|
||||
(function createMirrorModal() {
|
||||
if (
|
||||
(navigator.languages.includes('zh') || navigator.languages.includes('zh-CN')) &&
|
||||
/-cn\/?$/.test(window.location.pathname) &&
|
||||
!['ant-design.gitee.io', 'ant-design.antgroup.com'].includes(window.location.hostname) &&
|
||||
!window.location.host.includes('surge') &&
|
||||
window.location.hostname !== 'localhost'
|
||||
) {
|
||||
const ANTD_DOT_NOT_SHOW_MIRROR_MODAL = 'ANT_DESIGN_DO_NOT_OPEN_MIRROR_MODAL';
|
||||
|
||||
const lastShowTime = window.localStorage.getItem(ANTD_DOT_NOT_SHOW_MIRROR_MODAL);
|
||||
if (
|
||||
lastShowTime &&
|
||||
lastShowTime !== 'true' &&
|
||||
Date.now() - new Date(lastShowTime).getTime() < 7 * 24 * 60 * 60 * 1000
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const style = document.createElement('style');
|
||||
style.innerHTML = `
|
||||
@keyframes mirror-fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes mirror-zoom-in {
|
||||
from {
|
||||
transform: scale(0.8);
|
||||
}
|
||||
to {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.mirror-modal-mask {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
z-index: 9999;
|
||||
animation: mirror-fade-in 0.3s forwards;
|
||||
}
|
||||
|
||||
.mirror-modal-dialog {
|
||||
position: fixed;
|
||||
top: 120px;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: 0;
|
||||
margin: 0 auto;
|
||||
width: 420px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #eee;
|
||||
background: #fff;
|
||||
padding: 20px 24px;
|
||||
box-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
|
||||
animation: mirror-zoom-in 0.3s forwards;
|
||||
box-sizing: border-box;
|
||||
max-width: 100vw;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.mirror-modal-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
align-self: flex-start;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.mirror-modal-content {
|
||||
font-size: 14px;
|
||||
align-self: flex-start;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.mirror-modal-btns {
|
||||
align-self: flex-end;
|
||||
margin-top: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mirror-modal-btn {
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
height: 32px;
|
||||
box-sizing: border-box;
|
||||
font-size: 14px;
|
||||
padding: 4px 16px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
text-decoration: none;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.mirror-modal-confirm-btn {
|
||||
background: #1677ff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.mirror-modal-confirm-btn:hover {
|
||||
background: #4096ff;
|
||||
}
|
||||
|
||||
.mirror-modal-confirm-btn:active {
|
||||
background: #0958d9;
|
||||
}
|
||||
|
||||
.mirror-modal-cancel-btn {
|
||||
border: 1px solid #eee;
|
||||
color: #000;
|
||||
margin-inline-end: 8px;
|
||||
}
|
||||
|
||||
.mirror-modal-cancel-btn:hover {
|
||||
border-color: #4096ff;
|
||||
color: #4096ff
|
||||
}
|
||||
|
||||
.mirror-modal-cancel-btn:active {
|
||||
border-color: #0958d9;
|
||||
color: #0958d9;
|
||||
}
|
||||
`;
|
||||
document.head.append(style);
|
||||
|
||||
const modal = document.createElement('div');
|
||||
modal.className = 'mirror-modal-mask';
|
||||
|
||||
const dialog = document.createElement('div');
|
||||
dialog.className = 'mirror-modal-dialog';
|
||||
modal.append(dialog);
|
||||
|
||||
const title = document.createElement('div');
|
||||
title.className = 'mirror-modal-title';
|
||||
title.textContent = '提示';
|
||||
dialog.append(title);
|
||||
|
||||
const content = document.createElement('div');
|
||||
content.className = 'mirror-modal-content';
|
||||
content.textContent = '🚀 国内用户推荐访问国内镜像以获得极速体验~';
|
||||
dialog.append(content);
|
||||
|
||||
const btnWrapper = document.createElement('div');
|
||||
btnWrapper.className = 'mirror-modal-btns';
|
||||
dialog.append(btnWrapper);
|
||||
|
||||
const cancelBtn = document.createElement('a');
|
||||
cancelBtn.className = 'mirror-modal-cancel-btn mirror-modal-btn';
|
||||
cancelBtn.textContent = '7 天内不再显示';
|
||||
btnWrapper.append(cancelBtn);
|
||||
cancelBtn.addEventListener('click', () => {
|
||||
window.localStorage.setItem(ANTD_DOT_NOT_SHOW_MIRROR_MODAL, new Date().toISOString());
|
||||
document.body.removeChild(modal);
|
||||
document.head.removeChild(style);
|
||||
document.body.style.overflow = '';
|
||||
});
|
||||
|
||||
const confirmBtn = document.createElement('a');
|
||||
confirmBtn.className = 'mirror-modal-confirm-btn mirror-modal-btn';
|
||||
confirmBtn.href = window.location.href.replace(window.location.host, 'ant-design.antgroup.com');
|
||||
confirmBtn.textContent = '🚀 立刻前往';
|
||||
btnWrapper.append(confirmBtn);
|
||||
|
||||
document.body.append(modal);
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
})();
|
230
.dumi/scripts/mirror-notify.js
Normal file
230
.dumi/scripts/mirror-notify.js
Normal file
@ -0,0 +1,230 @@
|
||||
(function createMirrorModal() {
|
||||
const SIGN = Symbol.for('antd.mirror-notify');
|
||||
const always = window.localStorage.getItem('DEBUG') === 'antd';
|
||||
const officialChinaMirror = 'https://ant-design.antgroup.com';
|
||||
|
||||
const enabledCondition = [
|
||||
// Check if the browser language is Chinese
|
||||
navigator.languages.includes('zh') || navigator.languages.includes('zh-CN'),
|
||||
// Check if the URL path ends with -cn
|
||||
/-cn\/?$/.test(window.location.pathname),
|
||||
// chinese mirror URL
|
||||
!['ant-design.gitee.io', new URL(officialChinaMirror).hostname].includes(
|
||||
window.location.hostname,
|
||||
),
|
||||
// PR review URL
|
||||
!window.location.host.includes('surge'),
|
||||
// development mode
|
||||
!['127.0.0.1', 'localhost'].includes(window.location.hostname),
|
||||
];
|
||||
|
||||
const isEnabled = always || enabledCondition.every(Boolean);
|
||||
|
||||
if (!isEnabled) return;
|
||||
|
||||
const prefixCls = 'antd-mirror-notify';
|
||||
const primaryColor = '#1677ff';
|
||||
|
||||
function insertCss() {
|
||||
const style = document.createElement('style');
|
||||
style.innerHTML = `
|
||||
@keyframes slideInRight {
|
||||
from {
|
||||
transform: translate3d(100%, 0, 0);
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.${prefixCls} {
|
||||
position: fixed;
|
||||
inset-inline-end: 12px;
|
||||
inset-block-start: 12px;
|
||||
z-index: 9999;
|
||||
width: 360px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
animation: slideInRight 0.3s ease-in-out;
|
||||
}
|
||||
.${prefixCls}-content {
|
||||
padding: 16px;
|
||||
}
|
||||
.${prefixCls}-content a {
|
||||
color: ${primaryColor};
|
||||
text-decoration: none;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
.${prefixCls}-title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-block-end: 8px;
|
||||
}
|
||||
.${prefixCls}-message {
|
||||
font-size: 14px;
|
||||
color: #555;
|
||||
line-height: 1.57;
|
||||
}
|
||||
.${prefixCls}-footer {
|
||||
display: none;
|
||||
margin-block-start: 16px;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.${prefixCls}-progress {
|
||||
position: relative;
|
||||
inset-inline-end: 0;
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.${prefixCls}-progress::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: var(--progress, 0%);
|
||||
background-color: ${primaryColor};
|
||||
transition: width 0.05s linear; /* Adjusted for smoother animation matching refreshRate */
|
||||
}
|
||||
.${prefixCls}-close {
|
||||
all: unset;
|
||||
position: absolute;
|
||||
inset-inline-end: 2px;
|
||||
inset-block-start: 2px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
font-size: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.${prefixCls}-close:hover {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.${prefixCls}-action {
|
||||
all: unset;
|
||||
display: inline-block;
|
||||
padding: 4px 8px;
|
||||
background-color: ${primaryColor};
|
||||
color: #fff;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
}
|
||||
`;
|
||||
|
||||
document.head.append(style);
|
||||
}
|
||||
|
||||
function createNotification() {
|
||||
insertCss();
|
||||
|
||||
const notify = document.createElement('div');
|
||||
notify.className = `${prefixCls} slideInRight`;
|
||||
notify.innerHTML = `
|
||||
<div class="${prefixCls}-content">
|
||||
<div class="${prefixCls}-title">🇨🇳 访问不畅?试试国内镜像</div>
|
||||
<div class="${prefixCls}-message">
|
||||
国内镜像站点可以帮助您更快地访问文档和资源。<br>
|
||||
请尝试访问 <a href="${officialChinaMirror}">国内镜像站点</a>,以获得更好的体验。
|
||||
</div>
|
||||
<div class="${prefixCls}-footer">
|
||||
<button class="${prefixCls}-action">🚀 立即前往</button>
|
||||
</div>
|
||||
</div>
|
||||
<button class="${prefixCls}-close">X</button>
|
||||
<div class="${prefixCls}-progress" style="--progress: 100%;"></div>
|
||||
`;
|
||||
document.body.appendChild(notify);
|
||||
|
||||
notify.querySelector(`.${prefixCls}-close`).addEventListener('click', () => {
|
||||
removeNotify();
|
||||
});
|
||||
|
||||
notify.querySelector(`.${prefixCls}-action`).addEventListener('click', () => {
|
||||
window.location.href = officialChinaMirror;
|
||||
removeNotify();
|
||||
});
|
||||
|
||||
const refreshRate = 50; // ms
|
||||
const duration = 10; // s
|
||||
const step = 100 / ((duration * 1000) / refreshRate);
|
||||
let progressInterval = -1;
|
||||
|
||||
function removeNotify() {
|
||||
clearInterval(progressInterval);
|
||||
notify.remove();
|
||||
}
|
||||
|
||||
const progressEl = notify.querySelector(`.${prefixCls}-progress`);
|
||||
let currentProgressValue = 100;
|
||||
|
||||
const progress = {
|
||||
get value() {
|
||||
return currentProgressValue;
|
||||
},
|
||||
set value(val) {
|
||||
currentProgressValue = Math.max(0, Math.min(100, val));
|
||||
progressEl.style.setProperty('--progress', `${currentProgressValue}%`);
|
||||
},
|
||||
};
|
||||
|
||||
function startProgressTimer() {
|
||||
if (progressInterval !== -1) {
|
||||
clearInterval(progressInterval);
|
||||
}
|
||||
progressInterval = setInterval(() => {
|
||||
if (progress.value <= 0) {
|
||||
removeNotify();
|
||||
} else {
|
||||
progress.value -= step;
|
||||
}
|
||||
}, refreshRate);
|
||||
}
|
||||
|
||||
startProgressTimer();
|
||||
|
||||
notify.addEventListener('mouseenter', () => {
|
||||
clearInterval(progressInterval);
|
||||
});
|
||||
|
||||
notify.addEventListener('mouseleave', () => {
|
||||
startProgressTimer();
|
||||
});
|
||||
}
|
||||
|
||||
// 断定网络不畅阈值(秒)
|
||||
const delayDuration = 3;
|
||||
|
||||
const reactTimeoutId = setTimeout(() => {
|
||||
if (typeof window[SIGN]?.YES === 'undefined') {
|
||||
console.error(
|
||||
`antd.mirror-notify: 页面加载超过 ${delayDuration} 秒,可能是网络不畅。\n请尝试访问国内镜像站点。%c${officialChinaMirror}`,
|
||||
`color: ${primaryColor}; font-weight: bold;`,
|
||||
);
|
||||
createNotification();
|
||||
}
|
||||
}, delayDuration * 1000);
|
||||
|
||||
// 交给 React effect 清理
|
||||
window[SIGN] = function stopMirrorNotify() {
|
||||
window[SIGN].YES = Date.now();
|
||||
clearTimeout(reactTimeoutId);
|
||||
};
|
||||
})();
|
@ -19,25 +19,23 @@ const Container: React.FC<React.PropsWithChildren<ContainerProps>> = ({
|
||||
const { styles, cx } = useStyles();
|
||||
|
||||
return (
|
||||
<div data-type={type} className={styles.container}>
|
||||
<Alert
|
||||
showIcon
|
||||
type={type}
|
||||
title={title || type.toUpperCase()}
|
||||
description={
|
||||
<div
|
||||
className={cx(
|
||||
styles.desc,
|
||||
// 为了让 markdown 的样式生效,需要在这里添加一个额外的 class
|
||||
'markdown',
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
}
|
||||
className={styles.alert}
|
||||
/>
|
||||
</div>
|
||||
<Alert
|
||||
showIcon
|
||||
type={type}
|
||||
title={title || type.toUpperCase()}
|
||||
description={
|
||||
<div
|
||||
className={cx(
|
||||
styles.desc,
|
||||
// 为了让 markdown 的样式生效,需要在这里添加一个额外的 class
|
||||
'markdown',
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
}
|
||||
className={styles.alert}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,11 +1,8 @@
|
||||
import { createStyles } from 'antd-style';
|
||||
|
||||
const useStyles = createStyles(({ token, prefixCls, css }) => ({
|
||||
container: css`
|
||||
margin: ${token.marginXS}px 0;
|
||||
`,
|
||||
|
||||
const useStyles = createStyles(({ prefixCls, css }) => ({
|
||||
alert: css`
|
||||
padding: 12px 16px;
|
||||
.${prefixCls}-alert-message {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
@ -1,41 +1,8 @@
|
||||
import React, { Suspense, useEffect, useState } from 'react';
|
||||
import { Tooltip } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
import { Tooltip, App } from 'antd';
|
||||
import { LoadingOutlined } from '@ant-design/icons';
|
||||
import { FormattedMessage } from 'dumi';
|
||||
|
||||
const codeBlockJs =
|
||||
'https://renderoffice.a' +
|
||||
'lipay' +
|
||||
'objects.com/p' +
|
||||
'/yuyan/180020010001206410/parseFileData-v1.0.1.js';
|
||||
|
||||
function useShowCodeBlockButton() {
|
||||
const [showCodeBlockButton, setShowCodeBlockButton] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const scriptId = 'hitu-code-block-js';
|
||||
const existScript = document.getElementById(scriptId) as HTMLScriptElement | null;
|
||||
|
||||
if (existScript) {
|
||||
// 如果已标记 loaded,直接显示按钮
|
||||
if (existScript.dataset.loaded) {
|
||||
setShowCodeBlockButton(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
const script = document.createElement('script');
|
||||
script.src = codeBlockJs;
|
||||
script.async = true;
|
||||
script.id = scriptId;
|
||||
script.onload = () => {
|
||||
script.dataset.loaded = 'true';
|
||||
setShowCodeBlockButton(true);
|
||||
};
|
||||
document.body.appendChild(script);
|
||||
}, []);
|
||||
|
||||
return showCodeBlockButton;
|
||||
}
|
||||
|
||||
interface CodeBlockButtonProps {
|
||||
title?: string;
|
||||
dependencies: Record<PropertyKey, string>;
|
||||
@ -43,7 +10,8 @@ interface CodeBlockButtonProps {
|
||||
}
|
||||
|
||||
const CodeBlockButton: React.FC<CodeBlockButtonProps> = ({ title, dependencies = {}, jsx }) => {
|
||||
const showCodeBlockButton = useShowCodeBlockButton();
|
||||
const { message } = App.useApp();
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const codeBlockPrefillConfig = {
|
||||
title: `${title} - antd@${dependencies.antd}`,
|
||||
@ -57,24 +25,56 @@ const CodeBlockButton: React.FC<CodeBlockButtonProps> = ({ title, dependencies =
|
||||
json: JSON.stringify({ name: 'antd-demo', dependencies }, null, 2),
|
||||
};
|
||||
|
||||
return showCodeBlockButton ? (
|
||||
const openHituCodeBlockFn = () => {
|
||||
setLoading(false);
|
||||
// @ts-ignore
|
||||
if (window.openHituCodeBlock) {
|
||||
// @ts-ignore
|
||||
window.openHituCodeBlock(JSON.stringify(codeBlockPrefillConfig));
|
||||
} else {
|
||||
message.error('此功能仅在内网环境可用');
|
||||
}
|
||||
};
|
||||
|
||||
const handleClick = () => {
|
||||
const scriptId = 'hitu-code-block-js';
|
||||
const existScript = document.getElementById(scriptId) as HTMLScriptElement | null;
|
||||
// @ts-ignore
|
||||
if (existScript?.dataset.loaded) {
|
||||
openHituCodeBlockFn();
|
||||
return;
|
||||
}
|
||||
setLoading(true);
|
||||
const script = document.createElement('script');
|
||||
script.src = `https://renderoffice.alipayobjects.com/p/yuyan/180020010001206410/parseFileData-v1.0.1.js?t=${Date.now()}`;
|
||||
script.async = true;
|
||||
script.id = scriptId;
|
||||
script.onload = () => {
|
||||
script.dataset.loaded = 'true';
|
||||
openHituCodeBlockFn();
|
||||
};
|
||||
script.onerror = () => {
|
||||
openHituCodeBlockFn();
|
||||
};
|
||||
document.body.appendChild(script);
|
||||
};
|
||||
|
||||
return (
|
||||
<Tooltip title={<FormattedMessage id="app.demo.codeblock" />}>
|
||||
<div className="code-box-code-action">
|
||||
<img
|
||||
alt="codeblock"
|
||||
src="https://mdn.alipayobjects.com/huamei_wtld8u/afts/img/A*K8rjSJpTNQ8AAAAAAAAAAAAADhOIAQ/original"
|
||||
className="code-box-codeblock"
|
||||
onClick={() => {
|
||||
openHituCodeBlock?.(JSON.stringify(codeBlockPrefillConfig));
|
||||
}}
|
||||
/>
|
||||
{loading ? (
|
||||
<LoadingOutlined className="code-box-codeblock" />
|
||||
) : (
|
||||
<img
|
||||
alt="codeblock"
|
||||
src="https://mdn.alipayobjects.com/huamei_wtld8u/afts/img/A*K8rjSJpTNQ8AAAAAAAAAAAAADhOIAQ/original"
|
||||
className="code-box-codeblock"
|
||||
onClick={handleClick}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Tooltip>
|
||||
) : null;
|
||||
);
|
||||
};
|
||||
|
||||
export default (props: CodeBlockButtonProps) => (
|
||||
<Suspense>
|
||||
<CodeBlockButton {...props} />
|
||||
</Suspense>
|
||||
);
|
||||
export default CodeBlockButton;
|
||||
|
131
.dumi/theme/builtins/RefinedChangelog/index.tsx
Normal file
131
.dumi/theme/builtins/RefinedChangelog/index.tsx
Normal file
@ -0,0 +1,131 @@
|
||||
import * as React from 'react';
|
||||
import { BugOutlined } from '@ant-design/icons';
|
||||
import { Button, Flex, Popover, theme } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import dayjs, { Dayjs } from 'dayjs';
|
||||
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
import { matchDeprecated } from '../../utils';
|
||||
|
||||
interface RefinedChangelogProps {
|
||||
version?: string;
|
||||
date?: string;
|
||||
}
|
||||
|
||||
interface ContextProps {
|
||||
version: string;
|
||||
date?: Dayjs;
|
||||
isDeprecated?: boolean;
|
||||
reason?: string[];
|
||||
}
|
||||
|
||||
const ChangelogContext = React.createContext<ContextProps>({
|
||||
version: '0.0.0',
|
||||
});
|
||||
|
||||
const locales = {
|
||||
cn: {
|
||||
deprecatedTitle: '🚨 该版本存在缺陷, 请升级至下一个新版本',
|
||||
},
|
||||
en: {
|
||||
deprecatedTitle: '🚨 This version has defects, please upgrade to the next version',
|
||||
},
|
||||
};
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => ({
|
||||
container: css`
|
||||
margin-block: ${token.margin}px;
|
||||
padding: ${token.padding}px;
|
||||
|
||||
.changelog-version {
|
||||
line-height: ${token.lineHeight} !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
`,
|
||||
isDeprecated: css``,
|
||||
}));
|
||||
|
||||
function RefinedChangelog(props: React.PropsWithChildren<RefinedChangelogProps>) {
|
||||
const { version, date, children } = props;
|
||||
|
||||
const { styles, cx } = useStyle();
|
||||
|
||||
const memoizedValue = React.useMemo(() => {
|
||||
const realVersion = version || '0.0.0';
|
||||
const bugVersionInfo = matchDeprecated(realVersion);
|
||||
return {
|
||||
version: realVersion,
|
||||
isDeprecated: !!bugVersionInfo?.match,
|
||||
reason: bugVersionInfo?.reason,
|
||||
date: date ? dayjs(date) : undefined,
|
||||
};
|
||||
}, [version, date]);
|
||||
|
||||
return (
|
||||
<ChangelogContext.Provider value={memoizedValue}>
|
||||
<div
|
||||
className={cx('refined-changelog', styles.container, {
|
||||
[styles.isDeprecated]: memoizedValue.isDeprecated,
|
||||
})}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</ChangelogContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
function Version({ children }: React.PropsWithChildren) {
|
||||
const { isDeprecated, reason } = React.use(ChangelogContext);
|
||||
const { token } = theme.useToken();
|
||||
const [locale] = useLocale(locales);
|
||||
|
||||
if (!isDeprecated) {
|
||||
return children;
|
||||
}
|
||||
|
||||
const reasonContent = (
|
||||
<Flex vertical align="start">
|
||||
{reason?.map((item, index) => (
|
||||
<Button
|
||||
key={index}
|
||||
type="link"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href={item}
|
||||
icon={<BugOutlined />}
|
||||
>
|
||||
{item}
|
||||
</Button>
|
||||
))}
|
||||
</Flex>
|
||||
);
|
||||
|
||||
return (
|
||||
<Flex align="center" gap="small">
|
||||
{children}
|
||||
<Popover placement="right" title={locale.deprecatedTitle} content={reasonContent}>
|
||||
<BugOutlined
|
||||
style={{
|
||||
lineHeight: token.lineHeight,
|
||||
fontSize: token.fontSize,
|
||||
color: token.colorErrorText,
|
||||
}}
|
||||
/>
|
||||
</Popover>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
function DateComp(props: React.PropsWithChildren) {
|
||||
return props.children;
|
||||
}
|
||||
|
||||
function Details(props: React.PropsWithChildren) {
|
||||
return props.children;
|
||||
}
|
||||
|
||||
export default Object.assign(RefinedChangelog, {
|
||||
Version,
|
||||
Date: DateComp,
|
||||
Details,
|
||||
});
|
@ -79,7 +79,7 @@ const ArticleList: React.FC<ArticleListProps> = ({ name, data = [], authors = []
|
||||
<a href={author?.href} target="_blank" rel="noreferrer">
|
||||
<Avatar size="small" src={author?.avatar} />
|
||||
</a>
|
||||
<Divider type="vertical" />
|
||||
<Divider vertical />
|
||||
<a href={article.href} target="_blank" rel="noreferrer">
|
||||
{article?.title}
|
||||
</a>
|
||||
|
@ -3,19 +3,13 @@ import { BugOutlined } from '@ant-design/icons';
|
||||
import { Button, Drawer, Flex, Grid, Popover, Tag, Timeline, Typography } from 'antd';
|
||||
import type { TimelineItemProps } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import semver from 'semver';
|
||||
|
||||
import deprecatedVersions from '../../../../BUG_VERSIONS.json';
|
||||
import useFetch from '../../../hooks/useFetch';
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
import useLocation from '../../../hooks/useLocation';
|
||||
import { matchDeprecated } from '../../utils';
|
||||
import Link from '../Link';
|
||||
|
||||
interface MatchDeprecatedResult {
|
||||
match?: string;
|
||||
reason: string[];
|
||||
}
|
||||
|
||||
interface ChangelogInfo {
|
||||
version: string;
|
||||
changelog: string;
|
||||
@ -24,17 +18,6 @@ interface ChangelogInfo {
|
||||
releaseDate: string;
|
||||
}
|
||||
|
||||
function matchDeprecated(v: string): MatchDeprecatedResult {
|
||||
const match = Object.keys(deprecatedVersions).find((depreciated) =>
|
||||
semver.satisfies(v, depreciated),
|
||||
);
|
||||
const reason = deprecatedVersions[match as keyof typeof deprecatedVersions] || [];
|
||||
return {
|
||||
match,
|
||||
reason: Array.isArray(reason) ? reason : [reason],
|
||||
};
|
||||
}
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => ({
|
||||
listWrap: css`
|
||||
> li {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
import useLocale from '../hooks/useLocale';
|
||||
import useLocale from '../../hooks/useLocale';
|
||||
import SemanticPreview from './SemanticPreview';
|
||||
|
||||
export const locales = {
|
@ -1,4 +1,4 @@
|
||||
import React, { use } from 'react';
|
||||
import React, { use, useRef } from 'react';
|
||||
import { BgColorsOutlined, LinkOutlined, SmileOutlined, SunOutlined } from '@ant-design/icons';
|
||||
import { Badge, Button, Dropdown } from 'antd';
|
||||
import type { MenuProps } from 'antd';
|
||||
@ -22,6 +22,7 @@ const ThemeSwitch: React.FC<ThemeSwitchProps> = () => {
|
||||
const { pathname, search } = useLocation();
|
||||
const { theme, updateSiteConfig } = use<SiteContextProps>(SiteContext);
|
||||
const toggleAnimationTheme = useThemeAnimation();
|
||||
const lastThemeKey = useRef<string>(theme.includes('dark') ? 'dark' : 'light');
|
||||
|
||||
const badge = <Badge color="blue" style={{ marginTop: -1 }} />;
|
||||
|
||||
@ -95,10 +96,12 @@ const ThemeSwitch: React.FC<ThemeSwitchProps> = () => {
|
||||
// 处理主题切换
|
||||
const handleThemeChange = (key: string, domEvent: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
||||
// 主题编辑器特殊处理
|
||||
if (key === 'theme-editor') {
|
||||
if (key === 'theme-editor' || key === lastThemeKey.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastThemeKey.current = key;
|
||||
|
||||
// 亮色/暗色模式切换时应用动画效果
|
||||
if (key === 'dark' || key === 'light') {
|
||||
toggleAnimationTheme(domEvent, theme.includes('dark'));
|
||||
|
@ -14,8 +14,6 @@ import GlobalStyles from '../../common/GlobalStyles';
|
||||
import Header from '../../slots/Header';
|
||||
import SiteContext from '../../slots/SiteContext';
|
||||
|
||||
import '../../static/style';
|
||||
|
||||
import IndexLayout from '../IndexLayout';
|
||||
import ResourceLayout from '../ResourceLayout';
|
||||
import SidebarLayout from '../SidebarLayout';
|
||||
|
@ -137,6 +137,12 @@ const GlobalLayout: React.FC = () => {
|
||||
// Handle isMobile
|
||||
updateMobileMode();
|
||||
|
||||
// 配合 dumi 的 mirror-notify 脚本使用
|
||||
const retrieveMirrorNotification = (window as any)[Symbol.for('antd.mirror-notify')];
|
||||
if (typeof retrieveMirrorNotification === 'function') {
|
||||
retrieveMirrorNotification();
|
||||
}
|
||||
|
||||
window.addEventListener('resize', updateMobileMode);
|
||||
return () => {
|
||||
window.removeEventListener('resize', updateMobileMode);
|
||||
|
@ -1,24 +0,0 @@
|
||||
import React, { Suspense } from 'react';
|
||||
import { Skeleton } from 'antd';
|
||||
import { InView } from 'react-intersection-observer';
|
||||
import type { IntersectionObserverProps } from 'react-intersection-observer';
|
||||
|
||||
type InViewSuspenseProps = Pick<IntersectionObserverProps, 'delay'> & {
|
||||
fallback?: React.ReactNode;
|
||||
};
|
||||
|
||||
const InViewSuspense: React.FC<React.PropsWithChildren<InViewSuspenseProps>> = ({
|
||||
children,
|
||||
fallback = <Skeleton.Input active size="small" />,
|
||||
delay = 200,
|
||||
}) => (
|
||||
<InView triggerOnce delay={delay}>
|
||||
{({ inView, ref }) => (
|
||||
<div ref={ref}>
|
||||
<Suspense fallback={fallback}>{inView ? children : <span />}</Suspense>
|
||||
</div>
|
||||
)}
|
||||
</InView>
|
||||
);
|
||||
|
||||
export default InViewSuspense;
|
@ -1,5 +1,5 @@
|
||||
import React, { useLayoutEffect, useMemo, useState } from 'react';
|
||||
import { Col, Flex, Skeleton, Space, Typography } from 'antd';
|
||||
import React, { Suspense, useLayoutEffect, useMemo, useState } from 'react';
|
||||
import { Col, Flex, FloatButton, Skeleton, Space, Typography } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import { FormattedMessage, useRouteMeta } from 'dumi';
|
||||
|
||||
@ -9,16 +9,13 @@ import ComponentMeta from '../../builtins/ComponentMeta';
|
||||
import type { DemoContextProps } from '../DemoContext';
|
||||
import DemoContext from '../DemoContext';
|
||||
import SiteContext from '../SiteContext';
|
||||
import { useStyle } from './DocAnchor';
|
||||
import InViewSuspense from './InViewSuspense';
|
||||
|
||||
const Contributors = React.lazy(() => import('./Contributors'));
|
||||
const ColumnCard = React.lazy(() => import('./ColumnCard'));
|
||||
const DocAnchor = React.lazy(() => import('./DocAnchor'));
|
||||
const DocMeta = React.lazy(() => import('./DocMeta'));
|
||||
const Footer = React.lazy(() => import('../Footer'));
|
||||
const PrevAndNext = React.lazy(() => import('../../common/PrevAndNext'));
|
||||
const EditButton = React.lazy(() => import('../../common/EditButton'));
|
||||
import DocAnchor, { useStyle } from './DocAnchor';
|
||||
import Contributors from './Contributors';
|
||||
import ColumnCard from './ColumnCard';
|
||||
import DocMeta from './DocMeta';
|
||||
import Footer from '../Footer';
|
||||
import PrevAndNext from '../../common/PrevAndNext';
|
||||
import EditButton from '../../common/EditButton';
|
||||
|
||||
const AvatarPlaceholder: React.FC<{ num?: number }> = ({ num = 6 }) =>
|
||||
Array.from({ length: num }).map<React.ReactNode>((_, i) => (
|
||||
@ -54,9 +51,7 @@ const Content: React.FC<React.PropsWithChildren> = ({ children }) => {
|
||||
return (
|
||||
<DemoContext value={contextValue}>
|
||||
<Col xxl={20} xl={19} lg={18} md={18} sm={24} xs={24}>
|
||||
<InViewSuspense fallback={null}>
|
||||
<DocAnchor showDebug={showDebug} debugDemos={debugDemos} />
|
||||
</InViewSuspense>
|
||||
<DocAnchor showDebug={showDebug} debugDemos={debugDemos} />
|
||||
<article className={classNames(styles.articleWrapper, { rtl: isRTL })}>
|
||||
{meta.frontmatter?.title ? (
|
||||
<Flex justify="space-between">
|
||||
@ -65,20 +60,16 @@ const Content: React.FC<React.PropsWithChildren> = ({ children }) => {
|
||||
<span>{meta.frontmatter?.title}</span>
|
||||
<span>{meta.frontmatter?.subtitle}</span>
|
||||
{!pathname.startsWith('/components/overview') && (
|
||||
<InViewSuspense fallback={null}>
|
||||
<EditButton
|
||||
title={<FormattedMessage id="app.content.edit-page" />}
|
||||
filename={meta.frontmatter.filename}
|
||||
/>
|
||||
</InViewSuspense>
|
||||
<EditButton
|
||||
title={<FormattedMessage id="app.content.edit-page" />}
|
||||
filename={meta.frontmatter.filename}
|
||||
/>
|
||||
)}
|
||||
</Space>
|
||||
</Typography.Title>
|
||||
</Flex>
|
||||
) : null}
|
||||
<InViewSuspense fallback={null}>
|
||||
<DocMeta />
|
||||
</InViewSuspense>
|
||||
<DocMeta />
|
||||
{!meta.frontmatter.__autoDescription && meta.frontmatter.description}
|
||||
|
||||
{/* Import Info */}
|
||||
@ -92,23 +83,22 @@ const Content: React.FC<React.PropsWithChildren> = ({ children }) => {
|
||||
designUrl={meta.frontmatter.designUrl}
|
||||
/>
|
||||
)}
|
||||
<div style={{ minHeight: 'calc(100vh - 64px)' }}>{children}</div>
|
||||
<InViewSuspense fallback={null}>
|
||||
<ColumnCard
|
||||
zhihuLink={meta.frontmatter.zhihu_url}
|
||||
yuqueLink={meta.frontmatter.yuque_url}
|
||||
juejinLink={meta.frontmatter.juejin_url}
|
||||
/>
|
||||
</InViewSuspense>
|
||||
<div style={{ minHeight: 'calc(100vh - 64px)' }}>
|
||||
{children}
|
||||
<FloatButton.BackTop />
|
||||
</div>
|
||||
<ColumnCard
|
||||
zhihuLink={meta.frontmatter.zhihu_url}
|
||||
yuqueLink={meta.frontmatter.yuque_url}
|
||||
juejinLink={meta.frontmatter.juejin_url}
|
||||
/>
|
||||
<div style={{ marginTop: 120 }}>
|
||||
<InViewSuspense fallback={<AvatarPlaceholder />}>
|
||||
<Suspense fallback={<AvatarPlaceholder />}>
|
||||
<Contributors filename={meta.frontmatter.filename} />
|
||||
</InViewSuspense>
|
||||
</Suspense>
|
||||
</div>
|
||||
</article>
|
||||
<InViewSuspense fallback={null}>
|
||||
<PrevAndNext rtl={isRTL} />
|
||||
</InViewSuspense>
|
||||
<PrevAndNext rtl={isRTL} />
|
||||
<Footer />
|
||||
</Col>
|
||||
</DemoContext>
|
||||
|
@ -1 +0,0 @@
|
||||
import 'rc-footer/assets/index.css';
|
@ -1,107 +0,0 @@
|
||||
import tsToJs from '../tsToJs';
|
||||
|
||||
// 简单测试用例:基本的 TypeScript 到 JavaScript 转换
|
||||
console.log('测试 1: 基本 TypeScript 转换');
|
||||
const tsInput = `
|
||||
interface Person {
|
||||
name: string;
|
||||
age: number;
|
||||
}
|
||||
|
||||
function greet(person: Person): string {
|
||||
return \`Hello, \${person.name}!\`;
|
||||
}
|
||||
|
||||
const john: Person = { name: 'John', age: 30 };
|
||||
greet(john);
|
||||
`;
|
||||
|
||||
const jsOutput = tsToJs(tsInput);
|
||||
console.log('输入:', tsInput);
|
||||
console.log('输出:', jsOutput);
|
||||
console.log('检查点:');
|
||||
console.log('- interface 被移除:', !jsOutput.includes('interface'));
|
||||
console.log('- 类型注解被移除:', !jsOutput.includes(': string') && !jsOutput.includes(': Person'));
|
||||
console.log('- 函数定义正确:', jsOutput.includes('function greet(person)'));
|
||||
console.log('- 对象定义正确:', jsOutput.includes('const john = { name:'));
|
||||
|
||||
// 测试用例 2: JSX 转换
|
||||
console.log('\n测试 2: JSX 转换');
|
||||
const tsxInput = `
|
||||
import React, { FC } from 'react';
|
||||
|
||||
interface ButtonProps {
|
||||
text: string;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
const Button: FC<ButtonProps> = ({ text, onClick }) => {
|
||||
return (
|
||||
<button
|
||||
className="primary-button"
|
||||
onClick={onClick}
|
||||
>
|
||||
{text}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
export default Button;
|
||||
`;
|
||||
|
||||
const jsxOutput = tsToJs(tsxInput);
|
||||
console.log('输入:', tsxInput);
|
||||
console.log('输出:', jsxOutput);
|
||||
console.log('检查点:');
|
||||
console.log('- interface 被移除:', !jsxOutput.includes('interface ButtonProps'));
|
||||
console.log('- 类型注解被移除:', !jsxOutput.includes(': FC<ButtonProps>'));
|
||||
console.log('- JSX 被保留:', jsxOutput.includes('<button') && jsxOutput.includes('</button>'));
|
||||
console.log(
|
||||
'- 属性被保留:',
|
||||
jsxOutput.includes('className="primary-button"') && jsxOutput.includes('onClick={onClick}'),
|
||||
);
|
||||
|
||||
// 测试用例 3: 类型导入处理
|
||||
console.log('\n测试 3: 类型导入处理');
|
||||
const typeImportInput = `
|
||||
import React from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
import { Button } from 'antd';
|
||||
import type { ButtonProps } from 'antd/es/button';
|
||||
|
||||
const MyButton = (props: ButtonProps) => {
|
||||
return <Button {...props} />;
|
||||
};
|
||||
`;
|
||||
|
||||
const typeImportOutput = tsToJs(typeImportInput);
|
||||
console.log('输入:', typeImportInput);
|
||||
console.log('输出:', typeImportOutput);
|
||||
console.log('检查点:');
|
||||
console.log('- 类型导入被移除:', !typeImportOutput.includes('import type'));
|
||||
console.log('- ReactNode 被移除:', !typeImportOutput.includes('ReactNode'));
|
||||
console.log('- ButtonProps 被移除:', !typeImportOutput.includes('ButtonProps'));
|
||||
console.log(
|
||||
'- 普通导入被保留:',
|
||||
typeImportOutput.includes("import React from 'react'") &&
|
||||
typeImportOutput.includes("import { Button } from 'antd'"),
|
||||
);
|
||||
|
||||
// 总结测试结果
|
||||
console.log('\n测试总结:');
|
||||
const test1Pass =
|
||||
!jsOutput.includes('interface') &&
|
||||
!jsOutput.includes(': string') &&
|
||||
jsOutput.includes('function greet(person)');
|
||||
const test2Pass =
|
||||
!jsxOutput.includes('interface ButtonProps') &&
|
||||
jsxOutput.includes('<button') &&
|
||||
jsxOutput.includes('</button>');
|
||||
const test3Pass =
|
||||
!typeImportOutput.includes('import type') &&
|
||||
typeImportOutput.includes("import React from 'react'");
|
||||
|
||||
console.log('测试 1 (基本 TypeScript 转换):', test1Pass ? '通过' : '失败');
|
||||
console.log('测试 2 (JSX 转换):', test2Pass ? '通过' : '失败');
|
||||
console.log('测试 3 (类型导入处理):', test3Pass ? '通过' : '失败');
|
||||
console.log('所有测试:', test1Pass && test2Pass && test3Pass ? '通过' : '失败');
|
@ -1,93 +0,0 @@
|
||||
import tsToJs from '../tsToJs';
|
||||
|
||||
describe('tsToJs', () => {
|
||||
it('应该将基本的 TypeScript 转换为 JavaScript', () => {
|
||||
const tsInput = `
|
||||
interface Person {
|
||||
name: string;
|
||||
age: number;
|
||||
}
|
||||
|
||||
function greet(person: Person): string {
|
||||
return \`Hello, \${person.name}!\`;
|
||||
}
|
||||
|
||||
const john: Person = { name: 'John', age: 30 };
|
||||
greet(john);
|
||||
`;
|
||||
|
||||
const jsOutput = tsToJs(tsInput);
|
||||
|
||||
// 检查结果中不应包含 TypeScript 特有的语法
|
||||
expect(jsOutput).not.toContain('interface');
|
||||
expect(jsOutput).not.toContain(': string');
|
||||
expect(jsOutput).not.toContain(': Person');
|
||||
expect(jsOutput).not.toContain(': number');
|
||||
|
||||
// 检查结果应包含 JavaScript 代码
|
||||
expect(jsOutput).toContain('function greet(person)');
|
||||
expect(jsOutput).toContain('return');
|
||||
expect(jsOutput).toContain('Hello');
|
||||
expect(jsOutput).toContain("const john = { name: 'John', age: 30 }");
|
||||
});
|
||||
|
||||
it('应该保留 JSX 语法', () => {
|
||||
const tsxInput = `
|
||||
import React, { FC } from 'react';
|
||||
|
||||
interface ButtonProps {
|
||||
text: string;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
const Button: FC<ButtonProps> = ({ text, onClick }) => {
|
||||
return (
|
||||
<button
|
||||
className="primary-button"
|
||||
onClick={onClick}
|
||||
>
|
||||
{text}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
export default Button;
|
||||
`;
|
||||
|
||||
const jsxOutput = tsToJs(tsxInput);
|
||||
|
||||
// 检查结果中不应包含 TypeScript 特有的语法
|
||||
expect(jsxOutput).not.toContain('interface ButtonProps');
|
||||
expect(jsxOutput).not.toContain(': FC<ButtonProps>');
|
||||
|
||||
// 检查结果应保留 JSX 语法
|
||||
expect(jsxOutput).toContain('<button');
|
||||
expect(jsxOutput).toContain('className="primary-button"');
|
||||
expect(jsxOutput).toContain('</button>');
|
||||
expect(jsxOutput).toContain('onClick={onClick}');
|
||||
});
|
||||
|
||||
it('应该删除类型导入', () => {
|
||||
const tsInput = `
|
||||
import React from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
import { Button } from 'antd';
|
||||
import type { ButtonProps } from 'antd/es/button';
|
||||
|
||||
const MyButton = (props: ButtonProps) => {
|
||||
return <Button {...props} />;
|
||||
};
|
||||
`;
|
||||
|
||||
const jsOutput = tsToJs(tsInput);
|
||||
|
||||
// 检查结果中不应包含类型导入
|
||||
expect(jsOutput).not.toContain('import type');
|
||||
expect(jsOutput).not.toContain('ReactNode');
|
||||
expect(jsOutput).not.toContain('ButtonProps');
|
||||
|
||||
// 保留普通导入
|
||||
expect(jsOutput).toContain("import React from 'react'");
|
||||
expect(jsOutput).toContain("import { Button } from 'antd'");
|
||||
});
|
||||
});
|
@ -1,7 +1,8 @@
|
||||
import semver from 'semver';
|
||||
import flatten from 'lodash/flatten';
|
||||
import flattenDeep from 'lodash/flattenDeep';
|
||||
|
||||
import themeConfig from './themeConfig';
|
||||
import deprecatedVersions from '../../../BUG_VERSIONS.json';
|
||||
import themeConfig from '../themeConfig';
|
||||
|
||||
interface Meta {
|
||||
skip?: boolean;
|
||||
@ -24,6 +25,11 @@ interface Orders {
|
||||
[key: string]: number;
|
||||
}
|
||||
|
||||
interface MatchDeprecatedResult {
|
||||
match?: string;
|
||||
reason: string[];
|
||||
}
|
||||
|
||||
export function getMenuItems(
|
||||
moduleData: ModuleDataItem[],
|
||||
locale: string,
|
||||
@ -201,4 +207,15 @@ export function getMetaDescription(jml?: any[] | null) {
|
||||
return paragraph;
|
||||
}
|
||||
|
||||
export function matchDeprecated(v: string): MatchDeprecatedResult {
|
||||
const match = Object.keys(deprecatedVersions).find((depreciated) =>
|
||||
semver.satisfies(v, depreciated),
|
||||
);
|
||||
const reason = deprecatedVersions[match as keyof typeof deprecatedVersions] || [];
|
||||
return {
|
||||
match,
|
||||
reason: Array.isArray(reason) ? reason : [reason],
|
||||
};
|
||||
}
|
||||
|
||||
export const getThemeConfig = () => themeConfig;
|
@ -1,273 +0,0 @@
|
||||
import { parseText } from './tsToJs';
|
||||
|
||||
// 简单 TypeScript 代码示例
|
||||
const tsCode = `
|
||||
interface Person {
|
||||
name: string;
|
||||
age: number;
|
||||
}
|
||||
|
||||
class Employee implements Person {
|
||||
name: string;
|
||||
age: number;
|
||||
department: string;
|
||||
|
||||
constructor(name: string, age: number, department: string) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
this.department = department;
|
||||
}
|
||||
|
||||
getInfo(): string {
|
||||
return \`\${this.name}, \${this.age}, \${this.department}\`;
|
||||
}
|
||||
}
|
||||
|
||||
const employee: Employee = new Employee('张三', 30, '研发部');
|
||||
console.log(employee.getInfo());
|
||||
`;
|
||||
|
||||
// 包含 JSX 的 TypeScript 代码示例
|
||||
const tsxCode = `
|
||||
import React, { FC, useState } from 'react';
|
||||
import { Button } from 'antd';
|
||||
|
||||
interface CounterProps {
|
||||
initialCount?: number;
|
||||
label: string;
|
||||
}
|
||||
|
||||
const Counter: FC<CounterProps> = ({ initialCount = 0, label }) => {
|
||||
const [count, setCount] = useState<number>(initialCount);
|
||||
|
||||
const increment = (): void => {
|
||||
setCount(count + 1);
|
||||
};
|
||||
|
||||
const decrement = (): void => {
|
||||
setCount(count - 1);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="counter">
|
||||
<h3>{label}: {count}</h3>
|
||||
<Button type="primary" onClick={increment}>+</Button>
|
||||
<Button onClick={decrement}>-</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Counter;
|
||||
`;
|
||||
|
||||
// 复杂 TypeScript 代码示例,包含泛型、类型导入、类型别名等
|
||||
const complexTsCode = `
|
||||
import React from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
import { Table } from 'antd';
|
||||
import type { TableProps, TableColumnType } from 'antd/es/table';
|
||||
|
||||
// 类型别名
|
||||
type Status = 'pending' | 'processing' | 'success' | 'failed';
|
||||
|
||||
// 泛型接口
|
||||
interface DataItem<T = string> {
|
||||
id: number;
|
||||
name: string;
|
||||
status: Status;
|
||||
details: T;
|
||||
createdAt: Date;
|
||||
}
|
||||
|
||||
// 类型映射和条件类型
|
||||
type ReadonlyDataItem<T> = {
|
||||
readonly [K in keyof DataItem<T>]: DataItem<T>[K];
|
||||
};
|
||||
|
||||
// 工具类型
|
||||
type OptionalId<T> = Omit<T, 'id'> & { id?: number };
|
||||
|
||||
// 类型断言函数
|
||||
function assertIsDataItem<T>(item: any): asserts item is DataItem<T> {
|
||||
if (!item || typeof item.id !== 'number') {
|
||||
throw new Error('Invalid DataItem: missing or invalid id');
|
||||
}
|
||||
}
|
||||
|
||||
// 使用泛型组件
|
||||
const DataTable = <T extends string>(props: {
|
||||
data: DataItem<T>[];
|
||||
renderDetails?: (details: T) => ReactNode;
|
||||
}) => {
|
||||
const { data, renderDetails } = props;
|
||||
|
||||
// 定义表格列
|
||||
const columns: TableColumnType<DataItem<T>>[] = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
render: (status: Status) => {
|
||||
const statusColors = {
|
||||
pending: 'blue',
|
||||
processing: 'orange',
|
||||
success: 'green',
|
||||
failed: 'red',
|
||||
};
|
||||
return <span style={{ color: statusColors[status] }}>{status}</span>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '详情',
|
||||
dataIndex: 'details',
|
||||
key: 'details',
|
||||
render: (details: T) => renderDetails ? renderDetails(details) : details,
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createdAt',
|
||||
key: 'createdAt',
|
||||
render: (date: Date) => date.toLocaleString(),
|
||||
},
|
||||
];
|
||||
|
||||
return <Table<DataItem<T>> columns={columns} dataSource={data} rowKey="id" />;
|
||||
};
|
||||
|
||||
// 使用工具类型创建数据
|
||||
const createDataItem = <T extends string>(item: OptionalId<DataItem<T>>): DataItem<T> => {
|
||||
return {
|
||||
id: item.id ?? Math.floor(Math.random() * 1000),
|
||||
name: item.name,
|
||||
status: item.status,
|
||||
details: item.details,
|
||||
createdAt: item.createdAt || new Date(),
|
||||
};
|
||||
};
|
||||
|
||||
// 示例数据
|
||||
const exampleData: DataItem<string>[] = [
|
||||
createDataItem({
|
||||
name: '项目 A',
|
||||
status: 'success',
|
||||
details: '项目顺利完成',
|
||||
createdAt: new Date(2023, 0, 15),
|
||||
}),
|
||||
createDataItem({
|
||||
name: '项目 B',
|
||||
status: 'processing',
|
||||
details: '正在进行中...',
|
||||
createdAt: new Date(2023, 2, 10),
|
||||
}),
|
||||
];
|
||||
|
||||
// 渲染组件
|
||||
const App = () => {
|
||||
return (
|
||||
<div>
|
||||
<h1>数据表格示例</h1>
|
||||
<DataTable
|
||||
data={exampleData}
|
||||
renderDetails={(details) => <em>{details}</em>}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
`;
|
||||
|
||||
// 加入Jest测试用例
|
||||
describe('tsToJs函数测试', () => {
|
||||
// 转换普通 TypeScript 代码
|
||||
it('应该能正确转换普通TypeScript代码', () => {
|
||||
const jsCode = parseText(tsCode);
|
||||
|
||||
// 验证类型注解被移除
|
||||
expect(jsCode).not.toContain('interface Person');
|
||||
expect(jsCode).not.toContain(': string');
|
||||
expect(jsCode).not.toContain(': number');
|
||||
|
||||
// 验证类实现被保留
|
||||
expect(jsCode).toContain('class Employee');
|
||||
expect(jsCode).toContain('constructor(name, age, department)');
|
||||
expect(jsCode).toContain('getInfo()');
|
||||
|
||||
// 验证实例创建
|
||||
expect(jsCode).toContain("new Employee('张三', 30, '研发部')");
|
||||
|
||||
console.log('转换前的 TypeScript 代码:');
|
||||
console.log(tsCode);
|
||||
console.log('\n转换后的 JavaScript 代码:');
|
||||
console.log(jsCode);
|
||||
});
|
||||
|
||||
// 转换包含 JSX 的 TypeScript 代码
|
||||
it('应该能正确转换TSX代码', () => {
|
||||
const jsxCode = parseText(tsxCode);
|
||||
|
||||
// 验证React导入被保留
|
||||
expect(jsxCode).toContain('import React');
|
||||
|
||||
// 验证类型注解和类型导入被移除
|
||||
expect(jsxCode).not.toContain('FC<');
|
||||
expect(jsxCode).not.toContain('interface CounterProps');
|
||||
expect(jsxCode).not.toContain('<number>');
|
||||
expect(jsxCode).not.toContain(': void');
|
||||
|
||||
// 验证JSX结构被保留
|
||||
expect(jsxCode).toContain('<div className="counter">');
|
||||
expect(jsxCode).toContain('<Button type="primary"');
|
||||
|
||||
// 验证默认参数被保留
|
||||
expect(jsxCode).toContain('initialCount = 0');
|
||||
|
||||
console.log('\n\n转换前的 TSX 代码:');
|
||||
console.log(tsxCode);
|
||||
console.log('\n转换后的 JSX 代码:');
|
||||
console.log(jsxCode);
|
||||
});
|
||||
|
||||
// 转换复杂 TypeScript 代码
|
||||
it('应该能正确转换复杂TypeScript代码', () => {
|
||||
const complexJsCode = parseText(complexTsCode);
|
||||
|
||||
// 验证类型导入被移除
|
||||
expect(complexJsCode).not.toContain('import type');
|
||||
|
||||
// 验证泛型被移除
|
||||
expect(complexJsCode).not.toContain('<T>');
|
||||
expect(complexJsCode).not.toContain('<T extends string>');
|
||||
|
||||
// 验证类型别名和接口被移除
|
||||
expect(complexJsCode).not.toContain('type Status');
|
||||
expect(complexJsCode).not.toContain('interface DataItem');
|
||||
|
||||
// 验证函数和组件结构被保留
|
||||
expect(complexJsCode).toContain('function assertIsDataItem');
|
||||
expect(complexJsCode).toContain('const DataTable = ');
|
||||
expect(complexJsCode).toContain('const createDataItem = ');
|
||||
|
||||
// 验证JSX结构被保留
|
||||
expect(complexJsCode).toContain('<Table');
|
||||
expect(complexJsCode).toContain('<span style=');
|
||||
|
||||
// 验证空值合并运算符的处理
|
||||
expect(complexJsCode).toContain('_a = item.id'); // TypeScript会将 ?? 转换为更兼容的语法
|
||||
|
||||
console.log('\n\n转换前的复杂 TypeScript 代码:');
|
||||
console.log(complexTsCode);
|
||||
console.log('\n转换后的 JavaScript 代码:');
|
||||
console.log(complexJsCode);
|
||||
});
|
||||
});
|
@ -2,27 +2,16 @@ import * as ts from 'typescript';
|
||||
import { format } from '@prettier/sync';
|
||||
|
||||
/**
|
||||
* TypeScript 到 JavaScript 代码转换工具
|
||||
* 将 TypeScript 代码(含 TSX)转换为 JavaScript 代码(含 JSX)。
|
||||
*
|
||||
* 这个模块用于将 TypeScript 代码(包括 TSX)转换为 JavaScript 代码(包括 JSX)
|
||||
* 主要用于替代 sylvanas 库的功能,用于文档站点中的代码示例转换
|
||||
* 使用 TypeScript 编译器 API 移除类型注解和类型导入,保留 JSX 语法和注释,并将代码转换为 JavaScript。转换结果会通过 Prettier 进行格式化,提升可读性。适用于文档示例、代码展示等场景。
|
||||
*
|
||||
* 实现原理:使用 TypeScript 编译器 API 将 TS 代码转换为 JS 代码
|
||||
* @param tsCode - 输入的 TypeScript 代码字符串。
|
||||
* @returns 转换并格式化后的 JavaScript 代码字符串。
|
||||
*
|
||||
* 特性:
|
||||
* 1. 删除所有类型注解
|
||||
* 2. 保留 JSX 语法
|
||||
* 3. 删除类型导入
|
||||
* 4. 转换 ES6+ 语法为更兼容的语法(如空值合并运算符)
|
||||
* 5. 保留原始代码风格和注释
|
||||
* 6. 使用 Prettier 格式化输出代码,提高可读性
|
||||
* 7. 处理 React 组件和 hooks 的转换
|
||||
* 8. 支持 TypeScript 特有语法(如装饰器、枚举等)的转换
|
||||
*
|
||||
* @param tsCode TypeScript 代码字符串
|
||||
* @returns 转换后的 JavaScript 代码
|
||||
* @remark 若 Prettier 格式化失败,将返回未格式化的转换结果。
|
||||
*/
|
||||
export default function (tsCode: string): string {
|
||||
export default function tsToJs(tsCode: string): string {
|
||||
// 设置编译器选项,保留 JSX 语法
|
||||
const compilerOptions: ts.CompilerOptions = {
|
||||
target: ts.ScriptTarget.ES2016, // 目标 ECMAScript 版本
|
||||
@ -61,15 +50,3 @@ export default function (tsCode: string): string {
|
||||
return result.outputText;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 TypeScript 代码转换为 JavaScript 代码
|
||||
*
|
||||
* 这是一个公开的 API,供测试和外部调用使用
|
||||
*
|
||||
* @param tsCode TypeScript 代码字符串
|
||||
* @returns 转换后的 JavaScript 代码
|
||||
*/
|
||||
export function parseText(tsCode: string): string {
|
||||
return exports.default(tsCode);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import * as fs from 'fs-extra';
|
||||
import os from 'node:os';
|
||||
|
||||
import rehypeAntd from './.dumi/rehypeAntd';
|
||||
import rehypeChangelog from './.dumi/rehypeChangelog';
|
||||
import remarkAntd from './.dumi/remarkAntd';
|
||||
import remarkAnchor from './.dumi/remarkAnchor';
|
||||
import { version } from './package.json';
|
||||
@ -52,7 +53,7 @@ export default defineConfig({
|
||||
// https://github.com/ant-design/ant-design/issues/46628
|
||||
'@ant-design/icons$': '@ant-design/icons/lib',
|
||||
},
|
||||
extraRehypePlugins: [rehypeAntd],
|
||||
extraRehypePlugins: [rehypeAntd, rehypeChangelog],
|
||||
extraRemarkPlugins: [remarkAntd, remarkAnchor],
|
||||
metas: [
|
||||
{ name: 'theme-color', content: '#1677ff' },
|
||||
@ -189,7 +190,7 @@ export default defineConfig({
|
||||
{
|
||||
async: true,
|
||||
content: fs
|
||||
.readFileSync(path.join(__dirname, '.dumi', 'scripts', 'mirror-modal.js'))
|
||||
.readFileSync(path.join(__dirname, '.dumi', 'scripts', 'mirror-notify.js'))
|
||||
.toString(),
|
||||
},
|
||||
{
|
||||
|
2
.github/workflows/upgrade-deps.yml
vendored
2
.github/workflows/upgrade-deps.yml
vendored
@ -43,7 +43,7 @@ jobs:
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }} # Cannot be default!!!
|
||||
assignees: 'afc163, zombieJ, xrkffgg, MadCcc'
|
||||
assignees: 'afc163, yoyo837, Wxh16144'
|
||||
title: "chore: upgrade deps"
|
||||
commit-message: "chore: upgrade deps"
|
||||
body: |
|
||||
|
@ -15,6 +15,27 @@ tag: vVERSION
|
||||
|
||||
---
|
||||
|
||||
## 5.25.4
|
||||
|
||||
`2025-05-31`
|
||||
|
||||
- 💄 Tweak Select selected item background in dark theme to make it easier to identify. [#53956](https://github.com/ant-design/ant-design/pull/53956) [@afc163](https://github.com/afc163)
|
||||
- ⌨️ Timeline now uses `ol` instead of `ul` to meet HTML semantic requirements. [#53944](https://github.com/ant-design/ant-design/pull/53944) [@fnoopv](https://github.com/fnoopv)
|
||||
- 🐞 Fix Drawer mask does not fade out when changing from true to false. [#53955](https://github.com/ant-design/ant-design/pull/53955) [@afc163](https://github.com/afc163)
|
||||
- 🐞 Fix Input.Search does not support `onPressEnter`. [#53898](https://github.com/ant-design/ant-design/pull/53898) [@codingories](https://github.com/codingories)
|
||||
- 🛠 Remove `!important` style syntax from Checkbox. [#53953](https://github.com/ant-design/ant-design/pull/53953) [@doandevhere](https://github.com/doandevhere)
|
||||
- TypeScript
|
||||
- 🤖 Fix Descriptions.Item `span` property type. [#53913](https://github.com/ant-design/ant-design/pull/53913) [@DDDDD12138](https://github.com/DDDDD12138)
|
||||
|
||||
## 5.25.3
|
||||
|
||||
`2025-05-26`
|
||||
|
||||
- 🐞 Fix Typography.Text `delete` property not updating. [#53861](https://github.com/ant-design/ant-design/pull/53861) [@codingories](https://github.com/codingories)
|
||||
- 🐞 Fix the Statistic.Timer as a subcomponent of Tooltip could not display text prompts properly. [#53888](https://github.com/ant-design/ant-design/pull/53888) [@jin19980928](https://github.com/jin19980928)
|
||||
- 🐞 Fix the `style` setting of the Upload component did not take effect in more types. [#53877](https://github.com/ant-design/ant-design/pull/53877) [@QuentinHsu](https://github.com/QuentinHsu)
|
||||
- 💄 Fix the residual focus style after clicking Tabs. [#53901](https://github.com/ant-design/ant-design/pull/53901)
|
||||
|
||||
## 5.25.2
|
||||
|
||||
`2025-05-19`
|
||||
@ -24,7 +45,6 @@ tag: vVERSION
|
||||
- 🐞 Fix Statistic.Timer ssr hydrate issue. [#53817](https://github.com/ant-design/ant-design/pull/53817) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 Fix Table header blink issue when sticky is enable. [#53803](https://github.com/ant-design/ant-design/pull/53803) [@afc163](https://github.com/afc163)
|
||||
- 💄 Fix Input.Search `variant="filled"` broken UI. [#53787](https://github.com/ant-design/ant-design/pull/53787) [@afc163](https://github.com/afc163)
|
||||
|
||||
- TypeScript
|
||||
- 🤖 Fix Upload.Dragger does not accept generic parameter problem. [#53842](https://github.com/ant-design/ant-design/pull/53842) [@fnoopv](https://github.com/fnoopv)
|
||||
- 🤖 Remove Modal invalid properties type definition. [#53808](https://github.com/ant-design/ant-design/pull/53808) [@wanpan11](https://github.com/wanpan11)
|
||||
@ -67,7 +87,7 @@ tag: vVERSION
|
||||
- 🛠 MISC:Refactor compatible code, use standard web API first, and downgrade to deprecated API when not compatibale [#53107](https://github.com/ant-design/ant-design/pull/53107) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- ⌨️ Opt Tour's `aria-*` props. [#53345](https://github.com/ant-design/ant-design/pull/53345) [@kiner-tang](https://github.com/kiner-tang)
|
||||
- ⌨️ MISC: Optimized closable component's aria props. [#53410](https://github.com/ant-design/ant-design/pull/53410) [@kiner-tang](https://github.com/kiner-tang)
|
||||
- 🗑 MISC: Deprecate `destory*` of some components for `destroyOnHidden` prop。 [#53739](https://github.com/ant-design/ant-design/pull/53739) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- 🗑 MISC: Deprecate `destroy*` of some components for `destroyOnHidden` prop. [#53739](https://github.com/ant-design/ant-design/pull/53739) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- 🗑 Deprecate `dropdownRender` of Dropdown for `popupRender` [#53263](https://github.com/ant-design/ant-design/pull/53263) [@aojunhao123](https://github.com/aojunhao123)
|
||||
- 🗑 Deprecated `dropdown*` props in Cascader [#53133](https://github.com/ant-design/ant-design/pull/53133) [@aojunhao123](https://github.com/aojunhao123)
|
||||
- 🇨🇿 Add cs_CZ locale for QRCode and ColorPicker. [#53741](https://github.com/ant-design/ant-design/pull/53741) [@malda26](https://github.com/malda26)
|
||||
@ -544,7 +564,7 @@ Last version of the Dragon Year, Happy Chinese New Year! 🐲
|
||||
- 🐞 Fix Transfer width issue when customized as TableTransfer. [#50974](https://github.com/ant-design/ant-design/pull/50974) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🇹🇷 Add Turkish text for `filterCheckall` in Table component. [#51000](https://github.com/ant-design/ant-design/pull/51000) [@ytahirkose](https://github.com/ytahirkose)
|
||||
|
||||
## 5.21.0 🔥
|
||||
## 5.21.0
|
||||
|
||||
`2024-09-22`
|
||||
|
||||
@ -884,9 +904,9 @@ Last version of the Dragon Year, Happy Chinese New Year! 🐲
|
||||
- 🆕 Rate add `keyboard` property to ignore keyboard events. [#49132](https://github.com/ant-design/ant-design/pull/49132) [@Wxh16144](https://github.com/Wxh16144)
|
||||
- 🆕 Spin support `percent` to render as progress. [#48657](https://github.com/ant-design/ant-design/pull/48657)
|
||||
- 🐞 Watermark add `overflow: hidden` style to prevent set `height: 0` to hide the watermark case. [#49130](https://github.com/ant-design/ant-design/pull/49130)
|
||||
- 🐞 Anchor fix scroll animation lost bug when set `replace` property. [#49136](https://github.com/ant-design/ant-design/pull/49136) [@mySkey](https://github.com/mySkey)
|
||||
- 🐞 Tour fix `current` argument of `onClose` is wrong. [#49124](https://github.com/ant-design/ant-design/pull/49124)
|
||||
- 💄 List.Item add `styles` and `className` properties. [#49154](https://github.com/ant-design/ant-design/pull/49154) [@wanpan11](https://github.com/wanpan11)
|
||||
- 🐞 Fix Anchor scroll animation lost bug when set `replace` property. [#49136](https://github.com/ant-design/ant-design/pull/49136) [@mySkey](https://github.com/mySkey)
|
||||
- 🐞 Fix Tour `current` argument of `onClose` is wrong. [#49124](https://github.com/ant-design/ant-design/pull/49124)
|
||||
- 🆕 List.Item add `styles` and `className` properties. [#49154](https://github.com/ant-design/ant-design/pull/49154) [@wanpan11](https://github.com/wanpan11)
|
||||
- 🇯🇵 DatePicker add missing ja_JP translations. [#49155](https://github.com/ant-design/ant-design/pull/49155) [@huyikai](https://github.com/huyikai)
|
||||
- 🛠 Simplify several logics and type definitions. [#49146](https://github.com/ant-design/ant-design/pull/49146) [#49156](https://github.com/ant-design/ant-design/pull/49156) [#49169](https://github.com/ant-design/ant-design/pull/49169) [#49162](https://github.com/ant-design/ant-design/pull/49162) [@coding-ice](https://github.com/coding-ice)
|
||||
|
||||
|
@ -15,6 +15,27 @@ tag: vVERSION
|
||||
|
||||
---
|
||||
|
||||
## 5.25.4
|
||||
|
||||
`2025-05-31`
|
||||
|
||||
- 💄 调整 Select 选中项在暗色模式下的背景色,使其更容易识别。[#53956](https://github.com/ant-design/ant-design/pull/53956) [@afc163](https://github.com/afc163)
|
||||
- ⌨️ Timeline 使用 `ol` 代替 `ul` 以符合 html 语义要求。[#53944](https://github.com/ant-design/ant-design/pull/53944) [@fnoopv](https://github.com/fnoopv)
|
||||
- 🐞 修复 Drawer `mask` 从 true 改为 false 时没有渐出的问题。[#53955](https://github.com/ant-design/ant-design/pull/53955) [@afc163](https://github.com/afc163)
|
||||
- 🐞 修复 Input.Search 不支持 `onPressEnter` 的问题。[#53898](https://github.com/ant-design/ant-design/pull/53898) [@codingories](https://github.com/codingories)
|
||||
- 🛠 移除 Checkbox 的 `!important` 样式语法。[#53953](https://github.com/ant-design/ant-design/pull/53953) [@doandevhere](https://github.com/doandevhere)
|
||||
- TypeScript
|
||||
- 🤖 修正 Descriptions.Item `span` 属性类型。[#53913](https://github.com/ant-design/ant-design/pull/53913) [@DDDDD12138](https://github.com/DDDDD12138)
|
||||
|
||||
## 5.25.3
|
||||
|
||||
`2025-05-26`
|
||||
|
||||
- 🐞 修复 Typography.Text `delete` 属性无法更新的问题。[#53861](https://github.com/ant-design/ant-design/pull/53861) [@codingories](https://github.com/codingories)
|
||||
- 🐞 修复 Statistic.Timer 组件作为 Tooltip 的子组件无法正常展示文字提示的问题。[#53888](https://github.com/ant-design/ant-design/pull/53888) [@jin19980928](https://github.com/jin19980928)
|
||||
- 🐞 修复 Upload 组件在更多类型时 `style` 设置未生效的问题。[#53877](https://github.com/ant-design/ant-design/pull/53877) [@QuentinHsu](https://github.com/QuentinHsu)
|
||||
- 💄 修复 Tabs 点击后有残留 focus 样式的问题。[#53901](https://github.com/ant-design/ant-design/pull/53901)
|
||||
|
||||
## 5.25.2
|
||||
|
||||
`2025-05-19`
|
||||
@ -24,7 +45,6 @@ tag: vVERSION
|
||||
- 🐞 修复 Statistic.Timer ssr 注水渲染不一致的问题。[#53817](https://github.com/ant-design/ant-design/pull/53817) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 修复 Table 开启 `sticky` 时的一个列头渲染闪烁问题。[#53803](https://github.com/ant-design/ant-design/pull/53803) [@afc163](https://github.com/afc163)
|
||||
- 💄 修复 Input.Search `variant="filled"` 的样式。[#53787](https://github.com/ant-design/ant-design/pull/53787) [@afc163](https://github.com/afc163)
|
||||
|
||||
- TypeScript
|
||||
- 🤖 修复 Upload.Dragger 不支持泛型参数的问题。[#53842](https://github.com/ant-design/ant-design/pull/53842) [@fnoopv](https://github.com/fnoopv)
|
||||
- 🤖 移除 Modal 无效的属性类型定义。[#53808](https://github.com/ant-design/ant-design/pull/53808) [@wanpan11](https://github.com/wanpan11)
|
||||
@ -67,12 +87,11 @@ tag: vVERSION
|
||||
- 🛠 杂项:重构兼容逻辑,优先使用标准 Web API,不兼容的时候降级为废弃 API。[#53107](https://github.com/ant-design/ant-design/pull/53107) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- ⌨️ 优化 Tour 的 `aria-*` 属性。[#53345](https://github.com/ant-design/ant-design/pull/53345) [@kiner-tang](https://github.com/kiner-tang)
|
||||
- ⌨️ 杂项:优化可关闭组件的无障碍属性。[#53410](https://github.com/ant-design/ant-design/pull/53410) [@kiner-tang](https://github.com/kiner-tang)
|
||||
- 🗑 杂项:废弃多个可开关组件的 `destory*` 属性,统一为 `destroyOnHidden`。 [#53739](https://github.com/ant-design/ant-design/pull/53739) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- 🗑 杂项:废弃多个可开关组件的 `destroy*` 属性,统一为 `destroyOnHidden`。 [#53739](https://github.com/ant-design/ant-design/pull/53739) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- 🗑 废弃 Dropdown 中 `dropdownRender` 属性,用 `popupRender` 替代。[#53263](https://github.com/ant-design/ant-design/pull/53263) [@aojunhao123](https://github.com/aojunhao123)
|
||||
- 🗑 废弃 Cascader 组件的 `dropdown*` 等属性。[#53133](https://github.com/ant-design/ant-design/pull/53133) [@aojunhao123](https://github.com/aojunhao123)
|
||||
- 🇨🇿 添加 QRCode 和 ColorPicker 的捷克语(cs_CZ)支持。[#53741](https://github.com/ant-design/ant-design/pull/53741) [@malda26](https://github.com/malda26)
|
||||
|
||||
|
||||
## 5.24.9
|
||||
|
||||
`2025-04-29`
|
||||
@ -547,7 +566,7 @@ tag: vVERSION
|
||||
- 💄 修复 Transfer 在自定义为 TableTransfer 时,宽度不正确的问题。[#50974](https://github.com/ant-design/ant-design/pull/50974) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🇹🇷 补充 Table 组件 `filterCheckall` 的土耳其语文案。[#51000](https://github.com/ant-design/ant-design/pull/51000) [@ytahirkose](https://github.com/ytahirkose)
|
||||
|
||||
## 5.21.0 🔥
|
||||
## 5.21.0
|
||||
|
||||
`2024-09-22`
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Alert, Button, Space } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import SemanticPreview from '../../../.dumi/theme/common/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { Anchor } from 'antd';
|
||||
import type { AnchorProps } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import SemanticPreview from '../../../.dumi/theme/common/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { AutoComplete } from 'antd';
|
||||
|
||||
import SelectSemanticTemplate from '../../../.dumi/components/SelectSemanticTemplate';
|
||||
import SelectSemanticTemplate from '../../../.dumi/theme/common/SelectSemanticTemplate';
|
||||
|
||||
const mockVal = (str: string, repeat = 1) => ({
|
||||
value: str.repeat(repeat),
|
||||
|
@ -805,7 +805,7 @@ Array [
|
||||
</span>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<div
|
||||
@ -935,7 +935,7 @@ Array [
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<div
|
||||
@ -1065,7 +1065,7 @@ Array [
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<div
|
||||
@ -1195,7 +1195,7 @@ Array [
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<div
|
||||
|
@ -683,7 +683,7 @@ Array [
|
||||
</span>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<div
|
||||
@ -721,7 +721,7 @@ Array [
|
||||
</span>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<div
|
||||
@ -759,7 +759,7 @@ Array [
|
||||
</span>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<div
|
||||
@ -797,7 +797,7 @@ Array [
|
||||
</span>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<div
|
||||
|
@ -309,11 +309,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Presets
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-space ant-space-vertical ant-space-gap-row-small ant-space-gap-col-small css-var-test-id"
|
||||
@ -531,11 +537,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Custom
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-space ant-space-vertical ant-space-gap-row-small ant-space-gap-col-small css-var-test-id"
|
||||
|
@ -305,11 +305,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Presets
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-space ant-space-vertical ant-space-gap-row-small ant-space-gap-col-small css-var-test-id"
|
||||
@ -527,11 +533,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Custom
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-space ant-space-vertical ant-space-gap-row-small ant-space-gap-col-small css-var-test-id"
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Avatar, Badge } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import SemanticPreview from '../../../.dumi/theme/common/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { Badge, Card } from 'antd';
|
||||
import type { RibbonProps } from 'antd/es/badge/Ribbon';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import SemanticPreview from '../../../.dumi/theme/common/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
|
@ -19,13 +19,13 @@ const colors = [
|
||||
|
||||
const App: React.FC = () => (
|
||||
<>
|
||||
<Divider orientation="left">Presets</Divider>
|
||||
<Divider titlePlacement="start">Presets</Divider>
|
||||
<Space vertical>
|
||||
{colors.map((color) => (
|
||||
<Badge key={color} color={color} text={color} />
|
||||
))}
|
||||
</Space>
|
||||
<Divider orientation="left">Custom</Divider>
|
||||
<Divider titlePlacement="start">Custom</Divider>
|
||||
<Space vertical>
|
||||
<Badge color="#f50" text="#f50" />
|
||||
<Badge color="rgb(45, 183, 245)" text="rgb(45, 183, 245)" />
|
||||
|
@ -3,7 +3,7 @@ import { HomeOutlined, UserOutlined } from '@ant-design/icons';
|
||||
import { Breadcrumb } from 'antd';
|
||||
import type { BreadcrumbProps } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import SemanticPreview from '../../../.dumi/theme/common/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
|
@ -998,11 +998,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start ant-divider-plain"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Preview
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-flex css-var-test-id ant-flex-align-stretch ant-flex-gap-small ant-flex-vertical"
|
||||
@ -1404,11 +1410,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-center ant-divider-plain"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
https://github.com/ant-design/ant-design/issues/51811
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
@ -1455,11 +1467,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-center ant-divider-plain"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
https://github.com/ant-design/ant-design/issues/52124
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
@ -1508,11 +1526,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-center ant-divider-plain"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
https://github.com/ant-design/ant-design/issues/51380
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
@ -1685,11 +1709,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-center ant-divider-plain"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
https://github.com/ant-design/ant-design/issues/51380
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-flex css-var-test-id ant-flex-gap-small"
|
||||
@ -2467,11 +2497,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start ant-divider-plain"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Preview
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-flex css-var-test-id ant-flex-align-stretch ant-flex-gap-small ant-flex-vertical"
|
||||
@ -3800,11 +3836,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start ant-divider-plain"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Preview
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-flex css-var-test-id ant-flex-align-flex-start ant-flex-gap-small ant-flex-vertical"
|
||||
|
@ -980,11 +980,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start ant-divider-plain"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Preview
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-flex css-var-test-id ant-flex-align-stretch ant-flex-gap-small ant-flex-vertical"
|
||||
@ -1306,11 +1312,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-center ant-divider-plain"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
https://github.com/ant-design/ant-design/issues/51811
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
@ -1357,11 +1369,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-center ant-divider-plain"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
https://github.com/ant-design/ant-design/issues/52124
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
@ -1410,11 +1428,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-center ant-divider-plain"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
https://github.com/ant-design/ant-design/issues/51380
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
@ -1587,11 +1611,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-center ant-divider-plain"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
https://github.com/ant-design/ant-design/issues/51380
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-flex css-var-test-id ant-flex-gap-small"
|
||||
@ -2281,11 +2311,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start ant-divider-plain"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Preview
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-flex css-var-test-id ant-flex-align-stretch ant-flex-gap-small ant-flex-vertical"
|
||||
@ -3291,11 +3327,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start ant-divider-plain"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Preview
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-flex css-var-test-id ant-flex-align-flex-start ant-flex-gap-small ant-flex-vertical"
|
||||
|
@ -513,6 +513,7 @@ describe('Button', () => {
|
||||
fireEvent.click(getByRole('link'));
|
||||
expect(handleClick).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should support classnames and styles', () => {
|
||||
const cusomStyles = {
|
||||
root: { color: 'red' },
|
||||
@ -524,20 +525,27 @@ describe('Button', () => {
|
||||
icon: 'custom-icon',
|
||||
content: 'custom-content',
|
||||
};
|
||||
const { container } = render(
|
||||
const { container, rerender, getByText } = render(
|
||||
<Button classNames={customClassNames} styles={cusomStyles} icon={<SearchOutlined />}>
|
||||
antd
|
||||
</Button>,
|
||||
);
|
||||
const root = container.querySelector('.ant-btn') as HTMLElement;
|
||||
const icon = container.querySelector('.ant-btn-icon') as HTMLElement;
|
||||
const root = container.querySelector('.ant-btn');
|
||||
const icon = container.querySelector('.ant-btn-icon');
|
||||
const content = getByText('antd');
|
||||
expect(root).toHaveClass(customClassNames.root);
|
||||
expect(icon).toHaveClass(customClassNames.icon);
|
||||
expect(root).toHaveStyle(cusomStyles.root);
|
||||
expect(icon).toHaveStyle(cusomStyles.icon);
|
||||
expect(container.querySelector(`.${customClassNames.content}`)).toHaveStyle(
|
||||
cusomStyles.content,
|
||||
expect(content).toHaveStyle(cusomStyles.content);
|
||||
rerender(
|
||||
<Button classNames={customClassNames} styles={cusomStyles} loading>
|
||||
antd
|
||||
</Button>,
|
||||
);
|
||||
const loadingIcon = container.querySelector('.ant-btn-icon');
|
||||
expect(loadingIcon).toHaveClass(customClassNames.icon);
|
||||
expect(loadingIcon).toHaveStyle(cusomStyles.icon);
|
||||
});
|
||||
|
||||
it('should support customizing the background color of default type button in disabled state', () => {
|
||||
|
@ -27,7 +27,7 @@ import Compact from './style/compact';
|
||||
|
||||
export type LegacyButtonType = ButtonType | 'danger';
|
||||
|
||||
type SemanticName = 'root' | 'icon' | 'content';
|
||||
export type ButtonSemanticName = 'root' | 'icon' | 'content';
|
||||
export interface BaseButtonProps {
|
||||
type?: ButtonType;
|
||||
color?: ButtonColorType;
|
||||
@ -46,8 +46,8 @@ export interface BaseButtonProps {
|
||||
block?: boolean;
|
||||
children?: React.ReactNode;
|
||||
[key: `data-${string}`]: string;
|
||||
classNames?: Partial<Record<SemanticName, string>>;
|
||||
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
|
||||
classNames?: Partial<Record<ButtonSemanticName, string>>;
|
||||
styles?: Partial<Record<ButtonSemanticName, React.CSSProperties>>;
|
||||
}
|
||||
|
||||
type MergedHTMLAttributes = Omit<
|
||||
@ -351,6 +351,8 @@ const InternalCompoundedButton = React.forwardRef<
|
||||
</IconWrapper>
|
||||
) : (
|
||||
<DefaultLoadingIcon
|
||||
className={iconClasses}
|
||||
style={iconStyle}
|
||||
existIcon={!!icon}
|
||||
prefixCls={prefixCls}
|
||||
loading={innerLoading}
|
||||
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { AntDesignOutlined } from '@ant-design/icons';
|
||||
import { Button } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import SemanticPreview from '../../../.dumi/theme/common/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
|
@ -22,7 +22,7 @@ const App: React.FC = () => {
|
||||
<Radio.Button value="default">Default</Radio.Button>
|
||||
<Radio.Button value="small">Small</Radio.Button>
|
||||
</Radio.Group>
|
||||
<Divider orientation="left" plain>
|
||||
<Divider titlePlacement="start" plain>
|
||||
Preview
|
||||
</Divider>
|
||||
<ConfigProvider componentSize={size}>
|
||||
|
@ -13,7 +13,7 @@ const App: React.FC = () => {
|
||||
<Radio.Button value="end">end</Radio.Button>
|
||||
</Radio.Group>
|
||||
</Space>
|
||||
<Divider orientation="left" plain>
|
||||
<Divider titlePlacement="start" plain>
|
||||
Preview
|
||||
</Divider>
|
||||
<Flex gap="small" vertical>
|
||||
|
@ -14,7 +14,7 @@ const App: React.FC = () => {
|
||||
<Radio.Button value="default">Default</Radio.Button>
|
||||
<Radio.Button value="small">Small</Radio.Button>
|
||||
</Radio.Group>
|
||||
<Divider orientation="left" plain>
|
||||
<Divider titlePlacement="start" plain>
|
||||
Preview
|
||||
</Divider>
|
||||
<Flex gap="small" align="flex-start" vertical>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Calendar } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import SemanticPreview from '../../../.dumi/theme/common/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { EditOutlined, EllipsisOutlined, SettingOutlined } from '@ant-design/icons';
|
||||
import { Avatar, Card } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import SemanticPreview from '../../../.dumi/theme/common/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const { Meta } = Card;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Avatar, Card } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import SemanticPreview from '../../../.dumi/theme/common/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const { Meta } = Card;
|
||||
|
@ -595,7 +595,7 @@ exports[`renders components/cascader/demo/custom-dropdown.tsx extend context cor
|
||||
</ul>
|
||||
</div>
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
style="margin: 0px;"
|
||||
/>
|
||||
|
@ -15,8 +15,10 @@ exports[`Cascader can be selected 1`] = `
|
||||
>
|
||||
<li
|
||||
aria-checked="false"
|
||||
aria-label="Zhejiang"
|
||||
class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active"
|
||||
data-path-key="zhejiang"
|
||||
data-title="Zhejiang"
|
||||
role="menuitemcheckbox"
|
||||
title="Zhejiang"
|
||||
>
|
||||
@ -92,8 +94,10 @@ exports[`Cascader can be selected 1`] = `
|
||||
>
|
||||
<li
|
||||
aria-checked="false"
|
||||
aria-label="Hangzhou"
|
||||
class="ant-cascader-menu-item ant-cascader-menu-item-expand"
|
||||
data-path-key="zhejiang__RC_CASCADER_SPLIT__hangzhou"
|
||||
data-title="Hangzhou"
|
||||
role="menuitemcheckbox"
|
||||
title="Hangzhou"
|
||||
>
|
||||
@ -147,8 +151,10 @@ exports[`Cascader can be selected 2`] = `
|
||||
>
|
||||
<li
|
||||
aria-checked="false"
|
||||
aria-label="Zhejiang"
|
||||
class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active"
|
||||
data-path-key="zhejiang"
|
||||
data-title="Zhejiang"
|
||||
role="menuitemcheckbox"
|
||||
title="Zhejiang"
|
||||
>
|
||||
@ -224,8 +230,10 @@ exports[`Cascader can be selected 2`] = `
|
||||
>
|
||||
<li
|
||||
aria-checked="false"
|
||||
aria-label="Hangzhou"
|
||||
class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active"
|
||||
data-path-key="zhejiang__RC_CASCADER_SPLIT__hangzhou"
|
||||
data-title="Hangzhou"
|
||||
role="menuitemcheckbox"
|
||||
title="Hangzhou"
|
||||
>
|
||||
@ -297,8 +305,10 @@ exports[`Cascader can be selected 3`] = `
|
||||
>
|
||||
<li
|
||||
aria-checked="false"
|
||||
aria-label="Zhejiang"
|
||||
class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active"
|
||||
data-path-key="zhejiang"
|
||||
data-title="Zhejiang"
|
||||
role="menuitemcheckbox"
|
||||
title="Zhejiang"
|
||||
>
|
||||
@ -374,8 +384,10 @@ exports[`Cascader can be selected 3`] = `
|
||||
>
|
||||
<li
|
||||
aria-checked="false"
|
||||
aria-label="Hangzhou"
|
||||
class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active"
|
||||
data-path-key="zhejiang__RC_CASCADER_SPLIT__hangzhou"
|
||||
data-title="Hangzhou"
|
||||
role="menuitemcheckbox"
|
||||
title="Hangzhou"
|
||||
>
|
||||
@ -1241,8 +1253,10 @@ exports[`Cascader popup correctly with defaultValue 1`] = `
|
||||
>
|
||||
<li
|
||||
aria-checked="false"
|
||||
aria-label="Zhejiang"
|
||||
class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active"
|
||||
data-path-key="zhejiang"
|
||||
data-title="Zhejiang"
|
||||
role="menuitemcheckbox"
|
||||
title="Zhejiang"
|
||||
>
|
||||
@ -1318,8 +1332,10 @@ exports[`Cascader popup correctly with defaultValue 1`] = `
|
||||
>
|
||||
<li
|
||||
aria-checked="true"
|
||||
aria-label="Hangzhou"
|
||||
class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active"
|
||||
data-path-key="zhejiang__RC_CASCADER_SPLIT__hangzhou"
|
||||
data-title="Hangzhou"
|
||||
role="menuitemcheckbox"
|
||||
title="Hangzhou"
|
||||
>
|
||||
@ -1428,8 +1444,10 @@ exports[`Cascader popup correctly with defaultValue RTL 1`] = `
|
||||
>
|
||||
<li
|
||||
aria-checked="false"
|
||||
aria-label="Zhejiang"
|
||||
class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active"
|
||||
data-path-key="zhejiang"
|
||||
data-title="Zhejiang"
|
||||
role="menuitemcheckbox"
|
||||
title="Zhejiang"
|
||||
>
|
||||
@ -1505,8 +1523,10 @@ exports[`Cascader popup correctly with defaultValue RTL 1`] = `
|
||||
>
|
||||
<li
|
||||
aria-checked="true"
|
||||
aria-label="Hangzhou"
|
||||
class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active"
|
||||
data-path-key="zhejiang__RC_CASCADER_SPLIT__hangzhou"
|
||||
data-title="Hangzhou"
|
||||
role="menuitemcheckbox"
|
||||
title="Hangzhou"
|
||||
>
|
||||
|
@ -40,10 +40,14 @@ const options = [
|
||||
{
|
||||
value: 'zhejiang',
|
||||
label: 'Zhejiang',
|
||||
'aria-label': 'Zhejiang',
|
||||
'data-title': 'Zhejiang',
|
||||
children: [
|
||||
{
|
||||
value: 'hangzhou',
|
||||
label: 'Hangzhou',
|
||||
'aria-label': 'Hangzhou',
|
||||
'data-title': 'Hangzhou',
|
||||
children: [
|
||||
{
|
||||
value: 'xihu',
|
||||
@ -788,4 +792,14 @@ describe('Cascader', () => {
|
||||
|
||||
errSpy.mockRestore();
|
||||
});
|
||||
it('Support aria-* and data-* in options', () => {
|
||||
const { container } = render(
|
||||
<Cascader options={options} open defaultValue={['zhejiang', 'hangzhou']} />,
|
||||
);
|
||||
const menuItems = container.querySelectorAll('.ant-cascader-menu-item');
|
||||
expect(menuItems[0].getAttribute('aria-label')).toBe('Zhejiang');
|
||||
expect(menuItems[0].getAttribute('data-title')).toBe('Zhejiang');
|
||||
expect(menuItems[2].getAttribute('aria-label')).toBe('Hangzhou');
|
||||
expect(menuItems[2].getAttribute('data-title')).toBe('Hangzhou');
|
||||
});
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Cascader } from 'antd';
|
||||
|
||||
import TemplateSemanticPreview from '../../../.dumi/components/SelectSemanticTemplate';
|
||||
import TemplateSemanticPreview from '../../../.dumi/theme/common/SelectSemanticTemplate';
|
||||
|
||||
interface Option {
|
||||
value: string;
|
||||
|
@ -48,7 +48,7 @@ Array [
|
||||
</span>
|
||||
</label>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<div
|
||||
|
@ -46,7 +46,7 @@ Array [
|
||||
</span>
|
||||
</label>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<div
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Checkbox } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import SemanticPreview from '../../../.dumi/theme/common/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
|
@ -199,28 +199,30 @@ export const genCheckboxStyle: GenerateStyle<CheckboxToken> = (token) => {
|
||||
{
|
||||
[checkboxCls]: {
|
||||
'&-indeterminate': {
|
||||
// Wrapper > Checkbox > inner
|
||||
[`${checkboxCls}-inner`]: {
|
||||
backgroundColor: `${token.colorBgContainer} !important`,
|
||||
borderColor: `${token.colorBorder} !important`,
|
||||
'&': {
|
||||
// Wrapper > Checkbox > inner
|
||||
[`${checkboxCls}-inner`]: {
|
||||
backgroundColor: `${token.colorBgContainer}`,
|
||||
borderColor: `${token.colorBorder}`,
|
||||
|
||||
'&:after': {
|
||||
top: '50%',
|
||||
insetInlineStart: '50%',
|
||||
width: token.calc(token.fontSizeLG).div(2).equal(),
|
||||
height: token.calc(token.fontSizeLG).div(2).equal(),
|
||||
backgroundColor: token.colorPrimary,
|
||||
border: 0,
|
||||
transform: 'translate(-50%, -50%) scale(1)',
|
||||
opacity: 1,
|
||||
content: '""',
|
||||
'&:after': {
|
||||
top: '50%',
|
||||
insetInlineStart: '50%',
|
||||
width: token.calc(token.fontSizeLG).div(2).equal(),
|
||||
height: token.calc(token.fontSizeLG).div(2).equal(),
|
||||
backgroundColor: token.colorPrimary,
|
||||
border: 0,
|
||||
transform: 'translate(-50%, -50%) scale(1)',
|
||||
opacity: 1,
|
||||
content: '""',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/50074
|
||||
[`&:hover ${checkboxCls}-inner`]: {
|
||||
backgroundColor: `${token.colorBgContainer} !important`,
|
||||
borderColor: `${token.colorPrimary} !important`,
|
||||
// https://github.com/ant-design/ant-design/issues/50074
|
||||
[`&:hover ${checkboxCls}-inner`]: {
|
||||
backgroundColor: `${token.colorBgContainer}`,
|
||||
borderColor: `${token.colorPrimary}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1601,11 +1601,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Default Size
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-collapse ant-collapse-icon-position-start css-var-test-id"
|
||||
@ -1655,11 +1661,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Small Size
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-collapse ant-collapse-icon-position-start ant-collapse-small css-var-test-id"
|
||||
@ -1709,11 +1721,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Large Size
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-collapse ant-collapse-icon-position-start ant-collapse-large css-var-test-id"
|
||||
|
@ -1500,11 +1500,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Default Size
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-collapse ant-collapse-icon-position-start css-var-test-id"
|
||||
@ -1554,11 +1560,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Small Size
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-collapse ant-collapse-icon-position-start ant-collapse-small css-var-test-id"
|
||||
@ -1608,11 +1620,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Large Size
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-collapse ant-collapse-icon-position-start ant-collapse-large css-var-test-id"
|
||||
|
@ -3,7 +3,7 @@ import type { CollapseProps } from 'antd';
|
||||
import { Collapse } from 'antd';
|
||||
import { useToken } from '../../theme/internal';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import SemanticPreview from '../../../.dumi/theme/common/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
|
@ -9,16 +9,16 @@ const text = `
|
||||
|
||||
const App: React.FC = () => (
|
||||
<>
|
||||
<Divider orientation="left">Default Size</Divider>
|
||||
<Divider titlePlacement="start">Default Size</Divider>
|
||||
<Collapse
|
||||
items={[{ key: '1', label: 'This is default size panel header', children: <p>{text}</p> }]}
|
||||
/>
|
||||
<Divider orientation="left">Small Size</Divider>
|
||||
<Divider titlePlacement="start">Small Size</Divider>
|
||||
<Collapse
|
||||
size="small"
|
||||
items={[{ key: '1', label: 'This is small size panel header', children: <p>{text}</p> }]}
|
||||
/>
|
||||
<Divider orientation="left">Large Size</Divider>
|
||||
<Divider titlePlacement="start">Large Size</Divider>
|
||||
<Collapse
|
||||
size="large"
|
||||
items={[{ key: '1', label: 'This is large size panel header', children: <p>{text}</p> }]}
|
||||
|
@ -5910,7 +5910,7 @@ exports[`renders components/color-picker/demo/panel-render.tsx extend context co
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-vertical"
|
||||
class="ant-divider css-var-test-id ant-divider-vertical ant-divider-rail"
|
||||
role="separator"
|
||||
style="height: auto;"
|
||||
/>
|
||||
@ -6658,7 +6658,7 @@ Array [
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>
|
||||
<div
|
||||
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import type { ColorPickerProps } from 'antd';
|
||||
import { ColorPicker } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import SemanticPreview from '../../../.dumi/theme/common/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
|
@ -27,7 +27,7 @@ const HorizontalLayoutDemo = () => {
|
||||
<Col span={12}>
|
||||
<Presets />
|
||||
</Col>
|
||||
<Divider type="vertical" style={{ height: 'auto' }} />
|
||||
<Divider vertical style={{ height: 'auto' }} />
|
||||
<Col flex="auto">
|
||||
<Picker />
|
||||
</Col>
|
||||
|
@ -14188,49 +14188,49 @@ exports[`ConfigProvider components DatePicker WeekPicker prefixCls 1`] = `
|
||||
|
||||
exports[`ConfigProvider components Divider configProvider 1`] = `
|
||||
<div
|
||||
class="config-divider css-var-root config-divider-horizontal"
|
||||
class="config-divider css-var-root config-divider-horizontal config-divider-rail"
|
||||
role="separator"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`ConfigProvider components Divider configProvider componentDisabled 1`] = `
|
||||
<div
|
||||
class="config-divider css-var-root config-divider-horizontal"
|
||||
class="config-divider css-var-root config-divider-horizontal config-divider-rail"
|
||||
role="separator"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`ConfigProvider components Divider configProvider componentSize large 1`] = `
|
||||
<div
|
||||
class="config-divider css-var-root config-divider-horizontal"
|
||||
class="config-divider css-var-root config-divider-horizontal config-divider-rail"
|
||||
role="separator"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`ConfigProvider components Divider configProvider componentSize middle 1`] = `
|
||||
<div
|
||||
class="config-divider css-var-root config-divider-horizontal config-divider-md"
|
||||
class="config-divider css-var-root config-divider-horizontal config-divider-md config-divider-rail"
|
||||
role="separator"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`ConfigProvider components Divider configProvider componentSize small 1`] = `
|
||||
<div
|
||||
class="config-divider css-var-root config-divider-horizontal config-divider-sm"
|
||||
class="config-divider css-var-root config-divider-horizontal config-divider-sm config-divider-rail"
|
||||
role="separator"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`ConfigProvider components Divider normal 1`] = `
|
||||
<div
|
||||
class="ant-divider css-var-root ant-divider-horizontal"
|
||||
class="ant-divider css-var-root ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`ConfigProvider components Divider prefixCls 1`] = `
|
||||
<div
|
||||
class="prefix-Divider css-var-root prefix-Divider-horizontal"
|
||||
class="prefix-Divider css-var-root prefix-Divider-horizontal prefix-Divider-rail"
|
||||
role="separator"
|
||||
/>
|
||||
`;
|
||||
@ -39072,7 +39072,7 @@ Array [
|
||||
`;
|
||||
|
||||
exports[`ConfigProvider components Timeline configProvider 1`] = `
|
||||
<ul
|
||||
<ol
|
||||
class="config-timeline css-var-root config-timeline-css-var"
|
||||
>
|
||||
<li
|
||||
@ -39090,11 +39090,11 @@ exports[`ConfigProvider components Timeline configProvider 1`] = `
|
||||
Bamboo
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</ol>
|
||||
`;
|
||||
|
||||
exports[`ConfigProvider components Timeline configProvider componentDisabled 1`] = `
|
||||
<ul
|
||||
<ol
|
||||
class="config-timeline css-var-root config-timeline-css-var"
|
||||
>
|
||||
<li
|
||||
@ -39112,11 +39112,11 @@ exports[`ConfigProvider components Timeline configProvider componentDisabled 1`]
|
||||
Bamboo
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</ol>
|
||||
`;
|
||||
|
||||
exports[`ConfigProvider components Timeline configProvider componentSize large 1`] = `
|
||||
<ul
|
||||
<ol
|
||||
class="config-timeline css-var-root config-timeline-css-var"
|
||||
>
|
||||
<li
|
||||
@ -39134,11 +39134,11 @@ exports[`ConfigProvider components Timeline configProvider componentSize large 1
|
||||
Bamboo
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</ol>
|
||||
`;
|
||||
|
||||
exports[`ConfigProvider components Timeline configProvider componentSize middle 1`] = `
|
||||
<ul
|
||||
<ol
|
||||
class="config-timeline css-var-root config-timeline-css-var"
|
||||
>
|
||||
<li
|
||||
@ -39156,11 +39156,11 @@ exports[`ConfigProvider components Timeline configProvider componentSize middle
|
||||
Bamboo
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</ol>
|
||||
`;
|
||||
|
||||
exports[`ConfigProvider components Timeline configProvider componentSize small 1`] = `
|
||||
<ul
|
||||
<ol
|
||||
class="config-timeline css-var-root config-timeline-css-var"
|
||||
>
|
||||
<li
|
||||
@ -39178,11 +39178,11 @@ exports[`ConfigProvider components Timeline configProvider componentSize small 1
|
||||
Bamboo
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</ol>
|
||||
`;
|
||||
|
||||
exports[`ConfigProvider components Timeline normal 1`] = `
|
||||
<ul
|
||||
<ol
|
||||
class="ant-timeline css-var-root ant-timeline-css-var"
|
||||
>
|
||||
<li
|
||||
@ -39200,11 +39200,11 @@ exports[`ConfigProvider components Timeline normal 1`] = `
|
||||
Bamboo
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</ol>
|
||||
`;
|
||||
|
||||
exports[`ConfigProvider components Timeline prefixCls 1`] = `
|
||||
<ul
|
||||
<ol
|
||||
class="prefix-Timeline css-var-root prefix-Timeline-css-var"
|
||||
>
|
||||
<li
|
||||
@ -39222,7 +39222,7 @@ exports[`ConfigProvider components Timeline prefixCls 1`] = `
|
||||
Bamboo
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</ol>
|
||||
`;
|
||||
|
||||
exports[`ConfigProvider components Tooltip configProvider 1`] = `
|
||||
|
@ -18,6 +18,7 @@ import type { CollapseProps } from '../collapse';
|
||||
import type { ColorPickerProps } from '../color-picker';
|
||||
import type { DatePickerProps, RangePickerProps } from '../date-picker';
|
||||
import type { DescriptionsProps } from '../descriptions';
|
||||
import type { DividerProps } from '../divider';
|
||||
import type { DrawerProps } from '../drawer';
|
||||
import type { DropdownProps } from '../dropdown';
|
||||
import type { EmptyProps } from '../empty';
|
||||
@ -25,8 +26,9 @@ import type { FlexProps } from '../flex/interface';
|
||||
import type { FloatButtonGroupProps } from '../float-button/interface';
|
||||
import type { FormProps } from '../form/Form';
|
||||
import type { ImageProps } from '../image';
|
||||
import type { InputProps, TextAreaProps } from '../input';
|
||||
import type { InputProps, SearchProps, TextAreaProps } from '../input';
|
||||
import type { InputNumberProps } from '../input-number';
|
||||
import type { OTPProps } from '../input/OTP';
|
||||
import type { ListItemProps } from '../list';
|
||||
import type { Locale } from '../locale';
|
||||
import type { MasonryProps } from '../masonry';
|
||||
@ -215,9 +217,13 @@ export type BreadcrumbConfig = ComponentStyleConfig &
|
||||
export type InputConfig = ComponentStyleConfig &
|
||||
Pick<InputProps, 'autoComplete' | 'classNames' | 'styles' | 'allowClear' | 'variant'>;
|
||||
|
||||
export type InputSearchConfig = ComponentStyleConfig & Pick<SearchProps, 'classNames' | 'styles'>;
|
||||
|
||||
export type TextAreaConfig = ComponentStyleConfig &
|
||||
Pick<TextAreaProps, 'autoComplete' | 'classNames' | 'styles' | 'allowClear' | 'variant'>;
|
||||
|
||||
export type OTPConfig = ComponentStyleConfig & Pick<OTPProps, 'classNames' | 'styles'>;
|
||||
|
||||
export type ButtonConfig = ComponentStyleConfig &
|
||||
Pick<ButtonProps, 'classNames' | 'styles' | 'autoInsertSpace' | 'variant' | 'color'>;
|
||||
|
||||
@ -243,6 +249,8 @@ export type CardMetaConfig = ComponentStyleConfig & Pick<CardMetaProps, 'classNa
|
||||
export type DrawerConfig = ComponentStyleConfig &
|
||||
Pick<DrawerProps, 'classNames' | 'styles' | 'closeIcon' | 'closable'>;
|
||||
|
||||
export type DividerConfig = ComponentStyleConfig & Pick<DividerProps, 'classNames' | 'styles'>;
|
||||
|
||||
export type DropdownConfig = ComponentStyleConfig & Pick<DropdownProps, 'classNames' | 'styles'>;
|
||||
|
||||
export type FlexConfig = ComponentStyleConfig & Pick<FlexProps, 'vertical'>;
|
||||
@ -364,7 +372,9 @@ export interface WaveConfig {
|
||||
|
||||
export interface ConfigComponentProps {
|
||||
input?: InputConfig;
|
||||
inputSearch?: InputSearchConfig;
|
||||
textArea?: TextAreaConfig;
|
||||
otp?: OTPConfig;
|
||||
inputNumber?: InputNumberConfig;
|
||||
pagination?: PaginationConfig;
|
||||
space?: SpaceConfig;
|
||||
@ -375,7 +385,7 @@ export interface ConfigComponentProps {
|
||||
affix?: ComponentStyleConfig;
|
||||
anchor?: AnchorStyleConfig;
|
||||
button?: ButtonConfig;
|
||||
divider?: ComponentStyleConfig;
|
||||
divider?: DividerConfig;
|
||||
drawer?: DrawerConfig;
|
||||
calendar?: CalendarConfig;
|
||||
carousel?: ComponentStyleConfig;
|
||||
|
@ -163,7 +163,7 @@ const Page: React.FC<{ placement: Placement }> = ({ placement }) => {
|
||||
<div className="direction-components">
|
||||
<Row>
|
||||
<Col span={24}>
|
||||
<Divider orientation="left">Cascader example</Divider>
|
||||
<Divider titlePlacement="start">Cascader example</Divider>
|
||||
<Cascader
|
||||
suffixIcon={<SearchIcon />}
|
||||
options={cascaderOptions}
|
||||
@ -185,7 +185,7 @@ const Page: React.FC<{ placement: Placement }> = ({ placement }) => {
|
||||
<br />
|
||||
<Row>
|
||||
<Col span={12}>
|
||||
<Divider orientation="left">Switch example</Divider>
|
||||
<Divider titlePlacement="start">Switch example</Divider>
|
||||
|
||||
<Switch defaultChecked />
|
||||
|
||||
@ -194,7 +194,7 @@ const Page: React.FC<{ placement: Placement }> = ({ placement }) => {
|
||||
<Switch size="small" loading />
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Divider orientation="left">Radio Group example</Divider>
|
||||
<Divider titlePlacement="start">Radio Group example</Divider>
|
||||
<Radio.Group defaultValue="c" buttonStyle="solid">
|
||||
<Radio.Button value="a">تهران</Radio.Button>
|
||||
<Radio.Button value="b" disabled>
|
||||
@ -208,7 +208,7 @@ const Page: React.FC<{ placement: Placement }> = ({ placement }) => {
|
||||
<br />
|
||||
<Row>
|
||||
<Col span={12}>
|
||||
<Divider orientation="left">Button example</Divider>
|
||||
<Divider titlePlacement="start">Button example</Divider>
|
||||
<div className="button-demo">
|
||||
<Button type="primary" icon={<DownloadOutlined />} />
|
||||
<Button type="primary" shape="circle" icon={<DownloadOutlined />} />
|
||||
@ -239,7 +239,7 @@ const Page: React.FC<{ placement: Placement }> = ({ placement }) => {
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Divider orientation="left">Tree example</Divider>
|
||||
<Divider titlePlacement="start">Tree example</Divider>
|
||||
<Tree
|
||||
showLine
|
||||
checkable
|
||||
@ -262,7 +262,7 @@ const Page: React.FC<{ placement: Placement }> = ({ placement }) => {
|
||||
<br />
|
||||
<Row>
|
||||
<Col span={24}>
|
||||
<Divider orientation="left">Input (Input Group) example</Divider>
|
||||
<Divider titlePlacement="start">Input (Input Group) example</Divider>
|
||||
<InputGroup size="large">
|
||||
<Row gutter={8}>
|
||||
<Col span={5}>
|
||||
@ -297,7 +297,7 @@ const Page: React.FC<{ placement: Placement }> = ({ placement }) => {
|
||||
<br />
|
||||
<Row>
|
||||
<Col span={12}>
|
||||
<Divider orientation="left">Select example</Divider>
|
||||
<Divider titlePlacement="start">Select example</Divider>
|
||||
<Space wrap>
|
||||
<Select mode="multiple" defaultValue="مورچه" style={{ width: 120 }}>
|
||||
<Option value="jack">Jack</Option>
|
||||
@ -321,7 +321,7 @@ const Page: React.FC<{ placement: Placement }> = ({ placement }) => {
|
||||
</Space>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Divider orientation="left">TreeSelect example</Divider>
|
||||
<Divider titlePlacement="start">TreeSelect example</Divider>
|
||||
<TreeSelect
|
||||
showSearch
|
||||
style={{ width: '100%' }}
|
||||
@ -349,7 +349,7 @@ const Page: React.FC<{ placement: Placement }> = ({ placement }) => {
|
||||
<br />
|
||||
<Row>
|
||||
<Col span={24}>
|
||||
<Divider orientation="left">Modal example</Divider>
|
||||
<Divider titlePlacement="start">Modal example</Divider>
|
||||
<Button type="primary" onClick={showModal}>
|
||||
Open Modal
|
||||
</Button>
|
||||
@ -363,7 +363,7 @@ const Page: React.FC<{ placement: Placement }> = ({ placement }) => {
|
||||
<br />
|
||||
<Row>
|
||||
<Col span={24}>
|
||||
<Divider orientation="left">Steps example</Divider>
|
||||
<Divider titlePlacement="start">Steps example</Divider>
|
||||
<Steps
|
||||
progressDot
|
||||
current={currentStep}
|
||||
@ -406,7 +406,7 @@ const Page: React.FC<{ placement: Placement }> = ({ placement }) => {
|
||||
<br />
|
||||
<Row>
|
||||
<Col span={12}>
|
||||
<Divider orientation="left">Rate example</Divider>
|
||||
<Divider titlePlacement="start">Rate example</Divider>
|
||||
<Rate defaultValue={2.5} />
|
||||
<br />
|
||||
<strong>* Note:</strong> Half star not implemented in RTL direction, it will be
|
||||
@ -417,7 +417,7 @@ const Page: React.FC<{ placement: Placement }> = ({ placement }) => {
|
||||
implement rtl support.
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Divider orientation="left">Badge example</Divider>
|
||||
<Divider titlePlacement="start">Badge example</Divider>
|
||||
<Badge count={badgeCount}>
|
||||
<a href="#" className="head-example" />
|
||||
</Badge>
|
||||
@ -443,14 +443,14 @@ const Page: React.FC<{ placement: Placement }> = ({ placement }) => {
|
||||
<br />
|
||||
<Row>
|
||||
<Col span={24}>
|
||||
<Divider orientation="left">Pagination example</Divider>
|
||||
<Divider titlePlacement="start">Pagination example</Divider>
|
||||
<Pagination showSizeChanger defaultCurrent={3} total={500} />
|
||||
</Col>
|
||||
</Row>
|
||||
<br />
|
||||
<Row>
|
||||
<Col span={24}>
|
||||
<Divider orientation="left">Grid System example</Divider>
|
||||
<Divider titlePlacement="start">Grid System example</Divider>
|
||||
<div className="grid-demo">
|
||||
<div className="code-box-demo">
|
||||
<p>
|
||||
|
@ -188,7 +188,7 @@ const Page: React.FC = () => {
|
||||
/>
|
||||
</Space>
|
||||
<Upload listType="picture-card" fileList={fileList} />
|
||||
<Divider orientation="left">Tour</Divider>
|
||||
<Divider titlePlacement="start">Tour</Divider>
|
||||
<Button type="primary" onClick={() => setTourOpen(true)}>
|
||||
Begin Tour
|
||||
</Button>
|
||||
|
@ -126,7 +126,7 @@ const {
|
||||
| datePicker | Set datePicker common props | { className?: string, style?: React.CSSProperties, classNames?: [DatePickerConfig\["classNames"\]](/components/date-picker#semantic-dom), styles?: [DatePickerConfig\["styles"\]](/components/date-picker#semantic-dom) } | - | 5.7.0 |
|
||||
| rangePicker | Set rangePicker common props | { className?: string, style?: React.CSSProperties } | - | 5.11.0 |
|
||||
| descriptions | Set Descriptions common props | { className?: string, style?: React.CSSProperties, classNames?: [DescriptionsProps\["classNames"\]](/components/descriptions#semantic-dom), styles?: [DescriptionsProps\["styles"\]](/components/descriptions#semantic-dom) } | - | 5.7.0, `classNames` and `styles`: 5.23.0 |
|
||||
| divider | Set Divider common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
|
||||
| divider | Set Divider common props | { className?: string, style?: React.CSSProperties, classNames?: [DividerProps\["classNames"\]](/components/divider#semantic-dom), styles?: [DividerProps\["styles"\]](/components/divider#semantic-dom) } | - | |
|
||||
| drawer | Set Drawer common props | { className?: string, style?: React.CSSProperties, classNames?: [DrawerProps\["classNames"\]](/components/drawer#semantic-dom), styles?: [DrawerProps\["styles"\]](/components/drawer#semantic-dom), closeIcon?: ReactNode } | - | 5.7.0, `classNames` and `styles`: 5.10.0, `closeIcon`: 5.14.0 |
|
||||
| dropdown | Set Dropdown common props | { className?: string, style?: React.CSSProperties, classNames?: [DropdownConfig\["classNames"\]](/components/dropdown#semantic-dom), styles?: [DropdownConfig\["styles"\]](/components/dropdown#semantic-dom) } | - | |
|
||||
| empty | Set Empty common props | { className?: string, style?: React.CSSProperties, classNames?: [EmptyProps\["classNames"\]](/components/empty#semantic-dom), styles?: [EmptyProps\["styles"\]](/components/empty#semantic-dom) } | - | 5.7.0, `classNames` and `styles`: 5.23.0 |
|
||||
@ -136,7 +136,9 @@ const {
|
||||
| image | Set Image common props | { className?: string, style?: React.CSSProperties, preview?: { closeIcon?: React.ReactNode, classNames?:[ImageConfig\["classNames"\]](/components/image#semantic-dom), styles?: [ImageConfig\["styles"\]](/components/image#semantic-dom) } } | - | 5.7.0, `closeIcon`: 5.14.0, `classNames` and `styles`: 6.0.0 |
|
||||
| input | Set Input common props | { autoComplete?: string, className?: string, style?: React.CSSProperties, allowClear?: boolean \| { clearIcon?: ReactNode } } | - | 4.2.0, `allowClear`: 5.15.0 |
|
||||
| inputNumber | Set InputNumber common props | { className?: string, style?: React.CSSProperties, classNames?: [InputNumberConfig\["classNames"\]](/components/input-number#semantic-dom), styles?: [InputNumberConfig\["styles"\]](/components/input-number#semantic-dom) } | - | |
|
||||
| textArea | Set TextArea common props | { autoComplete?: string, className?: string, style?: React.CSSProperties, allowClear?: boolean \| { clearIcon?: ReactNode } } | - | 5.15.0 |
|
||||
| otp | Set OTP common props | { className?: string, style?: React.CSSProperties, classNames?: [OTPConfig\["classNames"\]](/components/input#semantic-otp), styles?: [OTPConfig\["styles"\]](/components/input#semantic-otp) } | - | |
|
||||
| inputSearch | Set Search common props | { className?: string, style?: React.CSSProperties, classNames?: [InputSearchConfig\["classNames"\]](/components/input#semantic-search), styles?: [InputSearchConfig\["styles"\]](/components/input#semantic-search) } | - | |
|
||||
| textArea | Set TextArea common props | { autoComplete?: string, className?: string, style?: React.CSSProperties,classNames?:[TextAreaConfig\["classNames"\]](/components/input#semantic-textarea), styles?: [TextAreaConfig\["styles"\]](/components/input#semantic-textarea), allowClear?: boolean \| { clearIcon?: ReactNode } } | - | 5.15.0 |
|
||||
| layout | Set Layout common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
|
||||
| list | Set List common props | { className?: string, style?: React.CSSProperties, item?:{ classNames: [ListItemProps\["classNames"\]](/components/list#listitem), styles: [ListItemProps\["styles"\]](/components/list#listitem) } } | - | 5.7.0 |
|
||||
| masonry | Set Masonry common props | { className?: string, style?: React.CSSProperties, classNames?: [MasonryProps\["classNames"\]](/components/masonry#semantic-dom), styles?: [MasonryProps\["styles"\]](/components/masonry#semantic-dom) } | - | |
|
||||
@ -161,7 +163,7 @@ const {
|
||||
| spin | Set Spin common props | { className?: string, style?: React.CSSProperties, indicator?: React.ReactElement, classNames?:[SpinConfig\["classNames"\]](/components/spin#semantic-dom), styles?: [SpinConfig\["styles"\]](/components/spin#semantic-dom) } | - | 5.7.0, `indicator`: 5.20.0, `classNames` and `styles`: 6.0.0 |
|
||||
| statistic | Set Statistic common props | { className?: string, style?: React.CSSProperties, classNames?: [StatisticProps\["classNames"\]](/components/statistic#semantic-dom), styles?: [StatisticProps\["styles"\]](/components/statistic#semantic-dom)} | - | 5.7.0, `classNames` and `styles`: 6.0.0 |
|
||||
| steps | Set Steps common props | { className?: string, style?: React.CSSProperties, classNames?:[StepsConfig\["classNames"\]](/components/steps#semantic-dom), styles?: [StepsConfig\["styles"\]](/components/steps#semantic-dom) } | - | |
|
||||
| table | Set Table common props | { className?: string, style?: React.CSSProperties, expandable?: { expandIcon?: props => React.ReactNode }, classNames?: [TableProps\["classNames"\]](/components/table#semantic-dom), styles?: [TableProps\["styles"\]](/components/table#semantic-dom) } | - | |
|
||||
| table | Set Table common props | { className?: string, style?: React.CSSProperties, expandable?: { expandIcon?: props => React.ReactNode }, classNames?: [TableProps\["classNames"\]](/components/table#semantic-dom), styles?: [TableProps\["styles"\]](/components/table#semantic-dom) } | - | |
|
||||
| tabs | Set Tabs common props | { className?: string, style?: React.CSSProperties, indicator?: { size?: GetIndicatorSize, align?: `start` \| `center` \| `end` }, moreIcon?: ReactNode, addIcon?: ReactNode, removeIcon?: ReactNode, classNames?: [TabsConfig\["classNames"\]](/components/tabs#semantic-dom), styles?: [TabsConfig\["styles"\]](/components/tabs#semantic-dom) } | - | 5.7.0, `moreIcon` and `addIcon`: 5.14.0, `removeIcon`: 5.15.0, `classNames` and `styles`: 6.0.0 |
|
||||
| tag | Set Tag common props | { className?: string, style?: React.CSSProperties, closeIcon?: React.ReactNode, classNames?: [TagProps\["classNames"\]](/components/tag#semantic-dom), styles?: [TagProps\["styles"\]](/components/tag#semantic-dom) } | - | 5.7.0, `closeIcon`: 5.14.0, `classNames` and `styles`: 6.0.0 |
|
||||
| timeline | Set Timeline common props | { className?: string, style?: React.CSSProperties, classNames?: [TimelineConfig\["classNames"\]](/components/timeline#semantic-dom), styles?: [TimelineConfig\["styles"\]](/components/timeline#semantic-dom) } | - | 5.7.0, `classNames` and `styles`: 6.0.0 |
|
||||
|
@ -35,7 +35,9 @@ import type {
|
||||
FormConfig,
|
||||
ImageConfig,
|
||||
InputConfig,
|
||||
InputSearchConfig,
|
||||
InputNumberConfig,
|
||||
OTPConfig,
|
||||
ListConfig,
|
||||
MasonryConfig,
|
||||
MentionsConfig,
|
||||
@ -158,6 +160,8 @@ export interface ConfigProviderProps {
|
||||
variant?: Variant;
|
||||
form?: FormConfig;
|
||||
input?: InputConfig;
|
||||
inputSearch?: InputSearchConfig;
|
||||
otp?: OTPConfig;
|
||||
inputNumber?: InputNumberConfig;
|
||||
textArea?: TextAreaConfig;
|
||||
select?: SelectConfig;
|
||||
@ -372,6 +376,7 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
|
||||
pagination,
|
||||
input,
|
||||
textArea,
|
||||
otp,
|
||||
empty,
|
||||
badge,
|
||||
radio,
|
||||
@ -470,6 +475,7 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
|
||||
image,
|
||||
input,
|
||||
textArea,
|
||||
otp,
|
||||
layout,
|
||||
list,
|
||||
mentions,
|
||||
|
@ -128,7 +128,7 @@ const {
|
||||
| datePicker | 设置 DatePicker 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [DatePickerConfig\["classNames"\]](/components/date-picker-cn#semantic-dom), styles?: [DatePickerConfig\["styles"\]](/components/date-picker-cn#semantic-dom) } | - | 5.7.0 |
|
||||
| rangePicker | 设置 RangePicker 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.11.0 |
|
||||
| descriptions | 设置 Descriptions 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [DescriptionsProps\["classNames"\]](/components/descriptions-cn#semantic-dom), styles?: [DescriptionsProps\["styles"\]](/components/descriptions-cn#semantic-dom) } | - | 5.7.0, `classNames` 和 `styles`: 5.23.0 |
|
||||
| divider | 设置 Divider 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
|
||||
| divider | 设置 Divider 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [DividerProps\["classNames"\]](/components/divider-cn#semantic-dom), styles?: [DividerProps\["styles"\]](/components/divider-cn#semantic-dom) } | - | |
|
||||
| drawer | 设置 Drawer 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [DrawerProps\["classNames"\]](/components/drawer-cn#semantic-dom), styles?: [DrawerProps\["styles"\]](/components/drawer-cn#semantic-dom), closeIcon?: ReactNode } | - | 5.7.0, `classNames` 和 `styles`: 5.10.0, `closeIcon`: 5.14.0 |
|
||||
| dropdown | 设置 Dropdown 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [DropdownConfig\["classNames"\]](/components/dropdown-cn#semantic-dom), styles?: [DropdownConfig\["styles"\]](/components/dropdown-cn#semantic-dom) } | - | |
|
||||
| empty | 设置 Empty 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?:[EmptyProps\["classNames"\]](/components/empty-cn#semantic-dom), styles?: [EmptyProps\["styles"\]](/components/empty-cn#semantic-dom) } | - | 5.7.0, `classNames` 和 `styles`: 5.23.0 |
|
||||
@ -136,9 +136,11 @@ const {
|
||||
| floatButtonGroup | 设置 FloatButton.Group 组件的通用属性 | { closeIcon?: React.ReactNode } | - | 5.16.0 |
|
||||
| form | 设置 Form 组件的通用属性 | { className?: string, style?: React.CSSProperties, validateMessages?: [ValidateMessages](/components/form-cn#validatemessages), requiredMark?: boolean \| `optional`, colon?: boolean, scrollToFirstError?: boolean \| [Options](https://github.com/stipsan/scroll-into-view-if-needed/tree/ece40bd9143f48caf4b99503425ecb16b0ad8249#options), classNames?:[FormConfig\["classNames"\]](/components/form-cn#semantic-dom), styles?: [FormConfig\["styles"\]](/components/form-cn#semantic-dom) } | - | `requiredMark`: 4.8.0; `colon`: 4.18.0; `scrollToFirstError`: 5.2.0; `className` 和 `style`: 5.7.0 |
|
||||
| image | 设置 Image 组件的通用属性 | { className?: string, style?: React.CSSProperties, preview?: { closeIcon?: React.ReactNode, classNames?:[ImageConfig\["classNames"\]](/components/image-cn#semantic-dom), styles?: [ImageConfig\["styles"\]](/components/image-cn#semantic-dom) } } | - | 5.7.0, `closeIcon`: 5.14.0, `classNames` 和 `styles`: 6.0.0 |
|
||||
| input | 设置 Input 组件的通用属性 | { autoComplete?: string, className?: string, style?: React.CSSProperties, allowClear?: boolean \| { clearIcon?: ReactNode } } | - | 5.7.0, `allowClear`: 5.15.0 |
|
||||
| input | 设置 Input 组件的通用属性 | { autoComplete?: string, className?: string, style?: React.CSSProperties,classNames?:[InputConfig\["classNames"\]](/components/input-cn#semantic-input), styles?: [InputConfig\["styles"\]](/components/input-cn#semantic-input), allowClear?: boolean \| { clearIcon?: ReactNode } } | - | 5.7.0, `allowClear`: 5.15.0 |
|
||||
| inputNumber | 设置 Input 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [InputNumberConfig\["classNames"\]](/components/input-number-cn#semantic-dom), styles?: [InputNumberConfig\["styles"\]](/components/input-number-cn#semantic-dom) } | - | |
|
||||
| textArea | 设置 TextArea 组件的通用属性 | { autoComplete?: string, className?: string, style?: React.CSSProperties, allowClear?: boolean \| { clearIcon?: ReactNode } } | - | 5.15.0 |
|
||||
| otp | 设置 OTP 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [OTPConfig\["classNames"\]](/components/input-cn#semantic-otp), styles?: [OTPConfig\["styles"\]](/components/input-cn#semantic-otp) } | - | |
|
||||
| inputSearch | 设置 Search 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [InputSearchConfig\["classNames"\]](/components/input-cn#semantic-search), styles?: [InputSearchConfig\["styles"\]](/components/input-cn#semantic-search) } | - | |
|
||||
| textArea | 设置 TextArea 组件的通用属性 | { autoComplete?: string, className?: string, style?: React.CSSProperties,classNames?:[TextAreaConfig\["classNames"\]](/components/input-cn#semantic-textarea), styles?: [TextAreaConfig\["styles"\]](/components/input-cn#semantic-textarea), allowClear?: boolean \| { clearIcon?: ReactNode } } | - | 5.15.0 |
|
||||
| layout | 设置 Layout 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
|
||||
| list | 设置 List 组件的通用属性 | { className?: string, style?: React.CSSProperties, item?:{ classNames: [ListItemProps\["classNames"\]](/components/list-cn#listitem), styles: [ListItemProps\["styles"\]](/components/list-cn#listitem) } } | - | 5.7.0 |
|
||||
| masonry | 设置 Masonry 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [MasonryProps\["classNames"\]](/components/masonry#semantic-dom), styles?: [MasonryProps\["styles"\]](/components/masonry#semantic-dom) } | - | |
|
||||
@ -163,7 +165,7 @@ const {
|
||||
| spin | 设置 Spin 组件的通用属性 | { className?: string, style?: React.CSSProperties, indicator?: React.ReactElement, classNames?:[SpinConfig\["classNames"\]](/components/spin-cn#semantic-dom), styles?: [SpinConfig\["styles"\]](/components/spin-cn#semantic-dom) } | - | 5.7.0, `indicator`: 5.20.0, `classNames` 和 `styles`: 6.0.0 |
|
||||
| statistic | 设置 Statistic 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [StatisticProps\["classNames"\]](/components/statistic-cn#semantic-dom), styles?: [StatisticProps\["styles"\]](/components/statistic-cn#semantic-dom) } | - | 5.7.0, `classNames` 和 `styles`: 6.0.0 |
|
||||
| steps | 设置 Steps 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?:[StepsConfig\["classNames"\]](/components/steps#semantic-dom), styles?: [StepsConfig\["styles"\]](/components/steps#semantic-dom) } | - | |
|
||||
| table | 设置 Table 组件的通用属性 | { className?: string, style?: React.CSSProperties, expandable?: { expandIcon?: props => React.ReactNode }, classNames?: [TableProps\["classNames"\]](/components/table-cn#semantic-dom), styles?: [TableProps\["styles"\]](/components/table-cn#semantic-dom) } | - | |
|
||||
| table | 设置 Table 组件的通用属性 | { className?: string, style?: React.CSSProperties, expandable?: { expandIcon?: props => React.ReactNode }, classNames?: [TableProps\["classNames"\]](/components/table-cn#semantic-dom), styles?: [TableProps\["styles"\]](/components/table-cn#semantic-dom) } | - | |
|
||||
| tabs | 设置 Tabs 组件的通用属性 | { className?: string, style?: React.CSSProperties, indicator?: { size?: GetIndicatorSize, align?: `start` \| `center` \| `end` }, moreIcon?: ReactNode, addIcon?: ReactNode, removeIcon?: ReactNode, classNames?: [TabsConfig\["classNames"\]](/components/tabs-cn#semantic-dom), styles?: [TabsConfig\["styles"\]](/components/tabs-cn#semantic-dom) } | - | 5.7.0, `moreIcon` and `addIcon`: 5.14.0, `removeIcon`: 5.15.0, `classNames` 和 `styles`: 6.0.0 |
|
||||
| tag | 设置 Tag 组件的通用属性 | { className?: string, style?: React.CSSProperties, closeIcon?: React.ReactNode, classNames?: [TagProps\["classNames"\]](/components/tag-cn#semantic-dom), styles?: [TagProps\["styles"\]](/components/tag-cn#semantic-dom) } | - | 5.7.0, closeIcon: 5.14.0, `classNames` 和 `styles`: 6.0.0 |
|
||||
| timeline | 设置 Timeline 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [TimelineConfig\["classNames"\]](/components/timeline-cn#semantic-dom), styles?: [TimelineConfig\["styles"\]](/components/timeline-cn#semantic-dom) } | - | 5.7.0, `classNames` 和 `styles`: 6.0.0 |
|
||||
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { SmileOutlined } from '@ant-design/icons';
|
||||
import { DatePicker, Flex, Segmented } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import SemanticPreview from '../../../.dumi/theme/common/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
|
@ -1,5 +1,7 @@
|
||||
import type * as React from 'react';
|
||||
|
||||
import type { Breakpoint } from '../_util/responsiveObserver';
|
||||
|
||||
type SemanticName = 'label' | 'content';
|
||||
export interface DescriptionsItemProps {
|
||||
prefixCls?: string;
|
||||
@ -13,7 +15,7 @@ export interface DescriptionsItemProps {
|
||||
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
|
||||
classNames?: Partial<Record<SemanticName, string>>;
|
||||
children: React.ReactNode;
|
||||
span?: number;
|
||||
span?: number | 'filled' | { [key in Breakpoint]?: number };
|
||||
}
|
||||
|
||||
// JSX Structure Syntactic Sugar. Never reach the render code.
|
||||
|
@ -2063,7 +2063,7 @@ Array [
|
||||
</span>
|
||||
</button>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<div
|
||||
@ -2116,7 +2116,7 @@ Array [
|
||||
</label>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<div
|
||||
@ -2203,7 +2203,7 @@ Array [
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<div
|
||||
|
@ -1911,7 +1911,7 @@ Array [
|
||||
</span>
|
||||
</button>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<div
|
||||
@ -1964,7 +1964,7 @@ Array [
|
||||
</label>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<div
|
||||
@ -2043,7 +2043,7 @@ Array [
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<div
|
||||
|
193
components/descriptions/__tests__/type.test.tsx
Normal file
193
components/descriptions/__tests__/type.test.tsx
Normal file
@ -0,0 +1,193 @@
|
||||
import React from 'react';
|
||||
import { render } from '../../../tests/utils';
|
||||
import Descriptions from '..';
|
||||
import { resetWarned } from '../../_util/warning';
|
||||
|
||||
describe('Descriptions.Item span property types', () => {
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
afterEach(() => {
|
||||
errorSpy.mockReset();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
errorSpy.mockRestore();
|
||||
});
|
||||
|
||||
// 测试数字类型的 span
|
||||
it('should support number type span in JSX mode', () => {
|
||||
const { container } = render(
|
||||
<Descriptions column={4}>
|
||||
<Descriptions.Item label="Normal" span={1}>
|
||||
Normal span
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="Double" span={2}>
|
||||
Double span
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="Single">Default span (1)</Descriptions.Item>
|
||||
</Descriptions>,
|
||||
);
|
||||
|
||||
const items = container.querySelectorAll('.ant-descriptions-item');
|
||||
expect(items[0]).toHaveAttribute('colSpan', '1');
|
||||
expect(items[1]).toHaveAttribute('colSpan', '2');
|
||||
expect(items[2]).toHaveAttribute('colSpan', '1');
|
||||
});
|
||||
|
||||
// 测试 'filled' 类型的 span
|
||||
it('should support "filled" type span in JSX mode', () => {
|
||||
const { container } = render(
|
||||
<Descriptions column={3}>
|
||||
<Descriptions.Item label="Item 1">Content 1</Descriptions.Item>
|
||||
<Descriptions.Item label="Item 2" span="filled">
|
||||
This should fill the rest of the row
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="Item 3">Content 3</Descriptions.Item>
|
||||
</Descriptions>,
|
||||
);
|
||||
|
||||
const items = container.querySelectorAll('.ant-descriptions-item');
|
||||
expect(items[0]).toHaveAttribute('colSpan', '1');
|
||||
expect(items[1]).toHaveAttribute('colSpan', '2'); // 应该填充剩余的列
|
||||
expect(items[2]).toHaveAttribute('colSpan', '3'); // 下一行应该占满整行
|
||||
});
|
||||
|
||||
// 测试响应式对象类型的 span
|
||||
it('should support responsive object type span in JSX mode', () => {
|
||||
const { container } = render(
|
||||
<Descriptions column={4}>
|
||||
<Descriptions.Item label="Responsive" span={{ xs: 1, sm: 2, md: 3, lg: 4, xl: 2, xxl: 1 }}>
|
||||
Responsive span
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="Normal">Normal content</Descriptions.Item>
|
||||
</Descriptions>,
|
||||
);
|
||||
|
||||
// 由于测试环境中无法真实模拟响应式断点,这里只能测试是否正确渲染
|
||||
// 实际的响应式行为需要在浏览器环境中测试
|
||||
expect(container.querySelectorAll('.ant-descriptions-item')).toHaveLength(2);
|
||||
});
|
||||
|
||||
// 测试 items 模式下的所有 span 类型
|
||||
it('should support all span types in items mode', () => {
|
||||
const { container } = render(
|
||||
<Descriptions
|
||||
column={4}
|
||||
items={[
|
||||
{
|
||||
key: '1',
|
||||
label: 'Number Span',
|
||||
children: 'Using number span',
|
||||
span: 2,
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
label: 'Filled Span',
|
||||
children: 'Using filled span',
|
||||
span: 'filled',
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
label: 'Responsive Span',
|
||||
children: 'Using responsive span',
|
||||
span: { xs: 1, sm: 2, md: 3, lg: 4 },
|
||||
},
|
||||
{
|
||||
key: '4',
|
||||
label: 'Default Span',
|
||||
children: 'Default span (1)',
|
||||
},
|
||||
]}
|
||||
/>,
|
||||
);
|
||||
|
||||
const items = container.querySelectorAll('.ant-descriptions-item');
|
||||
expect(items).toHaveLength(4);
|
||||
expect(items[0]).toHaveAttribute('colSpan', '2');
|
||||
// 其他项的 colSpan 会根据实际渲染情况而定
|
||||
});
|
||||
|
||||
// 测试混合使用不同类型的 span
|
||||
it('should handle mixed span types in the same descriptions', () => {
|
||||
const { container } = render(
|
||||
<Descriptions
|
||||
column={6}
|
||||
items={[
|
||||
// 第一行
|
||||
{ key: '1', label: 'Number', children: 'Content', span: 2 },
|
||||
{ key: '2', label: 'Default', children: 'Content' }, // 默认 span=1
|
||||
{ key: '3', label: 'Responsive', children: 'Content', span: { xs: 1, sm: 2, md: 3 } },
|
||||
// 第二行
|
||||
{ key: '4', label: 'Filled', children: 'Content', span: 'filled' },
|
||||
{ key: '5', label: 'Last', children: 'Content' },
|
||||
]}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(container.querySelectorAll('.ant-descriptions-item')).toHaveLength(5);
|
||||
});
|
||||
|
||||
// 测试 span 超出列数的警告
|
||||
it('should warn when span exceeds column count', () => {
|
||||
resetWarned();
|
||||
|
||||
render(
|
||||
<Descriptions
|
||||
column={3}
|
||||
items={[{ key: '1', label: 'Excessive Span', children: 'Content', span: 4 }]}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(errorSpy).toHaveBeenCalledWith(
|
||||
expect.stringContaining('Sum of column `span` in a line not match `column` of Descriptions.'),
|
||||
);
|
||||
});
|
||||
|
||||
// 测试多个 'filled' span 的行为
|
||||
it('should handle multiple filled spans correctly', () => {
|
||||
const { container } = render(
|
||||
<Descriptions
|
||||
column={4}
|
||||
items={[
|
||||
// 第一行
|
||||
{ key: '1', label: 'Item 1', children: 'Content 1' },
|
||||
{ key: '2', label: 'Filled 1', children: 'Content 2', span: 'filled' },
|
||||
// 第二行
|
||||
{ key: '3', label: 'Item 3', children: 'Content 3' },
|
||||
{ key: '4', label: 'Filled 2', children: 'Content 4', span: 'filled' },
|
||||
]}
|
||||
/>,
|
||||
);
|
||||
|
||||
const items = container.querySelectorAll('.ant-descriptions-item');
|
||||
expect(items[0]).toHaveAttribute('colSpan', '1');
|
||||
expect(items[1]).toHaveAttribute('colSpan', '3'); // 填充第一行剩余的列
|
||||
expect(items[2]).toHaveAttribute('colSpan', '1');
|
||||
expect(items[3]).toHaveAttribute('colSpan', '3'); // 填充第二行剩余的列
|
||||
});
|
||||
|
||||
// 测试所有响应式断点
|
||||
it('should support all responsive breakpoints', () => {
|
||||
const { container } = render(
|
||||
<Descriptions
|
||||
column={6}
|
||||
items={[
|
||||
{
|
||||
key: '1',
|
||||
label: 'All Breakpoints',
|
||||
children: 'Using all responsive breakpoints',
|
||||
span: { xs: 1, sm: 2, md: 3, lg: 4, xl: 5, xxl: 6 },
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
label: 'Partial Breakpoints',
|
||||
children: 'Using some responsive breakpoints',
|
||||
span: { xs: 1, md: 3, xl: 5 },
|
||||
},
|
||||
]}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(container.querySelectorAll('.ant-descriptions-item')).toHaveLength(2);
|
||||
});
|
||||
});
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { Button, Descriptions, Divider, Switch } from 'antd';
|
||||
import type { DescriptionsProps } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import SemanticPreview from '../../../.dumi/theme/common/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
|
@ -21,14 +21,14 @@ interface CompoundedComponent {
|
||||
Item: typeof DescriptionsItem;
|
||||
}
|
||||
|
||||
export interface InternalDescriptionsItemType extends DescriptionsItemProps {
|
||||
export interface InternalDescriptionsItemType extends Omit<DescriptionsItemProps, 'span'> {
|
||||
key?: React.Key;
|
||||
filled?: boolean;
|
||||
span?: number;
|
||||
}
|
||||
|
||||
export interface DescriptionsItemType
|
||||
extends Omit<InternalDescriptionsItemType, 'span' | 'filled'> {
|
||||
span?: number | 'filled' | { [key in Breakpoint]?: number };
|
||||
export interface DescriptionsItemType extends Omit<DescriptionsItemProps, 'prefixCls'> {
|
||||
key?: React.Key;
|
||||
}
|
||||
|
||||
type SemanticName = 'root' | 'header' | 'title' | 'extra' | 'label' | 'content';
|
||||
|
@ -9,11 +9,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-center"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -22,11 +28,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Left Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -35,39 +47,57 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-end"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Right Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start ant-divider-no-default-orientation-margin-start"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
style="margin-inline-start: 0;"
|
||||
style="margin: 0px;"
|
||||
>
|
||||
Left Text with 0 orientationMargin
|
||||
Left Text margin with 0
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-end ant-divider-no-default-orientation-margin-end"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-end"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
style="margin-inline-end: 50px;"
|
||||
style="margin: 0px 50px;"
|
||||
>
|
||||
Right Text with 50px orientationMargin
|
||||
Right Text margin with 50px
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -80,12 +110,12 @@ exports[`renders components/divider/demo/component-token.tsx extend context corr
|
||||
exports[`renders components/divider/demo/customize-style.tsx extend context correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
style="border-width: 2px; border-color: #7cb305;"
|
||||
/>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-dashed"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-dashed ant-divider-rail"
|
||||
role="separator"
|
||||
style="border-color: #7cb305;"
|
||||
/>,
|
||||
@ -94,19 +124,25 @@ Array [
|
||||
role="separator"
|
||||
style="border-color: #7cb305;"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-vertical"
|
||||
class="ant-divider css-var-test-id ant-divider-vertical ant-divider-rail"
|
||||
role="separator"
|
||||
style="height: 60px; border-color: #7cb305;"
|
||||
/>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-vertical ant-divider-dashed"
|
||||
class="ant-divider css-var-test-id ant-divider-vertical ant-divider-dashed ant-divider-rail"
|
||||
role="separator"
|
||||
style="height: 60px; border-color: #7cb305;"
|
||||
/>,
|
||||
@ -118,11 +154,17 @@ Array [
|
||||
role="separator"
|
||||
style="background: rgba(0, 255, 0, 0.05);"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
@ -136,14 +178,14 @@ Array [
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-dashed"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-dashed ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<p>
|
||||
@ -163,11 +205,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-center ant-divider-plain"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -176,11 +224,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start ant-divider-plain"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Left Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -189,11 +243,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-end ant-divider-plain"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Right Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -209,21 +269,21 @@ Array [
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-sm"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-sm ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-md"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-md ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<p>
|
||||
@ -244,11 +304,17 @@ Array [
|
||||
role="separator"
|
||||
style="border-color: #7cb305;"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Solid
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -258,11 +324,17 @@ Array [
|
||||
role="separator"
|
||||
style="border-color: #7cb305;"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Dotted
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -272,11 +344,17 @@ Array [
|
||||
role="separator"
|
||||
style="border-color: #7cb305;"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Dashed
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -290,7 +368,7 @@ exports[`renders components/divider/demo/vertical.tsx extend context correctly 1
|
||||
Array [
|
||||
Text,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-vertical"
|
||||
class="ant-divider css-var-test-id ant-divider-vertical ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<a
|
||||
@ -299,7 +377,7 @@ Array [
|
||||
Link
|
||||
</a>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-vertical"
|
||||
class="ant-divider css-var-test-id ant-divider-vertical ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<a
|
||||
@ -321,11 +399,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-center"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -334,11 +418,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Left Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -347,39 +437,57 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-end"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Right Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start ant-divider-no-default-orientation-margin-start"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
style="margin-inline-start: 0;"
|
||||
style="margin: 0px;"
|
||||
>
|
||||
Left Text with 0 orientationMargin
|
||||
Left Text margin with 0
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-end ant-divider-no-default-orientation-margin-end"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-end"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
style="margin-inline-end: 50px;"
|
||||
style="margin: 0px 50px;"
|
||||
>
|
||||
Right Text with 50px orientationMargin
|
||||
Right Text margin with 50px
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
|
@ -9,11 +9,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-center"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -22,11 +28,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Left Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -35,39 +47,57 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-end"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Right Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start ant-divider-no-default-orientation-margin-start"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
style="margin-inline-start:0"
|
||||
style="margin:0"
|
||||
>
|
||||
Left Text with 0 orientationMargin
|
||||
Left Text margin with 0
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-end ant-divider-no-default-orientation-margin-end"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-end"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
style="margin-inline-end:50px"
|
||||
style="margin:0 50px"
|
||||
>
|
||||
Right Text with 50px orientationMargin
|
||||
Right Text margin with 50px
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -78,12 +108,12 @@ Array [
|
||||
exports[`renders components/divider/demo/customize-style.tsx correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
style="border-width:2px;border-color:#7cb305"
|
||||
/>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-dashed"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-dashed ant-divider-rail"
|
||||
role="separator"
|
||||
style="border-color:#7cb305"
|
||||
/>,
|
||||
@ -92,19 +122,25 @@ Array [
|
||||
role="separator"
|
||||
style="border-color:#7cb305"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-vertical"
|
||||
class="ant-divider css-var-test-id ant-divider-vertical ant-divider-rail"
|
||||
role="separator"
|
||||
style="height:60px;border-color:#7cb305"
|
||||
/>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-vertical ant-divider-dashed"
|
||||
class="ant-divider css-var-test-id ant-divider-vertical ant-divider-dashed ant-divider-rail"
|
||||
role="separator"
|
||||
style="height:60px;border-color:#7cb305"
|
||||
/>,
|
||||
@ -116,11 +152,17 @@ Array [
|
||||
role="separator"
|
||||
style="background:rgba(0,255,0,0.05)"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
@ -132,14 +174,14 @@ Array [
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-dashed"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-dashed ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<p>
|
||||
@ -157,11 +199,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-center ant-divider-plain"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -170,11 +218,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start ant-divider-plain"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Left Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -183,11 +237,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-end ant-divider-plain"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Right Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -201,21 +261,21 @@ Array [
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-sm"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-sm ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-md"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-md ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<p>
|
||||
@ -234,11 +294,17 @@ Array [
|
||||
role="separator"
|
||||
style="border-color:#7cb305"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Solid
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -248,11 +314,17 @@ Array [
|
||||
role="separator"
|
||||
style="border-color:#7cb305"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Dotted
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -262,11 +334,17 @@ Array [
|
||||
role="separator"
|
||||
style="border-color:#7cb305"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Dashed
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -278,7 +356,7 @@ exports[`renders components/divider/demo/vertical.tsx correctly 1`] = `
|
||||
Array [
|
||||
Text,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-vertical"
|
||||
class="ant-divider css-var-test-id ant-divider-vertical ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<a
|
||||
@ -287,7 +365,7 @@ Array [
|
||||
Link
|
||||
</a>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-vertical"
|
||||
class="ant-divider css-var-test-id ant-divider-vertical ant-divider-rail"
|
||||
role="separator"
|
||||
/>,
|
||||
<a
|
||||
@ -307,11 +385,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-center"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -320,11 +404,17 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Left Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
@ -333,39 +423,57 @@ Array [
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-end"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
>
|
||||
Right Text
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start ant-divider-no-default-orientation-margin-start"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-start"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
style="margin-inline-start:0"
|
||||
style="margin:0"
|
||||
>
|
||||
Left Text with 0 orientationMargin
|
||||
Left Text margin with 0
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>,
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-end ant-divider-no-default-orientation-margin-end"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-with-text ant-divider-with-text-end"
|
||||
role="separator"
|
||||
>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-divider-inner-text"
|
||||
style="margin-inline-end:50px"
|
||||
style="margin:0 50px"
|
||||
>
|
||||
Right Text with 50px orientationMargin
|
||||
Right Text margin with 50px
|
||||
</span>
|
||||
<div
|
||||
class="ant-divider-rail ant-divider-rail-end"
|
||||
/>
|
||||
</div>,
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
|
@ -2,8 +2,10 @@ import * as React from 'react';
|
||||
import { ConfigProvider } from 'antd';
|
||||
|
||||
import Divider from '..';
|
||||
import type { Orientation } from '../../_util/hooks/useOrientation';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import { render } from '../../../tests/utils';
|
||||
import type { TitlePlacement } from '../index';
|
||||
|
||||
describe('Divider', () => {
|
||||
mountTest(Divider);
|
||||
@ -19,7 +21,7 @@ describe('Divider', () => {
|
||||
|
||||
it('support string orientationMargin', () => {
|
||||
const { container } = render(
|
||||
<Divider orientation="right" orientationMargin="10">
|
||||
<Divider titlePlacement="end" orientationMargin="10">
|
||||
test test test
|
||||
</Divider>,
|
||||
);
|
||||
@ -65,4 +67,49 @@ describe('Divider', () => {
|
||||
rerender(<Divider type="vertical" size="small" />);
|
||||
expect(container.querySelector<HTMLSpanElement>('.ant-divider-sm')).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('orientation and placement attribute', () => {
|
||||
jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const testCases: Array<
|
||||
[
|
||||
params: [
|
||||
orientation?: Orientation | TitlePlacement,
|
||||
vertical?: boolean,
|
||||
type?: Orientation,
|
||||
titlePlacement?: TitlePlacement,
|
||||
orientationMargin?: number,
|
||||
],
|
||||
expected: string,
|
||||
]
|
||||
> = [
|
||||
[['right'], '.ant-divider-with-text-end'],
|
||||
[['vertical', undefined, 'horizontal'], '.ant-divider-vertical'],
|
||||
[[undefined, undefined, 'vertical'], '.ant-divider-vertical'],
|
||||
[['center', undefined, undefined, 'left'], '.ant-divider-with-text-start'],
|
||||
[['horizontal', true, undefined], '.ant-divider-horizontal'],
|
||||
[[undefined, true, 'horizontal'], '.ant-divider-vertical'],
|
||||
[['center', undefined, 'horizontal', 'left', 20], '.ant-divider-with-text-start'],
|
||||
];
|
||||
it.each(testCases)('with args %j should have %s node', (params, expected) => {
|
||||
const { container } = render(
|
||||
<Divider
|
||||
orientation={params[0] as Orientation}
|
||||
vertical={params[1]}
|
||||
type={params[2]}
|
||||
titlePlacement={params[3]}
|
||||
{...(params[4] && { orientationMargin: params[4] })}
|
||||
>
|
||||
Bamboo
|
||||
</Divider>,
|
||||
);
|
||||
expect(container.querySelector<HTMLSpanElement>(expected)).not.toBeNull();
|
||||
if (params[4]) {
|
||||
expect(
|
||||
container
|
||||
.querySelector<HTMLSpanElement>('.ant-divider-inner-text')
|
||||
?.style.getPropertyValue('margin-inline-start'),
|
||||
).toBe('20px');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
36
components/divider/__tests__/semantic.test.tsx
Normal file
36
components/divider/__tests__/semantic.test.tsx
Normal file
@ -0,0 +1,36 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import Divider from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import { render } from '../../../tests/utils';
|
||||
|
||||
describe('Divider', () => {
|
||||
mountTest(Divider);
|
||||
|
||||
it('not show children when vertical', () => {
|
||||
const testClassNames = {
|
||||
root: 'test-root',
|
||||
rail: 'test-rail',
|
||||
content: 'test-content',
|
||||
};
|
||||
const testStyles = {
|
||||
root: { color: 'red' },
|
||||
rail: { color: 'blue' },
|
||||
content: { color: 'green' },
|
||||
};
|
||||
const { container } = render(
|
||||
<Divider classNames={testClassNames} styles={testStyles}>
|
||||
Text
|
||||
</Divider>,
|
||||
);
|
||||
const root = container.querySelector('.ant-divider');
|
||||
const rail = container.querySelector('.ant-divider-rail');
|
||||
const content = container.querySelector('.ant-divider-inner-text');
|
||||
expect(root).toHaveClass(testClassNames.root);
|
||||
expect(root).toHaveStyle(testStyles.root);
|
||||
expect(rail).toHaveClass(testClassNames.rail);
|
||||
expect(rail).toHaveStyle(testStyles.rail);
|
||||
expect(content).toHaveClass(testClassNames.content);
|
||||
expect(content).toHaveStyle(testStyles.content);
|
||||
});
|
||||
});
|
76
components/divider/demo/_semantic.tsx
Normal file
76
components/divider/demo/_semantic.tsx
Normal file
@ -0,0 +1,76 @@
|
||||
import React from 'react';
|
||||
import { Divider } from 'antd';
|
||||
import type { DividerProps } from 'antd';
|
||||
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
import SemanticPreview from '../../../.dumi/theme/common/SemanticPreview';
|
||||
|
||||
const locales = {
|
||||
cn: {
|
||||
root: '根元素',
|
||||
content: '内容元素',
|
||||
rail: '背景条元素',
|
||||
},
|
||||
en: {
|
||||
root: 'Root element',
|
||||
content: 'Content element',
|
||||
rail: 'Background rail element',
|
||||
},
|
||||
};
|
||||
|
||||
const Block: React.FC<DividerProps> = (props) => {
|
||||
return (
|
||||
<div>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi
|
||||
ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>
|
||||
<Divider {...props} />
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi
|
||||
ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>
|
||||
<Divider {...props}>Solid</Divider>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi
|
||||
ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>
|
||||
<Divider titlePlacement="left" variant="dotted" {...props}>
|
||||
Dotted
|
||||
</Divider>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi
|
||||
ista probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>
|
||||
<Divider titlePlacement="right" variant="dashed" {...props}>
|
||||
Dashed
|
||||
</Divider>
|
||||
<>
|
||||
These
|
||||
<Divider orientation="vertical" {...props} />
|
||||
are
|
||||
<Divider orientation="vertical" {...props} />
|
||||
vertical
|
||||
<Divider orientation="vertical" {...props} />
|
||||
Dividers
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
const App: React.FC = () => {
|
||||
const [locale] = useLocale(locales);
|
||||
return (
|
||||
<SemanticPreview
|
||||
componentName="Divider"
|
||||
semantics={[
|
||||
{ name: 'root', desc: locale.root },
|
||||
{ name: 'rail', desc: locale.rail },
|
||||
{ name: 'content', desc: locale.content },
|
||||
]}
|
||||
>
|
||||
<Block />
|
||||
</SemanticPreview>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
@ -28,25 +28,25 @@ const App: React.FC = () => (
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
|
||||
probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>
|
||||
<Divider orientation="left">Left Text</Divider>
|
||||
<Divider titlePlacement="start">Left Text</Divider>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
|
||||
probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>
|
||||
<Divider orientation="right">Right Text</Divider>
|
||||
<Divider titlePlacement="end">Right Text</Divider>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
|
||||
probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>
|
||||
<Divider orientation="left" orientationMargin="0">
|
||||
Left Text with 0 orientationMargin
|
||||
<Divider titlePlacement="start" styles={{ content: { margin: 0 } }}>
|
||||
Left Text margin with 0
|
||||
</Divider>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
|
||||
probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>
|
||||
<Divider orientation="right" orientationMargin={50}>
|
||||
Right Text with 50px orientationMargin
|
||||
<Divider titlePlacement="end" styles={{ content: { margin: '0 50px' } }}>
|
||||
Right Text margin with 50px
|
||||
</Divider>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
|
||||
|
@ -8,11 +8,11 @@ const App: React.FC = () => (
|
||||
<Divider style={{ borderColor: '#7cb305' }} dashed>
|
||||
Text
|
||||
</Divider>
|
||||
<Divider type="vertical" style={{ height: 60, borderColor: '#7cb305' }} />
|
||||
<Divider type="vertical" style={{ height: 60, borderColor: '#7cb305' }} dashed />
|
||||
<Divider vertical style={{ height: 60, borderColor: '#7cb305' }} />
|
||||
<Divider vertical style={{ height: 60, borderColor: '#7cb305' }} dashed />
|
||||
|
||||
<div style={{ display: 'flex', flexDirection: 'column', height: 50, boxShadow: '0 0 1px red' }}>
|
||||
<Divider style={{ background: 'rgba(0,255,0,0.05)' }} orientation="left">
|
||||
<Divider style={{ background: 'rgba(0,255,0,0.05)' }} titlePlacement="start">
|
||||
Text
|
||||
</Divider>
|
||||
</div>
|
||||
|
@ -12,14 +12,14 @@ const App: React.FC = () => (
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
|
||||
probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>
|
||||
<Divider orientation="left" plain>
|
||||
<Divider titlePlacement="start" plain>
|
||||
Left Text
|
||||
</Divider>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
|
||||
probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>
|
||||
<Divider orientation="right" plain>
|
||||
<Divider titlePlacement="end" plain>
|
||||
Right Text
|
||||
</Divider>
|
||||
<p>
|
||||
|
@ -1,7 +1,7 @@
|
||||
## zh-CN
|
||||
|
||||
使用 `type="vertical"` 设置为行内的垂直分割线。
|
||||
使用 `orientation="vertical"` 或者 `vertical` 设置为行内的垂直分割线。
|
||||
|
||||
## en-US
|
||||
|
||||
Use `type="vertical"` to make the divider vertical.
|
||||
Use `orientation="vertical"` or `vertical` to make the divider vertical.
|
||||
|
@ -4,9 +4,9 @@ import { Divider } from 'antd';
|
||||
const App: React.FC = () => (
|
||||
<>
|
||||
Text
|
||||
<Divider type="vertical" />
|
||||
<Divider orientation="vertical" />
|
||||
<a href="#">Link</a>
|
||||
<Divider type="vertical" />
|
||||
<Divider vertical />
|
||||
<a href="#">Link</a>
|
||||
</>
|
||||
);
|
||||
|
@ -1,7 +1,7 @@
|
||||
## zh-CN
|
||||
|
||||
分割线中带有文字,可以用 `orientation` 指定文字位置。
|
||||
分割线中带有文字,可以用 `titlePlacement` 指定文字位置。
|
||||
|
||||
## en-US
|
||||
|
||||
Divider with inner title, set `orientation="left/right"` to align it.
|
||||
Divider with inner title, set `titlePlacement="start/end"` to align it.
|
||||
|
@ -12,25 +12,25 @@ const App: React.FC = () => (
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
|
||||
probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>
|
||||
<Divider orientation="left">Left Text</Divider>
|
||||
<Divider titlePlacement="start">Left Text</Divider>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
|
||||
probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>
|
||||
<Divider orientation="right">Right Text</Divider>
|
||||
<Divider titlePlacement="end">Right Text</Divider>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
|
||||
probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>
|
||||
<Divider orientation="left" orientationMargin="0">
|
||||
Left Text with 0 orientationMargin
|
||||
<Divider titlePlacement="start" styles={{ content: { margin: 0 } }}>
|
||||
Left Text margin with 0
|
||||
</Divider>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
|
||||
probare, quae sunt a te dicta? Refert tamen, quo modo.
|
||||
</p>
|
||||
<Divider orientation="right" orientationMargin={50}>
|
||||
Right Text with 50px orientationMargin
|
||||
<Divider titlePlacement="end" styles={{ content: { margin: '0 50px' } }}>
|
||||
Right Text margin with 50px
|
||||
</Divider>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi ista
|
||||
|
@ -37,13 +37,19 @@ Common props ref:[Common props](/docs/react/common-props)
|
||||
| children | The wrapped title | ReactNode | - | |
|
||||
| className | The className of container | string | - | |
|
||||
| dashed | Whether line is dashed | boolean | false | |
|
||||
| variant | Whether line is dashed, dotted or solid | `dashed` \| `dotted` \| `solid` | solid | 5.20.0 |
|
||||
| orientation | The position of title inside divider | `start` \| `end` \| `center` | `center` | `start` `end`: 5.24.0 |
|
||||
| orientationMargin | The margin-left/right between the title and its closest border, while the `orientation` should not be `center`, If a numeric value of type `string` is provided without a unit, it is assumed to be in pixels (px) by default. | string \| number | - | |
|
||||
| orientation | Whether line is horizontal or vertical | `horizontal` \| `vertical` | `horizontal` | - |
|
||||
| ~~orientationMargin~~ | The margin-left/right between the title and its closest border, while the `titlePlacement` should not be `center`, If a numeric value of type `string` is provided without a unit, it is assumed to be in pixels (px) by default. | string \| number | - | |
|
||||
| plain | Divider text show as plain style | boolean | true | 4.2.0 |
|
||||
| style | The style object of container | CSSProperties | - | |
|
||||
| size | The size of divider. Only valid for horizontal layout | `small` \| `middle` \| `large` | - | 5.25.0 |
|
||||
| type | The direction type of divider | `horizontal` \| `vertical` | `horizontal` | |
|
||||
| titlePlacement | The position of title inside divider | `start` \| `end` \| `center` | `center` | - |
|
||||
| ~~type~~ | The direction type of divider | `horizontal` \| `vertical` | `horizontal` | - |
|
||||
| variant | Whether line is dashed, dotted or solid | `dashed` \| `dotted` \| `solid` | solid | 5.20.0 |
|
||||
| vertical | Orientation, Simultaneously configure with `orientation` and prioritize `orientation` | boolean | false | - |
|
||||
|
||||
## Semantic DOM
|
||||
|
||||
<code src="./demo/_semantic.tsx" simplify="true"></code>
|
||||
|
||||
## Design Token
|
||||
|
||||
|
@ -1,24 +1,32 @@
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import cls from 'classnames';
|
||||
|
||||
import useMergeSemantic from '../_util/hooks/useMergeSemantic';
|
||||
import useOrientation from '../_util/hooks/useOrientation';
|
||||
import type { Orientation } from '../_util/hooks/useOrientation';
|
||||
import { devUseWarning } from '../_util/warning';
|
||||
import { useComponentConfig } from '../config-provider/context';
|
||||
import useSize from '../config-provider/hooks/useSize';
|
||||
import { SizeType } from '../config-provider/SizeContext';
|
||||
import useStyle from './style';
|
||||
|
||||
type SemanticName = 'root' | 'rail' | 'content';
|
||||
|
||||
export type TitlePlacement =
|
||||
| 'left'
|
||||
| 'right'
|
||||
| 'center'
|
||||
| 'start' // 👈 5.24.0+
|
||||
| 'end'; // 👈 5.24.0+
|
||||
const titlePlacementList = ['left', 'right', 'center', 'start', 'end'];
|
||||
export interface DividerProps {
|
||||
prefixCls?: string;
|
||||
type?: 'horizontal' | 'vertical';
|
||||
/**
|
||||
* @default center
|
||||
*/
|
||||
orientation?:
|
||||
| 'left'
|
||||
| 'right'
|
||||
| 'center'
|
||||
| 'start' // 👈 5.24.0+
|
||||
| 'end'; // 👈 5.24.0+
|
||||
/** @deprecated please use `orientation`*/
|
||||
type?: Orientation;
|
||||
orientation?: Orientation;
|
||||
vertical?: boolean;
|
||||
titlePlacement?: TitlePlacement;
|
||||
/** @deprecated please use `styles.content.margin` */
|
||||
orientationMargin?: string | number;
|
||||
className?: string;
|
||||
rootClassName?: string;
|
||||
@ -32,22 +40,27 @@ export interface DividerProps {
|
||||
style?: React.CSSProperties;
|
||||
size?: SizeType;
|
||||
plain?: boolean;
|
||||
classNames?: Partial<Record<SemanticName, string>>;
|
||||
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
|
||||
}
|
||||
|
||||
const sizeClassNameMap: Record<string, string> = { small: 'sm', middle: 'md' };
|
||||
|
||||
const Divider: React.FC<DividerProps> = (props) => {
|
||||
const {
|
||||
getPrefixCls,
|
||||
direction,
|
||||
className: dividerClassName,
|
||||
style: dividerStyle,
|
||||
classNames: contextClassNames,
|
||||
styles: contextStyles,
|
||||
} = useComponentConfig('divider');
|
||||
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
type = 'horizontal',
|
||||
orientation = 'center',
|
||||
type,
|
||||
orientation,
|
||||
vertical,
|
||||
titlePlacement,
|
||||
orientationMargin,
|
||||
className,
|
||||
rootClassName,
|
||||
@ -57,9 +70,17 @@ const Divider: React.FC<DividerProps> = (props) => {
|
||||
plain,
|
||||
style,
|
||||
size: customSize,
|
||||
classNames,
|
||||
styles,
|
||||
...restProps
|
||||
} = props;
|
||||
|
||||
const prefixCls = getPrefixCls('divider', customizePrefixCls);
|
||||
const railCls = `${prefixCls}-rail`;
|
||||
const [mergedClassNames, mergedStyles] = useMergeSemantic(
|
||||
[contextClassNames, classNames],
|
||||
[contextStyles, styles],
|
||||
);
|
||||
|
||||
const [hashId, cssVarCls] = useStyle(prefixCls);
|
||||
|
||||
@ -68,29 +89,34 @@ const Divider: React.FC<DividerProps> = (props) => {
|
||||
|
||||
const hasChildren = !!children;
|
||||
|
||||
const mergedOrientation = React.useMemo<'start' | 'end' | 'center'>(() => {
|
||||
if (orientation === 'left') {
|
||||
const validTitlePlacement = titlePlacementList.includes(orientation || '');
|
||||
const mergedTitlePlacement = React.useMemo<'start' | 'end' | 'center'>(() => {
|
||||
const placement =
|
||||
titlePlacement ?? (validTitlePlacement ? (orientation as TitlePlacement) : 'center');
|
||||
if (placement === 'left') {
|
||||
return direction === 'rtl' ? 'end' : 'start';
|
||||
}
|
||||
if (orientation === 'right') {
|
||||
if (placement === 'right') {
|
||||
return direction === 'rtl' ? 'start' : 'end';
|
||||
}
|
||||
return orientation;
|
||||
return placement;
|
||||
}, [direction, orientation]);
|
||||
|
||||
const hasMarginStart = mergedOrientation === 'start' && orientationMargin != null;
|
||||
const hasMarginStart = mergedTitlePlacement === 'start' && orientationMargin != null;
|
||||
|
||||
const hasMarginEnd = mergedOrientation === 'end' && orientationMargin != null;
|
||||
const hasMarginEnd = mergedTitlePlacement === 'end' && orientationMargin != null;
|
||||
|
||||
const classString = classNames(
|
||||
const [mergedOrientation, mergedVertical] = useOrientation(orientation, vertical, type);
|
||||
|
||||
const classString = cls(
|
||||
prefixCls,
|
||||
dividerClassName,
|
||||
hashId,
|
||||
cssVarCls,
|
||||
`${prefixCls}-${type}`,
|
||||
`${prefixCls}-${mergedOrientation}`,
|
||||
{
|
||||
[`${prefixCls}-with-text`]: hasChildren,
|
||||
[`${prefixCls}-with-text-${mergedOrientation}`]: hasChildren,
|
||||
[`${prefixCls}-with-text-${mergedTitlePlacement}`]: hasChildren,
|
||||
[`${prefixCls}-dashed`]: !!dashed,
|
||||
[`${prefixCls}-${variant}`]: variant !== 'solid',
|
||||
[`${prefixCls}-plain`]: !!plain,
|
||||
@ -98,12 +124,15 @@ const Divider: React.FC<DividerProps> = (props) => {
|
||||
[`${prefixCls}-no-default-orientation-margin-start`]: hasMarginStart,
|
||||
[`${prefixCls}-no-default-orientation-margin-end`]: hasMarginEnd,
|
||||
[`${prefixCls}-${sizeCls}`]: !!sizeCls,
|
||||
[railCls]: !children,
|
||||
[mergedClassNames.rail as string]: mergedClassNames.rail && !children,
|
||||
},
|
||||
className,
|
||||
rootClassName,
|
||||
mergedClassNames.root,
|
||||
);
|
||||
|
||||
const memoizedOrientationMargin = React.useMemo<string | number>(() => {
|
||||
const memoizedPlacementMargin = React.useMemo<string | number>(() => {
|
||||
if (typeof orientationMargin === 'number') {
|
||||
return orientationMargin;
|
||||
}
|
||||
@ -114,32 +143,57 @@ const Divider: React.FC<DividerProps> = (props) => {
|
||||
}, [orientationMargin]);
|
||||
|
||||
const innerStyle: React.CSSProperties = {
|
||||
marginInlineStart: hasMarginStart ? memoizedOrientationMargin : undefined,
|
||||
marginInlineEnd: hasMarginEnd ? memoizedOrientationMargin : undefined,
|
||||
marginInlineStart: hasMarginStart ? memoizedPlacementMargin : undefined,
|
||||
marginInlineEnd: hasMarginEnd ? memoizedPlacementMargin : undefined,
|
||||
};
|
||||
|
||||
// Warning children not work in vertical mode
|
||||
// =================== Warning =====================
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
const warning = devUseWarning('Divider');
|
||||
|
||||
warning(!children || !mergedVertical, 'usage', '`children` not working in `vertical` mode.');
|
||||
warning(
|
||||
!children || type !== 'vertical',
|
||||
!validTitlePlacement,
|
||||
'usage',
|
||||
'`children` not working in `vertical` mode.',
|
||||
'`orientation` is used for direction, please use `titlePlacement` replace this',
|
||||
);
|
||||
[
|
||||
['type', 'orientation'],
|
||||
['orientationMargin', 'styles.content.margin'],
|
||||
].forEach(([deprecatedName, newName]) => {
|
||||
warning.deprecated(!(deprecatedName in props), deprecatedName, newName);
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classString}
|
||||
style={{ ...dividerStyle, ...style }}
|
||||
style={{
|
||||
...dividerStyle,
|
||||
...mergedStyles.root,
|
||||
...(children ? {} : mergedStyles.rail),
|
||||
...style,
|
||||
}}
|
||||
{...restProps}
|
||||
role="separator"
|
||||
>
|
||||
{children && type !== 'vertical' && (
|
||||
<span className={`${prefixCls}-inner-text`} style={innerStyle}>
|
||||
{children}
|
||||
</span>
|
||||
{children && !mergedVertical && (
|
||||
<>
|
||||
<div
|
||||
className={cls(railCls, `${railCls}-start`, mergedClassNames.rail)}
|
||||
style={mergedStyles.rail}
|
||||
/>
|
||||
<span
|
||||
className={cls(`${prefixCls}-inner-text`, mergedClassNames.content)}
|
||||
style={{ ...innerStyle, ...mergedStyles.content }}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
<div
|
||||
className={cls(railCls, `${railCls}-end`, mergedClassNames.rail)}
|
||||
style={mergedStyles.rail}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
@ -38,13 +38,19 @@ group:
|
||||
| children | 嵌套的标题 | ReactNode | - | |
|
||||
| className | 分割线样式类 | string | - | |
|
||||
| dashed | 是否虚线 | boolean | false | |
|
||||
| variant | 分割线是虚线、点线还是实线 | `dashed` \| `dotted` \| `solid` | solid | 5.20.0 |
|
||||
| orientation | 分割线标题的位置 | `start` \| `end` \| `center` | `center` | `start` `end`: 5.24.0 |
|
||||
| orientationMargin | 标题和最近 left/right 边框之间的距离,去除了分割线,同时 `orientation` 不能为 `center`。如果传入 `string` 类型的数字且不带单位,默认单位是 px | string \| number | - | |
|
||||
| orientation | 水平或垂直类型 | `horizontal` \| `vertical` | `horizontal` | - |
|
||||
| ~~orientationMargin~~ | 标题和最近 left/right 边框之间的距离,去除了分割线,同时 `titlePlacement` 不能为 `center`。如果传入 `string` 类型的数字且不带单位,默认单位是 px | string \| number | - | |
|
||||
| plain | 文字是否显示为普通正文样式 | boolean | false | 4.2.0 |
|
||||
| style | 分割线样式对象 | CSSProperties | - | |
|
||||
| size | 间距大小,仅对水平布局有效 | `small` \| `middle` \| `large` | - | 5.25.0 |
|
||||
| type | 水平还是垂直类型 | `horizontal` \| `vertical` | `horizontal` | |
|
||||
| titlePlacement | 分割线标题的位置 | `start` \| `end` \| `center` | `center` | - |
|
||||
| ~~type~~ | 水平还是垂直类型 | `horizontal` \| `vertical` | `horizontal` | - |
|
||||
| variant | 分割线是虚线、点线还是实线 | `dashed` \| `dotted` \| `solid` | solid | 5.20.0 |
|
||||
| vertical | 是否垂直,和 orientation 同时配置以 orientation 优先 | boolean | false | - |
|
||||
|
||||
## Semantic DOM
|
||||
|
||||
<code src="./demo/_semantic.tsx" simplify="true"></code>
|
||||
|
||||
## 主题变量(Design Token)
|
||||
|
||||
|
@ -17,7 +17,7 @@ export interface ComponentToken {
|
||||
* @desc 文本与边缘距离,取值 0 ~ 1
|
||||
* @descEN Distance between text and edge, which should be a number between 0 and 1.
|
||||
*/
|
||||
orientationMargin: number;
|
||||
orientationMargin?: number;
|
||||
/**
|
||||
* @desc 纵向分割线的横向外间距
|
||||
* @descEN Horizontal margin of vertical Divider
|
||||
@ -73,12 +73,17 @@ const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject =>
|
||||
orientationMargin,
|
||||
verticalMarginInline,
|
||||
} = token;
|
||||
const railCls = `${componentCls}-rail`;
|
||||
|
||||
return {
|
||||
[componentCls]: {
|
||||
...resetComponent(token),
|
||||
borderBlockStart: `${unit(lineWidth)} solid ${colorSplit}`,
|
||||
|
||||
[railCls]: {
|
||||
borderBlockStart: `${unit(lineWidth)} solid ${colorSplit}`,
|
||||
},
|
||||
|
||||
// vertical
|
||||
'&-vertical': {
|
||||
position: 'relative',
|
||||
@ -110,33 +115,29 @@ const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject =>
|
||||
whiteSpace: 'nowrap',
|
||||
textAlign: 'center',
|
||||
borderBlockStart: `0 ${colorSplit}`,
|
||||
|
||||
'&::before, &::after': {
|
||||
position: 'relative',
|
||||
[`${railCls}-start, ${railCls}-end`]: {
|
||||
width: '50%',
|
||||
borderBlockStart: `${unit(lineWidth)} solid transparent`,
|
||||
// Chrome not accept `inherit` in `border-top`
|
||||
borderBlockStartColor: 'inherit',
|
||||
borderBlockEnd: 0,
|
||||
transform: 'translateY(50%)',
|
||||
content: "''",
|
||||
},
|
||||
},
|
||||
|
||||
[`&-horizontal${componentCls}-with-text-start`]: {
|
||||
'&::before': {
|
||||
[`${railCls}-start`]: {
|
||||
width: `calc(${orientationMargin} * 100%)`,
|
||||
},
|
||||
'&::after': {
|
||||
[`${railCls}-end`]: {
|
||||
width: `calc(100% - ${orientationMargin} * 100%)`,
|
||||
},
|
||||
},
|
||||
|
||||
[`&-horizontal${componentCls}-with-text-end`]: {
|
||||
'&::before': {
|
||||
[`${railCls}-start`]: {
|
||||
width: `calc(100% - ${orientationMargin} * 100%)`,
|
||||
},
|
||||
'&::after': {
|
||||
[`${railCls}-end`]: {
|
||||
width: `calc(${orientationMargin} * 100%)`,
|
||||
},
|
||||
},
|
||||
@ -152,10 +153,13 @@ const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject =>
|
||||
borderColor: colorSplit,
|
||||
borderStyle: 'dashed',
|
||||
borderWidth: `${unit(lineWidth)} 0 0`,
|
||||
[railCls]: {
|
||||
borderBlockStart: `${unit(lineWidth)} dashed ${colorSplit}`,
|
||||
},
|
||||
},
|
||||
|
||||
[`&-horizontal${componentCls}-with-text${componentCls}-dashed`]: {
|
||||
'&::before, &::after': {
|
||||
[`${railCls}-start, ${railCls}-end`]: {
|
||||
borderStyle: 'dashed none none',
|
||||
},
|
||||
},
|
||||
@ -172,6 +176,9 @@ const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject =>
|
||||
borderColor: colorSplit,
|
||||
borderStyle: 'dotted',
|
||||
borderWidth: `${unit(lineWidth)} 0 0`,
|
||||
[railCls]: {
|
||||
borderBlockStart: `${unit(lineWidth)} dotted ${colorSplit}`,
|
||||
},
|
||||
},
|
||||
|
||||
[`&-horizontal${componentCls}-with-text${componentCls}-dotted`]: {
|
||||
@ -195,11 +202,11 @@ const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject =>
|
||||
|
||||
[`&-horizontal${componentCls}-with-text-start${componentCls}-no-default-orientation-margin-start`]:
|
||||
{
|
||||
'&::before': {
|
||||
[`${railCls}-start`]: {
|
||||
width: 0,
|
||||
},
|
||||
|
||||
'&::after': {
|
||||
[`${railCls}-end`]: {
|
||||
width: '100%',
|
||||
},
|
||||
|
||||
@ -210,11 +217,11 @@ const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject =>
|
||||
|
||||
[`&-horizontal${componentCls}-with-text-end${componentCls}-no-default-orientation-margin-end`]:
|
||||
{
|
||||
'&::before': {
|
||||
[`${railCls}-start`]: {
|
||||
width: '100%',
|
||||
},
|
||||
|
||||
'&::after': {
|
||||
[`${railCls}-end`]: {
|
||||
width: 0,
|
||||
},
|
||||
|
||||
|
@ -4218,7 +4218,7 @@ Array [
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>
|
||||
<p
|
||||
@ -4311,7 +4311,7 @@ Array [
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
/>
|
||||
<p
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Button, Drawer, Typography } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import SemanticPreview from '../../../.dumi/theme/common/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
|
@ -2271,7 +2271,7 @@ Array [
|
||||
style="display: none;"
|
||||
/>
|
||||
<div
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal"
|
||||
class="ant-divider css-var-test-id ant-divider-horizontal ant-divider-rail"
|
||||
role="separator"
|
||||
style="margin: 0px;"
|
||||
/>
|
||||
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { DeleteOutlined, DownOutlined, EditOutlined, SaveOutlined } from '@ant-design/icons';
|
||||
import { Dropdown, MenuProps, Space } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import SemanticPreview from '../../../.dumi/theme/common/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user