Compare commits

..

16 Commits

Author SHA1 Message Date
lijianan
c27219b997 type: typeScript definition improvement 2026-02-16 15:21:53 +08:00
renovate[bot]
3b52894cf3 chore(deps): update dependency @eslint-react/eslint-plugin to v2.13.0 (#57004)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-15 09:35:38 +08:00
github-actions[bot]
ad9149ba24 chore: upgrade deps (#57003)
Co-authored-by: afc163 <507615+afc163@users.noreply.github.com>
2026-02-15 09:14:48 +08:00
thinkasany
95f032bc3d refactor: turn on react-naming-convention/use-state (#56998)
Co-authored-by: 遇见同学 <1875694521@qq.com>
2026-02-14 11:50:16 +08:00
lijianan
5dfaf14db7 feat(a11y): apply prefers-reduced-motion handling for transitions (#56902)
* up

* up

* update

* update

---------

Co-authored-by: 遇见同学 <1875694521@qq.com>
2026-02-14 11:14:18 +08:00
遇见同学
5ad1ecd723 chore: remove duplicate classNames example code (#56994)
Co-authored-by: thinkasany <480968828@qq.com>
2026-02-14 10:57:07 +08:00
遇见同学
9b03f7ae6c chore(transfer): code style optimization (#56993)
* fix(Transfer): improve RTL support and type safety for item selection

* chore: adj

---------

Co-authored-by: thinkasany <480968828@qq.com>
2026-02-14 10:51:35 +08:00
遇见同学
852ed686d2 docs: remove duplicate demo classNames (#56991)
* docs:  remove unused classNames demo for Modal component

* chore: update

* chore: rm
2026-02-14 10:22:57 +08:00
lijianan
47159dd3b2 chore: code style optimization (#56990) 2026-02-14 10:19:48 +08:00
lijianan
70f564603b chore: unify coding style (#56989)
* chore: 统一代码风格

* update
2026-02-14 09:32:30 +08:00
luozz
d534dd8b17 fix: issue with echoing when the value of Select is an empty string. … (#56966)
* fix: issue with echoing when the value of Select is an empty string. #56960

* ci: add select's demo when defaultValue is empty

* ci: trigger

* test: update snap

* chore: upgrade deps (#56977)

Co-authored-by: afc163 <507615+afc163@users.noreply.github.com>

* test: update demo for image diff (#56976)

* chore: update @rc-component/select to v1.6.7 and update debug demo

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: update Input component snapshots

Add updated snapshot tests for input component demo and demo-extend.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: bump deps

* chore: trigger CI re-run

* chore: format

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* ci: resolving conflicts.

* chore(deps): update @rc-component/select to 1.6.9

* test: update snap

---------

Co-authored-by: 罗忠泽 <victor.luo@spotterio.com>
Co-authored-by: thinkasany <480968828@qq.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: afc163 <507615+afc163@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 16:13:49 +08:00
yanyu
d271104014 fix(Progress): prevent animation overflow when status is set to active (#56972)
Co-authored-by: thinkasany <480968828@qq.com>
2026-02-13 14:31:34 +08:00
二货爱吃白萝卜
6915342818 test: update demo for image diff (#56976)
* chore: update @rc-component/select to v1.6.7 and update debug demo

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: update Input component snapshots

Add updated snapshot tests for input component demo and demo-extend.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: bump deps

* chore: trigger CI re-run

* chore: format

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:41:03 +08:00
github-actions[bot]
956c1d1b51 chore: upgrade deps (#56977)
Co-authored-by: afc163 <507615+afc163@users.noreply.github.com>
2026-02-13 09:44:05 +08:00
高艳兵
6e993d2ef8 fix: correct mismatched JSDoc parameter names in plugin files (#56969) 2026-02-12 20:54:15 +08:00
luozz
a46cd9d8ba fix: TreeSelect's multi-line text will cause CheckBox compression. #56957 (#56961)
Co-authored-by: 罗忠泽 <victor.luo@spotterio.com>
2026-02-12 14:59:49 +08:00
142 changed files with 997 additions and 1818 deletions

View File

@@ -31,7 +31,7 @@ export const useIssueCount = (options: UseIssueCountOptions) => {
// Note: current query only filters by title keywords. Filtering by component name can be added later if needed.
const searchUrl = useMemo(() => {
const tokens = (titleKeywords || []).filter(Boolean).map((k) => encodeURIComponent(String(k)));
const tokens = (titleKeywords || []).filter(Boolean).map<string>(encodeURIComponent);
const orExpr = tokens.length > 0 ? tokens.join('%20OR%20') : '';
const titlePart = orExpr ? `in:title+(${orExpr})` : 'in:title';
const q = `repo:${repo}+is:issue+is:open+${titlePart}`;
@@ -45,7 +45,7 @@ export const useIssueCount = (options: UseIssueCountOptions) => {
const issueNewUrl = `https://github.com/${repo}/issues/new/choose`;
const issueSearchUrl = useMemo(() => {
const keywords = (titleKeywords || []).filter(Boolean).map((k) => String(k));
const keywords = (titleKeywords || []).filter(Boolean).map<string>(String);
const groupExpr =
keywords.length > 0 ? `(${keywords.map((k) => `is:issue in:title ${k}`).join(' OR ')})` : '';
const qRaw = `is:open ${groupExpr}`.trim();

View File

@@ -113,8 +113,10 @@ const RecommendItem: React.FC<RecommendItemProps> = (props) => {
const [mousePosition, setMousePosition] = React.useState<[number, number]>([0, 0]);
const [transMousePosition, setTransMousePosition] = React.useState<[number, number]>([0, 0]);
const onMouseMove = (e: React.MouseEvent<HTMLAnchorElement>) => {
if (!cardRef.current) return;
const onMouseMove: React.MouseEventHandler<HTMLAnchorElement> = (e) => {
if (!cardRef.current) {
return;
}
const rect = cardRef.current.getBoundingClientRect();
const x = e.clientX - rect.left;

View File

@@ -29,13 +29,13 @@ const VersionUpgradeModal = () => {
const [locale, lang] = useLocale(locales);
const { pathname } = useLocation();
const [open, updateOpen] = React.useState(false);
const [open, setOpen] = React.useState(false);
const isCN = lang === 'cn' || utils.isZhCN(pathname);
function handleClose() {
localStorage.setItem(STORAGE_KEY, Date.now().toString());
updateOpen(false);
setOpen(false);
}
React.useEffect(() => {
@@ -48,7 +48,7 @@ const VersionUpgradeModal = () => {
if (!lastTime) {
const timer = setTimeout(() => {
updateOpen(true);
setOpen(true);
}, 1000);
return () => {

View File

@@ -101,7 +101,9 @@ let TOKEN_CACHE: { meta: TokenMeta; data: TokenData } | null | undefined;
*/
function readJsonIfExists<T>(abs: string): T | null {
try {
if (!fs.existsSync(abs)) return null;
if (!fs.existsSync(abs)) {
return null;
}
return JSON.parse(fs.readFileSync(abs, 'utf-8')) as T;
} catch {
return null;
@@ -144,7 +146,9 @@ function replaceSemanticDomSection(md: string, context: ContentFilterContext) {
// 从文档路径推断组件路径(用于生成链接)
// 例如components/card/index.en-US.md -> components/card/semantic.md
const componentPathMatch = context.file.match(/components\/([^/]+)\//);
if (!componentPathMatch) return md;
if (!componentPathMatch) {
return md;
}
const componentName = componentPathMatch[1];
const isZhCN = /-cn\.md$/i.test(context.file) || /\.zh-CN\.md$/i.test(context.file);
@@ -154,10 +158,14 @@ function replaceSemanticDomSection(md: string, context: ContentFilterContext) {
return md.replace(/<code[^>]*_semantic[^>]*>.*?<\/code>/g, (match) => {
// 从匹配的标签中提取文件名
const demoIndex = match.indexOf('./demo/');
if (demoIndex === -1) return match;
if (demoIndex === -1) {
return match;
}
const start = demoIndex + './demo/'.length;
const end = match.indexOf('"', start);
if (end === -1) return match;
if (end === -1) {
return match;
}
const semanticFile = match.substring(start, end);
// 生成对应的 semantic.md 文件名_semantic.tsx -> semantic.md, _semantic_meta.tsx -> semantic_meta.md
const semanticMdFileName = semanticFile
@@ -180,7 +188,9 @@ function getMaxBacktickRun(text: string) {
let m: RegExpExecArray | null = re.exec(text);
while (m) {
if (m[0].length > max) max = m[0].length;
if (m[0].length > max) {
max = m[0].length;
}
m = re.exec(text);
}
return max;
@@ -244,7 +254,9 @@ function antdCodeAppend(docFileAbs: string, src: string): string {
'i',
);
const match = demoMd.match(re);
if (!match) return demoMd.trim();
if (!match) {
return demoMd.trim();
}
return (match[2] ?? '').trim();
}
@@ -255,7 +267,7 @@ function antdCodeAppend(docFileAbs: string, src: string): string {
*
* @param md - 原始 markdown 内容
* @param docFileAbs - 文档文件的绝对路径,用于解析相对路径和检测语言
* @param enablePickLocaleBlock - 是否启用多语言块提取,可以是布尔值或函数,默认为 true
* @param codeAppend - 代码追加函数:在替换 <code src> 标签时,用于追加额外的内容(如 demo 描述信息)
* @returns 替换后的 markdown 内容
*/
function replaceCodeSrcToMarkdown(
@@ -305,8 +317,9 @@ function replaceCodeSrcToMarkdown(
* @returns token 元数据和数据对象,如果文件不存在则返回 null
*/
function loadTokenFromRepo(api: IApi) {
if (TOKEN_CACHE !== undefined) return TOKEN_CACHE;
if (TOKEN_CACHE !== undefined) {
return TOKEN_CACHE;
}
const cwd = api.paths.cwd;
const metaPath = path.join(cwd, 'components', 'version', 'token-meta.json');
const dataPath = path.join(cwd, 'components', 'version', 'token.json');
@@ -345,9 +358,15 @@ function escapeMdCell(v: unknown) {
* @returns 规范化后的字符串null/undefined 返回空字符串
*/
function normalizeValue(v: unknown) {
if (v === undefined || v === null) return '';
if (typeof v === 'string') return v.trim();
if (typeof v === 'number' || typeof v === 'boolean') return String(v);
if (v === undefined || v === null) {
return '';
}
if (typeof v === 'string') {
return v.trim();
}
if (typeof v === 'number' || typeof v === 'boolean') {
return String(v);
}
try {
return JSON.stringify(v);
} catch {
@@ -369,7 +388,9 @@ function normalizeValue(v: unknown) {
*/
function replaceComponentTokenTable(md: string, context: ContentFilterContext) {
const tokens = loadTokenFromRepo(context.api);
if (!tokens) return md;
if (!tokens) {
return md;
}
const { meta: tokenMeta, data: tokenData } = tokens;
const locale = detectDocLocale(context.file);
@@ -398,7 +419,9 @@ function replaceComponentTokenTable(md: string, context: ContentFilterContext) {
return md.replace(re, (full, componentProp) => {
const comp = String(componentProp || '').trim();
if (!comp) return full;
if (!comp) {
return full;
}
const comps = comp
.split(',')
@@ -474,7 +497,9 @@ function replaceComponentTokenTable(md: string, context: ContentFilterContext) {
}
// 如果没有生成任何内容,则保留原标签
if (!out.length) return full;
if (!out.length) {
return full;
}
// 返回生成的 markdown 表格,前后添加换行确保格式正确
return `\n\n${out.join('\n').trim()}\n\n`;
});
@@ -489,8 +514,12 @@ function replaceComponentTokenTable(md: string, context: ContentFilterContext) {
* @param api - Dumi API 实例,用于获取输出路径等配置
*/
function emitRawMd(api: IApi) {
if (process.env.NODE_ENV !== 'production') return;
if (RAW_MD_EMITTED) return;
if (process.env.NODE_ENV !== 'production') {
return;
}
if (RAW_MD_EMITTED) {
return;
}
RAW_MD_EMITTED = true;
const outRoot = api.paths.absOutputPath;
@@ -499,7 +528,9 @@ function emitRawMd(api: IApi) {
try {
const { absPath, file } = route;
const relPath = absPath.replace(/^\//, '');
if (!relPath || !fs.existsSync(file)) return;
if (!relPath || !fs.existsSync(file)) {
return;
}
// 应用路由过滤器
if (PLUGIN_OPTIONS.routeFilter && !PLUGIN_OPTIONS.routeFilter(route)) {
@@ -556,7 +587,6 @@ function emitRawMd(api: IApi) {
* 2. 在 HTML 文件导出阶段输出处理后的 raw markdown 文件
*
* @param api - Dumi API 实例
* @param options - 插件配置选项
*/
export default function rawMdPlugin(api: IApi) {
// 注册配置键,允许用户在配置中使用 rawMd 键

View File

@@ -19,8 +19,8 @@ function extractSemantics(objContent: string): Record<string, string> {
}
/**
* 从 _semantic*.tsx 文件中提取语义信息
* @param semanticFile - _semantic*.tsx 文件的绝对路径
* 从 _semantic*.tsx 文件内容中提取语义信息
* @param content - _semantic*.tsx 文件的文件内容字符串
* @returns 包含中文和英文语义描述的对象,失败返回 null
*/
function extractLocaleInfoFromContent(content: string): {
@@ -29,14 +29,20 @@ function extractLocaleInfoFromContent(content: string): {
} | null {
// 匹配 locales 对象定义
const localesMatch = content.match(/const locales = \{([\s\S]*?)\};/);
if (!localesMatch) return null;
if (!localesMatch) {
return null;
}
// 提取中文和英文的语义描述
const cnMatch = content.match(/cn:\s*\{([\s\S]*?)\},?\s*en:/);
if (!cnMatch) return null;
if (!cnMatch) {
return null;
}
const enMatch = content.match(/en:\s*\{([\s\S]*?)\}\s*[,;]/);
if (!enMatch) return null;
if (!enMatch) {
return null;
}
const cnContent = cnMatch[1];
const enContent = enMatch[1];
@@ -44,7 +50,9 @@ function extractLocaleInfoFromContent(content: string): {
const cnSemantics = extractSemantics(cnContent);
const enSemantics = extractSemantics(enContent);
if (Object.keys(cnSemantics).length === 0) return null;
if (Object.keys(cnSemantics).length === 0) {
return null;
}
return { cn: cnSemantics, en: enSemantics };
}
@@ -60,7 +68,9 @@ function resolveTemplateFilePath(semanticFile: string, importPath: string): stri
path.join(basePath, 'index.ts'),
];
for (const candidate of candidates) {
if (fs.existsSync(candidate)) return candidate;
if (fs.existsSync(candidate)) {
return candidate;
}
}
return null;
}
@@ -72,7 +82,9 @@ function parseTemplateUsage(content: string): Array<{ componentName: string; imp
for (const match of content.matchAll(importRegex)) {
const importClause = match[1].trim();
const importPath = match[2].trim();
if (!importPath.startsWith('.')) continue;
if (!importPath.startsWith('.')) {
continue;
}
const componentNames: string[] = [];
if (importClause.startsWith('{')) {
@@ -119,7 +131,9 @@ function parseTemplateUsage(content: string): Array<{ componentName: string; imp
// 解析 ignoreSemantics 属性值
function parseIgnoreSemantics(propsString: string): string[] {
const ignoreMatch = propsString.match(/ignoreSemantics\s*=\s*\{([\s\S]*?)\}/);
if (!ignoreMatch) return [];
if (!ignoreMatch) {
return [];
}
const ignoreContent = ignoreMatch[1];
return Array.from(ignoreContent.matchAll(/['"]([^'"]+)['"]/g)).map((match) => match[1]);
}
@@ -127,8 +141,12 @@ function parseIgnoreSemantics(propsString: string): string[] {
// 解析 singleOnly 属性值
function parseSingleOnly(propsString: string): boolean {
const singleOnlyMatch = propsString.match(/singleOnly(\s*=\s*\{?([^}\s]+)\}?)?/);
if (!singleOnlyMatch) return false;
if (!singleOnlyMatch[1]) return true;
if (!singleOnlyMatch) {
return false;
}
if (!singleOnlyMatch[1]) {
return true;
}
const value = singleOnlyMatch[2];
return value !== 'false';
}
@@ -136,7 +154,9 @@ function parseSingleOnly(propsString: string): boolean {
// 抽取模板组件 JSX 的属性字符串
function extractTemplateProps(content: string, componentName: string): string {
const start = content.indexOf(`<${componentName}`);
if (start === -1) return '';
if (start === -1) {
return '';
}
let index = start + componentName.length + 1;
const propsStart = index;
let braceDepth = 0;
@@ -164,7 +184,9 @@ function extractTemplateProps(content: string, componentName: string): string {
}
if (ch === '}') {
if (braceDepth > 0) braceDepth -= 1;
if (braceDepth > 0) {
braceDepth -= 1;
}
continue;
}
@@ -198,15 +220,21 @@ function extractSemanticInfoFromTemplate(
content: string,
): { cn: Record<string, string>; en: Record<string, string> } | null {
const templates = parseTemplateUsage(content);
if (templates.length === 0) return null;
if (templates.length === 0) {
return null;
}
for (const template of templates) {
const templatePath = resolveTemplateFilePath(semanticFile, template.importPath);
if (!templatePath) continue;
if (!templatePath) {
continue;
}
const templateContent = fs.readFileSync(templatePath, 'utf-8');
const templateLocales = extractLocaleInfoFromContent(templateContent);
if (!templateLocales) continue;
if (!templateLocales) {
continue;
}
const propsString = extractTemplateProps(content, template.componentName);
const ignoreSemantics = parseIgnoreSemantics(propsString);
@@ -235,11 +263,15 @@ function extractSemanticInfo(semanticFile: string): {
en: Record<string, string>;
} | null {
try {
if (!fs.existsSync(semanticFile)) return null;
if (!fs.existsSync(semanticFile)) {
return null;
}
const content = fs.readFileSync(semanticFile, 'utf-8');
const localeInfo = extractLocaleInfoFromContent(content);
if (localeInfo) return localeInfo;
if (localeInfo) {
return localeInfo;
}
return extractSemanticInfoFromTemplate(semanticFile, content);
} catch (error) {
@@ -324,9 +356,12 @@ function getComponentHTMLSnapshot(semanticFile: string, cwd: string): string | n
try {
const relativePath = path.relative(cwd, semanticFile);
const pathMatch = relativePath.match(/^components\/([^/]+)\/demo\/([^/]+)\.tsx$/);
if (!pathMatch) return null;
if (!pathMatch) {
return null;
}
const [, componentName, fileName] = pathMatch;
const snapshotPath = path.join(
cwd,
'components',
@@ -336,7 +371,9 @@ function getComponentHTMLSnapshot(semanticFile: string, cwd: string): string | n
'demo-semantic.test.tsx.snap',
);
if (!fs.existsSync(snapshotPath)) return null;
if (!fs.existsSync(snapshotPath)) {
return null;
}
const snapshotContent = fs.readFileSync(snapshotPath, 'utf-8');
// 匹配快照 keyexports[`renders components/button/demo/_semantic.tsx correctly 1`] = `...`;
@@ -345,7 +382,9 @@ function getComponentHTMLSnapshot(semanticFile: string, cwd: string): string | n
`exports\\[\\\`[^\\\`]*${snapshotKeyPattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}[^\\\`]*\\\`\\]\\s*=\\s*\\\`([\\s\\S]*?)\\\`;`,
);
const snapshotMatch = snapshotContent.match(regex);
if (!snapshotMatch) return null;
if (!snapshotMatch) {
return null;
}
let html = snapshotMatch[1].trim();
@@ -415,8 +454,12 @@ function getComponentHTMLSnapshot(semanticFile: string, cwd: string): string | n
* @param api - Dumi API 实例
*/
function emitSemanticMd(api: IApi) {
if (process.env.NODE_ENV !== 'production') return;
if (SEMANTIC_MD_EMITTED) return;
if (process.env.NODE_ENV !== 'production') {
return;
}
if (SEMANTIC_MD_EMITTED) {
return;
}
SEMANTIC_MD_EMITTED = true;
const outRoot = api.paths.absOutputPath;

View File

@@ -343,7 +343,7 @@ export const prepareComponentToken: GetDefaultToken<'ComponentName'> = (token) =
});
// 3. 样式生成函数
const genComponentStyle: GenerateStyle<ComponentToken> = (token) => {
const genComponentStyle: GenerateStyle<ComponentToken, CSSObject> = (token) => {
const { componentCls } = token;
return {
[componentCls]: {
@@ -767,9 +767,14 @@ export const prepareComponentToken: GetDefaultToken<'ComponentName'> = (token) =
componentPadding: token.paddingXS,
});
const genComponentStyle: GenerateStyle<ComponentToken> = (token) => {
const genComponentStyle: GenerateStyle<ComponentToken, CSSObject> = (token) => {
const { componentCls, fontSize, padding } = token;
return { [componentCls]: { fontSize, padding } };
return {
[componentCls]: {
fontSize,
padding,
},
};
};
export default genStyleHooks(
@@ -837,10 +842,8 @@ export default genStyleHooks(
- **组件名不用反引号**:组件名(如 Modal、Drawer、Button、Upload.Dragger不使用 `` ` `` 包裹属性名、API、token 等仍用反引号
3. **中英文条目句式**
- **中文**`Emoji 组件名 动词/描述 … [#PR](链接) [@贡献者]`
例:`🐞 Button 修复暗色主题下 \`color\` 的 \`hover\` 与 \`active\` 状态颜色相反的问题。`
- **英文**`Emoji 动词 组件名 描述 … [#PR](链接) [@贡献者]`(动词在前,如 Fix / Add / Support / Remove / Disable / Refactor / Improve / Change
例:`🐞 Fix Button reversed \`hover\` and \`active\` colors for \`color\` in dark theme.`
- **中文**`Emoji 组件名 动词/描述 … [#PR](链接) [@贡献者]` 例:`🐞 Button 修复暗色主题下 \`color\` 的 \`hover\` 与 \`active\` 状态颜色相反的问题。`
- **英文**`Emoji 动词 组件名 描述 … [#PR](链接) [@贡献者]`(动词在前,如 Fix / Add / Support / Remove / Disable / Refactor / Improve / Change例:`🐞 Fix Button reversed \`hover\` and \`active\` colors for \`color\` in dark theme.`
4. **分组逻辑**
- **多项改动**:同一组件有 2 条及以上改动时,使用 `- 组件名` 作为分类标题(不加粗),具体条目缩进排列,子条中仍须包含组件名

View File

@@ -34,7 +34,7 @@ const WaveEffect: React.FC<WaveEffectProps> = (props) => {
const [varName] = genCssVar(rootPrefixCls, 'wave');
// ===================== Effect =====================
const [color, setWaveColor] = React.useState<string | null>(null);
const [waveColor, setWaveColor] = React.useState<string | null>(null);
const [borderRadius, setBorderRadius] = React.useState<number[]>([]);
const [left, setLeft] = React.useState(0);
const [top, setTop] = React.useState(0);
@@ -50,8 +50,8 @@ const WaveEffect: React.FC<WaveEffectProps> = (props) => {
borderRadius: borderRadius.map((radius) => `${radius}px`).join(' '),
};
if (color) {
waveStyle[varName('color')] = color;
if (waveColor) {
waveStyle[varName('color')] = waveColor;
}
function syncPos() {

View File

@@ -1,3 +1,5 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { genComponentStyleHook } from '../../theme/internal';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genCssVar } from '../../theme/util/genStyleUtils';
@@ -7,7 +9,7 @@ export interface ComponentToken {}
export interface WaveToken extends FullToken<'Wave'> {}
const genWaveStyle: GenerateStyle<WaveToken> = (token) => {
const genWaveStyle: GenerateStyle<WaveToken, CSSObject> = (token) => {
const {
componentCls,
colorPrimary,

View File

@@ -1,5 +1,3 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks } from '../../theme/internal';
@@ -16,7 +14,7 @@ interface AffixToken extends FullToken<'Affix'> {
}
// ============================== Shared ==============================
const genSharedAffixStyle: GenerateStyle<AffixToken> = (token): CSSObject => {
const genSharedAffixStyle: GenerateStyle<AffixToken> = (token) => {
const { componentCls } = token;
return {
[componentCls]: {

View File

@@ -43,7 +43,7 @@ const genAlertTypeStyle = (
},
});
export const genBaseStyle: GenerateStyle<AlertToken> = (token: AlertToken): CSSObject => {
export const genBaseStyle: GenerateStyle<AlertToken, CSSObject> = (token) => {
const {
componentCls,
motionDurationSlow: duration,
@@ -142,7 +142,7 @@ export const genBaseStyle: GenerateStyle<AlertToken> = (token: AlertToken): CSSO
};
};
export const genTypeStyle: GenerateStyle<AlertToken> = (token: AlertToken): CSSObject => {
export const genTypeStyle: GenerateStyle<AlertToken, CSSObject> = (token) => {
const {
componentCls,
@@ -191,7 +191,7 @@ export const genTypeStyle: GenerateStyle<AlertToken> = (token: AlertToken): CSSO
};
};
export const genActionStyle: GenerateStyle<AlertToken> = (token: AlertToken): CSSObject => {
export const genActionStyle: GenerateStyle<AlertToken, CSSObject> = (token) => {
const {
componentCls,
iconCls,

View File

@@ -1,3 +1,4 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { unit } from '@ant-design/cssinjs';
import { resetComponent, textEllipsis } from '../../style';
@@ -45,7 +46,7 @@ interface AnchorToken extends FullToken<'Anchor'> {
}
// ============================== Shared ==============================
const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token) => {
const genSharedAnchorStyle: GenerateStyle<AnchorToken, CSSObject> = (token) => {
const {
componentCls,
holderOffsetBlock,
@@ -131,7 +132,7 @@ const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token) => {
};
};
const genSharedAnchorHorizontalStyle: GenerateStyle<AnchorToken> = (token) => {
const genSharedAnchorHorizontalStyle: GenerateStyle<AnchorToken, CSSObject> = (token) => {
const { componentCls, motionDurationSlow, lineWidthBold, colorPrimary } = token;
return {

View File

@@ -21,7 +21,7 @@ export interface AppProps<P = AnyObject> extends AppConfig {
component?: CustomComponent<P> | false;
}
const App = React.forwardRef<HTMLElement, AppProps>((props, ref) => {
const App: React.FC<AppProps> = (props) => {
const {
prefixCls: customizePrefixCls,
children,
@@ -79,12 +79,6 @@ const App = React.forwardRef<HTMLElement, AppProps>((props, ref) => {
'When using cssVar, ensure `component` is assigned a valid React component string.',
);
devUseWarning('App')(
!ref || component !== false,
'usage',
'`ref` is not supported when `component` is `false`. Please provide a valid `component` instead.',
);
// ============================ Render ============================
const Component = component === false ? React.Fragment : component;
@@ -96,7 +90,7 @@ const App = React.forwardRef<HTMLElement, AppProps>((props, ref) => {
return (
<AppContext.Provider value={memoizedContextValue}>
<AppConfigContext.Provider value={mergedAppConfig}>
<Component {...(component === false ? undefined : { ...rootProps, ref })}>
<Component {...(component === false ? undefined : rootProps)}>
{ModalContextHolder}
{messageContextHolder}
{notificationContextHolder}
@@ -105,7 +99,7 @@ const App = React.forwardRef<HTMLElement, AppProps>((props, ref) => {
</AppConfigContext.Provider>
</AppContext.Provider>
);
});
};
if (process.env.NODE_ENV !== 'production') {
App.displayName = 'App';

View File

@@ -247,20 +247,5 @@ describe('App', () => {
'Warning: [antd: App] When using cssVar, ensure `component` is assigned a valid React component string.',
);
});
it('should warn if component is false and ref is not empty', () => {
const domRef = React.createRef<HTMLSpanElement>();
render(<App ref={domRef} component={false} />);
expect(errorSpy).toHaveBeenCalledWith(
'Warning: [antd: App] `ref` is not supported when `component` is `false`. Please provide a valid `component` instead.',
);
});
it('App should support Ref', () => {
const domRef = React.createRef<HTMLSpanElement>();
const { container } = render(<App ref={domRef} className="bamboo" component="span" />);
expect(domRef.current).toBe(container.querySelector('.bamboo'));
});
});
});

View File

@@ -1,3 +1,5 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks } from '../../theme/internal';
@@ -7,7 +9,7 @@ export interface ComponentToken {}
interface AppToken extends FullToken<'App'> {}
// =============================== Base ===============================
const genBaseStyle: GenerateStyle<AppToken> = (token) => {
const genBaseStyle: GenerateStyle<AppToken, CSSObject> = (token) => {
const { componentCls, colorText, fontSize, lineHeight, fontFamily } = token;
return {
[componentCls]: {

View File

@@ -78,7 +78,7 @@ type AvatarToken = FullToken<'Avatar'> & {
avatarColor: string;
};
const genBaseStyle: GenerateStyle<AvatarToken> = (token) => {
const genBaseStyle: GenerateStyle<AvatarToken, CSSObject> = (token) => {
const {
antCls,
componentCls,
@@ -168,7 +168,7 @@ const genBaseStyle: GenerateStyle<AvatarToken> = (token) => {
};
};
const genGroupStyle: GenerateStyle<AvatarToken> = (token) => {
const genGroupStyle: GenerateStyle<AvatarToken, CSSObject> = (token) => {
const { componentCls, groupBorderColor, groupOverlapping, groupSpace } = token;
return {

View File

@@ -65,7 +65,7 @@ type BackTopToken = FullToken<'BackTop'> & {
};
// ============================== Shared ==============================
const genSharedBackTopStyle: GenerateStyle<BackTopToken, CSSObject> = (token): CSSObject => {
const genSharedBackTopStyle: GenerateStyle<BackTopToken, CSSObject> = (token) => {
const { componentCls, backTopFontSize, backTopSize, zIndexPopup } = token;
return {
@@ -109,7 +109,7 @@ const genSharedBackTopStyle: GenerateStyle<BackTopToken, CSSObject> = (token): C
};
};
const genMediaBackTopStyle: GenerateStyle<BackTopToken> = (token): CSSObject => {
const genMediaBackTopStyle: GenerateStyle<BackTopToken, CSSObject> = (token) => {
const { componentCls, screenMD, screenXS, backTopInlineEndMD, backTopInlineEndXS } = token;
return {
[`@media (max-width: ${unit(screenMD)})`]: {

View File

@@ -1,3 +1,4 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { Keyframes, unit } from '@ant-design/cssinjs';
import { resetComponent } from '../../style';
@@ -139,7 +140,7 @@ const antBadgeLoadingCircle = new Keyframes('antBadgeLoadingCircle', {
},
});
const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (token) => {
const genSharedBadgeStyle: GenerateStyle<BadgeToken, CSSObject> = (token) => {
const {
componentCls,
iconCls,
@@ -372,7 +373,7 @@ const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (token) => {
};
// ============================== Export ==============================
export const prepareToken: (token: Parameters<GenStyleFn<'Badge'>>[0]) => BadgeToken = (token) => {
export const prepareToken = (token: Parameters<GenStyleFn<'Badge'>>[0]) => {
const { fontHeight, lineWidth, marginXS, colorBorderBg } = token;
const badgeFontHeight = fontHeight;

View File

@@ -1,3 +1,4 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { unit } from '@ant-design/cssinjs';
import { prepareComponentToken, prepareToken } from '.';
@@ -7,7 +8,7 @@ import type { GenerateStyle } from '../../theme/internal';
import { genPresetColor, genStyleHooks } from '../../theme/internal';
// ============================== Ribbon ==============================
const genRibbonStyle: GenerateStyle<BadgeToken> = (token) => {
const genRibbonStyle: GenerateStyle<BadgeToken, CSSObject> = (token) => {
const { antCls, badgeFontHeight, marginXS, badgeRibbonOffset, calc } = token;
const ribbonPrefixCls = `${antCls}-ribbon`;
const ribbonWrapperPrefixCls = `${antCls}-ribbon-wrapper`;

View File

@@ -225,7 +225,7 @@ const InternalCompoundedButton = React.forwardRef<
const loadingOrDelay = useMemo<LoadingConfigType>(() => getLoadingConfig(loading), [loading]);
const [innerLoading, setLoading] = useState<boolean>(loadingOrDelay.loading);
const [innerLoading, setInnerLoading] = useState<boolean>(loadingOrDelay.loading);
const [hasTwoCNChar, setHasTwoCNChar] = useState<boolean>(false);
@@ -255,10 +255,10 @@ const InternalCompoundedButton = React.forwardRef<
if (loadingOrDelay.delay > 0) {
delayTimer = setTimeout(() => {
delayTimer = null;
setLoading(true);
setInnerLoading(true);
}, loadingOrDelay.delay);
} else {
setLoading(loadingOrDelay.loading);
setInnerLoading(loadingOrDelay.loading);
}
function cleanupTimer() {

View File

@@ -2,6 +2,7 @@ import type { CSSInterpolation, CSSObject } from '@ant-design/cssinjs';
import { unit } from '@ant-design/cssinjs';
import { genFocusStyle, resetIcon } from '../../style';
import { genNoMotionStyle } from '../../style/motion';
import type { GenerateStyle } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
import genGroupStyle from './group';
@@ -12,7 +13,7 @@ import genVariantStyle from './variant';
export type { ComponentToken };
// ============================== Shared ==============================
const genSharedButtonStyle: GenerateStyle<ButtonToken, CSSObject> = (token): CSSObject => {
const genSharedButtonStyle: GenerateStyle<ButtonToken, CSSObject> = (token) => {
const {
componentCls,
iconCls,
@@ -40,7 +41,7 @@ const genSharedButtonStyle: GenerateStyle<ButtonToken, CSSObject> = (token): CSS
transition: `all ${token.motionDurationMid} ${token.motionEaseInOut}`,
userSelect: 'none',
touchAction: 'manipulation',
...genNoMotionStyle(),
'&:disabled > *': {
pointerEvents: 'none',
},
@@ -80,7 +81,7 @@ const genSharedButtonStyle: GenerateStyle<ButtonToken, CSSObject> = (token): CSS
[`${componentCls}-loading-icon`]: {
transition: ['width', 'opacity', 'margin']
.map((transition) => `${transition} ${motionDurationSlow} ${motionEaseInOut}`)
.map((prop) => `${prop} ${motionDurationSlow} ${motionEaseInOut}`)
.join(','),
},
@@ -210,7 +211,7 @@ const genSizeLargeButtonStyle: GenerateStyle<ButtonToken> = (token) => {
return genButtonStyle(largeToken, `${token.componentCls}-lg`);
};
const genBlockButtonStyle: GenerateStyle<ButtonToken> = (token) => {
const genBlockButtonStyle: GenerateStyle<ButtonToken, CSSObject> = (token) => {
const { componentCls } = token;
return {
[componentCls]: {

View File

@@ -283,9 +283,7 @@ export interface ButtonToken
buttonIconOnlyFontSize: number | string;
}
export const prepareToken: (token: Parameters<GenStyleFn<'Button'>>[0]) => ButtonToken = (
token,
) => {
export const prepareToken = (token: Parameters<GenStyleFn<'Button'>>[0]) => {
const { paddingInline, onlyIconSize, borderColorDisabled } = token;
const buttonToken = mergeToken<ButtonToken>(token, {
@@ -310,7 +308,7 @@ export const prepareComponentToken: GetDefaultToken<'Button'> = (token) => {
: '#fff';
const shadowColorTokens = PresetColors.reduce<CSSObject>(
(prev: CSSObject, colorKey: PresetColorKey) => ({
(prev, colorKey) => ({
...prev,
[`${colorKey}ShadowColor`]: `0 ${unit(token.controlOutlineWidth)} 0 ${getAlphaColor(token[`${colorKey}1`], token.colorBgContainer)}`,
}),

View File

@@ -1,9 +1,11 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { PresetColors } from '../../theme/interface';
import type { GenerateStyle } from '../../theme/interface';
import { genCssVar } from '../../theme/util/genStyleUtils';
import type { ButtonToken } from './token';
const genVariantStyle: GenerateStyle<ButtonToken> = (token) => {
const genVariantStyle: GenerateStyle<ButtonToken, CSSObject> = (token) => {
const { componentCls, antCls, lineWidth } = token;
const [varName, varRef] = genCssVar(antCls, 'btn');

View File

@@ -99,7 +99,7 @@ const App: React.FC = () => {
const { styles } = useStyle({ test: true });
const [selectDate, setSelectDate] = React.useState<Dayjs>(() => dayjs());
const [panelDateDate, setPanelDate] = React.useState<Dayjs>(() => dayjs());
const [panelDate, setPanelDate] = React.useState<Dayjs>(() => dayjs());
const onPanelChange = (value: Dayjs, mode: CalendarProps<Dayjs>['mode']) => {
console.log(value.format('YYYY-MM-DD'), mode);
@@ -131,7 +131,7 @@ const App: React.FC = () => {
<span
className={clsx({
[styles.weekend]: isWeekend,
gray: !panelDateDate.isSame(date, 'month'),
gray: !panelDate.isSame(date, 'month'),
})}
>
{date.get('date')}

View File

@@ -8,7 +8,7 @@ import {
initPickerPanelToken,
} from '../../date-picker/style';
import { resetComponent } from '../../style';
import type { FullToken, GetDefaultToken } from '../../theme/internal';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
export interface ComponentToken {
@@ -67,7 +67,7 @@ interface CalendarToken extends FullToken<'Calendar'>, PickerPanelToken, PanelCo
dateContentHeight: number | string;
}
export const genCalendarStyles = (token: CalendarToken): CSSObject => {
export const genCalendarStyles: GenerateStyle<CalendarToken, CSSObject> = (token) => {
const { calendarCls, componentCls, fullBg, fullPanelBg, itemActiveBg } = token;
return {
[calendarCls]: {

View File

@@ -1,3 +1,4 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { Keyframes, unit } from '@ant-design/cssinjs';
import { resetComponent } from '../../style';
@@ -48,7 +49,7 @@ interface CarouselToken extends FullToken<'Carousel'> {}
export const DotDuration = '--dot-duration';
const genCarouselStyle: GenerateStyle<CarouselToken> = (token) => {
const genCarouselStyle: GenerateStyle<CarouselToken, CSSObject> = (token) => {
const { componentCls, antCls } = token;
return {

View File

@@ -44,12 +44,12 @@ const options: Option[] = [
];
const App: React.FC = () => {
const [placement, SetPlacement] = useState<'bottomLeft' | 'bottomRight' | 'topLeft' | 'topRight'>(
const [placement, setPlacement] = useState<'bottomLeft' | 'bottomRight' | 'topLeft' | 'topRight'>(
'topLeft',
);
const placementChange = (e: RadioChangeEvent) => {
SetPlacement(e.target.value);
setPlacement(e.target.value);
};
return (

View File

@@ -6,7 +6,7 @@ import { getStyle as getCheckboxStyle } from '../../checkbox/style';
import { textEllipsis } from '../../style';
import type { GenerateStyle } from '../../theme/internal';
const getColumnsStyle: GenerateStyle<CascaderToken> = (token: CascaderToken): CSSInterpolation => {
const getColumnsStyle: GenerateStyle<CascaderToken, CSSInterpolation> = (token) => {
const { prefixCls, componentCls } = token;
const cascaderMenuItemCls = `${componentCls}-menu-item`;

View File

@@ -96,7 +96,6 @@ export const prepareComponentToken = (token: GlobalToken) => {
const itemPaddingVertical = Math.round(
(token.controlHeight - token.fontSize * token.lineHeight) / 2,
);
return {
controlWidth: 184,
controlItemWidth: 111,

View File

@@ -8,7 +8,7 @@ import type { GenerateStyle } from '../../theme/internal';
import getColumnsStyle from './columns';
// ============================== Panel ===============================
const genPanelStyle: GenerateStyle<CascaderToken> = (token: CascaderToken): CSSObject => {
const genPanelStyle: GenerateStyle<CascaderToken, CSSObject> = (token) => {
const { componentCls } = token;
return {

View File

@@ -1,6 +1,7 @@
import { unit } from '@ant-design/cssinjs';
import { genFocusOutline, resetComponent } from '../../style';
import { genNoMotionStyle } from '../../style/motion';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
@@ -99,6 +100,7 @@ export const genCheckboxStyle: GenerateStyle<CheckboxToken> = (token) => {
borderRadius: token.borderRadiusSM,
borderCollapse: 'separate',
transition: `all ${token.motionDurationSlow}`,
...genNoMotionStyle(),
// Checkmark
'&:after': {
@@ -116,6 +118,7 @@ export const genCheckboxStyle: GenerateStyle<CheckboxToken> = (token) => {
opacity: 0,
content: '""',
transition: `all ${token.motionDurationFast} ${token.motionEaseInBack}, opacity ${token.motionDurationFast}`,
...genNoMotionStyle(),
},
// Wrapper > Checkbox > input
@@ -173,6 +176,7 @@ export const genCheckboxStyle: GenerateStyle<CheckboxToken> = (token) => {
opacity: 1,
transform: 'rotate(45deg) scale(1) translate(-50%,-50%)',
transition: `all ${token.motionDurationMid} ${token.motionEaseOutBack} ${token.motionDurationFast}`,
...genNoMotionStyle(),
},
// Hover on checked checkbox directly

View File

@@ -1,4 +1,5 @@
import type { CSSProperties } from 'react';
import type { CSSObject } from '@ant-design/cssinjs';
import { unit } from '@ant-design/cssinjs';
import { genFocusStyle, resetComponent, resetIcon } from '../../style';
@@ -59,7 +60,7 @@ type CollapseToken = FullToken<'Collapse'> & {
collapsePanelBorderRadius: number;
};
export const genBaseStyle: GenerateStyle<CollapseToken> = (token) => {
export const genBaseStyle: GenerateStyle<CollapseToken, CSSObject> = (token) => {
const {
componentCls,
contentBg,
@@ -269,7 +270,7 @@ export const genBaseStyle: GenerateStyle<CollapseToken> = (token) => {
};
};
const genArrowStyle: GenerateStyle<CollapseToken> = (token) => {
const genArrowStyle: GenerateStyle<CollapseToken, CSSObject> = (token) => {
const { componentCls } = token;
const fixedSelector = `> ${componentCls}-item > ${componentCls}-header ${componentCls}-arrow`;
@@ -283,7 +284,7 @@ const genArrowStyle: GenerateStyle<CollapseToken> = (token) => {
};
};
const genBorderlessStyle: GenerateStyle<CollapseToken> = (token) => {
const genBorderlessStyle: GenerateStyle<CollapseToken, CSSObject> = (token) => {
const { componentCls, headerBg, borderlessContentPadding, borderlessContentBg, colorBorder } =
token;
@@ -319,7 +320,7 @@ const genBorderlessStyle: GenerateStyle<CollapseToken> = (token) => {
};
};
const genGhostStyle: GenerateStyle<CollapseToken> = (token) => {
const genGhostStyle: GenerateStyle<CollapseToken, CSSObject> = (token) => {
const { componentCls, paddingSM } = token;
return {

View File

@@ -76,7 +76,7 @@ export const genActiveStyle = (
outline: 0,
});
const genRtlStyle = (token: ColorPickerToken): CSSObject => {
const genRtlStyle: GenerateStyle<ColorPickerToken, CSSObject> = (token) => {
const { componentCls } = token;
return {
'&-rtl': {
@@ -133,7 +133,7 @@ const genClearStyle = (
};
};
const genStatusStyle = (token: ColorPickerToken): CSSObject => {
const genStatusStyle: GenerateStyle<ColorPickerToken, CSSObject> = (token) => {
const {
componentCls,
colorError,
@@ -164,7 +164,7 @@ const genStatusStyle = (token: ColorPickerToken): CSSObject => {
},
};
};
const genSizeStyle = (token: ColorPickerToken): CSSObject => {
const genSizeStyle: GenerateStyle<ColorPickerToken, CSSObject> = (token) => {
const {
componentCls,
controlHeightLG,

View File

@@ -2,7 +2,7 @@ import React, { useEffect } from 'react';
import { Modal } from 'antd';
import ConfigProvider from '..';
import { Button, InputNumber, Select, Space } from '../..';
import { Button, InputNumber, Select } from '../..';
import { render, waitFakeTimer } from '../../../tests/utils';
import theme from '../../theme';
import type { GlobalToken } from '../../theme/internal';
@@ -113,21 +113,6 @@ describe('ConfigProvider.Theme', () => {
).toBeTruthy();
});
it('should support Addon component token', () => {
const { container } = render(
<ConfigProvider theme={{ components: { Addon: { colorText: '#0000FF', algorithm: true } } }}>
<Space.Compact>
<Space.Addon className="test-addon">Addon Content</Space.Addon>
</Space.Compact>
</ConfigProvider>,
);
const addon = container.querySelector('.test-addon')!;
expect(addon).toHaveStyle({
'--ant-color-text': '#0000FF',
});
});
it('hashed should be true if not changed', () => {
let hashId = 'hashId';

View File

@@ -65,7 +65,6 @@ import type { TourProps } from '../tour/interface';
import type { TransferProps } from '../transfer';
import type { TreeProps } from '../tree';
import type { TreeSelectProps } from '../tree-select';
import type { TypographyClassNamesType, TypographyStylesType } from '../typography/Base';
import type { UploadProps } from '../upload';
import type { RenderEmptyHandler } from './defaultRenderEmpty';
@@ -243,11 +242,6 @@ export type AlertConfig = ComponentStyleConfig &
export type BadgeConfig = ComponentStyleConfig & Pick<BadgeProps, 'classNames' | 'styles'>;
export type TypographyConfig = ComponentStyleConfig & {
classNames?: TypographyClassNamesType;
styles?: TypographyStylesType;
};
export type BreadcrumbConfig = ComponentStyleConfig &
Pick<BreadcrumbProps, 'classNames' | 'styles' | 'separator' | 'dropdownIcon'>;
@@ -453,7 +447,7 @@ export interface ConfigComponentProps {
collapse?: CollapseConfig;
floatButton?: FloatButtonConfig;
floatButtonGroup?: FloatButtonGroupConfig;
typography?: TypographyConfig;
typography?: ComponentStyleConfig;
skeleton?: SkeletonConfig;
spin?: SpinConfig;
segmented?: SegmentedConfig;

View File

@@ -225,11 +225,11 @@ const Page: React.FC = () => {
};
const App: React.FC = () => {
const [locale, setLocal] = useState<Locale>(enUS);
const [locale, setLocale] = useState<Locale>(enUS);
const changeLocale = (e: RadioChangeEvent) => {
const localeValue = e.target.value;
setLocal(localeValue);
setLocale(localeValue);
if (!localeValue) {
dayjs.locale('en');
} else {

View File

@@ -74,7 +74,6 @@ import type {
TourConfig,
TransferConfig,
TreeSelectConfig,
TypographyConfig,
UploadConfig,
Variant,
WaveConfig,
@@ -226,7 +225,7 @@ export interface ConfigProviderProps {
collapse?: CollapseConfig;
divider?: ComponentStyleConfig;
drawer?: DrawerConfig;
typography?: TypographyConfig;
typography?: ComponentStyleConfig;
skeleton?: SkeletonConfig;
spin?: SpinConfig;
segmented?: ComponentStyleConfig;

View File

@@ -5,10 +5,10 @@ import { DatePicker, Radio } from 'antd';
const { RangePicker } = DatePicker;
const App: React.FC = () => {
const [placement, SetPlacement] = useState<DatePickerProps['placement']>('topLeft');
const [placement, setPlacement] = useState<DatePickerProps['placement']>('topLeft');
const placementChange = (e: RadioChangeEvent) => {
SetPlacement(e.target.value);
setPlacement(e.target.value);
};
return (

View File

@@ -30,7 +30,7 @@ const genPickerPadding = (paddingBlock: number, paddingInline: number): CSSObjec
};
};
const genPickerStatusStyle: GenerateStyle<PickerToken> = (token) => {
const genPickerStatusStyle: GenerateStyle<PickerToken, CSSObject> = (token) => {
const { componentCls, colorError, colorWarning } = token;
return {

View File

@@ -5,7 +5,7 @@ import { FastColor } from '@ant-design/fast-color';
import type { GenerateStyle } from '../../theme/internal';
import type { PickerToken, SharedPickerToken } from './token';
const genPickerCellInnerStyle = (token: SharedPickerToken): CSSObject => {
const genPickerCellInnerStyle: GenerateStyle<SharedPickerToken, CSSObject> = (token) => {
const {
pickerCellCls,
pickerCellInnerCls,
@@ -141,7 +141,7 @@ const genPickerCellInnerStyle = (token: SharedPickerToken): CSSObject => {
};
};
export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
export const genPanelStyle: GenerateStyle<SharedPickerToken, CSSObject> = (token) => {
const {
componentCls,
pickerCellCls,
@@ -625,7 +625,7 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
};
};
const genPickerPanelStyle: GenerateStyle<PickerToken> = (token) => {
const genPickerPanelStyle: GenerateStyle<PickerToken, CSSObject> = (token) => {
const {
componentCls,
textHeight,

View File

@@ -7,9 +7,10 @@ import {
genOutlinedStyle,
genUnderlinedStyle,
} from '../../input/style/variants';
import type { GenerateStyle } from '../../theme/interface';
import type { PickerToken } from './token';
const genVariantsStyle = (token: PickerToken): CSSObject => {
const genVariantsStyle: GenerateStyle<PickerToken, CSSObject> = (token) => {
const { componentCls } = token;
return {

View File

@@ -62,7 +62,7 @@ export interface ComponentToken {
interface DescriptionsToken extends FullToken<'Descriptions'> {}
const genBorderedStyle = (token: DescriptionsToken): CSSObject => {
const genBorderedStyle: GenerateStyle<DescriptionsToken, CSSObject> = (token) => {
const { componentCls, labelBg } = token;
return {
[`&${componentCls}-bordered`]: {
@@ -118,7 +118,7 @@ const genBorderedStyle = (token: DescriptionsToken): CSSObject => {
};
};
const genDescriptionStyles: GenerateStyle<DescriptionsToken> = (token) => {
const genDescriptionStyles: GenerateStyle<DescriptionsToken, CSSObject> = (token) => {
const {
componentCls,
extraColor,

View File

@@ -43,7 +43,7 @@ interface DividerToken extends FullToken<'Divider'> {
}
// ============================== Size ================================
const genSizeDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject => {
const genSizeDividerStyle: GenerateStyle<DividerToken, CSSObject> = (token) => {
const { componentCls } = token;
return {
@@ -63,7 +63,7 @@ const genSizeDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject => {
};
// ============================== Shared ==============================
const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject => {
const genSharedDividerStyle: GenerateStyle<DividerToken, CSSObject> = (token) => {
const {
componentCls,
sizePaddingEdgeHorizontal,

View File

@@ -88,205 +88,6 @@ Array [
exports[`renders components/drawer/demo/basic-right.tsx extend context correctly 2`] = `[]`;
exports[`renders components/drawer/demo/classNames.tsx extend context correctly 1`] = `
Array [
<div
class="ant-space ant-space-horizontal ant-space-align-center ant-space-gap-row-small ant-space-gap-col-small css-var-test-id"
>
<div
class="ant-space-item"
>
<button
class="ant-btn css-var-test-id ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
type="button"
>
<span>
Open
</span>
</button>
</div>
<div
class="ant-space-item"
>
<button
class="ant-btn css-var-test-id ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
type="button"
>
<span>
ConfigProvider
</span>
</button>
</div>
</div>,
<div
class="ant-drawer ant-drawer-right css-var-test-id ant-drawer-open ant-drawer-inline"
tabindex="-1"
>
<div
class="ant-drawer-mask acss-c0hvaj"
/>
<div
class="ant-drawer-content-wrapper"
style="width: 378px;"
>
<div
aria-labelledby="test-id"
aria-modal="true"
class="ant-drawer-section acss-10412ne"
role="dialog"
style="box-shadow: -10px 0 10px #666;"
>
<div
class="ant-drawer-header acss-1l0wu1y"
style="border-bottom: 1px solid rgb(22, 119, 255);"
>
<div
class="ant-drawer-header-title"
>
<button
aria-label="Close"
class="ant-drawer-close"
type="button"
>
<span
aria-label="close"
class="anticon anticon-close"
role="img"
>
<svg
aria-hidden="true"
data-icon="close"
fill="currentColor"
fill-rule="evenodd"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M799.86 166.31c.02 0 .04.02.08.06l57.69 57.7c.04.03.05.05.06.08a.12.12 0 010 .06c0 .03-.02.05-.06.09L569.93 512l287.7 287.7c.04.04.05.06.06.09a.12.12 0 010 .07c0 .02-.02.04-.06.08l-57.7 57.69c-.03.04-.05.05-.07.06a.12.12 0 01-.07 0c-.03 0-.05-.02-.09-.06L512 569.93l-287.7 287.7c-.04.04-.06.05-.09.06a.12.12 0 01-.07 0c-.02 0-.04-.02-.08-.06l-57.69-57.7c-.04-.03-.05-.05-.06-.07a.12.12 0 010-.07c0-.03.02-.05.06-.09L454.07 512l-287.7-287.7c-.04-.04-.05-.06-.06-.09a.12.12 0 010-.07c0-.02.02-.04.06-.08l57.7-57.69c.03-.04.05-.05.07-.06a.12.12 0 01.07 0c.03 0 .05.02.09.06L512 454.07l287.7-287.7c.04-.04.06-.05.09-.06a.12.12 0 01.07 0z"
/>
</svg>
</span>
</button>
<div
class="ant-drawer-title"
id="test-id"
>
Basic Drawer
</div>
</div>
</div>
<div
class="ant-drawer-body acss-pgpe64"
style="font-size: 16px;"
>
<p>
Some contents...
</p>
<p>
Some contents...
</p>
<p>
Some contents...
</p>
</div>
<div
class="ant-drawer-footer acss-r4s437"
style="border-top: 1px solid rgb(217, 217, 217);"
>
Footer
</div>
</div>
</div>
</div>,
<div
class="ant-drawer ant-drawer-right css-var-test-id ant-drawer-open ant-drawer-inline"
tabindex="-1"
>
<div
class="ant-drawer-mask acss-c0hvaj"
/>
<div
class="ant-drawer-content-wrapper"
style="width: 378px;"
>
<div
aria-labelledby="test-id"
aria-modal="true"
class="ant-drawer-section acss-10412ne"
role="dialog"
style="box-shadow: -10px 0 10px #666;"
>
<div
class="ant-drawer-header acss-1l0wu1y"
style="border-bottom: 1px solid rgb(22, 119, 255);"
>
<div
class="ant-drawer-header-title"
>
<button
aria-label="Close"
class="ant-drawer-close"
type="button"
>
<span
aria-label="close"
class="anticon anticon-close"
role="img"
>
<svg
aria-hidden="true"
data-icon="close"
fill="currentColor"
fill-rule="evenodd"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M799.86 166.31c.02 0 .04.02.08.06l57.69 57.7c.04.03.05.05.06.08a.12.12 0 010 .06c0 .03-.02.05-.06.09L569.93 512l287.7 287.7c.04.04.05.06.06.09a.12.12 0 010 .07c0 .02-.02.04-.06.08l-57.7 57.69c-.03.04-.05.05-.07.06a.12.12 0 01-.07 0c-.03 0-.05-.02-.09-.06L512 569.93l-287.7 287.7c-.04.04-.06.05-.09.06a.12.12 0 01-.07 0c-.02 0-.04-.02-.08-.06l-57.69-57.7c-.04-.03-.05-.05-.06-.07a.12.12 0 010-.07c0-.03.02-.05.06-.09L454.07 512l-287.7-287.7c-.04-.04-.05-.06-.06-.09a.12.12 0 010-.07c0-.02.02-.04.06-.08l57.7-57.69c.03-.04.05-.05.07-.06a.12.12 0 01.07 0c.03 0 .05.02.09.06L512 454.07l287.7-287.7c.04-.04.06-.05.09-.06a.12.12 0 01.07 0z"
/>
</svg>
</span>
</button>
<div
class="ant-drawer-title"
id="test-id"
>
Basic Drawer
</div>
</div>
</div>
<div
class="ant-drawer-body acss-pgpe64"
style="font-size: 16px;"
>
<p>
Some contents...
</p>
<p>
Some contents...
</p>
<p>
Some contents...
</p>
</div>
<div
class="ant-drawer-footer acss-r4s437"
style="border-top: 1px solid rgb(217, 217, 217);"
>
Footer
</div>
</div>
</div>
</div>,
]
`;
exports[`renders components/drawer/demo/classNames.tsx extend context correctly 2`] = `[]`;
exports[`renders components/drawer/demo/closable-placement.tsx extend context correctly 1`] = `
Array [
<button

View File

@@ -11,37 +11,6 @@ exports[`renders components/drawer/demo/basic-right.tsx correctly 1`] = `
</button>
`;
exports[`renders components/drawer/demo/classNames.tsx correctly 1`] = `
<div
class="ant-space ant-space-horizontal ant-space-align-center ant-space-gap-row-small ant-space-gap-col-small css-var-test-id"
>
<div
class="ant-space-item"
>
<button
class="ant-btn css-var-test-id ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
type="button"
>
<span>
Open
</span>
</button>
</div>
<div
class="ant-space-item"
>
<button
class="ant-btn css-var-test-id ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
type="button"
>
<span>
ConfigProvider
</span>
</button>
</div>
</div>
`;
exports[`renders components/drawer/demo/closable-placement.tsx correctly 1`] = `
<button
class="ant-btn css-var-test-id ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"

View File

@@ -1,7 +0,0 @@
## zh-CN
通过 `classNames` 属性设置抽屉内部区域header、body、footer、mask、wrapper`className`
## en-US
Set the `className` of the build-in module (header, body, footer, mask, wrapper) of the drawer through the `classNames`.

View File

@@ -1,102 +0,0 @@
import React, { useState } from 'react';
import { Button, ConfigProvider, Drawer, Space } from 'antd';
import type { DrawerProps } from 'antd';
import { createStyles, useTheme } from 'antd-style';
const useStyle = createStyles(({ token }) => ({
'my-drawer-body': {
background: token.blue1,
},
'my-drawer-mask': {
boxShadow: `inset 0 0 15px #fff`,
},
'my-drawer-header': {
background: token.green1,
},
'my-drawer-footer': {
color: token.colorPrimary,
},
'my-drawer-section': {
borderInlineStart: '2px dotted #333',
},
}));
const App: React.FC = () => {
const [open, setOpen] = useState([false, false]);
const { styles } = useStyle();
const token = useTheme();
const toggleDrawer = (idx: number, target: boolean) => {
setOpen((p) => {
p[idx] = target;
return [...p];
});
};
const classNames: DrawerProps['classNames'] = {
body: styles['my-drawer-body'],
mask: styles['my-drawer-mask'],
header: styles['my-drawer-header'],
footer: styles['my-drawer-footer'],
section: styles['my-drawer-section'],
};
const drawerStyles: DrawerProps['styles'] = {
mask: {
backdropFilter: 'blur(10px)',
},
section: {
boxShadow: '-10px 0 10px #666',
},
header: {
borderBottom: `1px solid ${token.colorPrimary}`,
},
body: {
fontSize: token.fontSizeLG,
},
footer: {
borderTop: `1px solid ${token.colorBorder}`,
},
};
return (
<>
<Space>
<Button type="primary" onClick={() => toggleDrawer(0, true)}>
Open
</Button>
<Button type="primary" onClick={() => toggleDrawer(1, true)}>
ConfigProvider
</Button>
</Space>
<Drawer
title="Basic Drawer"
placement="right"
footer="Footer"
onClose={() => toggleDrawer(0, false)}
open={open[0]}
classNames={classNames}
styles={drawerStyles}
>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</Drawer>
<ConfigProvider drawer={{ classNames, styles: drawerStyles }}>
<Drawer
title="Basic Drawer"
placement="right"
footer="Footer"
onClose={() => toggleDrawer(1, false)}
open={open[1]}
>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</Drawer>
</ConfigProvider>
</>
);
};
export default App;

View File

@@ -54,8 +54,8 @@ const stylesFn: DrawerProps['styles'] = (info) => {
};
const App: React.FC = () => {
const [drawerOpen, setOpen] = useState(false);
const [drawerFnOpen, setFnOpen] = useState(false);
const [drawerOpen, setDrawerOpen] = useState(false);
const [drawerFnOpen, setDrawerFnOpen] = useState(false);
const sharedProps: DrawerProps = {
classNames,
@@ -65,7 +65,7 @@ const App: React.FC = () => {
const footer: React.ReactNode = (
<Flex gap="middle" justify="flex-end">
<Button
onClick={() => setFnOpen(false)}
onClick={() => setDrawerFnOpen(false)}
styles={{ root: { borderColor: '#ccc', color: '#171717', backgroundColor: '#fff' } }}
>
Cancel
@@ -73,7 +73,7 @@ const App: React.FC = () => {
<Button
type="primary"
styles={{ root: { backgroundColor: '#171717' } }}
onClick={() => setOpen(true)}
onClick={() => setDrawerOpen(true)}
>
Submit
</Button>
@@ -82,8 +82,8 @@ const App: React.FC = () => {
return (
<Flex gap="middle">
<Button onClick={() => setOpen(true)}>Open Style Drawer</Button>
<Button type="primary" onClick={() => setFnOpen(true)}>
<Button onClick={() => setDrawerOpen(true)}>Open Style Drawer</Button>
<Button type="primary" onClick={() => setDrawerFnOpen(true)}>
Open Function Drawer
</Button>
<Drawer
@@ -92,7 +92,7 @@ const App: React.FC = () => {
title="Custom Style Drawer"
styles={styles}
open={drawerOpen}
onClose={() => setOpen(false)}
onClose={() => setDrawerOpen(false)}
>
{sharedContent}
</Drawer>
@@ -103,7 +103,7 @@ const App: React.FC = () => {
styles={stylesFn}
mask={{ enabled: true, blur: true }}
open={drawerFnOpen}
onClose={() => setFnOpen(false)}
onClose={() => setDrawerFnOpen(false)}
>
{sharedContent}
</Drawer>

View File

@@ -34,7 +34,6 @@ A Drawer is a panel that is typically overlaid on top of a page and slides in fr
<code src="./demo/user-profile.tsx">Preview drawer</code>
<code src="./demo/multi-level-drawer.tsx">Multi-level drawer</code>
<code src="./demo/size.tsx">Preset size</code>
<code src="./demo/classNames.tsx">Customize className for build-in module</code>
<code src="./demo/mask.tsx">mask</code>
<code src="./demo/closable-placement.tsx" version="5.28.0">Closable placement</code>
<code src="./demo/style-class.tsx" version="6.0.0">Custom semantic dom styling</code>

View File

@@ -35,7 +35,6 @@ demo:
<code src="./demo/multi-level-drawer.tsx">多层抽屉</code>
<code src="./demo/size.tsx">预设宽度</code>
<code src="./demo/mask.tsx">遮罩</code>
<code src="./demo/classNames.tsx">自定义内部样式</code>
<code src="./demo/closable-placement.tsx" version="5.28.0">关闭按钮位置</code>
<code src="./demo/style-class.tsx" version="6.0.0">自定义语义结构的样式和类</code>
<code src="./demo/config-provider.tsx" debug>ConfigProvider</code>

View File

@@ -1,7 +1,9 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { DropdownToken } from '.';
import type { GenerateStyle } from '../../theme/internal';
const genStatusStyle: GenerateStyle<DropdownToken> = (token) => {
const genStatusStyle: GenerateStyle<DropdownToken, CSSObject> = (token) => {
const { componentCls, menuCls, colorError, colorTextLightSolid } = token;
const itemCls = `${menuCls}-item`;

View File

@@ -829,13 +829,13 @@ describe('Form', () => {
// https://github.com/ant-design/ant-design/issues/20813
it('should update help directly when provided', async () => {
const App: React.FC = () => {
const [message, updateMessage] = React.useState('');
const [message, setMessage] = React.useState('');
return (
<Form>
<Form.Item label="hello" help={message}>
<Input />
</Form.Item>
<Button onClick={() => updateMessage('bamboo')} />
<Button onClick={() => setMessage('bamboo')} />
</Form>
);
};

View File

@@ -14,10 +14,10 @@ const customizeRequiredMark = (label: React.ReactNode, { required }: { required:
const App: React.FC = () => {
const [form] = Form.useForm();
const [requiredMark, setRequiredMarkType] = useState<RequiredMark>('optional');
const [requiredMark, setRequiredMark] = useState<RequiredMark>('optional');
const onRequiredTypeChange: FormProps<any>['onValuesChange'] = ({ requiredMarkValue }) => {
setRequiredMarkType(requiredMarkValue);
setRequiredMark(requiredMarkValue);
};
return (

View File

@@ -1,7 +1,9 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { FormToken } from '.';
import type { GenerateStyle } from '../../theme/internal';
const genFormValidateMotionStyle: GenerateStyle<FormToken> = (token) => {
const genFormValidateMotionStyle: GenerateStyle<FormToken, CSSObject> = (token) => {
const { componentCls, motionDurationFast, motionEaseInOut } = token;
const helpCls = `${componentCls}-show-help`;

View File

@@ -4,13 +4,15 @@
*/
// Style as inline component
import type { CSSObject } from '@ant-design/cssinjs';
import { prepareToken } from '.';
import type { FormToken } from '.';
import { genSubStyleComponent } from '../../theme/internal';
import type { GenerateStyle } from '../../theme/internal';
// ============================= Fallback =============================
const genFallbackStyle: GenerateStyle<FormToken> = (token) => {
const genFallbackStyle: GenerateStyle<FormToken, CSSObject> = (token) => {
const { formItemCls } = token;
return {

View File

@@ -85,7 +85,7 @@ export interface FormToken extends FullToken<'Form'> {
rootPrefixCls: string;
}
const resetForm = (token: AliasToken): CSSObject => ({
const resetForm: GenerateStyle<AliasToken, CSSObject> = (token) => ({
legend: {
display: 'block',
width: '100%',
@@ -156,11 +156,10 @@ const genFormSize = (token: FormToken, height: number): CSSObject => {
};
};
const genFormStyle: GenerateStyle<FormToken> = (token) => {
const genFormStyle: GenerateStyle<FormToken, CSSObject> = (token) => {
const { componentCls } = token;
return {
[token.componentCls]: {
[componentCls]: {
...resetComponent(token),
...resetForm(token),
@@ -183,7 +182,7 @@ const genFormStyle: GenerateStyle<FormToken> = (token) => {
};
};
const genFormItemStyle: GenerateStyle<FormToken> = (token) => {
const genFormItemStyle: GenerateStyle<FormToken, CSSObject> = (token) => {
const {
formItemCls,
iconCls,
@@ -424,7 +423,7 @@ const genFormItemStyle: GenerateStyle<FormToken> = (token) => {
};
};
const makeVerticalLayoutLabel = (token: FormToken): CSSObject => ({
const makeVerticalLayoutLabel: GenerateStyle<FormToken, CSSObject> = (token) => ({
padding: token.verticalLabelPadding,
margin: token.verticalLabelMargin,
whiteSpace: 'initial',
@@ -440,7 +439,7 @@ const makeVerticalLayoutLabel = (token: FormToken): CSSObject => ({
},
});
const genHorizontalStyle = (token: FormToken): CSSObject => {
const genHorizontalStyle: GenerateStyle<FormToken, CSSObject> = (token) => {
const { antCls, formItemCls } = token;
return {
@@ -471,7 +470,7 @@ const genHorizontalStyle = (token: FormToken): CSSObject => {
};
};
const genInlineStyle: GenerateStyle<FormToken> = (token) => {
const genInlineStyle: GenerateStyle<FormToken, CSSObject> = (token) => {
const { componentCls, formItemCls, inlineItemMarginBottom } = token;
return {
@@ -510,7 +509,7 @@ const genInlineStyle: GenerateStyle<FormToken> = (token) => {
};
};
const makeVerticalLayout = (token: FormToken): CSSObject => {
const makeVerticalLayout: GenerateStyle<FormToken, CSSObject> = (token) => {
const { componentCls, formItemCls, rootPrefixCls } = token;
return {
@@ -606,10 +605,7 @@ export const prepareComponentToken: GetDefaultToken<'Form'> = (token) => ({
inlineItemMarginBottom: 0,
});
export const prepareToken: (
token: Parameters<GenStyleFn<'Form'>>[0],
rootPrefixCls: string,
) => FormToken = (token, rootPrefixCls) => {
export const prepareToken = (token: Parameters<GenStyleFn<'Form'>>[0], rootPrefixCls: string) => {
const formToken = mergeToken<FormToken>(token, {
formItemCls: `${token.componentCls}-item`,
rootPrefixCls,

View File

@@ -21,7 +21,7 @@ interface GridColToken extends FullToken<'Grid'> {
}
// ============================== Row-Shared ==============================
const genGridRowStyle: GenerateStyle<GridRowToken> = (token): CSSObject => {
const genGridRowStyle: GenerateStyle<GridRowToken, CSSObject> = (token) => {
const { componentCls } = token;
return {
@@ -84,7 +84,7 @@ const genGridRowStyle: GenerateStyle<GridRowToken> = (token): CSSObject => {
};
// ============================== Col-Shared ==============================
const genGridColStyle: GenerateStyle<GridColToken> = (token): CSSObject => {
const genGridColStyle: GenerateStyle<GridColToken, CSSObject> = (token) => {
const { componentCls } = token;
return {

View File

@@ -57,7 +57,7 @@ export const genBoxStyle = (position?: PositionType): CSSObject => ({
inset: 0,
});
export const genImageCoverStyle = (token: ImageToken): CSSObject => {
export const genImageCoverStyle: GenerateStyle<ImageToken, CSSObject> = (token) => {
const { componentCls, motionDurationSlow, colorTextLightSolid } = token;
return {
[componentCls]: {
@@ -90,7 +90,7 @@ export const genImageCoverStyle = (token: ImageToken): CSSObject => {
};
};
export const genImagePreviewStyle: GenerateStyle<ImageToken> = (token: ImageToken) => {
export const genImagePreviewStyle: GenerateStyle<ImageToken, CSSObject> = (token) => {
const {
motionEaseOut,
previewCls,
@@ -255,7 +255,7 @@ export const genImagePreviewStyle: GenerateStyle<ImageToken> = (token: ImageToke
};
};
const genImageStyle: GenerateStyle<ImageToken> = (token: ImageToken) => {
const genImageStyle: GenerateStyle<ImageToken, CSSObject> = (token) => {
const { componentCls } = token;
return {
// ============================== image ==============================
@@ -282,7 +282,7 @@ const genImageStyle: GenerateStyle<ImageToken> = (token: ImageToken) => {
};
};
const genPreviewMotion: GenerateStyle<ImageToken> = (token) => {
const genPreviewMotion: GenerateStyle<ImageToken, CSSObject> = (token) => {
const { previewCls, motionDurationSlow } = token;
return {

View File

@@ -1,3 +1,4 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { unit } from '@ant-design/cssinjs';
import { genBasicInputStyle, genPlaceholderStyle, initInputToken } from '../../input/style';
@@ -324,7 +325,7 @@ const genInputNumberStyles: GenerateStyle<InputNumberToken> = (token) => {
];
};
const genCompatibleStyles: GenerateStyle<InputNumberToken> = (token: InputNumberToken) => {
const genCompatibleStyles: GenerateStyle<InputNumberToken, CSSObject> = (token) => {
const { componentCls, antCls } = token;
return {

View File

@@ -3146,7 +3146,7 @@ Array [
style="width: 100px;"
>
<div
class="ant-select-content ant-select-content-has-value"
class="ant-select-content"
title=""
>
<input

View File

@@ -684,7 +684,7 @@ Array [
style="width:100px"
>
<div
class="ant-select-content ant-select-content-has-value"
class="ant-select-content"
title=""
>
<input

View File

@@ -347,7 +347,7 @@ export const genInputGroupStyle = (token: InputToken): CSSObject => {
};
};
export const genInputStyle: GenerateStyle<InputToken> = (token: InputToken) => {
export const genInputStyle: GenerateStyle<InputToken, CSSObject> = (token) => {
const { componentCls, controlHeightSM, lineWidth, calc } = token;
const FIXED_CHROME_COLOR_HEIGHT = 16;
@@ -426,7 +426,7 @@ const genAllowClearStyle = (token: InputToken): CSSObject => {
};
};
export const genAffixStyle: GenerateStyle<InputToken> = (token: InputToken) => {
export const genAffixStyle: GenerateStyle<InputToken, CSSObject> = (token) => {
const {
componentCls,
inputAffixPadding,
@@ -539,7 +539,7 @@ export const genAffixStyle: GenerateStyle<InputToken> = (token: InputToken) => {
};
};
const genGroupStyle: GenerateStyle<InputToken> = (token: InputToken) => {
const genGroupStyle: GenerateStyle<InputToken, CSSObject> = (token) => {
const { componentCls, borderRadiusLG, borderRadiusSM } = token;
return {
@@ -630,7 +630,7 @@ const genGroupStyle: GenerateStyle<InputToken> = (token: InputToken) => {
};
// ============================== Range ===============================
const genRangeStyle: GenerateStyle<InputToken> = (token) => {
const genRangeStyle: GenerateStyle<InputToken, CSSObject> = (token) => {
const { componentCls } = token;
return {

View File

@@ -1,10 +1,12 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { GenerateStyle } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
import type { InputToken } from './token';
import { initComponentToken, initInputToken } from './token';
// =============================== OTP ================================
const genOTPStyle: GenerateStyle<InputToken> = (token) => {
const genOTPStyle: GenerateStyle<InputToken, CSSObject> = (token) => {
const { componentCls, paddingXS } = token;
return {

View File

@@ -1,7 +1,9 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genStyleHooks } from '../../theme/internal';
const genSearchStyle: GenerateStyle<FullToken<'Input'>> = (token) => {
const genSearchStyle: GenerateStyle<FullToken<'Input'>, CSSObject> = (token) => {
const { componentCls } = token;
const btnCls = `${componentCls}-btn`;

View File

@@ -1,15 +1,16 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { unit } from '@ant-design/cssinjs';
import type { GenerateStyle } from '../../theme/internal';
import { mergeToken } from '../../theme/internal';
import type { InputToken } from './token';
export const genHoverStyle = (token: InputToken): CSSObject => ({
export const genHoverStyle: GenerateStyle<InputToken, CSSObject> = (token) => ({
borderColor: token.hoverBorderColor,
backgroundColor: token.hoverBg,
});
export const genDisabledStyle = (token: InputToken): CSSObject => ({
export const genDisabledStyle: GenerateStyle<InputToken, CSSObject> = (token) => ({
color: token.colorTextDisabled,
backgroundColor: token.colorBgContainerDisabled,
borderColor: token.colorBorder,
@@ -133,7 +134,7 @@ const genOutlinedGroupStatusStyle = (
},
});
export const genOutlinedGroupStyle = (token: InputToken): CSSObject => ({
export const genOutlinedGroupStyle: GenerateStyle<InputToken, CSSObject> = (token) => ({
'&-outlined': {
[`${token.componentCls}-group`]: {
'&-addon': {
@@ -308,7 +309,7 @@ const genFilledGroupStatusStyle = (
},
});
export const genFilledGroupStyle = (token: InputToken): CSSObject => ({
export const genFilledGroupStyle: GenerateStyle<InputToken, CSSObject> = (token) => ({
'&-filled': {
[`${token.componentCls}-group-addon`]: {
background: token.colorFillTertiary,

View File

@@ -81,7 +81,7 @@ interface ListToken extends FullToken<'List'> {
minHeight: number | string;
}
const genBorderedStyle = (token: ListToken): CSSObject => {
const genBorderedStyle: GenerateStyle<ListToken, CSSObject> = (token) => {
const {
listBorderedCls,
componentCls,
@@ -128,7 +128,7 @@ const genBorderedStyle = (token: ListToken): CSSObject => {
},
};
};
const genResponsiveStyle = (token: ListToken): CSSObject => {
const genResponsiveStyle: GenerateStyle<ListToken, CSSObject> = (token) => {
const { componentCls, screenSM, screenMD, marginLG, marginSM, margin } = token;
return {
[`@media screen and (max-width:${screenMD}px)`]: {
@@ -178,7 +178,7 @@ const genResponsiveStyle = (token: ListToken): CSSObject => {
};
// =============================== Base ===============================
const genBaseStyle: GenerateStyle<ListToken> = (token) => {
const genBaseStyle: GenerateStyle<ListToken, CSSObject> = (token) => {
const {
componentCls,
antCls,

View File

@@ -8,7 +8,7 @@ export interface ComponentToken {}
export interface MasonryToken extends FullToken<'Masonry'> {}
export const genMasonryStyle: GenerateStyle<MasonryToken> = (token: MasonryToken): CSSObject => {
export const genMasonryStyle: GenerateStyle<MasonryToken, CSSObject> = (token) => {
const { componentCls } = token;
const itemCls = `${componentCls}-item`;

View File

@@ -406,7 +406,7 @@ export interface MenuToken extends FullToken<'Menu'> {
darkPopupBg: string;
}
const genMenuItemStyle = (token: MenuToken): CSSObject => {
const genMenuItemStyle: GenerateStyle<MenuToken, CSSObject> = (token) => {
const {
componentCls,
motionDurationSlow,
@@ -486,7 +486,7 @@ const genMenuItemStyle = (token: MenuToken): CSSObject => {
};
};
const genSubMenuArrowStyle = (token: MenuToken): CSSObject => {
const genSubMenuArrowStyle: GenerateStyle<MenuToken, CSSObject> = (token) => {
const {
componentCls,
motionDurationSlow,

View File

@@ -39,39 +39,6 @@ exports[`renders components/modal/demo/button-props.tsx extend context correctly
exports[`renders components/modal/demo/button-props.tsx extend context correctly 2`] = `[]`;
exports[`renders components/modal/demo/classNames.tsx extend context correctly 1`] = `
<div
class="ant-space ant-space-horizontal ant-space-align-center ant-space-gap-row-small ant-space-gap-col-small css-var-test-id"
>
<div
class="ant-space-item"
>
<button
class="ant-btn css-var-test-id ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
type="button"
>
<span>
Open Modal
</span>
</button>
</div>
<div
class="ant-space-item"
>
<button
class="ant-btn css-var-test-id ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
type="button"
>
<span>
ConfigProvider
</span>
</button>
</div>
</div>
`;
exports[`renders components/modal/demo/classNames.tsx extend context correctly 2`] = `[]`;
exports[`renders components/modal/demo/component-token.tsx extend context correctly 1`] = `
<div
style="display: flex; flex-direction: column; row-gap: 16px;"

View File

@@ -33,37 +33,6 @@ exports[`renders components/modal/demo/button-props.tsx correctly 1`] = `
</button>
`;
exports[`renders components/modal/demo/classNames.tsx correctly 1`] = `
<div
class="ant-space ant-space-horizontal ant-space-align-center ant-space-gap-row-small ant-space-gap-col-small css-var-test-id"
>
<div
class="ant-space-item"
>
<button
class="ant-btn css-var-test-id ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
type="button"
>
<span>
Open Modal
</span>
</button>
</div>
<div
class="ant-space-item"
>
<button
class="ant-btn css-var-test-id ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
type="button"
>
<span>
ConfigProvider
</span>
</button>
</div>
</div>
`;
exports[`renders components/modal/demo/component-token.tsx correctly 1`] = `
<div
style="display:flex;flex-direction:column;row-gap:16px"

View File

@@ -1,7 +0,0 @@
## zh-CN
通过 `classNames` 属性设置弹窗内部区域header、body、footer、mask、wrapper`className`
## en-US
Set the className of the build-in module (header, body, footer, mask, wrapper) of the modal through the classNames property.

View File

@@ -1,110 +0,0 @@
import React, { useState } from 'react';
import { Button, ConfigProvider, Modal, Space } from 'antd';
import { createStyles, useTheme } from 'antd-style';
const useStyle = createStyles(({ token }) => ({
'my-modal-body': {
background: token.blue1,
padding: token.paddingSM,
},
'my-modal-mask': {
boxShadow: `inset 0 0 15px #fff`,
},
'my-modal-header': {
borderBottom: `1px dotted ${token.colorPrimary}`,
},
'my-modal-footer': {
color: token.colorPrimary,
},
'my-modal-content': {
border: '1px solid #333',
},
}));
const App: React.FC = () => {
const [isModalOpen, setIsModalOpen] = useState([false, false]);
const { styles } = useStyle();
const token = useTheme();
const toggleModal = (idx: number, target: boolean) => {
setIsModalOpen((p) => {
p[idx] = target;
return [...p];
});
};
const classNames = {
body: styles['my-modal-body'],
mask: styles['my-modal-mask'],
header: styles['my-modal-header'],
footer: styles['my-modal-footer'],
content: styles['my-modal-content'],
};
const modalStyles = {
header: {
borderInlineStart: `5px solid ${token.colorPrimary}`,
borderRadius: 0,
paddingInlineStart: 5,
},
body: {
boxShadow: 'inset 0 0 5px #999',
borderRadius: 5,
},
mask: {
backdropFilter: 'blur(10px)',
},
footer: {
borderTop: '1px solid #333',
},
content: {
boxShadow: '0 0 30px #999',
},
};
return (
<>
<Space>
<Button type="primary" onClick={() => toggleModal(0, true)}>
Open Modal
</Button>
<Button type="primary" onClick={() => toggleModal(1, true)}>
ConfigProvider
</Button>
</Space>
<Modal
title="Basic Modal"
open={isModalOpen[0]}
onOk={() => toggleModal(0, false)}
onCancel={() => toggleModal(0, false)}
footer="Footer"
classNames={classNames}
styles={modalStyles}
>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</Modal>
<ConfigProvider
modal={{
classNames,
styles: modalStyles,
}}
>
<Modal
title="Basic Modal"
open={isModalOpen[1]}
onOk={() => toggleModal(1, false)}
onCancel={() => toggleModal(1, false)}
footer="Footer"
>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</Modal>
</ConfigProvider>
</>
);
};
export default App;

View File

@@ -60,8 +60,8 @@ const stylesFn: ModalProps['styles'] = (info) => {
};
const App: React.FC = () => {
const [modalOpen, setOpen] = useState(false);
const [modalFnOpen, setFnOpen] = useState(false);
const [modalOpen, setModalOpen] = useState(false);
const [modalFnOpen, setModalFnOpen] = useState(false);
const sharedProps: ModalProps = {
centered: true,
@@ -71,7 +71,7 @@ const App: React.FC = () => {
const footer: React.ReactNode = (
<>
<Button
onClick={() => setFnOpen(false)}
onClick={() => setModalFnOpen(false)}
styles={{ root: { borderColor: '#ccc', color: '#171717', backgroundColor: '#fff' } }}
>
Cancel
@@ -79,7 +79,7 @@ const App: React.FC = () => {
<Button
type="primary"
styles={{ root: { backgroundColor: '#171717' } }}
onClick={() => setOpen(true)}
onClick={() => setModalOpen(true)}
>
Submit
</Button>
@@ -88,8 +88,8 @@ const App: React.FC = () => {
return (
<Flex gap="middle">
<Button onClick={() => setOpen(true)}>Open Style Modal</Button>
<Button type="primary" onClick={() => setFnOpen(true)}>
<Button onClick={() => setModalOpen(true)}>Open Style Modal</Button>
<Button type="primary" onClick={() => setModalFnOpen(true)}>
Open Function Modal
</Button>
<Modal
@@ -98,8 +98,8 @@ const App: React.FC = () => {
title="Custom Style Modal"
styles={styles}
open={modalOpen}
onOk={() => setOpen(false)}
onCancel={() => setOpen(false)}
onOk={() => setModalOpen(false)}
onCancel={() => setModalOpen(false)}
>
{sharedContent}
</Modal>
@@ -110,8 +110,8 @@ const App: React.FC = () => {
styles={stylesFn}
mask={{ enabled: true, blur: true }}
open={modalFnOpen}
onOk={() => setFnOpen(false)}
onCancel={() => setFnOpen(false)}
onOk={() => setModalFnOpen(false)}
onCancel={() => setModalFnOpen(false)}
>
{sharedContent}
</Modal>

View File

@@ -34,7 +34,6 @@ Additionally, if you need to show a simple confirmation dialog, you can use [`Ap
<code src="./demo/width.tsx">To customize the width of modal</code>
<code src="./demo/static-info.tsx">Static Method</code>
<code src="./demo/confirm.tsx">Static confirmation</code>
<code src="./demo/classNames.tsx">Customize className for build-in module</code>
<code src="./demo/confirm-router.tsx">destroy confirmation modal dialog</code>
<code src="./demo/style-class.tsx" version="6.0.0">Custom semantic dom styling</code>
<code src="./demo/nested.tsx" debug>Nested Modal</code>

View File

@@ -35,7 +35,6 @@ demo:
<code src="./demo/width.tsx">自定义模态的宽度</code>
<code src="./demo/static-info.tsx">静态方法</code>
<code src="./demo/confirm.tsx">静态确认对话框</code>
<code src="./demo/classNames.tsx">自定义内部模块 className</code>
<code src="./demo/confirm-router.tsx">销毁确认对话框</code>
<code src="./demo/style-class.tsx" version="6.0.0">自定义语义结构的样式和类</code>
<code src="./demo/nested.tsx" debug>嵌套弹框</code>

View File

@@ -1,4 +1,5 @@
import type React from 'react';
import type { CSSObject } from '@ant-design/cssinjs';
import { unit } from '@ant-design/cssinjs';
import { getMediaSize } from '../../grid/style';
@@ -396,7 +397,7 @@ const genRTLStyle: GenerateStyle<ModalToken> = (token) => {
};
};
const genResponsiveWidthStyle: GenerateStyle<ModalToken> = (token) => {
const genResponsiveWidthStyle: GenerateStyle<ModalToken, CSSObject> = (token) => {
const { componentCls } = token;
const oriGridMediaSizesMap: Record<string, number> = getMediaSize(token);
@@ -434,7 +435,7 @@ const genResponsiveWidthStyle: GenerateStyle<ModalToken> = (token) => {
};
// ============================== Export ==============================
export const prepareToken: (token: Parameters<GenStyleFn<'Modal'>>[0]) => ModalToken = (token) => {
export const prepareToken = (token: Parameters<GenStyleFn<'Modal'>>[0]) => {
const headerPaddingVertical = token.padding;
const headerFontSize = token.fontSizeHeading5;
const headerLineHeight = token.lineHeightHeading5;

View File

@@ -109,7 +109,7 @@ export interface NotificationToken extends FullToken<'Notification'> {
notificationProgressHeight: number;
}
export const genNoticeStyle = (token: NotificationToken): CSSObject => {
export const genNoticeStyle: GenerateStyle<NotificationToken, CSSObject> = (token) => {
const {
iconCls,
componentCls, // .ant-notification

View File

@@ -30,7 +30,7 @@ const genPlacementStackStyle = (
};
};
const genStackChildrenStyle = (token: NotificationToken): CSSObject => {
const genStackChildrenStyle: GenerateStyle<NotificationToken, CSSObject> = (token) => {
const childrenStyle: CSSObject = {};
for (let i = 1; i < token.notificationStackLayer; i++) {
childrenStyle[`&:nth-last-child(${i + 1})`] = {

View File

@@ -148,7 +148,7 @@ const Pagination: React.FC<PaginationProps> = (props) => {
// Generate options
const mergedPageSizeOptions = React.useMemo(() => {
return pageSizeOptions ? pageSizeOptions.map((option) => Number(option)) : undefined;
return pageSizeOptions ? pageSizeOptions.map<number>(Number) : undefined;
}, [pageSizeOptions]);
// Render size changer

View File

@@ -147,6 +147,7 @@ const genLineStyle: GenerateStyle<ProgressToken> = (token) => {
borderRadius: token.lineBorderRadius,
position: 'relative',
width: '100%',
overflow: 'hidden',
},
[`&${componentCls}-status-active`]: {
@@ -301,7 +302,7 @@ const genCircleStyle: GenerateStyle<ProgressToken> = (token) => {
// ====================================================================
// == Step ==
// ====================================================================
const genStepStyle: GenerateStyle<ProgressToken> = (token: ProgressToken): CSSObject => {
const genStepStyle: GenerateStyle<ProgressToken, CSSObject> = (token) => {
const { componentCls: progressCls } = token;
return {
@@ -336,7 +337,7 @@ const genStepStyle: GenerateStyle<ProgressToken> = (token: ProgressToken): CSSOb
// ====================================================================
// == Small Line ==
// ====================================================================
const genSmallLine: GenerateStyle<ProgressToken> = (token: ProgressToken): CSSObject => {
const genSmallLine: GenerateStyle<ProgressToken, CSSObject> = (token) => {
const { componentCls: progressCls, iconCls: iconPrefixCls } = token;
return {

View File

@@ -98,13 +98,13 @@ const genRateStarStyle: GenerateStyle<RateToken, CSSObject> = (token) => {
};
};
const genRateRtlStyle = (token: RateToken): CSSObject => ({
const genRateRtlStyle: GenerateStyle<RateToken, CSSObject> = (token) => ({
[`&-rtl${token.componentCls}`]: {
direction: 'rtl',
},
});
const genRateStyle: GenerateStyle<RateToken> = (token) => {
const genRateStyle: GenerateStyle<RateToken, CSSObject> = (token) => {
const { componentCls } = token;
return {

View File

@@ -38,7 +38,7 @@ interface ResultToken extends FullToken<'Result'> {
}
// ============================== Styles ==============================
const genBaseStyle: GenerateStyle<ResultToken> = (token): CSSObject => {
const genBaseStyle: GenerateStyle<ResultToken, CSSObject> = (token) => {
const {
componentCls,
lineHeightHeading3,

View File

@@ -63,12 +63,12 @@ function getItemDisabledStyle(cls: string, token: SegmentedToken): CSSObject {
};
}
function getItemSelectedStyle(token: SegmentedToken): CSSObject {
const getItemSelectedStyle: GenerateStyle<SegmentedToken, CSSObject> = (token) => {
return {
background: token.itemSelectedBg,
boxShadow: token.boxShadowTertiary,
};
}
};
const segmentedTextEllipsisCss: CSSObject = {
overflow: 'hidden',
@@ -77,7 +77,7 @@ const segmentedTextEllipsisCss: CSSObject = {
};
// ============================== Styles ==============================
const genSegmentedStyle: GenerateStyle<SegmentedToken> = (token: SegmentedToken) => {
const genSegmentedStyle: GenerateStyle<SegmentedToken, CSSObject> = (token) => {
const { componentCls, motionDurationSlow, motionEaseInOut, motionDurationMid } = token;
const labelHeight = token

View File

@@ -1778,7 +1778,9 @@ Array [
exports[`renders components/select/demo/custom-tag-render.tsx extend context correctly 2`] = `[]`;
exports[`renders components/select/demo/debug.tsx extend context correctly 1`] = `
Array [
<div
class="ant-flex css-var-test-id ant-flex-align-stretch ant-flex-gap-middle ant-flex-vertical"
>
<div
class="ant-space ant-space-horizontal ant-space-align-center ant-space-gap-row-small ant-space-gap-col-small css-var-test-id"
style="flex-wrap: wrap; width: 500px; position: relative; z-index: 1; border: 1px solid red; background-color: rgb(255, 255, 255);"
@@ -2210,9 +2212,184 @@ Array [
</span>
</button>
</div>
</div>,
<div
class="ant-space-item"
>
<div
class="ant-select ant-select-outlined css-var-test-id ant-select-css-var ant-select-single ant-select-show-arrow"
style="width: 120px;"
>
<div
class="ant-select-content"
title=" "
>
<input
aria-autocomplete="list"
aria-expanded="false"
aria-haspopup="listbox"
autocomplete="off"
class="ant-select-input"
id="test-id"
readonly=""
role="combobox"
type="search"
value=""
/>
</div>
<div
class="ant-select-suffix"
>
<span
aria-label="down"
class="anticon anticon-down"
role="img"
>
<svg
aria-hidden="true"
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
/>
</svg>
</span>
</div>
</div>
<div
class="ant-select-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up css-var-test-id ant-select-css-var ant-select-dropdown-placement-bottomLeft"
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; right: auto; bottom: auto; box-sizing: border-box;"
>
<div>
<div
id="test-id_list"
role="listbox"
style="height: 0px; width: 0px; overflow: hidden;"
>
<div
aria-label="Jack"
aria-selected="false"
id="test-id_list_0"
role="option"
>
jack
</div>
<div
aria-label="Lucy"
aria-selected="false"
id="test-id_list_1"
role="option"
>
lucy
</div>
</div>
<div
class="rc-virtual-list"
style="position: relative;"
>
<div
class="rc-virtual-list-holder"
style="max-height: 256px; overflow-y: auto; overflow-anchor: none;"
>
<div>
<div
class="rc-virtual-list-holder-inner"
style="display: flex; flex-direction: column;"
>
<div
class="ant-select-item ant-select-item-option ant-select-item-option-active"
title="Jack"
>
<div
class="ant-select-item-option-content"
>
Jack
</div>
<span
aria-hidden="true"
class="ant-select-item-option-state"
style="user-select: none;"
unselectable="on"
/>
</div>
<div
class="ant-select-item ant-select-item-option"
title="Lucy"
>
<div
class="ant-select-item-option-content"
>
Lucy
</div>
<span
aria-hidden="true"
class="ant-select-item-option-state"
style="user-select: none;"
unselectable="on"
/>
</div>
<div
class="ant-select-item ant-select-item-option ant-select-item-option-disabled"
title="Disabled"
>
<div
class="ant-select-item-option-content"
>
Disabled
</div>
<span
aria-hidden="true"
class="ant-select-item-option-state"
style="user-select: none;"
unselectable="on"
/>
</div>
<div
class="ant-select-item ant-select-item-option"
title="yiminghe"
>
<div
class="ant-select-item-option-content"
>
yiminghe
</div>
<span
aria-hidden="true"
class="ant-select-item-option-state"
style="user-select: none;"
unselectable="on"
/>
</div>
<div
class="ant-select-item ant-select-item-option"
title="I am super super long!"
>
<div
class="ant-select-item-option-content"
>
I am super super long!
</div>
<span
aria-hidden="true"
class="ant-select-item-option-state"
style="user-select: none;"
unselectable="on"
/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div
style="width: 200px; margin-top: 24px;"
style="width: 200px;"
>
<div
class="ant-select ant-select-outlined css-var-test-id ant-select-css-var ant-select-multiple ant-select-show-arrow ant-select-show-search"
@@ -2379,8 +2556,113 @@ Array [
</div>
</div>
</div>
</div>,
]
</div>
<div
class="ant-select ant-select-outlined css-var-test-id ant-select-css-var ant-select-single ant-select-show-arrow"
>
<div
class="ant-select-content"
title=""
>
<input
aria-autocomplete="list"
aria-expanded="false"
aria-haspopup="listbox"
autocomplete="off"
class="ant-select-input"
id="test-id"
readonly=""
role="combobox"
type="search"
value=""
/>
</div>
<div
class="ant-select-suffix"
>
<span
aria-label="down"
class="anticon anticon-down"
role="img"
>
<svg
aria-hidden="true"
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
/>
</svg>
</span>
</div>
</div>
<div
class="ant-select-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up css-var-test-id ant-select-css-var ant-select-dropdown-empty ant-select-dropdown-placement-bottomLeft"
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; right: auto; bottom: auto; box-sizing: border-box;"
>
<div>
<div
class="ant-select-item-empty"
id="test-id_list"
role="listbox"
>
<div
class="css-var-test-id ant-empty ant-empty-normal ant-empty-small"
>
<div
class="ant-empty-image"
>
<svg
height="41"
viewBox="0 0 64 41"
width="64"
xmlns="http://www.w3.org/2000/svg"
>
<title>
No data
</title>
<g
fill="none"
fill-rule="evenodd"
transform="translate(0 1)"
>
<ellipse
cx="32"
cy="33"
fill="#f5f5f5"
rx="32"
ry="7"
/>
<g
fill-rule="nonzero"
stroke="#d9d9d9"
>
<path
d="M55 12.8 44.9 1.3Q44 0 42.9 0H21.1q-1.2 0-2 1.3L9 12.8V22h46z"
/>
<path
d="M41.6 16c0-1.7 1-3 2.2-3H55v18.1c0 2.2-1.3 3.9-3 3.9H12c-1.7 0-3-1.7-3-3.9V13h11.2c1.2 0 2.2 1.3 2.2 3s1 2.9 2.2 2.9h14.8c1.2 0 2.2-1.4 2.2-3"
fill="#fafafa"
/>
</g>
</g>
</svg>
</div>
<div
class="ant-empty-description"
>
No data
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`renders components/select/demo/debug.tsx extend context correctly 2`] = `[]`;

View File

@@ -741,7 +741,9 @@ exports[`renders components/select/demo/custom-tag-render.tsx correctly 1`] = `
`;
exports[`renders components/select/demo/debug.tsx correctly 1`] = `
Array [
<div
class="ant-flex css-var-test-id ant-flex-align-stretch ant-flex-gap-middle ant-flex-vertical"
>
<div
class="ant-space ant-space-horizontal ant-space-align-center ant-space-gap-row-small ant-space-gap-col-small css-var-test-id"
style="flex-wrap:wrap;width:500px;position:relative;z-index:1;border:1px solid red;background-color:#fff"
@@ -924,9 +926,58 @@ Array [
</span>
</button>
</div>
</div>,
<div
class="ant-space-item"
>
<div
class="ant-select ant-select-outlined css-var-test-id ant-select-css-var ant-select-single ant-select-show-arrow"
style="width:120px"
>
<div
class="ant-select-content"
title=" "
>
<input
aria-autocomplete="list"
aria-expanded="false"
aria-haspopup="listbox"
autocomplete="off"
class="ant-select-input"
id="test-id"
readonly=""
role="combobox"
type="search"
value=""
/>
</div>
<div
class="ant-select-suffix"
>
<span
aria-label="down"
class="anticon anticon-down"
role="img"
>
<svg
aria-hidden="true"
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
/>
</svg>
</span>
</div>
</div>
</div>
</div>
<div
style="width:200px;margin-top:24px"
style="width:200px"
>
<div
class="ant-select ant-select-outlined css-var-test-id ant-select-css-var ant-select-multiple ant-select-show-arrow ant-select-show-search"
@@ -1018,8 +1069,52 @@ Array [
</span>
</div>
</div>
</div>,
]
</div>
<div
class="ant-select ant-select-outlined css-var-test-id ant-select-css-var ant-select-single ant-select-show-arrow"
>
<div
class="ant-select-content"
title=""
>
<input
aria-autocomplete="list"
aria-expanded="false"
aria-haspopup="listbox"
autocomplete="off"
class="ant-select-input"
id="test-id"
readonly=""
role="combobox"
type="search"
value=""
/>
</div>
<div
class="ant-select-suffix"
>
<span
aria-label="down"
class="anticon anticon-down"
role="img"
>
<svg
aria-hidden="true"
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
/>
</svg>
</span>
</div>
</div>
</div>
`;
exports[`renders components/select/demo/debug-flip-shift.tsx correctly 1`] = `

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Button, Input, Select, Space } from 'antd';
import { Button, Flex, Input, Select, Space } from 'antd';
const style: React.CSSProperties = {
width: 500,
@@ -14,7 +14,7 @@ const handleChange = (value: string | string[]) => {
};
const App: React.FC = () => (
<>
<Flex vertical gap="middle">
<Space style={style} wrap>
<Input style={{ width: 100 }} value="222" />
<Select
@@ -47,8 +47,21 @@ const App: React.FC = () => (
/>
<span className="debug-align">AntDesign</span>
<Button>222</Button>
{/* https://github.com/ant-design/ant-design/issues/56960 */}
<Select
style={{ width: 120 }}
defaultValue=" "
placeholder="Please select"
options={[
{ value: 'jack', label: 'Jack' },
{ value: 'lucy', label: 'Lucy' },
{ value: 'disabled', disabled: true, label: 'Disabled' },
{ value: 'Yiminghe', label: 'yiminghe' },
{ value: 'long', label: 'I am super super long!' },
]}
/>
</Space>
<div style={{ width: 200, marginTop: 24 }}>
<div style={{ width: 200 }}>
{/* https://github.com/ant-design/ant-design/issues/54179 */}
<Select
mode="multiple"
@@ -62,7 +75,9 @@ const App: React.FC = () => (
]}
/>
</div>
</>
<Select defaultValue="" />
</Flex>
);
export default App;

View File

@@ -15,12 +15,12 @@ const randomOptions = (count?: number) => {
};
const App: React.FC = () => {
const [placement, SetPlacement] = useState<SelectCommonPlacement>('topLeft');
const [placement, setPlacement] = useState<SelectCommonPlacement>('topLeft');
const [open, setOpen] = useState(false);
const [options, setOptions] = useState(() => randomOptions(3));
const placementChange = (e: RadioChangeEvent) => {
SetPlacement(e.target.value);
setPlacement(e.target.value);
};
return (

View File

@@ -5,10 +5,10 @@ import { Radio, Select } from 'antd';
type SelectCommonPlacement = SelectProps['placement'];
const App: React.FC = () => {
const [placement, SetPlacement] = useState<SelectCommonPlacement>('topLeft');
const [placement, setPlacement] = useState<SelectCommonPlacement>('topLeft');
const placementChange = (e: RadioChangeEvent) => {
SetPlacement(e.target.value);
setPlacement(e.target.value);
};
return (

View File

@@ -121,6 +121,10 @@ const genSingleStyle: GenerateStyle<SelectToken> = (token) => {
alignItems: 'center',
},
[`&-active:not(${selectItemCls}-option-disabled)`]: {
backgroundColor: token.optionActiveBg,
},
[`&-selected:not(${selectItemCls}-option-disabled)`]: {
color: token.optionSelectedColor,
fontWeight: token.optionSelectedFontWeight,
@@ -131,10 +135,6 @@ const genSingleStyle: GenerateStyle<SelectToken> = (token) => {
},
},
[`&-active:not(${selectItemCls}-option-disabled)`]: {
backgroundColor: token.optionActiveBg,
},
'&-disabled': {
[`&${selectItemCls}-option-selected`]: {
backgroundColor: token.colorBgContainerDisabled,

View File

@@ -12,7 +12,7 @@ import { prepareComponentToken } from './token';
export type { ComponentToken };
// =============================== Base ===============================
const genBaseStyle: GenerateStyle<SelectToken> = (token) => {
const genBaseStyle: GenerateStyle<SelectToken, CSSObject> = (token) => {
const { antCls, componentCls, motionDurationMid, inputPaddingHorizontalBase } = token;
const hoverShowClearStyle: CSSObject = {

View File

@@ -1,7 +1,9 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { GenerateStyle } from '../../theme/interface';
import type { SelectToken } from './token';
const genSelectInputCustomizeStyle: GenerateStyle<SelectToken> = (token) => {
const genSelectInputCustomizeStyle: GenerateStyle<SelectToken, CSSObject> = (token) => {
const { componentCls } = token;
return {

View File

@@ -89,7 +89,7 @@ const genSelectInputVariantStyle = (
};
};
const genSelectInputStyle: GenerateStyle<SelectToken> = (token) => {
const genSelectInputStyle: GenerateStyle<SelectToken, CSSObject> = (token) => {
const { componentCls, fontHeight, controlHeight, iconCls, antCls, calc } = token;
const [varName, varRef] = genCssVar(antCls, 'select');
return {

View File

@@ -74,7 +74,7 @@ const genSkeletonElementSize = (size: number | string): CSSObject => ({
...genSkeletonElementCommonSize(size),
});
const genSkeletonColor = (token: SkeletonToken): CSSObject => ({
const genSkeletonColor: GenerateStyle<SkeletonToken, CSSObject> = (token) => ({
background: token.skeletonLoadingBackground,
backgroundSize: '400% 100%',
animationName: skeletonClsLoading,
@@ -82,13 +82,14 @@ const genSkeletonColor = (token: SkeletonToken): CSSObject => ({
animationTimingFunction: 'ease',
animationIterationCount: 'infinite',
});
const genSkeletonElementInputSize = (size: number, calc: CSSUtil['calc']): CSSObject => ({
width: calc(size).mul(5).equal(),
minWidth: calc(size).mul(5).equal(),
...genSkeletonElementCommonSize(size),
});
const genSkeletonElementAvatar = (token: SkeletonToken): CSSObject => {
const genSkeletonElementAvatar: GenerateStyle<SkeletonToken, CSSObject> = (token) => {
const { skeletonAvatarCls, gradientFromColor, controlHeight, controlHeightLG, controlHeightSM } =
token;
return {
@@ -110,7 +111,7 @@ const genSkeletonElementAvatar = (token: SkeletonToken): CSSObject => {
};
};
const genSkeletonElementInput = (token: SkeletonToken): CSSObject => {
const genSkeletonElementInput: GenerateStyle<SkeletonToken, CSSObject> = (token) => {
const {
controlHeight,
borderRadiusSM,
@@ -139,7 +140,7 @@ const genSkeletonElementInput = (token: SkeletonToken): CSSObject => {
};
};
const genSkeletonElementShape = (token: SkeletonToken): CSSObject => {
const genSkeletonElementShape: GenerateStyle<SkeletonToken, CSSObject> = (token) => {
const { gradientFromColor, borderRadiusSM, imageSizeBase, calc } = token;
return {
display: 'inline-flex',
@@ -152,7 +153,7 @@ const genSkeletonElementShape = (token: SkeletonToken): CSSObject => {
};
};
const genSkeletonElementNode = (token: SkeletonToken): CSSObject => {
const genSkeletonElementNode: GenerateStyle<SkeletonToken, CSSObject> = (token) => {
return {
[token.skeletonNodeCls]: {
...genSkeletonElementShape(token),
@@ -160,7 +161,7 @@ const genSkeletonElementNode = (token: SkeletonToken): CSSObject => {
};
};
const genSkeletonElementImage = (token: SkeletonToken): CSSObject => {
const genSkeletonElementImage: GenerateStyle<SkeletonToken, CSSObject> = (token) => {
const { skeletonImageCls, imageSizeBase, calc } = token;
return {
@@ -209,7 +210,7 @@ const genSkeletonElementButtonSize = (size: number, calc: CSSUtil['calc']): CSSO
...genSkeletonElementCommonSize(size),
});
const genSkeletonElementButton = (token: SkeletonToken): CSSObject => {
const genSkeletonElementButton: GenerateStyle<SkeletonToken, CSSObject> = (token) => {
const {
borderRadiusSM,
skeletonButtonCls,
@@ -244,7 +245,7 @@ const genSkeletonElementButton = (token: SkeletonToken): CSSObject => {
};
// =============================== Base ===============================
const genBaseStyle: GenerateStyle<SkeletonToken> = (token: SkeletonToken) => {
const genBaseStyle: GenerateStyle<SkeletonToken, CSSObject> = (token) => {
const {
componentCls,
skeletonAvatarCls,

View File

@@ -16066,28 +16066,6 @@ exports[`renders components/space/demo/compact-nested.tsx extend context correct
exports[`renders components/space/demo/compact-nested.tsx extend context correctly 2`] = `[]`;
exports[`renders components/space/demo/component-token.tsx extend context correctly 1`] = `
<div
class="ant-space-compact"
>
<div
class="ant-space-addon ant-space-addon-compact-item ant-space-addon-compact-first-item css-var-test-id ant-space-addon-variant-outlined"
>
Addon
</div>
<button
class="ant-btn css-var-test-id ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-compact-item ant-btn-compact-last-item"
type="button"
>
<span>
Button
</span>
</button>
</div>
`;
exports[`renders components/space/demo/component-token.tsx extend context correctly 2`] = `[]`;
exports[`renders components/space/demo/debug.tsx extend context correctly 1`] = `
<div
class="ant-space ant-space-horizontal ant-space-align-center ant-space-gap-row-small ant-space-gap-col-small css-var-test-id"

View File

@@ -4097,26 +4097,6 @@ exports[`renders components/space/demo/compact-nested.tsx correctly 1`] = `
</div>
`;
exports[`renders components/space/demo/component-token.tsx correctly 1`] = `
<div
class="ant-space-compact"
>
<div
class="ant-space-addon ant-space-addon-compact-item ant-space-addon-compact-first-item css-var-test-id ant-space-addon-variant-outlined"
>
Addon
</div>
<button
class="ant-btn css-var-test-id ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-compact-item ant-btn-compact-last-item"
type="button"
>
<span>
Button
</span>
</button>
</div>
`;
exports[`renders components/space/demo/debug.tsx correctly 1`] = `
<div
class="ant-space ant-space-horizontal ant-space-align-center ant-space-gap-row-small ant-space-gap-col-small css-var-test-id"

View File

@@ -1,7 +0,0 @@
## zh-CN
使用 `ConfigProvider` 自定义 `Space.Addon` 的主题样式。
## en-US
Use `ConfigProvider` to customize the theme of `Space.Addon`.

View File

@@ -1,19 +0,0 @@
import React from 'react';
import { Button, ConfigProvider, Space } from 'antd';
const App: React.FC = () => (
<ConfigProvider
theme={{
components: {
Addon: { colorText: 'blue', algorithm: true },
},
}}
>
<Space.Compact>
<Space.Addon>Addon</Space.Addon>
<Button type="primary">Button</Button>
</Space.Compact>
</ConfigProvider>
);
export default App;

View File

@@ -34,7 +34,6 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*37T2R6O9oi0AAA
<code src="./demo/debug.tsx" debug>Diverse Child</code>
<code src="./demo/gap-in-line.tsx" debug>Flex gap style</code>
<code src="./demo/style-class.tsx" version="6.0.0">Custom semantic dom styling</code>
<code src="./demo/component-token.tsx" debug>Customize Addon with theme</code>
## API

View File

@@ -38,7 +38,6 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*37T2R6O9oi0AAA
<code src="./demo/debug.tsx" debug>多样的 Child</code>
<code src="./demo/gap-in-line.tsx" debug>Flex gap 样式</code>
<code src="./demo/style-class.tsx" version="6.0.0">自定义语义结构的样式和类</code>
<code src="./demo/component-token.tsx" debug>自定义主题</code>
## API

View File

@@ -1,4 +1,3 @@
import { resetComponent } from '../../style';
import { genCompactItemStyle } from '../../style/compact-item';
import { genStyleHooks } from '../../theme/internal';
import type { FullToken, GenerateStyle } from '../../theme/internal';
@@ -8,11 +7,11 @@ import { genCssVar } from '../../theme/util/genStyleUtils';
// biome-ignore lint/suspicious/noEmptyInterface: ComponentToken need to be empty by default
export interface ComponentToken {}
interface AddonToken extends FullToken<'Space'> {
interface SpaceToken extends FullToken<'Space'> {
// Custom token here
}
const genSpaceAddonStyle: GenerateStyle<AddonToken> = (token) => {
const genSpaceAddonStyle: GenerateStyle<SpaceToken> = (token) => {
const {
componentCls,
borderRadius,
@@ -28,7 +27,7 @@ const genSpaceAddonStyle: GenerateStyle<AddonToken> = (token) => {
antCls,
} = token;
const [varName, varRef] = genCssVar(antCls, 'space-addon');
const [varName, varRef] = genCssVar(antCls, 'space');
return {
[componentCls]: [
@@ -36,7 +35,6 @@ const genSpaceAddonStyle: GenerateStyle<AddonToken> = (token) => {
// == Base ==
// ==========================================================
{
...resetComponent(token),
display: 'inline-flex',
alignItems: 'center',
gap: 0,
@@ -146,7 +144,7 @@ const genSpaceAddonStyle: GenerateStyle<AddonToken> = (token) => {
};
// ============================== Export ==============================
export default genStyleHooks('Addon', (token) => [
export default genStyleHooks(['Space', 'Addon'], (token) => [
genSpaceAddonStyle(token),
genCompactItemStyle(token, { focus: false }),
]);

View File

@@ -41,7 +41,7 @@ const centerStyle: CSSObject = {
transform: 'translate(-50%, -50%)',
};
const genSplitterStyle: GenerateStyle<SplitterToken> = (token: SplitterToken): CSSObject => {
const genSplitterStyle: GenerateStyle<SplitterToken, CSSObject> = (token) => {
const {
componentCls,
colorFill,

Some files were not shown because too many files have changed in this diff Show More