mirror of
https://github.com/ant-design/ant-design.git
synced 2025-08-06 16:06:28 +08:00
commit
fb5c942925
76
.cursorrules
Normal file
76
.cursorrules
Normal file
@ -0,0 +1,76 @@
|
||||
## 项目背景
|
||||
|
||||
这是 ant-design/ant-design(antd)的源代码仓库,是一个 React 组件库,发布为 npm 包 antd 。
|
||||
|
||||
## 编码规范
|
||||
|
||||
- 使用 TypeScript 和 React 书写
|
||||
- 兼容 React 16 ~ 19 版本
|
||||
- 使用 @ant-design/cssinjs 书写 css
|
||||
- 使用 @ant-design/icons 图标库
|
||||
- 使用函数式组件和 hooks,避免类组件
|
||||
- 尽可能使用提前返回(early returns)以提高代码的可读性
|
||||
- 避免引入新的依赖,严控打包体积
|
||||
- demo 代码尽可能简洁,避免冗余代码,方便用户复制到应用项目里直接可用
|
||||
- 兼容 chrome 80+ 浏览器
|
||||
- 修改时请保持向下兼容,避免制造 break change
|
||||
|
||||
## 测试要求
|
||||
|
||||
- 使用 Jest 和 React Testing Library 编写单元测试
|
||||
- 对 UI 组件使用快照测试 (Snapshot Testing)
|
||||
- 测试覆盖率要求 100%
|
||||
|
||||
# 文档规范
|
||||
|
||||
- 提供中英文两个版本
|
||||
- 新的属性需要声明可用的版本号
|
||||
- 属性命名符合 antd 的 API 命名规则:https://github.com/ant-design/ant-design/wiki/API-Naming-rules
|
||||
|
||||
## Changelog 规范
|
||||
|
||||
- 在 CHANGELOG.en-US.md 和 CHANGELOG.zh-CN.md 书写每个版本的变更
|
||||
- 对用户使用上无感知的改动建议(文档修补、微小的样式优化、代码风格重构等等)不要提及,保持 CHANGELOG 的内容有效性。
|
||||
- 用面向开发者的角度和叙述方式撰写 CHANGELOG,不描述修复细节,描述问题和对开发者的影响;描述用户的原始问题,而非你的解决方式。
|
||||
* 例子一
|
||||
bad: 修复组件 Typography 的 dom 结构问题。
|
||||
good: 重构并简化了 List Item 的 dom 结构,并且修复了 Item 中内容空格丢失的问题。
|
||||
* 例子二
|
||||
bad: 修复 lib 下样式文件路径问题。
|
||||
good: 修复部分组件样式丢失的问题。
|
||||
- 新增属性时,建议用易于理解的语言补充描述用户可以感知的变化。(例如,新增 onCellClick 属性,可以定义单元格点击事件)
|
||||
- 尽量给出原始的 PR 链接,社区提交的 PR 改动加上提交者的链接。
|
||||
- 底层模块升级中间版本要去 rc-component 里找到改动,给出变动说明。
|
||||
- 建议参考之前版本的日志写法
|
||||
- 将同组件的改动放在一起,内容子级缩进。
|
||||
- 每一个改动前加 emoji 增加更新日志的可读性和生动性,可选 emoji 参考:
|
||||
- 🐞 Bug 修复
|
||||
- 💄 样式更新或 token 更新
|
||||
- 🆕 新增特性,新增属性
|
||||
- 🔥 极其值得关注的新增特性
|
||||
- 🇺🇸🇨🇳🇬🇧 国际化改动,注意这里直接用对应国家/地区的旗帜。
|
||||
- 📖 📝 文档或网站改进
|
||||
- ✅ 新增或更新测试用例
|
||||
- 🛎 更新警告/提示信息
|
||||
- ⌨️ ♿ 可访问性增强
|
||||
- 🗑 废弃或移除
|
||||
- 🛠 重构或工具链优化
|
||||
- ⚡️ 性能提升
|
||||
|
||||
## 实现要求
|
||||
|
||||
你是一名资深的前端开发工程师,同时也是 React、Ant Design、TypeScript、HTML、CSS 的专家。你思维缜密,能够给出细致入微的答案,并且在逻辑推理方面表现出色。你会谨慎地提供准确、真实、深思熟虑的答案,并且擅长逻辑推理。
|
||||
|
||||
- 严格遵循用户的需求,逐字逐句完成。
|
||||
- 首先逐步思考——用伪代码详细描述你要构建的内容的计划。
|
||||
- 确认后,再编写代码!
|
||||
- 始终编写正确、符合最佳实践、遵循 DRY 原则(不要重复自己)、无错误、功能齐全且可运行的代码。
|
||||
- 注重代码的易读性和可维护性。
|
||||
- 非常关注代码压缩后的体积。
|
||||
- 全面实现所有请求的功能。
|
||||
- 不留任何待办事项、占位符或缺失的部分。
|
||||
- 确保代码完整!彻底验证最终结果。
|
||||
- 包含所有必要的导入,并确保关键组件的命名得当。
|
||||
- 简洁明了,尽量减少其他冗长的说明。
|
||||
- 如果你认为可能没有正确的答案,请明确说明。
|
||||
- 如果你不知道答案,请坦诚说明,而不是猜测。
|
@ -1,6 +1,6 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import type { MenuProps } from 'antd';
|
||||
import { Space, Tag, version } from 'antd';
|
||||
import { Flex, Tag, version } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import classnames from 'classnames';
|
||||
import { useFullSidebarData, useSidebarData } from 'dumi';
|
||||
@ -25,6 +25,7 @@ const getTagColor = (val?: string) => {
|
||||
if (val?.toUpperCase() === 'DEPRECATED') {
|
||||
return 'red';
|
||||
}
|
||||
return 'success';
|
||||
};
|
||||
|
||||
const useStyle = createStyles(({ css, token }) => ({
|
||||
@ -61,13 +62,13 @@ const MenuItemLabelWithTag: React.FC<MenuItemLabelProps> = (props) => {
|
||||
if (!before && !after) {
|
||||
return (
|
||||
<Link to={`${link}${search}`} className={classnames(className, { [styles.link]: tag })}>
|
||||
<Space>
|
||||
<Flex justify="flex-start" align="center" gap="small">
|
||||
<span>{title}</span>
|
||||
{subtitle && <span className={styles.subtitle}>{subtitle}</span>}
|
||||
</Space>
|
||||
</Flex>
|
||||
{tag && (
|
||||
<Tag bordered={false} className={classnames(styles.tag)} color={getTagColor(tag)}>
|
||||
{tag.replace('VERSION', version)}
|
||||
{tag.replace(/VERSION/i, version)}
|
||||
</Tag>
|
||||
)}
|
||||
</Link>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { LinkOutlined, QuestionCircleOutlined, RightOutlined } from '@ant-design/icons';
|
||||
import { ConfigProvider, Popover, Table, Typography } from 'antd';
|
||||
import { ConfigProvider, Flex, Popover, Table, Typography } from 'antd';
|
||||
import { createStyles, css, useTheme } from 'antd-style';
|
||||
import { getDesignToken } from 'antd-token-previewer';
|
||||
import tokenMeta from 'antd/es/version/token-meta.json';
|
||||
@ -61,16 +61,15 @@ const useStyle = createStyles(({ token }) => ({
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
line-height: 40px;
|
||||
gap: ${token.marginXS}px;
|
||||
`,
|
||||
arrowIcon: css`
|
||||
font-size: ${token.fontSizeLG}px;
|
||||
margin-inline-end: ${token.marginXS}px;
|
||||
& svg {
|
||||
transition: all ${token.motionDurationSlow};
|
||||
}
|
||||
`,
|
||||
help: css`
|
||||
margin-inline-start: ${token.marginXS}px;
|
||||
font-size: ${token.fontSizeSM}px;
|
||||
font-weight: normal;
|
||||
color: #999;
|
||||
@ -78,6 +77,10 @@ const useStyle = createStyles(({ token }) => ({
|
||||
color: #999;
|
||||
}
|
||||
`,
|
||||
tokenTitle: css`
|
||||
font-size: ${token.fontSizeLG}px;
|
||||
font-weight: bold;
|
||||
`,
|
||||
}));
|
||||
|
||||
interface SubTokenTableProps {
|
||||
@ -153,15 +156,17 @@ const SubTokenTable: React.FC<SubTokenTableProps> = (props) => {
|
||||
<>
|
||||
<div className={styles.tableTitle} onClick={() => setOpen(!open)}>
|
||||
<RightOutlined className={styles.arrowIcon} rotate={open ? 90 : 0} />
|
||||
<h3>
|
||||
<Flex className={styles.tokenTitle} gap="small" justify="flex-start" align="center">
|
||||
{title}
|
||||
<Popover
|
||||
title={null}
|
||||
destroyTooltipOnHide
|
||||
styles={{ root: { width: 400 } }}
|
||||
content={
|
||||
<Typography>
|
||||
{/* <SourceCode lang="jsx">{code}</SourceCode> */}
|
||||
<pre style={{ fontSize: 12 }}>{code}</pre>
|
||||
<pre dir="ltr" style={{ fontSize: 12 }}>
|
||||
<code dir="ltr">{code}</code>
|
||||
</pre>
|
||||
<a href={helpLink} target="_blank" rel="noreferrer">
|
||||
<LinkOutlined style={{ marginInlineEnd: 4 }} />
|
||||
{helpText}
|
||||
@ -174,7 +179,7 @@ const SubTokenTable: React.FC<SubTokenTableProps> = (props) => {
|
||||
{helpText}
|
||||
</span>
|
||||
</Popover>
|
||||
</h3>
|
||||
</Flex>
|
||||
</div>
|
||||
{open && (
|
||||
<ConfigProvider theme={{ token: { borderRadius: 0 } }}>
|
||||
|
@ -118,7 +118,9 @@ const Footer: React.FC = () => {
|
||||
},
|
||||
{
|
||||
title: 'Pro Components',
|
||||
url: 'https://procomponents.ant.design',
|
||||
url: isZhCN
|
||||
? 'https://pro-components.antdigital.dev'
|
||||
: 'https://procomponents.ant.design',
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
|
@ -20,10 +20,27 @@ export type PickerLocale = {
|
||||
timePickerLocale: TimePickerLocale;
|
||||
} & AdditionalPickerLocaleProps;
|
||||
|
||||
/** @deprecated **Useless**. */
|
||||
export type AdditionalPickerLocaleProps = {
|
||||
/**
|
||||
* @deprecated **Invalid**, Please use `lang.fieldDateFormat` instead.
|
||||
* @see [Migration Guide](https://github.com/ant-design/ant-design/discussions/53011)
|
||||
*/
|
||||
dateFormat?: string;
|
||||
/**
|
||||
* @deprecated **Invalid**, Please use `lang.fieldDateTimeFormat` instead,
|
||||
* @see [Migration Guide](https://github.com/ant-design/ant-design/discussions/53011)
|
||||
*/
|
||||
dateTimeFormat?: string;
|
||||
/**
|
||||
* @deprecated **Invalid**, Please use `lang.fieldWeekFormat` instead,
|
||||
* @see [Migration Guide](https://github.com/ant-design/ant-design/discussions/53011)
|
||||
*/
|
||||
weekFormat?: string;
|
||||
/**
|
||||
* @deprecated **Invalid**, Please use `lang.fieldWeekFormat` instead,
|
||||
* @see [Migration Guide](https://github.com/ant-design/ant-design/discussions/53011)
|
||||
*/
|
||||
monthFormat?: string;
|
||||
};
|
||||
|
||||
|
@ -9,9 +9,6 @@ const locale: PickerLocale = {
|
||||
placeholder: 'اختيار التاريخ',
|
||||
rangePlaceholder: ['البداية', 'النهاية'],
|
||||
yearFormat: 'YYYY',
|
||||
dateFormat: 'D/M/YYYY',
|
||||
dayFormat: 'D',
|
||||
dateTimeFormat: 'DD/MM/YYYY HH:mm:ss',
|
||||
monthFormat: 'MMMM',
|
||||
monthBeforeYear: true,
|
||||
shortWeekDays: ['الأحد', 'الإثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
@ -34,10 +31,6 @@ const locale: PickerLocale = {
|
||||
timePickerLocale: {
|
||||
...TimePickerLocale,
|
||||
},
|
||||
dateFormat: 'DD-MM-YYYY',
|
||||
monthFormat: 'MM-YYYY',
|
||||
dateTimeFormat: 'DD-MM-YYYY HH:mm:ss',
|
||||
weekFormat: 'wo-YYYY',
|
||||
};
|
||||
|
||||
// All settings at:
|
||||
|
@ -16,10 +16,11 @@
|
||||
"yearSelect": "Choose a year",
|
||||
"decadeSelect": "Choose a decade",
|
||||
"yearFormat": "YYYY",
|
||||
"dateFormat": "M/D/YYYY",
|
||||
"dayFormat": "D",
|
||||
"dateTimeFormat": "M/D/YYYY HH:mm:ss",
|
||||
"fieldDateFormat": "M/D/YYYY",
|
||||
"cellDateFormat": "D",
|
||||
"fieldDateTimeFormat": "M/D/YYYY HH:mm:ss",
|
||||
"monthFormat": "MMMM",
|
||||
"fieldWeekFormat": "YYYY-wo",
|
||||
"monthBeforeYear": true,
|
||||
"previousMonth": "Previous month (PageUp)",
|
||||
"nextMonth": "Next month (PageDown)",
|
||||
@ -47,9 +48,5 @@
|
||||
},
|
||||
"timePickerLocale": {
|
||||
"placeholder": "Select time"
|
||||
},
|
||||
"dateFormat": "YYYY-MM-DD",
|
||||
"dateTimeFormat": "YYYY-MM-DD HH:mm:ss",
|
||||
"weekFormat": "YYYY-wo",
|
||||
"monthFormat": "YYYY-MM"
|
||||
}
|
||||
}
|
||||
|
@ -9,9 +9,6 @@ const locale: PickerLocale = {
|
||||
placeholder: 'Wybierz datę',
|
||||
rangePlaceholder: ['Data początkowa', 'Data końcowa'],
|
||||
yearFormat: 'YYYY',
|
||||
dateFormat: 'M/D/YYYY',
|
||||
dayFormat: 'D',
|
||||
dateTimeFormat: 'M/D/YYYY HH:mm:ss',
|
||||
monthFormat: 'MMMM',
|
||||
monthBeforeYear: true,
|
||||
shortWeekDays: ['Niedz', 'Pon', 'Wt', 'Śr', 'Czw', 'Pt', 'Sob'],
|
||||
|
@ -22,9 +22,6 @@ const locale: PickerLocale = {
|
||||
yearSelect: 'Selecionar ano',
|
||||
decadeSelect: 'Selecionar década',
|
||||
yearFormat: 'YYYY',
|
||||
dateFormat: 'D/M/YYYY',
|
||||
dayFormat: 'D',
|
||||
dateTimeFormat: 'D/M/YYYY HH:mm:ss',
|
||||
monthFormat: 'MMMM',
|
||||
monthBeforeYear: false,
|
||||
previousMonth: 'Mês anterior (PageUp)',
|
||||
|
@ -21,9 +21,6 @@ const locale: PickerLocale = {
|
||||
yearSelect: 'Izberite leto',
|
||||
decadeSelect: 'Izberite desetletje',
|
||||
yearFormat: 'YYYY',
|
||||
dateFormat: 'D.M.YYYY',
|
||||
dayFormat: 'D',
|
||||
dateTimeFormat: 'D.M.YYYY HH:mm:ss',
|
||||
monthFormat: 'MMMM',
|
||||
monthBeforeYear: true,
|
||||
previousMonth: 'Prejšnji mesec (PageUp)',
|
||||
|
@ -21,9 +21,7 @@ const datePickerLocale: PickerLocale = {
|
||||
yearSelect: 'Ընտրեք տարին',
|
||||
decadeSelect: 'Ընտրեք տասնամյակը',
|
||||
yearFormat: 'YYYY',
|
||||
dateFormat: 'DD/MM//YYYY',
|
||||
dayFormat: 'DD',
|
||||
dateTimeFormat: 'DD/MM//YYYY HH:mm:ss',
|
||||
monthBeforeYear: true,
|
||||
previousMonth: 'Անցած ամիս (PageUp)',
|
||||
nextMonth: 'Մյուս ամիս (PageDown)',
|
||||
|
@ -32,6 +32,11 @@ const localeValues: Locale = {
|
||||
triggerAsc: 'Artan düzende sırala',
|
||||
cancelSort: 'Sıralamayı kaldır',
|
||||
},
|
||||
Tour: {
|
||||
Next: 'Sonraki',
|
||||
Previous: 'Önceki',
|
||||
Finish: 'Bitir',
|
||||
},
|
||||
Modal: {
|
||||
okText: 'Tamam',
|
||||
cancelText: 'İptal',
|
||||
|
@ -277,7 +277,7 @@
|
||||
"open": "^10.1.0",
|
||||
"ora": "^8.1.0",
|
||||
"p-all": "^5.0.0",
|
||||
"package-manager-detector": "^0.2.8",
|
||||
"package-manager-detector": "^1.0.0",
|
||||
"pixelmatch": "^7.1.0",
|
||||
"pngjs": "^7.0.0",
|
||||
"prettier": "^3.4.1",
|
||||
|
@ -15,7 +15,7 @@ import { spawnSync } from 'child_process';
|
||||
import difference from 'lodash/difference';
|
||||
import open from 'open';
|
||||
import { select, input, checkbox, confirm } from '@inquirer/prompts';
|
||||
import { detectSync, resolveCommand } from 'package-manager-detector';
|
||||
import { getUserAgent, resolveCommand } from 'package-manager-detector';
|
||||
|
||||
const ROOT = path.resolve(__dirname, '../../');
|
||||
// ==================== 环境变量 ====================
|
||||
@ -36,7 +36,7 @@ const STORE_PATH = path.join(_VISUAL_STORE_PATH, GITHUB_OWNER, GITHUB_REPO);
|
||||
fs.ensureDirSync(STORE_PATH);
|
||||
const git = simpleGit(ROOT);
|
||||
const octokit = new Octokit({ auth: GITHUB_TOKEN });
|
||||
const packageManager = detectSync({ cwd: ROOT });
|
||||
const packageManager = getUserAgent();
|
||||
const components = fg.sync('components/*/index.ts[x]', { cwd: ROOT }).reduce((acc, file) => {
|
||||
const basePath = path.dirname(file);
|
||||
if (
|
||||
@ -109,7 +109,7 @@ async function getOssBranchHash(branch: string) {
|
||||
}
|
||||
|
||||
function runImageTests(args: string[]) {
|
||||
const { command, args: realArgs } = resolveCommand(packageManager!.agent, 'run', args)!;
|
||||
const { command, args: realArgs } = resolveCommand(packageManager!, 'run', args)!;
|
||||
spawnSync(command, realArgs, {
|
||||
stdio: 'inherit',
|
||||
env: {
|
||||
|
Loading…
Reference in New Issue
Block a user