chore: auto merge branches (#46232)

merge feature into master
This commit is contained in:
github-actions[bot] 2023-12-04 03:38:52 +00:00 committed by GitHub
commit d019521f74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
298 changed files with 5698 additions and 3768 deletions

View File

@ -68,6 +68,7 @@ const useThemeAnimation = () => {
if (!(event && typeof document.startViewTransition === 'function')) {
return;
}
const time = Date.now();
const x = event.clientX;
const y = event.clientY;
const endRadius = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y));
@ -98,6 +99,7 @@ const useThemeAnimation = () => {
root.classList.add(isDark ? 'light' : 'dark');
})
.ready.then(() => {
console.log(`Theme transition finished in ${Date.now() - time}ms`);
const clipPath = [
`circle(0px at ${x}px ${y}px)`,
`circle(${endRadius}px at ${x}px ${y}px)`,

View File

@ -403,7 +403,6 @@ export default function Theme() {
...themeToken,
colorPrimary: colorPrimaryValue,
},
hashed: true,
algorithm: algorithmFn,
components: {
Layout: isLight

View File

@ -1,15 +1,36 @@
import React, { useContext } from 'react';
import { DumiDemoGrid, FormattedMessage } from 'dumi';
import { BugFilled, BugOutlined, CodeFilled, CodeOutlined } from '@ant-design/icons';
import {
BugFilled,
BugOutlined,
CodeFilled,
CodeOutlined,
ExperimentFilled,
ExperimentOutlined,
} from '@ant-design/icons';
import classNames from 'classnames';
import { Tooltip } from 'antd';
import { ConfigProvider, Tooltip } from 'antd';
import DemoContext from '../../slots/DemoContext';
import useLayoutState from '../../../hooks/useLayoutState';
import useLocale from '../../../hooks/useLocale';
const locales = {
cn: {
enableCssVar: '启用 CSS 变量',
disableCssVar: '禁用 CSS 变量',
},
en: {
enableCssVar: 'Enable CSS Var',
disableCssVar: 'Disable CSS Var',
},
};
const DemoWrapper: typeof DumiDemoGrid = ({ items }) => {
const { showDebug, setShowDebug } = useContext(DemoContext);
const [locale] = useLocale(locales);
const [expandAll, setExpandAll] = useLayoutState(false);
const [enableCssVar, setEnableCssVar] = useLayoutState(true);
const expandTriggerClass = classNames('code-box-expand-trigger', {
'code-box-expand-trigger-active': expandAll,
@ -23,9 +44,14 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => {
setExpandAll(!expandAll);
};
const handleCssVarToggle = () => {
setEnableCssVar((v) => !v);
};
const demos = React.useMemo(
() =>
items.reduce((acc, item) => {
items.reduce(
(acc, item) => {
const { previewerProps } = item;
const { debug } = previewerProps;
@ -45,7 +71,9 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => {
originDebug: debug,
},
});
}, [] as typeof items),
},
[] as typeof items,
),
[expandAll, showDebug],
);
@ -74,8 +102,17 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => {
<BugOutlined className={expandTriggerClass} onClick={handleVisibleToggle} />
)}
</Tooltip>
<Tooltip title={enableCssVar ? locale.disableCssVar : locale.enableCssVar}>
{enableCssVar ? (
<ExperimentFilled className={expandTriggerClass} onClick={handleCssVarToggle} />
) : (
<ExperimentOutlined className={expandTriggerClass} onClick={handleCssVarToggle} />
)}
</Tooltip>
</span>
<ConfigProvider theme={{ cssVar: enableCssVar, hashed: !enableCssVar }}>
<DumiDemoGrid items={demos} />
</ConfigProvider>
</div>
);
};

View File

@ -5,7 +5,7 @@ import stackblitzSdk from '@stackblitz/sdk';
import { Alert, Badge, Space, Tooltip } from 'antd';
import { createStyles, css } from 'antd-style';
import classNames from 'classnames';
import { FormattedMessage, useSiteData, LiveContext } from 'dumi';
import { FormattedMessage, LiveContext, useSiteData } from 'dumi';
import LZString from 'lz-string';
import type { AntdPreviewerProps } from './Previewer';

View File

@ -4,7 +4,7 @@ import {
createCache,
extractStyle,
legacyNotSelectorLinter,
logicalPropertiesLinter,
NaNLinter,
parentSelectorLinter,
StyleProvider,
} from '@ant-design/cssinjs';
@ -45,7 +45,7 @@ const getAlgorithm = (themes: ThemeName[] = []) =>
}
return null;
})
.filter((item) => item) as typeof antdTheme.darkAlgorithm[];
.filter((item) => item) as (typeof antdTheme.darkAlgorithm)[];
const GlobalLayout: React.FC = () => {
const outlet = useOutlet();
@ -168,7 +168,7 @@ const GlobalLayout: React.FC = () => {
<DarkContext.Provider value={theme.includes('dark')}>
<StyleProvider
cache={styleCache}
linters={[logicalPropertiesLinter, legacyNotSelectorLinter, parentSelectorLinter]}
linters={[legacyNotSelectorLinter, parentSelectorLinter, NaNLinter]}
>
<SiteContext.Provider value={siteContextValue}>
<SiteThemeProvider
@ -177,6 +177,8 @@ const GlobalLayout: React.FC = () => {
token: {
motion: !theme.includes('motion-off'),
},
cssVar: true,
hashed: false,
}}
>
<HappyProvider disabled={!theme.includes('happy-work')}>{content}</HappyProvider>

View File

@ -166,7 +166,7 @@ const RoutesPlugin = (api: IApi) => {
});
// Insert antd style to head
const matchRegex = /<style data-type="antd-cssinjs">(.*?)<\/style>/;
const matchRegex = /<style data-type="antd-cssinjs">([\S\s]+?)<\/style>/;
const matchList = file.content.match(matchRegex) || [];
let antdStyle = '';

View File

@ -41,7 +41,6 @@ An enterprise-class UI design language and React UI library.
[dumi-image]: https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square
[dumi-url]: https://github.com/umijs/dumi
<!-- Copy-paste in your Readme.md file -->
<a href="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats?repo_id=34526884" target="_blank" style="display: block" align="center">

View File

@ -0,0 +1 @@
# antd-image-snapshots

View File

@ -1,7 +1,7 @@
/* eslint-disable default-case */
import type { AlignType, BuildInPlacements } from '@rc-component/trigger';
import { getArrowOffset } from '../style/placementArrow';
import { getArrowOffsetToken } from '../style/placementArrow';
export interface AdjustOverflow {
adjustX?: 0 | 1;
@ -19,7 +19,7 @@ export interface PlacementsConfig {
export function getOverflowOptions(
placement: string,
arrowOffset: ReturnType<typeof getArrowOffset>,
arrowOffset: ReturnType<typeof getArrowOffsetToken>,
arrowWidth: number,
autoAdjustOverflow?: boolean | AdjustOverflow,
) {
@ -38,14 +38,14 @@ export function getOverflowOptions(
switch (placement) {
case 'top':
case 'bottom':
baseOverflow.shiftX = arrowOffset.dropdownArrowOffset * 2 + arrowWidth;
baseOverflow.shiftX = arrowOffset.arrowOffsetHorizontal * 2 + arrowWidth;
baseOverflow.shiftY = true;
baseOverflow.adjustY = true;
break;
case 'left':
case 'right':
baseOverflow.shiftY = arrowOffset.dropdownArrowOffsetVertical * 2 + arrowWidth;
baseOverflow.shiftY = arrowOffset.arrowOffsetVertical * 2 + arrowWidth;
baseOverflow.shiftX = true;
baseOverflow.adjustX = true;
break;
@ -197,7 +197,7 @@ export default function getPlacements(config: PlacementsConfig) {
}
// Dynamic offset
const arrowOffset = getArrowOffset({
const arrowOffset = getArrowOffsetToken({
contentRadius: borderRadius,
limitVerticalRadius: true,
});
@ -206,22 +206,22 @@ export default function getPlacements(config: PlacementsConfig) {
switch (key) {
case 'topLeft':
case 'bottomLeft':
placementInfo.offset[0] = -arrowOffset.dropdownArrowOffset - halfArrowWidth;
placementInfo.offset[0] = -arrowOffset.arrowOffsetHorizontal - halfArrowWidth;
break;
case 'topRight':
case 'bottomRight':
placementInfo.offset[0] = arrowOffset.dropdownArrowOffset + halfArrowWidth;
placementInfo.offset[0] = arrowOffset.arrowOffsetHorizontal + halfArrowWidth;
break;
case 'leftTop':
case 'rightTop':
placementInfo.offset[1] = -arrowOffset.dropdownArrowOffset - halfArrowWidth;
placementInfo.offset[1] = -arrowOffset.arrowOffsetHorizontal - halfArrowWidth;
break;
case 'leftBottom':
case 'rightBottom':
placementInfo.offset[1] = arrowOffset.dropdownArrowOffset + halfArrowWidth;
placementInfo.offset[1] = arrowOffset.arrowOffsetHorizontal + halfArrowWidth;
break;
}
}

View File

@ -243,7 +243,7 @@ const Affix = React.forwardRef<AffixRef, AffixProps>((props, ref) => {
updatePosition();
}, [target, offsetTop, offsetBottom]);
const [wrapSSR, hashId] = useStyle(affixPrefixCls);
const [wrapCSSVar, hashId] = useStyle(affixPrefixCls);
const rootCls = classNames(rootClassName, hashId, affixPrefixCls);
@ -262,7 +262,7 @@ const Affix = React.forwardRef<AffixRef, AffixProps>((props, ref) => {
otherProps = omit(otherProps, ['onTestUpdatePosition' as any]);
}
return wrapSSR(
return wrapCSSVar(
<ResizeObserver onResize={updatePosition}>
<div style={style} className={className} ref={placeholderNodeRef} {...otherProps}>
{affixStyle && <div style={placeholderStyle} aria-hidden="true" />}

View File

@ -1,15 +1,19 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks } from '../../theme/internal';
export interface ComponentToken {
zIndexPopup: number;
}
interface AffixToken extends FullToken<'Affix'> {
zIndexPopup: number;
//
}
// ============================== Shared ==============================
const genSharedAffixStyle: GenerateStyle<AffixToken> = (token): CSSObject => {
const { componentCls } = token;
return {
[componentCls]: {
position: 'fixed',
@ -18,10 +22,9 @@ const genSharedAffixStyle: GenerateStyle<AffixToken> = (token): CSSObject => {
};
};
// ============================== Export ==============================
export default genComponentStyleHook('Affix', (token) => {
const affixToken = mergeToken<AffixToken>(token, {
export const prepareComponentToken: GetDefaultToken<'Affix'> = (token) => ({
zIndexPopup: token.zIndexBase + 10,
});
return [genSharedAffixStyle(affixToken)];
});
// ============================== Export ==============================
export default genStyleHooks('Affix', genSharedAffixStyle, prepareComponentToken);

View File

@ -12,7 +12,6 @@ import pickAttrs from 'rc-util/lib/pickAttrs';
import { replaceElement } from '../_util/reactNode';
import { devUseWarning } from '../_util/warning';
import { ConfigContext } from '../config-provider';
// CSSINJS
import useStyle from './style';
export interface AlertProps {
@ -127,7 +126,8 @@ const Alert: React.FC<AlertProps> = (props) => {
const ref = React.useRef<HTMLDivElement>(null);
const { getPrefixCls, direction, alert } = React.useContext(ConfigContext);
const prefixCls = getPrefixCls('alert', customizePrefixCls);
const [wrapSSR, hashId] = useStyle(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls);
const handleClose = (e: React.MouseEvent<HTMLButtonElement>) => {
setClosed(true);
@ -174,7 +174,7 @@ const Alert: React.FC<AlertProps> = (props) => {
const restProps = pickAttrs(otherProps, { aria: true, data: true });
return wrapSSR(
return wrapCSSVar(
<CSSMotion
visible={!closed}
motionName={`${prefixCls}-motion`}

View File

@ -1,8 +1,10 @@
import type { CSSInterpolation, CSSObject } from '@ant-design/cssinjs';
import type { CSSProperties } from 'react';
import type { CSSObject } from '@ant-design/cssinjs';
import { unit } from '@ant-design/cssinjs';
import { resetComponent } from '../../style';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook } from '../../theme/internal';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks } from '../../theme/internal';
export interface ComponentToken {
// Component token here
@ -35,7 +37,7 @@ const genAlertTypeStyle = (
alertCls: string,
): CSSObject => ({
background: bgColor,
border: `${token.lineWidth}px ${token.lineType} ${borderColor}`,
border: `${unit(token.lineWidth)} ${token.lineType} ${borderColor}`,
[`${alertCls}-icon`]: {
color: iconColor,
},
@ -113,7 +115,6 @@ export const genBaseStyle: GenerateStyle<AlertToken> = (token: AlertToken): CSSO
[`${componentCls}-with-description`]: {
alignItems: 'flex-start',
padding: withDescriptionPadding,
[`${componentCls}-icon`]: {
marginInlineEnd: marginSM,
fontSize: withDescriptionIconSize,
@ -212,7 +213,7 @@ export const genActionStyle: GenerateStyle<AlertToken> = (token: AlertToken): CS
padding: 0,
overflow: 'hidden',
fontSize: fontSizeIcon,
lineHeight: `${fontSizeIcon}px`,
lineHeight: unit(fontSizeIcon),
backgroundColor: 'transparent',
border: 'none',
outline: 'none',
@ -238,22 +239,17 @@ export const genActionStyle: GenerateStyle<AlertToken> = (token: AlertToken): CS
};
};
export const genAlertStyle: GenerateStyle<AlertToken> = (token: AlertToken): CSSInterpolation => [
genBaseStyle(token),
genTypeStyle(token),
genActionStyle(token),
];
export default genComponentStyleHook(
'Alert',
(token) => [genAlertStyle(token)],
(token) => {
export const prepareComponentToken: GetDefaultToken<'Alert'> = (token) => {
const paddingHorizontal = 12; // Fixed value here.
return {
withDescriptionIconSize: token.fontSizeHeading3,
defaultPadding: `${token.paddingContentVerticalSM}px ${paddingHorizontal}px`,
withDescriptionPadding: `${token.paddingMD}px ${token.paddingContentHorizontalLG}px`,
};
},
};
export default genStyleHooks(
'Alert',
(token) => [genBaseStyle(token), genTypeStyle(token), genActionStyle(token)],
prepareComponentToken,
);

View File

@ -9,6 +9,7 @@ import { devUseWarning } from '../_util/warning';
import Affix from '../affix';
import type { ConfigConsumerProps } from '../config-provider';
import { ConfigContext } from '../config-provider';
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
import type { AnchorLinkBaseProps } from './AnchorLink';
import AnchorLink from './AnchorLink';
import AnchorContext from './context';
@ -79,11 +80,6 @@ export interface AnchorProps {
replace?: boolean;
}
interface InternalAnchorProps extends AnchorProps {
anchorPrefixCls: string;
rootClassName: string;
}
export interface AnchorState {
activeLink: null | string;
}
@ -109,10 +105,10 @@ export interface AntAnchor {
direction: AnchorDirection;
}
const AnchorContent: React.FC<InternalAnchorProps> = (props) => {
const Anchor: React.FC<AnchorProps> = (props) => {
const {
rootClassName,
anchorPrefixCls: prefixCls,
prefixCls: customPrefixCls,
className,
style,
offsetTop,
@ -151,9 +147,14 @@ const AnchorContent: React.FC<InternalAnchorProps> = (props) => {
const spanLinkNode = React.useRef<HTMLSpanElement>(null);
const animating = React.useRef<boolean>(false);
const { direction, getTargetContainer, anchor } =
const { direction, anchor, getTargetContainer, getPrefixCls } =
React.useContext<ConfigConsumerProps>(ConfigContext);
const prefixCls = getPrefixCls('anchor', customPrefixCls);
const rootCls = useCSSVarCls(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls, rootCls);
const getCurrentContainer = getContainer ?? getTargetContainer ?? getDefaultContainer;
const dependencyListItem: React.DependencyList[number] = JSON.stringify(links);
@ -182,10 +183,7 @@ const AnchorContent: React.FC<InternalAnchorProps> = (props) => {
inkStyle.left = horizontalAnchor ? `${linkNode.offsetLeft}px` : '';
inkStyle.width = horizontalAnchor ? `${linkNode.clientWidth}px` : '';
if (horizontalAnchor) {
scrollIntoView(linkNode, {
scrollMode: 'if-needed',
block: 'nearest',
});
scrollIntoView(linkNode, { scrollMode: 'if-needed', block: 'nearest' });
}
}
};
@ -274,6 +272,8 @@ const AnchorContent: React.FC<InternalAnchorProps> = (props) => {
);
const wrapperClass = classNames(
hashId,
rootCls,
rootClassName,
`${prefixCls}-wrapper`,
{
@ -347,7 +347,7 @@ const AnchorContent: React.FC<InternalAnchorProps> = (props) => {
[activeLink, onClick, handleScrollTo, anchorDirection],
);
return (
return wrapCSSVar(
<AnchorContext.Provider value={memoizedContextValue}>
{affix ? (
<Affix offsetTop={offsetTop} target={getCurrentContainer}>
@ -356,23 +356,7 @@ const AnchorContent: React.FC<InternalAnchorProps> = (props) => {
) : (
anchorContent
)}
</AnchorContext.Provider>
);
};
const Anchor: React.FC<AnchorProps> = (props) => {
const { prefixCls: customizePrefixCls, rootClassName } = props;
const { getPrefixCls } = React.useContext<ConfigConsumerProps>(ConfigContext);
const anchorPrefixCls = getPrefixCls('anchor', customizePrefixCls);
const [wrapSSR, hashId] = useStyle(anchorPrefixCls);
return wrapSSR(
<AnchorContent
{...props}
rootClassName={classNames(hashId, rootClassName)}
anchorPrefixCls={anchorPrefixCls}
/>,
</AnchorContext.Provider>,
);
};

View File

@ -1,7 +1,8 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { unit } from '@ant-design/cssinjs';
import { resetComponent, textEllipsis } from '../../style';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
export interface ComponentToken {
/**
@ -18,13 +19,13 @@ export interface ComponentToken {
interface AnchorToken extends FullToken<'Anchor'> {
holderOffsetBlock: number;
anchorPaddingBlockSecondary: number;
anchorBallSize: number;
anchorTitleBlock: number;
anchorPaddingBlockSecondary: number | string;
anchorBallSize: number | string;
anchorTitleBlock: number | string;
}
// ============================== Shared ==============================
const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token) => {
const {
componentCls,
holderOffsetBlock,
@ -33,11 +34,12 @@ const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
colorPrimary,
lineType,
colorSplit,
calc,
} = token;
return {
[`${componentCls}-wrapper`]: {
marginBlockStart: -holderOffsetBlock,
marginBlockStart: calc(holderOffsetBlock).mul(-1).equal(),
paddingBlockStart: holderOffsetBlock,
// delete overflow: auto
@ -50,7 +52,7 @@ const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
[`${componentCls}-link`]: {
paddingBlock: token.linkPaddingBlock,
paddingInline: `${token.linkPaddingInlineStart}px 0`,
paddingInline: `${unit(token.linkPaddingInlineStart)} 0`,
'&-title': {
...textEllipsis,
@ -83,7 +85,7 @@ const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
insetInlineStart: 0,
top: 0,
height: '100%',
borderInlineStart: `${lineWidthBold}px ${lineType} ${colorSplit}`,
borderInlineStart: `${unit(lineWidthBold)} ${lineType} ${colorSplit}`,
content: '" "',
},
@ -95,7 +97,6 @@ const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
transition: `top ${motionDurationSlow} ease-in-out`,
width: lineWidthBold,
backgroundColor: colorPrimary,
[`&${componentCls}-ink-visible`]: {
display: 'inline-block',
},
@ -110,7 +111,7 @@ const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
};
};
const genSharedAnchorHorizontalStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
const genSharedAnchorHorizontalStyle: GenerateStyle<AnchorToken> = (token) => {
const { componentCls, motionDurationSlow, lineWidthBold, colorPrimary } = token;
return {
@ -128,7 +129,7 @@ const genSharedAnchorHorizontalStyle: GenerateStyle<AnchorToken> = (token): CSSO
value: 0,
},
bottom: 0,
borderBottom: `1px ${token.lineType} ${token.colorSplit}`,
borderBottom: `${unit(token.lineWidth)} ${token.lineType} ${token.colorSplit}`,
content: '" "',
},
@ -158,22 +159,23 @@ const genSharedAnchorHorizontalStyle: GenerateStyle<AnchorToken> = (token): CSSO
};
};
export const prepareComponentToken: GetDefaultToken<'Anchor'> = (token) => ({
linkPaddingBlock: token.paddingXXS,
linkPaddingInlineStart: token.padding,
});
// ============================== Export ==============================
export default genComponentStyleHook(
export default genStyleHooks(
'Anchor',
(token) => {
const { fontSize, fontSizeLG, paddingXXS } = token;
const { fontSize, fontSizeLG, paddingXXS, calc } = token;
const anchorToken = mergeToken<AnchorToken>(token, {
holderOffsetBlock: paddingXXS,
anchorPaddingBlockSecondary: paddingXXS / 2,
anchorTitleBlock: (fontSize / 14) * 3,
anchorBallSize: fontSizeLG / 2,
anchorPaddingBlockSecondary: calc(paddingXXS).div(2).equal(),
anchorTitleBlock: calc(fontSize).div(14).mul(3).equal(),
anchorBallSize: calc(fontSizeLG).div(2).equal(),
});
return [genSharedAnchorStyle(anchorToken), genSharedAnchorHorizontalStyle(anchorToken)];
},
(token) => ({
linkPaddingBlock: token.paddingXXS,
linkPaddingInlineStart: token.padding,
}),
prepareComponentToken,
);

View File

@ -36,7 +36,7 @@ const App: React.FC<AppProps> & { useApp: () => useAppProps } = (props) => {
} = props;
const { getPrefixCls } = useContext<ConfigConsumerProps>(ConfigContext);
const prefixCls = getPrefixCls('app', customizePrefixCls);
const [wrapSSR, hashId] = useStyle(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls);
const customClassName = classNames(hashId, prefixCls, className, rootClassName);
const appConfig = useContext<AppConfig>(AppConfigContext);
@ -71,7 +71,7 @@ const App: React.FC<AppProps> & { useApp: () => useAppProps } = (props) => {
style,
};
return wrapSSR(
return wrapCSSVar(
<AppContext.Provider value={memoizedContextValue}>
<AppConfigContext.Provider value={mergedAppConfig}>
<Component {...(component === false ? undefined : rootProps)}>

View File

@ -1,5 +1,5 @@
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook } from '../../theme/internal';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks } from '../../theme/internal';
export type ComponentToken = {};
@ -18,5 +18,7 @@ const genBaseStyle: GenerateStyle<AppToken> = (token) => {
};
};
export const prepareComponentToken: GetDefaultToken<'App'> = () => ({});
// ============================== Export ==============================
export default genComponentStyleHook('App', (token) => [genBaseStyle(token)]);
export default genStyleHooks('App', genBaseStyle, prepareComponentToken);

View File

@ -12,6 +12,7 @@ import useBreakpoint from '../grid/hooks/useBreakpoint';
import type { AvatarContextType, AvatarSize } from './AvatarContext';
import AvatarContext from './AvatarContext';
import useStyle from './style';
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
export interface AvatarProps {
/** Shape of avatar, options: `circle`, `square` */
@ -144,7 +145,8 @@ const InternalAvatar: React.ForwardRefRenderFunction<HTMLSpanElement, AvatarProp
}
const prefixCls = getPrefixCls('avatar', customizePrefixCls);
const [wrapSSR, hashId] = useStyle(prefixCls);
const cssVarCls = useCSSVarCls(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls, cssVarCls);
const sizeCls = classNames({
[`${prefixCls}-lg`]: size === 'large',
@ -164,6 +166,7 @@ const InternalAvatar: React.ForwardRefRenderFunction<HTMLSpanElement, AvatarProp
[`${prefixCls}-image`]: hasImageElement || (src && isImgExist),
[`${prefixCls}-icon`]: !!icon,
},
cssVarCls,
className,
rootClassName,
hashId,
@ -234,7 +237,7 @@ const InternalAvatar: React.ForwardRefRenderFunction<HTMLSpanElement, AvatarProp
delete others.onError;
delete others.gap;
return wrapSSR(
return wrapCSSVar(
<span
{...others}
style={{ ...sizeStyle, ...responsiveSizeStyle, ...avatar?.style, ...others.style }}

View File

@ -8,6 +8,7 @@ import Avatar from './avatar';
import AvatarContext from './AvatarContext';
import type { AvatarContextType, AvatarSize } from './AvatarContext';
import useStyle from './style';
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
interface ContextProps {
children?: React.ReactNode;
@ -60,13 +61,15 @@ const Group: React.FC<GroupProps> = (props) => {
const prefixCls = getPrefixCls('avatar', customizePrefixCls);
const groupPrefixCls = `${prefixCls}-group`;
const [wrapSSR, hashId] = useStyle(prefixCls);
const cssVarCls = useCSSVarCls(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls, cssVarCls);
const cls = classNames(
groupPrefixCls,
{
[`${groupPrefixCls}-rtl`]: direction === 'rtl',
},
cssVarCls,
className,
rootClassName,
hashId,
@ -91,7 +94,7 @@ const Group: React.FC<GroupProps> = (props) => {
<Avatar style={maxStyle}>{`+${numOfChildren - maxCount}`}</Avatar>
</Popover>,
);
return wrapSSR(
return wrapCSSVar(
<AvatarContextProvider shape={shape} size={size}>
<div className={cls} style={style}>
{childrenShow}
@ -100,7 +103,7 @@ const Group: React.FC<GroupProps> = (props) => {
);
}
return wrapSSR(
return wrapCSSVar(
<AvatarContextProvider shape={shape} size={size}>
<div className={cls} style={style}>
{childrenWithProps}

View File

@ -1,7 +1,8 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { type CSSObject, unit } from '@ant-design/cssinjs';
import { resetComponent } from '../../style';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
export interface ComponentToken {
/**
@ -75,13 +76,14 @@ const genBaseStyle: GenerateStyle<AvatarToken> = (token) => {
borderRadiusSM,
lineWidth,
lineType,
calc,
} = token;
// Avatar size style
const avatarSizeStyle = (size: number, fontSize: number, radius: number): CSSObject => ({
width: size,
height: size,
lineHeight: `${size - lineWidth * 2}px`,
lineHeight: unit(calc(size).sub(calc(lineWidth).mul(2)).equal()),
borderRadius: '50%',
[`&${componentCls}-square`]: {
@ -116,7 +118,7 @@ const genBaseStyle: GenerateStyle<AvatarToken> = (token) => {
textAlign: 'center',
verticalAlign: 'middle',
background: avatarBg,
border: `${lineWidth}px ${lineType} transparent`,
border: `${unit(lineWidth)} ${lineType} transparent`,
[`&-image`]: {
background: 'transparent',
@ -169,7 +171,33 @@ const genGroupStyle: GenerateStyle<AvatarToken> = (token) => {
};
};
export default genComponentStyleHook(
export const prepareComponentToken: GetDefaultToken<'Avatar'> = (token) => {
const {
controlHeight,
controlHeightLG,
controlHeightSM,
fontSize,
fontSizeLG,
fontSizeXL,
fontSizeHeading3,
marginXS,
marginXXS,
colorBorderBg,
} = token;
return {
containerSize: controlHeight,
containerSizeLG: controlHeightLG,
containerSizeSM: controlHeightSM,
textFontSize: Math.round((fontSizeLG + fontSizeXL) / 2),
textFontSizeLG: fontSizeHeading3,
textFontSizeSM: fontSize,
groupSpace: marginXXS,
groupOverlapping: -marginXS,
groupBorderColor: colorBorderBg,
};
};
export default genStyleHooks(
'Avatar',
(token) => {
const { colorTextLightSolid, colorTextPlaceholder } = token;
@ -179,33 +207,5 @@ export default genComponentStyleHook(
});
return [genBaseStyle(avatarToken), genGroupStyle(avatarToken)];
},
(token) => {
const {
controlHeight,
controlHeightLG,
controlHeightSM,
fontSize,
fontSizeLG,
fontSizeXL,
fontSizeHeading3,
marginXS,
marginXXS,
colorBorderBg,
} = token;
return {
containerSize: controlHeight,
containerSizeLG: controlHeightLG,
containerSizeSM: controlHeightSM,
textFontSize: Math.round((fontSizeLG + fontSizeXL) / 2),
textFontSizeLG: fontSizeHeading3,
textFontSizeSM: fontSize,
groupSpace: marginXXS,
groupOverlapping: -marginXS,
groupBorderColor: colorBorderBg,
};
},
prepareComponentToken,
);

View File

@ -74,8 +74,10 @@ const BackTop: React.FC<BackTopProps> = (props) => {
const { getPrefixCls, direction } = React.useContext<ConfigConsumerProps>(ConfigContext);
const prefixCls = getPrefixCls('back-top', customizePrefixCls);
const rootPrefixCls = getPrefixCls();
const [wrapSSR, hashId] = useStyle(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls);
const classString = classNames(
hashId,
@ -105,7 +107,7 @@ const BackTop: React.FC<BackTopProps> = (props) => {
</div>
);
return wrapSSR(
return wrapCSSVar(
<div {...divProps} className={classString} onClick={scrollToTop} ref={ref}>
<CSSMotion visible={visible} motionName={`${rootPrefixCls}-fade`}>
{({ className: motionClassName }) =>

View File

@ -1,7 +1,8 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { type CSSObject, unit } from '@ant-design/cssinjs';
import { resetComponent } from '../../style';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
/** Component only token. Which will handle additional calculation of alias token */
export interface ComponentToken {
@ -16,10 +17,10 @@ type BackTopToken = FullToken<'BackTop'> & {
backTopSize: number;
// Position
backTopBlockEnd: number;
backTopInlineEnd: number;
backTopInlineEndMD: number;
backTopInlineEndXS: number;
backTopBlockEnd: number | string;
backTopInlineEnd: number | string;
backTopInlineEndMD: number | string;
backTopInlineEndXS: number | string;
};
// ============================== Shared ==============================
@ -61,34 +62,35 @@ const genSharedBackTopStyle: GenerateStyle<BackTopToken, CSSObject> = (token): C
// change to .backtop .backtop-icon
[`${componentCls}-icon`]: {
fontSize: backTopFontSize,
lineHeight: `${backTopSize}px`,
lineHeight: unit(backTopSize),
},
},
};
};
const genMediaBackTopStyle: GenerateStyle<BackTopToken> = (token): CSSObject => {
const { componentCls } = token;
const { componentCls, screenMD, screenXS, backTopInlineEndMD, backTopInlineEndXS } = token;
return {
[`@media (max-width: ${token.screenMD}px)`]: {
[`@media (max-width: ${unit(screenMD)})`]: {
[componentCls]: {
insetInlineEnd: token.backTopInlineEndMD,
insetInlineEnd: backTopInlineEndMD,
},
},
[`@media (max-width: ${token.screenXS}px)`]: {
[`@media (max-width: ${unit(screenXS)})`]: {
[componentCls]: {
insetInlineEnd: token.backTopInlineEndXS,
insetInlineEnd: backTopInlineEndXS,
},
},
};
};
// ============================== Export ==============================
export default genComponentStyleHook<'BackTop'>(
'BackTop',
export const prepareComponentToken: GetDefaultToken<'BackTop'> = (token) => ({
zIndexPopup: token.zIndexBase + 10,
});
// ============================== Export ==============================
export default genStyleHooks(
'BackTop',
(token) => {
const {
fontSizeHeading3,
@ -96,23 +98,20 @@ export default genComponentStyleHook<'BackTop'>(
colorTextLightSolid,
colorText,
controlHeightLG,
calc,
} = token;
const backTopToken = mergeToken<BackTopToken>(token, {
backTopBackground: colorTextDescription,
backTopColor: colorTextLightSolid,
backTopHoverBackground: colorText,
backTopFontSize: fontSizeHeading3,
backTopSize: controlHeightLG,
backTopBlockEnd: controlHeightLG * 1.25,
backTopInlineEnd: controlHeightLG * 2.5,
backTopInlineEndMD: controlHeightLG * 1.5,
backTopInlineEndXS: controlHeightLG * 0.5,
backTopBlockEnd: calc(controlHeightLG).mul(1.25).equal(),
backTopInlineEnd: calc(controlHeightLG).mul(2.5).equal(),
backTopInlineEndMD: calc(controlHeightLG).mul(1.5).equal(),
backTopInlineEndXS: calc(controlHeightLG).mul(0.5).equal(),
});
return [genSharedBackTopStyle(backTopToken), genMediaBackTopStyle(backTopToken)];
},
(token) => ({
zIndexPopup: token.zIndexBase + 10,
}),
prepareComponentToken,
);

View File

@ -33,6 +33,9 @@ const Ribbon: React.FC<RibbonProps> = (props) => {
} = props;
const { getPrefixCls, direction } = React.useContext(ConfigContext);
const prefixCls = getPrefixCls('ribbon', customizePrefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls);
const colorInPreset = isPresetColor(color, false);
const ribbonCls = classNames(
prefixCls,
@ -43,14 +46,14 @@ const Ribbon: React.FC<RibbonProps> = (props) => {
},
className,
);
const [wrapSSR, hashId] = useStyle(prefixCls);
const colorStyle: React.CSSProperties = {};
const cornerColorStyle: React.CSSProperties = {};
if (color && !colorInPreset) {
colorStyle.background = color;
cornerColorStyle.color = color;
}
return wrapSSR(
return wrapCSSVar(
<div className={classNames(`${prefixCls}-wrapper`, rootClassName, hashId)}>
{children}
<div className={classNames(ribbonCls, hashId)} style={{ ...colorStyle, ...style }}>

View File

@ -1,7 +1,8 @@
import classnames from 'classnames';
import CSSMotion from 'rc-motion';
import * as React from 'react';
import { useMemo, useRef } from 'react';
import classnames from 'classnames';
import CSSMotion from 'rc-motion';
import type { PresetStatusColorType } from '../_util/colors';
import { isPresetColor } from '../_util/colors';
import { cloneElement } from '../_util/reactNode';
@ -75,8 +76,7 @@ const InternalBadge: React.ForwardRefRenderFunction<HTMLSpanElement, BadgeProps>
const { getPrefixCls, direction, badge } = React.useContext(ConfigContext);
const prefixCls = getPrefixCls('badge', customizePrefixCls);
// Style
const [wrapSSR, hashId] = useStyle(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls);
// ================================ Misc ================================
const numberedDisplayCount = (
@ -188,7 +188,7 @@ const InternalBadge: React.ForwardRefRenderFunction<HTMLSpanElement, BadgeProps>
// <Badge status="success" />
if (!children && hasStatus) {
const statusTextColor = mergedStyle.color;
return wrapSSR(
return wrapCSSVar(
<span
{...restProps}
className={badgeClassName}
@ -207,7 +207,7 @@ const InternalBadge: React.ForwardRefRenderFunction<HTMLSpanElement, BadgeProps>
);
}
return wrapSSR(
return wrapCSSVar(
<span
ref={ref}
{...restProps}

View File

@ -1,11 +1,9 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { Keyframes } from '@ant-design/cssinjs';
import { Keyframes, unit } from '@ant-design/cssinjs';
import { resetComponent } from '../../style';
import type { GlobalToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, genPresetColor, mergeToken } from '../../theme/internal';
import type { GenStyleFn } from '../../theme/util/genComponentStyleHook';
import { genPresetColor, genStyleHooks, mergeToken } from '../../theme/internal';
import type { GenStyleFn, GetDefaultToken } from '../../theme/util/genComponentStyleHook';
/** Component only token. Which will handle additional calculation of alias token */
export interface ComponentToken {
@ -84,10 +82,12 @@ const antNoWrapperZoomBadgeIn = new Keyframes('antNoWrapperZoomBadgeIn', {
'0%': { transform: 'scale(0)', opacity: 0 },
'100%': { transform: 'scale(1)' },
});
const antNoWrapperZoomBadgeOut = new Keyframes('antNoWrapperZoomBadgeOut', {
'0%': { transform: 'scale(1)' },
'100%': { transform: 'scale(0)', opacity: 0 },
});
const antBadgeLoadingCircle = new Keyframes('antBadgeLoadingCircle', {
'0%': { transformOrigin: '50%' },
'100%': {
@ -96,7 +96,7 @@ const antBadgeLoadingCircle = new Keyframes('antBadgeLoadingCircle', {
},
});
const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (token: BadgeToken): CSSObject => {
const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (token) => {
const {
componentCls,
iconCls,
@ -111,6 +111,7 @@ const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (token: BadgeToken): CSSO
indicatorHeight,
indicatorHeightSM,
marginXS,
calc,
} = token;
const numberPrefixCls = `${antCls}-scroll-number`;
@ -138,12 +139,12 @@ const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (token: BadgeToken): CSSO
color: token.badgeTextColor,
fontWeight: textFontWeight,
fontSize: textFontSize,
lineHeight: `${indicatorHeight}px`,
lineHeight: unit(indicatorHeight),
whiteSpace: 'nowrap',
textAlign: 'center',
background: token.badgeColor,
borderRadius: indicatorHeight / 2,
boxShadow: `0 0 0 ${badgeShadowSize}px ${token.badgeShadowColor}`,
borderRadius: calc(indicatorHeight).div(2).equal(),
boxShadow: `0 0 0 ${unit(badgeShadowSize)} ${token.badgeShadowColor}`,
transition: `background ${token.motionDurationMid}`,
a: {
@ -161,12 +162,12 @@ const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (token: BadgeToken): CSSO
minWidth: indicatorHeightSM,
height: indicatorHeightSM,
fontSize: textFontSizeSM,
lineHeight: `${indicatorHeightSM}px`,
borderRadius: indicatorHeightSM / 2,
lineHeight: unit(indicatorHeightSM),
borderRadius: calc(indicatorHeightSM).div(2).equal(),
},
[`${componentCls}-multiple-words`]: {
padding: `0 ${token.paddingXS}px`,
padding: `0 ${unit(token.paddingXS)}`,
bdi: {
unicodeBidi: 'plaintext',
@ -180,7 +181,7 @@ const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (token: BadgeToken): CSSO
height: dotSize,
background: token.badgeColor,
borderRadius: '100%',
boxShadow: `0 0 0 ${badgeShadowSize}px ${token.badgeShadowColor}`,
boxShadow: `0 0 0 ${unit(badgeShadowSize)} ${token.badgeShadowColor}`,
},
[`${componentCls}-dot${numberPrefixCls}`]: {
transition: `background ${motionDurationSlow}`,
@ -308,13 +309,14 @@ const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (token: BadgeToken): CSSO
WebkitBackfaceVisibility: 'hidden',
},
},
[`${numberPrefixCls}-symbol`]: { verticalAlign: 'top' },
[`${numberPrefixCls}-symbol`]: {
verticalAlign: 'top',
},
},
// ====================== RTL =======================
'&-rtl': {
direction: 'rtl',
[`${componentCls}-count, ${componentCls}-dot, ${numberPrefixCls}-custom-component`]: {
transform: 'translate(-50%, -50%)',
},
@ -325,9 +327,9 @@ const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (token: BadgeToken): CSSO
// ============================== Export ==============================
export const prepareToken: (token: Parameters<GenStyleFn<'Badge'>>[0]) => BadgeToken = (token) => {
const { fontSize, lineHeight, lineWidth, marginXS, colorBorderBg } = token;
const { fontHeight, lineWidth, marginXS, colorBorderBg } = token;
const badgeFontHeight = Math.round(fontSize * lineHeight);
const badgeFontHeight = fontHeight;
const badgeShadowSize = lineWidth;
const badgeTextColor = token.colorBgContainer;
const badgeColor = token.colorError;
@ -351,9 +353,8 @@ export const prepareToken: (token: Parameters<GenStyleFn<'Badge'>>[0]) => BadgeT
return badgeToken;
};
export const prepareComponentToken = (token: GlobalToken) => {
export const prepareComponentToken: GetDefaultToken<'Badge'> = (token) => {
const { fontSize, lineHeight, fontSizeSM, lineWidth } = token;
return {
indicatorZIndex: 'auto',
indicatorHeight: Math.round(fontSize * lineHeight) - 2 * lineWidth,
@ -366,12 +367,11 @@ export const prepareComponentToken = (token: GlobalToken) => {
};
};
export default genComponentStyleHook(
export default genStyleHooks(
'Badge',
(token) => {
const badgeToken = prepareToken(token);
return [genSharedBadgeStyle(badgeToken)];
return genSharedBadgeStyle(badgeToken);
},
prepareComponentToken,
);

View File

@ -1,4 +1,4 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { unit } from '@ant-design/cssinjs';
import { prepareComponentToken, prepareToken, type BadgeToken } from '.';
import { resetComponent } from '../../style';
@ -6,8 +6,8 @@ import type { GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, genPresetColor } from '../../theme/internal';
// ============================== Ribbon ==============================
const genRibbonStyle: GenerateStyle<BadgeToken> = (token: BadgeToken): CSSObject => {
const { antCls, badgeFontHeight, marginXS, badgeRibbonOffset } = token;
const genRibbonStyle: GenerateStyle<BadgeToken> = (token) => {
const { antCls, badgeFontHeight, marginXS, badgeRibbonOffset, calc } = token;
const ribbonPrefixCls = `${antCls}-ribbon`;
const ribbonWrapperPrefixCls = `${antCls}-ribbon-wrapper`;
@ -19,32 +19,36 @@ const genRibbonStyle: GenerateStyle<BadgeToken> = (token: BadgeToken): CSSObject
}));
return {
[`${ribbonWrapperPrefixCls}`]: { position: 'relative' },
[`${ribbonWrapperPrefixCls}`]: {
position: 'relative',
},
[`${ribbonPrefixCls}`]: {
...resetComponent(token),
position: 'absolute',
top: marginXS,
padding: `0 ${token.paddingXS}px`,
padding: `0 ${unit(token.paddingXS)}`,
color: token.colorPrimary,
lineHeight: `${badgeFontHeight}px`,
lineHeight: unit(badgeFontHeight),
whiteSpace: 'nowrap',
backgroundColor: token.colorPrimary,
borderRadius: token.borderRadiusSM,
[`${ribbonPrefixCls}-text`]: { color: token.colorTextLightSolid },
[`${ribbonPrefixCls}-text`]: {
color: token.colorTextLightSolid,
},
[`${ribbonPrefixCls}-corner`]: {
position: 'absolute',
top: '100%',
width: badgeRibbonOffset,
height: badgeRibbonOffset,
color: 'currentcolor',
border: `${badgeRibbonOffset / 2}px solid`,
border: `${unit(calc(badgeRibbonOffset).div(2).equal())} solid`,
transform: token.badgeRibbonCornerTransform,
transformOrigin: 'top',
filter: token.badgeRibbonCornerFilter,
},
...statusRibbonPreset,
[`&${ribbonPrefixCls}-placement-end`]: {
insetInlineEnd: -badgeRibbonOffset,
insetInlineEnd: calc(badgeRibbonOffset).mul(-1).equal(),
borderEndEndRadius: 0,
[`${ribbonPrefixCls}-corner`]: {
insetInlineEnd: 0,
@ -53,7 +57,7 @@ const genRibbonStyle: GenerateStyle<BadgeToken> = (token: BadgeToken): CSSObject
},
},
[`&${ribbonPrefixCls}-placement-start`]: {
insetInlineStart: -badgeRibbonOffset,
insetInlineStart: calc(badgeRibbonOffset).mul(-1).equal(),
borderEndStartRadius: 0,
[`${ribbonPrefixCls}-corner`]: {
insetInlineStart: 0,
@ -75,8 +79,7 @@ export default genComponentStyleHook(
['Badge', 'Ribbon'],
(token) => {
const badgeToken = prepareToken(token);
return [genRibbonStyle(badgeToken)];
return genRibbonStyle(badgeToken);
},
prepareComponentToken,
);

View File

@ -93,8 +93,9 @@ const Breadcrumb = <T extends AnyObject = AnyObject>(props: BreadcrumbProps<T>)
const { getPrefixCls, direction, breadcrumb } = React.useContext(ConfigContext);
let crumbs: React.ReactNode;
const prefixCls = getPrefixCls('breadcrumb', customizePrefixCls);
const [wrapSSR, hashId] = useStyle(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls);
const mergedItems = useItems(items, legacyRoutes);
@ -216,7 +217,7 @@ const Breadcrumb = <T extends AnyObject = AnyObject>(props: BreadcrumbProps<T>)
const mergedStyle: React.CSSProperties = { ...breadcrumb?.style, ...style };
return wrapSSR(
return wrapCSSVar(
<nav className={breadcrumbClassName} style={mergedStyle} {...restProps}>
<ol>{crumbs}</ol>
</nav>,

View File

@ -1,7 +1,8 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { type CSSObject, unit } from '@ant-design/cssinjs';
import { genFocusStyle, resetComponent } from '../../style';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
export interface ComponentToken {
/**
@ -44,7 +45,7 @@ export interface ComponentToken {
interface BreadcrumbToken extends FullToken<'Breadcrumb'> {}
const genBreadcrumbStyle: GenerateStyle<BreadcrumbToken, CSSObject> = (token) => {
const { componentCls, iconCls } = token;
const { componentCls, iconCls, calc } = token;
return {
[componentCls]: {
@ -67,11 +68,11 @@ const genBreadcrumbStyle: GenerateStyle<BreadcrumbToken, CSSObject> = (token) =>
a: {
color: token.linkColor,
transition: `color ${token.motionDurationMid}`,
padding: `0 ${token.paddingXXS}px`,
padding: `0 ${unit(token.paddingXXS)}`,
borderRadius: token.borderRadiusSM,
height: token.lineHeight * token.fontSize,
height: token.fontHeight,
display: 'inline-block',
marginInline: -token.marginXXS,
marginInline: calc(token.marginXXS).mul(-1).equal(),
'&:hover': {
color: token.linkHoverColor,
@ -101,10 +102,10 @@ const genBreadcrumbStyle: GenerateStyle<BreadcrumbToken, CSSObject> = (token) =>
[`${componentCls}-overlay-link`]: {
borderRadius: token.borderRadiusSM,
height: token.lineHeight * token.fontSize,
height: token.fontHeight,
display: 'inline-block',
padding: `0 ${token.paddingXXS}px`,
marginInline: -token.marginXXS,
padding: `0 ${unit(token.paddingXXS)}`,
marginInline: calc(token.marginXXS).mul(-1).equal(),
[`> ${iconCls}`]: {
marginInlineStart: token.marginXXS,
@ -135,14 +136,7 @@ const genBreadcrumbStyle: GenerateStyle<BreadcrumbToken, CSSObject> = (token) =>
};
};
// ============================== Export ==============================
export default genComponentStyleHook(
'Breadcrumb',
(token) => {
const BreadcrumbToken = mergeToken<BreadcrumbToken>(token, {});
return [genBreadcrumbStyle(BreadcrumbToken)];
},
(token) => ({
export const prepareComponentToken: GetDefaultToken<'Breadcrumb'> = (token) => ({
itemColor: token.colorTextDescription,
lastItemColor: token.colorText,
iconFontSize: token.fontSize,
@ -150,5 +144,14 @@ export default genComponentStyleHook(
linkHoverColor: token.colorText,
separatorColor: token.colorTextDescription,
separatorMargin: token.marginXS,
}),
});
// ============================== Export ==============================
export default genStyleHooks(
'Breadcrumb',
(token) => {
const breadcrumbToken = mergeToken<BreadcrumbToken>(token, {});
return genBreadcrumbStyle(breadcrumbToken);
},
prepareComponentToken,
);

View File

@ -430,9 +430,12 @@ exports[`renders components/button/demo/danger.tsx extend context correctly 1`]
exports[`renders components/button/demo/danger.tsx extend context correctly 2`] = `[]`;
exports[`renders components/button/demo/debug-block.tsx extend context correctly 1`] = `
<div
class="ant-form-item"
<form
class="ant-form ant-form-horizontal"
>
<div
class="ant-form-item"
>
<div
class="ant-row ant-form-item-row"
>
@ -486,7 +489,8 @@ exports[`renders components/button/demo/debug-block.tsx extend context correctly
</div>
</div>
</div>
</div>
</div>
</form>
`;
exports[`renders components/button/demo/debug-block.tsx extend context correctly 2`] = `[]`;

View File

@ -415,9 +415,12 @@ exports[`renders components/button/demo/danger.tsx correctly 1`] = `
`;
exports[`renders components/button/demo/debug-block.tsx correctly 1`] = `
<div
class="ant-form-item"
<form
class="ant-form ant-form-horizontal"
>
<div
class="ant-form-item"
>
<div
class="ant-row ant-form-item-row"
>
@ -471,7 +474,8 @@ exports[`renders components/button/demo/debug-block.tsx correctly 1`] = `
</div>
</div>
</div>
</div>
</div>
</form>
`;
exports[`renders components/button/demo/debug-icon.tsx correctly 1`] = `

View File

@ -118,7 +118,7 @@ const InternalButton: React.ForwardRefRenderFunction<
const { getPrefixCls, autoInsertSpaceInButton, direction, button } = useContext(ConfigContext);
const prefixCls = getPrefixCls('btn', customizePrefixCls);
const [wrapSSR, hashId] = useStyle(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls);
const disabled = useContext(DisabledContext);
const mergedDisabled = customDisabled ?? disabled;
@ -254,7 +254,7 @@ const InternalButton: React.ForwardRefRenderFunction<
children || children === 0 ? spaceChildren(children, needInserted && autoInsertSpace) : null;
if (linkButtonRestProps.href !== undefined) {
return wrapSSR(
return wrapCSSVar(
<a
{...linkButtonRestProps}
className={classNames(classes, {
@ -298,7 +298,7 @@ const InternalButton: React.ForwardRefRenderFunction<
);
}
return wrapSSR(buttonNode);
return wrapCSSVar(buttonNode);
};
const Button = forwardRef<HTMLButtonElement | HTMLAnchorElement, ButtonProps>(

View File

@ -3,12 +3,14 @@ import { DownloadOutlined } from '@ant-design/icons';
import { Form, Button } from 'antd';
const App: React.FC = () => (
<Form>
<Form.Item>
<Button size="large" shape="round" block style={{ marginBottom: 12 }}>
Submit
</Button>
<Button size="large" shape="round" icon={<DownloadOutlined />} />
</Form.Item>
</Form>
);
export default App;

View File

@ -1,8 +1,58 @@
// Style as inline component
import type { ButtonToken } from '.';
import { prepareComponentToken, prepareToken } from '.';
import { genCompactItemStyle } from '../../style/compact-item';
import { genCompactItemVerticalStyle } from '../../style/compact-item-vertical';
import type { GenerateStyle } from '../../theme/internal';
import { genSubStyleComponent } from '../../theme/internal';
import { unit } from '@ant-design/cssinjs';
const genButtonCompactStyle: GenerateStyle<ButtonToken> = (token) => {
const { componentCls, calc } = token;
return {
[componentCls]: {
// Special styles for Primary Button
[`&-compact-item${componentCls}-primary`]: {
[`&:not([disabled]) + ${componentCls}-compact-item${componentCls}-primary:not([disabled])`]:
{
position: 'relative',
'&:before': {
position: 'absolute',
top: calc(token.lineWidth).mul(-1).equal(),
insetInlineStart: calc(token.lineWidth).mul(-1).equal(),
display: 'inline-block',
width: token.lineWidth,
height: `calc(100% + ${unit(token.lineWidth)} * 2)`,
backgroundColor: token.colorPrimaryHover,
content: '""',
},
},
},
// Special styles for Primary Button
'&-compact-vertical-item': {
[`&${componentCls}-primary`]: {
[`&:not([disabled]) + ${componentCls}-compact-vertical-item${componentCls}-primary:not([disabled])`]:
{
position: 'relative',
'&:before': {
position: 'absolute',
top: calc(token.lineWidth).mul(-1).equal(),
insetInlineStart: calc(token.lineWidth).mul(-1).equal(),
display: 'inline-block',
width: `calc(100% + ${unit(token.lineWidth)} * 2)`,
height: token.lineWidth,
backgroundColor: token.colorPrimaryHover,
content: '""',
},
},
},
},
},
};
};
// ============================== Export ==============================
export default genSubStyleComponent(
@ -14,6 +64,7 @@ export default genSubStyleComponent(
// Space Compact
genCompactItemStyle(buttonToken),
genCompactItemVerticalStyle(buttonToken),
genButtonCompactStyle(buttonToken),
];
},
prepareComponentToken,

View File

@ -41,7 +41,7 @@ const genGroupStyle: GenerateStyle<ButtonToken> = (token) => {
},
'&:not(:first-child)': {
marginInlineStart: -lineWidth,
marginInlineStart: token.calc(lineWidth).mul(-1).equal(),
[`&, & > ${componentCls}`]: {
borderStartStartRadius: 0,

View File

@ -1,10 +1,10 @@
import type { CSSProperties } from 'react';
import type { CSSInterpolation, CSSObject } from '@ant-design/cssinjs';
import { unit } from '@ant-design/cssinjs';
import { genFocusStyle } from '../../style';
import type { GlobalToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
import type { GenStyleFn } from '../../theme/util/genComponentStyleHook';
import genGroupStyle from './group';
@ -90,6 +90,21 @@ export interface ComponentToken {
* @descEN Horizontal padding of small button
*/
paddingInlineSM: CSSProperties['paddingInline'];
/**
* @desc
* @descEN Horizontal padding of button
*/
paddingBlock: CSSProperties['paddingInline'];
/**
* @desc
* @descEN Horizontal padding of large button
*/
paddingBlockLG: CSSProperties['paddingInline'];
/**
* @desc
* @descEN Horizontal padding of small button
*/
paddingBlockSM: CSSProperties['paddingInline'];
/**
* @desc
* @descEN Icon size of button which only contains icon
@ -139,6 +154,7 @@ export interface ComponentToken {
export interface ButtonToken extends FullToken<'Button'> {
buttonPaddingHorizontal: CSSProperties['paddingInline'];
buttonPaddingVertical: CSSProperties['paddingBlock'];
buttonIconOnlyFontSize: number;
}
@ -156,7 +172,7 @@ const genSharedButtonStyle: GenerateStyle<ButtonToken, CSSObject> = (token): CSS
textAlign: 'center',
backgroundImage: 'none',
background: 'transparent',
border: `${token.lineWidth}px ${token.lineType} transparent`,
border: `${unit(token.lineWidth)} ${token.lineType} transparent`,
cursor: 'pointer',
transition: `all ${token.motionDurationMid} ${token.motionEaseInOut}`,
userSelect: 'none',
@ -208,44 +224,6 @@ const genSharedButtonStyle: GenerateStyle<ButtonToken, CSSObject> = (token): CSS
[`&-icon-only${componentCls}-compact-item`]: {
flex: 'none',
},
// Special styles for Primary Button
[`&-compact-item${componentCls}-primary`]: {
[`&:not([disabled]) + ${componentCls}-compact-item${componentCls}-primary:not([disabled])`]:
{
position: 'relative',
'&:before': {
position: 'absolute',
top: -token.lineWidth,
insetInlineStart: -token.lineWidth,
display: 'inline-block',
width: token.lineWidth,
height: `calc(100% + ${token.lineWidth * 2}px)`,
background: token.colorPrimaryHover,
content: '""',
},
},
},
// Special styles for Primary Button
'&-compact-vertical-item': {
[`&${componentCls}-primary`]: {
[`&:not([disabled]) + ${componentCls}-compact-vertical-item${componentCls}-primary:not([disabled])`]:
{
position: 'relative',
'&:before': {
position: 'absolute',
top: -token.lineWidth,
insetInlineStart: -token.lineWidth,
display: 'inline-block',
width: `calc(100% + ${token.lineWidth * 2}px)`,
height: token.lineWidth,
background: token.colorPrimaryHover,
content: '""',
},
},
},
},
},
};
};
@ -271,8 +249,8 @@ const genCircleButtonStyle: GenerateStyle<ButtonToken, CSSObject> = (token) => (
const genRoundButtonStyle: GenerateStyle<ButtonToken, CSSObject> = (token) => ({
borderRadius: token.controlHeight,
paddingInlineStart: token.controlHeight / 2,
paddingInlineEnd: token.controlHeight / 2,
paddingInlineStart: token.calc(token.controlHeight).div(2).equal(),
paddingInlineEnd: token.calc(token.controlHeight).div(2).equal(),
});
// =============================== Type ===============================
@ -569,15 +547,12 @@ const genSizeButtonStyle = (token: ButtonToken, sizePrefixCls: string = ''): CSS
componentCls,
controlHeight,
fontSize,
lineHeight,
lineWidth,
borderRadius,
buttonPaddingHorizontal,
iconCls,
buttonPaddingVertical,
} = token;
const paddingVertical = Math.max(0, (controlHeight - fontSize * lineHeight) / 2 - lineWidth);
const iconOnlyCls = `${componentCls}-icon-only`;
return [
@ -586,7 +561,7 @@ const genSizeButtonStyle = (token: ButtonToken, sizePrefixCls: string = ''): CSS
[`${componentCls}${sizePrefixCls}`]: {
fontSize,
height: controlHeight,
padding: `${paddingVertical}px ${buttonPaddingHorizontal}px`,
padding: `${unit(buttonPaddingVertical!)} ${unit(buttonPaddingHorizontal!)}`,
borderRadius,
[`&${iconOnlyCls}`]: {
@ -635,7 +610,8 @@ const genSizeSmallButtonStyle: GenerateStyle<ButtonToken> = (token) => {
controlHeight: token.controlHeightSM,
fontSize: token.contentFontSizeSM,
padding: token.paddingXS,
buttonPaddingHorizontal: token.paddingInlineSM, // Fixed padding
buttonPaddingHorizontal: token.paddingInlineSM,
buttonPaddingVertical: token.paddingBlockSM,
borderRadius: token.borderRadiusSM,
buttonIconOnlyFontSize: token.onlyIconSizeSM,
});
@ -648,6 +624,7 @@ const genSizeLargeButtonStyle: GenerateStyle<ButtonToken> = (token) => {
controlHeight: token.controlHeightLG,
fontSize: token.contentFontSizeLG,
buttonPaddingHorizontal: token.paddingInlineLG,
buttonPaddingVertical: token.paddingBlockLG,
borderRadius: token.borderRadiusLG,
buttonIconOnlyFontSize: token.onlyIconSizeLG,
});
@ -670,17 +647,23 @@ const genBlockButtonStyle: GenerateStyle<ButtonToken> = (token) => {
export const prepareToken: (token: Parameters<GenStyleFn<'Button'>>[0]) => ButtonToken = (
token,
) => {
const { paddingInline, onlyIconSize } = token;
const { paddingInline, onlyIconSize, paddingBlock } = token;
const buttonToken = mergeToken<ButtonToken>(token, {
buttonPaddingHorizontal: paddingInline,
buttonPaddingVertical: paddingBlock,
buttonIconOnlyFontSize: onlyIconSize,
});
return buttonToken;
};
export const prepareComponentToken = (token: GlobalToken) => ({
export const prepareComponentToken: GetDefaultToken<'Button'> = (token) => {
const contentFontSize = token.fontSize;
const contentFontSizeSM = token.fontSize;
const contentFontSizeLG = token.fontSizeLG;
return {
fontWeight: 400,
defaultShadow: `0 ${token.controlOutlineWidth}px 0 ${token.controlTmpOutline}`,
primaryShadow: `0 ${token.controlOutlineWidth}px 0 ${token.controlOutline}`,
@ -694,6 +677,18 @@ export const prepareComponentToken = (token: GlobalToken) => ({
paddingInline: token.paddingContentHorizontal - token.lineWidth,
paddingInlineLG: token.paddingContentHorizontal - token.lineWidth,
paddingInlineSM: 8 - token.lineWidth,
paddingBlock: Math.max(
(token.controlHeight - contentFontSize * token.lineHeight) / 2 - token.lineWidth,
0,
),
paddingBlockSM: Math.max(
(token.controlHeightSM - contentFontSizeSM * token.lineHeight) / 2 - token.lineWidth,
0,
),
paddingBlockLG: Math.max(
(token.controlHeightLG - contentFontSizeLG * token.lineHeight) / 2 - token.lineWidth,
0,
),
onlyIconSize: token.fontSizeLG,
onlyIconSizeSM: token.fontSizeLG - 2,
onlyIconSizeLG: token.fontSizeLG + 2,
@ -704,12 +699,13 @@ export const prepareComponentToken = (token: GlobalToken) => ({
defaultBg: token.colorBgContainer,
defaultBorderColor: token.colorBorder,
defaultBorderColorDisabled: token.colorBorder,
contentFontSize: token.fontSize,
contentFontSizeSM: token.fontSize,
contentFontSizeLG: token.fontSizeLG,
});
contentFontSize,
contentFontSizeSM,
contentFontSizeLG,
};
};
export default genComponentStyleHook(
export default genStyleHooks(
'Button',
(token) => {
const buttonToken = prepareToken(token);
@ -734,4 +730,9 @@ export default genComponentStyleHook(
];
},
prepareComponentToken,
{
unitless: {
fontWeight: true,
},
},
);

View File

@ -119,7 +119,7 @@ function generateCalendar<DateType>(generateConfig: GenerateConfig<DateType>) {
const prefixCls = getPrefixCls('picker', customizePrefixCls);
const calendarPrefixCls = `${prefixCls}-calendar`;
const [wrapSSR, hashId] = useStyle(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls, calendarPrefixCls);
const today = generateConfig.getNow();
@ -281,7 +281,7 @@ function generateCalendar<DateType>(generateConfig: GenerateConfig<DateType>) {
}
};
return wrapSSR(
return wrapCSSVar(
<div
className={classNames(
calendarPrefixCls,

View File

@ -1,4 +1,6 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { unit } from '@ant-design/cssinjs';
import type { PanelComponentToken, PickerPanelToken } from '../../date-picker/style';
import {
genPanelStyle,
@ -6,8 +8,8 @@ import {
initPickerPanelToken,
} from '../../date-picker/style';
import { resetComponent } from '../../style';
import type { FullToken } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import type { FullToken, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
export interface ComponentToken {
/**
@ -62,7 +64,7 @@ export const genCalendarStyles = (token: CalendarToken): CSSObject => {
[`${calendarCls}-header`]: {
display: 'flex',
justifyContent: 'flex-end',
padding: `${token.paddingSM}px 0`,
padding: `${unit(token.paddingSM)} 0`,
[`${calendarCls}-year-select`]: {
minWidth: token.yearControlWidth,
@ -79,13 +81,13 @@ export const genCalendarStyles = (token: CalendarToken): CSSObject => {
[`${calendarCls} ${componentCls}-panel`]: {
background: fullPanelBg,
border: 0,
borderTop: `${token.lineWidth}px ${token.lineType} ${token.colorSplit}`,
borderTop: `${unit(token.lineWidth)} ${token.lineType} ${token.colorSplit}`,
borderRadius: 0,
[`${componentCls}-month-panel, ${componentCls}-date-panel`]: {
width: 'auto',
},
[`${componentCls}-body`]: {
padding: `${token.paddingXS}px 0`,
padding: `${unit(token.paddingXS)} 0`,
},
[`${componentCls}-content`]: {
width: '100%',
@ -98,14 +100,14 @@ export const genCalendarStyles = (token: CalendarToken): CSSObject => {
paddingInlineStart: token.paddingXS,
},
[`${componentCls}-panel`]: {
borderRadius: `0 0 ${token.borderRadiusLG}px ${token.borderRadiusLG}px`,
borderRadius: `0 0 ${unit(token.borderRadiusLG)} ${unit(token.borderRadiusLG)}`,
},
[`${componentCls}-content`]: {
height: token.miniContentHeight,
th: {
height: 'auto',
padding: 0,
lineHeight: `${token.weekHeight}px`,
lineHeight: `${unit(token.weekHeight)}`,
},
},
[`${componentCls}-cell::before`]: {
@ -127,7 +129,7 @@ export const genCalendarStyles = (token: CalendarToken): CSSObject => {
height: 'auto',
paddingInlineEnd: token.paddingSM,
paddingBottom: token.paddingXXS,
lineHeight: `${token.weekHeight}px`,
lineHeight: `${unit(token.weekHeight)}`,
},
},
},
@ -161,14 +163,14 @@ export const genCalendarStyles = (token: CalendarToken): CSSObject => {
display: 'block',
width: 'auto',
height: 'auto',
margin: `0 ${token.marginXS / 2}px`,
padding: `${token.paddingXS / 2}px ${token.paddingXS}px 0`,
margin: `0 ${unit(token.calc(token.marginXS).div(2).equal())}`,
padding: `${unit(token.calc(token.paddingXS).div(2).equal())} ${unit(token.paddingXS)} 0`,
border: 0,
borderTop: `${token.lineWidthBold}px ${token.lineType} ${token.colorSplit}`,
borderTop: `${unit(token.lineWidthBold)} ${token.lineType} ${token.colorSplit}`,
borderRadius: 0,
transition: `background ${token.motionDurationSlow}`,
'&-value': {
lineHeight: `${token.dateValueHeight}px`,
lineHeight: `${unit(token.dateValueHeight)}`,
transition: `color ${token.motionDurationSlow}`,
},
'&-content': {
@ -188,7 +190,7 @@ export const genCalendarStyles = (token: CalendarToken): CSSObject => {
},
},
},
[`@media only screen and (max-width: ${token.screenXS}px) `]: {
[`@media only screen and (max-width: ${unit(token.screenXS)}) `]: {
[`${calendarCls}`]: {
[`${calendarCls}-header`]: {
display: 'block',
@ -196,7 +198,7 @@ export const genCalendarStyles = (token: CalendarToken): CSSObject => {
width: '50%',
},
[`${calendarCls}-month-select`]: {
width: `calc(50% - ${token.paddingXS}px)`,
width: `calc(50% - ${unit(token.paddingXS)})`,
},
[`${calendarCls}-mode-switch`]: {
width: '100%',
@ -213,32 +215,33 @@ export const genCalendarStyles = (token: CalendarToken): CSSObject => {
};
};
export default genComponentStyleHook(
'Calendar',
(token) => {
const calendarCls = `${token.componentCls}-calendar`;
const calendarToken = mergeToken<CalendarToken>(
token,
initPickerPanelToken(token),
initPanelComponentToken(token),
{
calendarCls,
pickerCellInnerCls: `${token.componentCls}-cell-inner`,
dateValueHeight: token.controlHeightSM,
weekHeight: token.controlHeightSM * 0.75,
dateContentHeight:
(token.fontSizeSM * token.lineHeightSM + token.marginXS) * 3 + token.lineWidth * 2,
},
);
return [genCalendarStyles(calendarToken)];
},
(token) => ({
export const prepareComponentToken: GetDefaultToken<'Calendar'> = (token) => ({
fullBg: token.colorBgContainer,
fullPanelBg: token.colorBgContainer,
itemActiveBg: token.controlItemBgActive,
yearControlWidth: 80,
monthControlWidth: 70,
miniContentHeight: 256,
}),
...initPanelComponentToken(token),
});
export default genStyleHooks(
'Calendar',
(token) => {
const calendarCls = `${token.componentCls}-calendar`;
const calendarToken = mergeToken<CalendarToken>(token, initPickerPanelToken(token), {
calendarCls,
pickerCellInnerCls: `${token.componentCls}-cell-inner`,
dateValueHeight: token.controlHeightSM,
weekHeight: token.calc(token.controlHeightSM).mul(0.75).equal() as number,
dateContentHeight: token
.calc(token.calc(token.fontHeightSM).add(token.marginXS))
.mul(3)
.add(token.calc(token.lineWidth).mul(2))
.equal() as number,
});
return [genCalendarStyles(calendarToken)];
},
prepareComponentToken,
);

View File

@ -109,7 +109,7 @@ const Card = React.forwardRef<HTMLDivElement, CardProps>((props, ref) => {
}, [children]);
const prefixCls = getPrefixCls('card', customizePrefixCls);
const [wrapSSR, hashId] = useStyle(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls);
const loadingBlock = (
<Skeleton loading active paragraph={{ rows: 4 }} title={false}>
@ -181,7 +181,7 @@ const Card = React.forwardRef<HTMLDivElement, CardProps>((props, ref) => {
const mergedStyle: React.CSSProperties = { ...card?.style, ...style };
return wrapSSR(
return wrapCSSVar(
<div ref={ref} {...divProps} className={classString} style={mergedStyle}>
{head}
{coverDom}

View File

@ -1,8 +1,8 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { type CSSObject, unit } from '@ant-design/cssinjs';
import { clearFix, resetComponent, textEllipsis } from '../../style';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
export interface ComponentToken {
/**
@ -72,13 +72,13 @@ const genCardHeadStyle: GenerateStyle<CardToken> = (token): CSSObject => {
flexDirection: 'column',
minHeight: headerHeight,
marginBottom: -1, // Fix card grid overflow bug: https://gw.alipayobjects.com/zos/rmsportal/XonYxBikwpgbqIQBeuhk.png
padding: `0 ${cardPaddingBase}px`,
padding: `0 ${unit(cardPaddingBase)}`,
color: token.colorTextHeading,
fontWeight: token.fontWeightStrong,
fontSize: token.headerFontSize,
background: token.headerBg,
borderBottom: `${token.lineWidth}px ${token.lineType} ${token.colorBorderSecondary}`,
borderRadius: `${token.borderRadiusLG}px ${token.borderRadiusLG}px 0 0`,
borderBottom: `${unit(token.lineWidth)} ${token.lineType} ${token.colorBorderSecondary}`,
borderRadius: `${unit(token.borderRadiusLG)} ${unit(token.borderRadiusLG)} 0 0`,
...clearFix(),
@ -111,7 +111,7 @@ const genCardHeadStyle: GenerateStyle<CardToken> = (token): CSSObject => {
fontSize: token.fontSize,
'&-bar': {
borderBottom: `${token.lineWidth}px ${token.lineType} ${token.colorBorderSecondary}`,
borderBottom: `${unit(token.lineWidth)} ${token.lineType} ${token.colorBorderSecondary}`,
},
},
};
@ -126,11 +126,11 @@ const genCardGridStyle: GenerateStyle<CardToken> = (token): CSSObject => {
border: 0,
borderRadius: 0,
boxShadow: `
${lineWidth}px 0 0 0 ${colorBorderSecondary},
0 ${lineWidth}px 0 0 ${colorBorderSecondary},
${lineWidth}px ${lineWidth}px 0 0 ${colorBorderSecondary},
${lineWidth}px 0 0 0 ${colorBorderSecondary} inset,
0 ${lineWidth}px 0 0 ${colorBorderSecondary} inset;
${unit(lineWidth)} 0 0 0 ${colorBorderSecondary},
0 ${unit(lineWidth)} 0 0 ${colorBorderSecondary},
${unit(lineWidth)} ${unit(lineWidth)} 0 0 ${colorBorderSecondary},
${unit(lineWidth)} 0 0 0 ${colorBorderSecondary} inset,
0 ${unit(lineWidth)} 0 0 ${colorBorderSecondary} inset;
`,
transition: `all ${token.motionDurationMid}`,
@ -157,9 +157,9 @@ const genCardActionsStyle: GenerateStyle<CardToken> = (token): CSSObject => {
padding: 0,
listStyle: 'none',
background: actionsBg,
borderTop: `${token.lineWidth}px ${token.lineType} ${colorBorderSecondary}`,
borderTop: `${unit(token.lineWidth)} ${token.lineType} ${colorBorderSecondary}`,
display: 'flex',
borderRadius: `0 0 ${token.borderRadiusLG}px ${token.borderRadiusLG}px `,
borderRadius: `0 0 ${unit(token.borderRadiusLG)} ${unit(token.borderRadiusLG)}`,
...clearFix(),
'& > li': {
@ -170,7 +170,7 @@ const genCardActionsStyle: GenerateStyle<CardToken> = (token): CSSObject => {
'> span': {
position: 'relative',
display: 'block',
minWidth: token.cardActionsIconSize * 2,
minWidth: token.calc(token.cardActionsIconSize).mul(2).equal(),
fontSize: token.fontSize,
lineHeight: token.lineHeight,
cursor: 'pointer',
@ -184,7 +184,7 @@ const genCardActionsStyle: GenerateStyle<CardToken> = (token): CSSObject => {
display: 'inline-block',
width: '100%',
color: token.colorTextDescription,
lineHeight: `${token.fontSize * token.lineHeight}px`,
lineHeight: unit(token.fontHeight),
transition: `color ${token.motionDurationMid}`,
'&:hover': {
@ -194,12 +194,12 @@ const genCardActionsStyle: GenerateStyle<CardToken> = (token): CSSObject => {
[`> ${iconCls}`]: {
fontSize: cardActionsIconSize,
lineHeight: `${cardActionsIconSize * token.lineHeight}px`,
lineHeight: unit(token.calc(cardActionsIconSize).mul(token.lineHeight).equal()),
},
},
'&:not(:last-child)': {
borderInlineEnd: `${token.lineWidth}px ${token.lineType} ${colorBorderSecondary}`,
borderInlineEnd: `${unit(token.lineWidth)} ${token.lineType} ${colorBorderSecondary}`,
},
},
};
@ -207,7 +207,7 @@ const genCardActionsStyle: GenerateStyle<CardToken> = (token): CSSObject => {
// ============================== Meta ==============================
const genCardMetaStyle: GenerateStyle<CardToken> = (token): CSSObject => ({
margin: `-${token.marginXXS}px 0`,
margin: `${unit(token.calc(token.marginXXS).mul(-1).equal())} 0`,
display: 'flex',
...clearFix(),
@ -242,7 +242,7 @@ const genCardTypeInnerStyle: GenerateStyle<CardToken> = (token): CSSObject => {
return {
[`${componentCls}-head`]: {
padding: `0 ${cardPaddingBase}px`,
padding: `0 ${unit(cardPaddingBase)}`,
background: colorFillAlter,
'&-title': {
@ -251,7 +251,7 @@ const genCardTypeInnerStyle: GenerateStyle<CardToken> = (token): CSSObject => {
},
[`${componentCls}-body`]: {
padding: `${token.padding}px ${cardPaddingBase}px`,
padding: `${unit(token.padding)} ${unit(cardPaddingBase)}`,
},
};
};
@ -306,7 +306,7 @@ const genCardStyle: GenerateStyle<CardToken> = (token): CSSObject => {
[`${componentCls}-body`]: {
padding: cardPaddingBase,
borderRadius: ` 0 0 ${token.borderRadiusLG}px ${token.borderRadiusLG}px`,
borderRadius: ` 0 0 ${unit(token.borderRadiusLG)} ${unit(token.borderRadiusLG)}`,
...clearFix(),
},
@ -319,7 +319,7 @@ const genCardStyle: GenerateStyle<CardToken> = (token): CSSObject => {
},
[`img, img + ${antCls}-image-mask`]: {
borderRadius: `${token.borderRadiusLG}px ${token.borderRadiusLG}px 0 0`,
borderRadius: `${unit(token.borderRadiusLG)} ${unit(token.borderRadiusLG)} 0 0`,
},
},
@ -329,7 +329,7 @@ const genCardStyle: GenerateStyle<CardToken> = (token): CSSObject => {
},
[`${componentCls}-bordered`]: {
border: `${token.lineWidth}px ${token.lineType} ${colorBorderSecondary}`,
border: `${unit(token.lineWidth)} ${token.lineType} ${colorBorderSecondary}`,
[`${componentCls}-cover`]: {
marginTop: -1,
@ -349,15 +349,15 @@ const genCardStyle: GenerateStyle<CardToken> = (token): CSSObject => {
},
[`${componentCls}-contain-grid`]: {
borderRadius: `${token.borderRadiusLG}px ${token.borderRadiusLG}px 0 0 `,
borderRadius: `${unit(token.borderRadiusLG)} ${unit(token.borderRadiusLG)} 0 0 `,
[`${componentCls}-body`]: {
display: 'flex',
flexWrap: 'wrap',
},
[`&:not(${componentCls}-loading) ${componentCls}-body`]: {
marginBlockStart: -token.lineWidth,
marginInlineStart: -token.lineWidth,
marginBlockStart: token.calc(token.lineWidth).mul(-1).equal(),
marginInlineStart: token.calc(token.lineWidth).mul(-1).equal(),
padding: 0,
},
},
@ -389,7 +389,7 @@ const genCardSizeStyle: GenerateStyle<CardToken> = (token): CSSObject => {
[`${componentCls}-small`]: {
[`> ${componentCls}-head`]: {
minHeight: headerHeightSM,
padding: `0 ${cardPaddingSM}px`,
padding: `0 ${unit(cardPaddingSM)}`,
fontSize: headerFontSizeSM,
[`> ${componentCls}-head-wrapper`]: {
@ -415,8 +415,20 @@ const genCardSizeStyle: GenerateStyle<CardToken> = (token): CSSObject => {
};
};
export const prepareComponentToken: GetDefaultToken<'Card'> = (token) => ({
headerBg: 'transparent',
headerFontSize: token.fontSizeLG,
headerFontSizeSM: token.fontSize,
headerHeight: token.fontSizeLG * token.lineHeightLG + token.padding * 2,
headerHeightSM: token.fontSize * token.lineHeight + token.paddingXS * 2,
actionsBg: token.colorBgContainer,
actionsLiMargin: `${token.paddingSM}px 0`,
tabsMarginBottom: -token.padding - token.lineWidth,
extraColor: token.colorText,
});
// ============================== Export ==============================
export default genComponentStyleHook(
export default genStyleHooks(
'Card',
(token) => {
const cardToken = mergeToken<CardToken>(token, {
@ -435,15 +447,5 @@ export default genComponentStyleHook(
genCardSizeStyle(cardToken),
];
},
(token) => ({
headerBg: 'transparent',
headerFontSize: token.fontSizeLG,
headerFontSizeSM: token.fontSize,
headerHeight: token.fontSizeLG * token.lineHeightLG + token.padding * 2,
headerHeightSM: token.fontSize * token.lineHeight + token.paddingXS * 2,
actionsBg: token.colorBgContainer,
actionsLiMargin: `${token.paddingSM}px 0`,
tabsMarginBottom: -token.padding - token.lineWidth,
extraColor: token.colorText,
}),
prepareComponentToken,
);

View File

@ -94,7 +94,7 @@ const Carousel = React.forwardRef<CarouselRef, CarouselProps>((props, ref) => {
typeof dots === 'boolean' ? false : dots?.className,
);
const [wrapSSR, hashId] = useStyle(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls);
const className = classNames(
prefixCls,
@ -106,7 +106,7 @@ const Carousel = React.forwardRef<CarouselRef, CarouselProps>((props, ref) => {
rootClassName,
);
return wrapSSR(
return wrapCSSVar(
<div className={className} id={id}>
<SlickCarousel
ref={slickRef}

View File

@ -1,6 +1,8 @@
import { unit } from '@ant-design/cssinjs';
import { resetComponent } from '../../style';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
export interface ComponentToken {
/**
@ -23,14 +25,14 @@ export interface ComponentToken {
}
interface CarouselToken extends FullToken<'Carousel'> {
carouselArrowSize: number;
carouselDotOffset: number;
carouselDotInline: number;
carouselArrowSize: string | number;
carouselDotOffset: string | number;
carouselDotInline: string | number;
}
const genCarouselStyle: GenerateStyle<CarouselToken> = (token) => {
const { componentCls, antCls, carouselArrowSize, carouselDotOffset, marginXXS } = token;
const arrowOffset = -carouselArrowSize * 1.25;
const arrowOffset = token.calc(carouselArrowSize).mul(-1.25).equal();
const carouselDotMargin = marginXXS;
@ -143,7 +145,7 @@ const genCarouselStyle: GenerateStyle<CarouselToken> = (token) => {
display: 'block',
width: carouselArrowSize,
height: carouselArrowSize,
marginTop: -carouselArrowSize / 2,
marginTop: token.calc(carouselArrowSize).mul(-1).div(2).equal(),
padding: 0,
color: 'transparent',
fontSize: 0,
@ -242,7 +244,7 @@ const genCarouselStyle: GenerateStyle<CarouselToken> = (token) => {
'&::after': {
position: 'absolute',
inset: -carouselDotMargin,
inset: token.calc(carouselDotMargin).mul(-1).equal(),
content: '""',
},
},
@ -297,7 +299,7 @@ const genCarouselVerticalStyle: GenerateStyle<CarouselToken> = (token) => {
li: {
// reverse width and height in vertical situation
...reverseSizeOfDot,
margin: `${marginXXS}px 0`,
margin: `${unit(marginXXS)} 0`,
verticalAlign: 'baseline',
button: reverseSizeOfDot,
@ -341,23 +343,7 @@ const genCarouselRtlStyle: GenerateStyle<CarouselToken> = (token) => {
];
};
// ============================== Export ==============================
export default genComponentStyleHook(
'Carousel',
(token) => {
const { controlHeightLG, controlHeightSM } = token;
const carouselToken = mergeToken<CarouselToken>(token, {
carouselArrowSize: controlHeightLG / 2,
carouselDotOffset: controlHeightSM / 2,
});
return [
genCarouselStyle(carouselToken),
genCarouselVerticalStyle(carouselToken),
genCarouselRtlStyle(carouselToken),
];
},
() => {
export const prepareComponentToken: GetDefaultToken<'Carousel'> = () => {
const dotActiveWidth = 24;
return {
@ -366,7 +352,25 @@ export default genComponentStyleHook(
dotWidthActive: dotActiveWidth,
dotActiveWidth,
};
};
// ============================== Export ==============================
export default genStyleHooks(
'Carousel',
(token) => {
const { controlHeightLG, controlHeightSM } = token;
const carouselToken = mergeToken<CarouselToken>(token, {
carouselArrowSize: token.calc(controlHeightLG).div(2).equal(),
carouselDotOffset: token.calc(controlHeightSM).div(2).equal(),
});
return [
genCarouselStyle(carouselToken),
genCarouselVerticalStyle(carouselToken),
genCarouselRtlStyle(carouselToken),
];
},
prepareComponentToken,
{
deprecatedTokens: [['dotWidthActive', 'dotActiveWidth']],
},

View File

@ -5,6 +5,7 @@ import type { PickType } from 'rc-cascader/lib/Panel';
import type { CascaderProps } from '.';
import DefaultRenderEmpty from '../config-provider/defaultRenderEmpty';
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
import useBase from './hooks/useBase';
import useCheckable from './hooks/useCheckable';
import useColumnIcons from './hooks/useColumnIcons';
@ -31,7 +32,8 @@ export default function CascaderPanel(props: CascaderPanelProps) {
direction,
);
const [, hashId] = useStyle(cascaderPrefixCls);
const rootCls = useCSSVarCls(cascaderPrefixCls);
const [wrapCSSVar, hashId] = useStyle(cascaderPrefixCls, rootCls);
usePanelStyle(cascaderPrefixCls);
const isRtl = mergedDirection === 'rtl';
@ -49,16 +51,16 @@ export default function CascaderPanel(props: CascaderPanelProps) {
// ==================== Render =====================
return (
return wrapCSSVar(
<Panel
{...props}
checkable={checkable}
prefixCls={cascaderPrefixCls}
className={classNames(className, hashId, rootClassName)}
className={classNames(className, hashId, rootClassName, rootCls)}
notFoundContent={mergedNotFoundContent}
direction={mergedDirection}
expandIcon={mergedExpandIcon}
loadingIcon={loadingIcon}
/>
/>,
);
}

View File

@ -12,6 +12,7 @@ import RcCascader from 'rc-cascader';
import type { Placement } from 'rc-select/lib/BaseSelect';
import omit from 'rc-util/lib/omit';
import { useZIndex } from '../_util/hooks/useZIndex';
import type { SelectCommonPlacement } from '../_util/motion';
import { getTransitionName } from '../_util/motion';
import genPurePanel from '../_util/PurePanel';
@ -21,6 +22,7 @@ import { devUseWarning } from '../_util/warning';
import { ConfigContext } from '../config-provider';
import DefaultRenderEmpty from '../config-provider/defaultRenderEmpty';
import DisabledContext from '../config-provider/DisabledContext';
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
import useSize from '../config-provider/hooks/useSize';
import type { SizeType } from '../config-provider/SizeContext';
import { FormItemInputContext } from '../form/context';
@ -34,7 +36,6 @@ import useCheckable from './hooks/useCheckable';
import useColumnIcons from './hooks/useColumnIcons';
import CascaderPanel from './Panel';
import useStyle from './style';
import { useZIndex } from '../_util/hooks/useZIndex';
// Align the design since we use `rc-select` in root. This help:
// - List search content will show all content
@ -211,8 +212,10 @@ const Cascader = React.forwardRef<CascaderRef, CascaderProps<any>>((props, ref)
const rootPrefixCls = getPrefixCls();
const [wrapSelectSSR, hashId] = useSelectStyle(prefixCls);
const [wrapCascaderSSR] = useStyle(cascaderPrefixCls);
const rootCls = useCSSVarCls(prefixCls);
const [wrapSelectCSSVar, hashId] = useSelectStyle(prefixCls, rootCls);
const cascaderRootCls = useCSSVarCls(cascaderPrefixCls);
const [wrapCascaderCSSVar] = useStyle(cascaderPrefixCls, cascaderRootCls);
const { compactSize, compactItemClassnames } = useCompactItemContext(prefixCls, direction);
@ -229,6 +232,8 @@ const Cascader = React.forwardRef<CascaderRef, CascaderProps<any>>((props, ref)
[`${cascaderPrefixCls}-dropdown-rtl`]: mergedDirection === 'rtl',
},
rootClassName,
rootCls,
cascaderRootCls,
hashId,
);
@ -310,6 +315,8 @@ const Cascader = React.forwardRef<CascaderRef, CascaderProps<any>>((props, ref)
cascader?.className,
className,
rootClassName,
rootCls,
cascaderRootCls,
hashId,
)}
disabled={mergedDisabled}
@ -339,7 +346,7 @@ const Cascader = React.forwardRef<CascaderRef, CascaderProps<any>>((props, ref)
/>
);
return wrapCascaderSSR(wrapSelectSSR(renderNode));
return wrapCascaderCSSVar(wrapSelectCSSVar(renderNode));
}) as unknown as (<OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType>(
props: React.PropsWithChildren<CascaderProps<OptionType>> & { ref?: React.Ref<CascaderRef> },
) => React.ReactElement) & {

View File

@ -1,4 +1,4 @@
import type { CSSInterpolation } from '@ant-design/cssinjs';
import { unit, type CSSInterpolation } from '@ant-design/cssinjs';
import type { CascaderToken } from '.';
import { getStyle as getCheckboxStyle } from '../../checkbox/style';
@ -59,7 +59,7 @@ const getColumnsStyle: GenerateStyle<CascaderToken> = (token: CascaderToken): CS
'-ms-overflow-style': '-ms-autohiding-scrollbar', // https://github.com/ant-design/ant-design/issues/11857
'&:not(:last-child)': {
borderInlineEnd: `${token.lineWidth}px ${token.lineType} ${token.colorSplit}`,
borderInlineEnd: `${unit(token.lineWidth)} ${token.lineType} ${token.colorSplit}`,
},
'&-item': {

View File

@ -3,7 +3,7 @@ import type { CSSProperties } from 'react';
import { genCompactItemStyle } from '../../style/compact-item';
import type { GlobalToken } from '../../theme';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook } from '../../theme/internal';
import { genStyleHooks } from '../../theme/internal';
import getColumnsStyle from './columns';
export interface ComponentToken {
@ -104,8 +104,4 @@ export const prepareComponentToken = (token: GlobalToken) => {
};
};
export default genComponentStyleHook(
'Cascader',
(token) => [genBaseStyle(token)],
prepareComponentToken,
);
export default genStyleHooks('Cascader', (token) => [genBaseStyle(token)], prepareComponentToken);

View File

@ -1,4 +1,4 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { unit, type CSSObject } from '@ant-design/cssinjs';
import { prepareComponentToken, type CascaderToken } from '.';
import { genComponentStyleHook, type GenerateStyle } from '../../theme/internal';
@ -13,7 +13,7 @@ const genPanelStyle: GenerateStyle<CascaderToken> = (token: CascaderToken): CSSO
getColumnsStyle(token),
{
display: 'inline-flex',
border: `${token.lineWidth}px ${token.lineType} ${token.colorSplit}`,
border: `${unit(token.lineWidth)} ${token.lineType} ${token.colorSplit}`,
borderRadius: token.borderRadiusLG,
overflowX: 'auto',
maxWidth: '100%',

View File

@ -8,6 +8,7 @@ import Wave from '../_util/wave';
import { TARGET_CLS } from '../_util/wave/interface';
import { ConfigContext } from '../config-provider';
import DisabledContext from '../config-provider/DisabledContext';
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
import { FormItemInputContext } from '../form/context';
import GroupContext from './GroupContext';
import useStyle from './style';
@ -105,7 +106,8 @@ const InternalCheckbox: React.ForwardRefRenderFunction<CheckboxRef, CheckboxProp
}, [restProps.value]);
const prefixCls = getPrefixCls('checkbox', customizePrefixCls);
const [wrapSSR, hashId] = useStyle(prefixCls);
const rootCls = useCSSVarCls(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls, rootCls);
const checkboxProps: CheckboxProps = { ...restProps };
if (checkboxGroup && !skipGroup) {
@ -131,6 +133,7 @@ const InternalCheckbox: React.ForwardRefRenderFunction<CheckboxRef, CheckboxProp
checkbox?.className,
className,
rootClassName,
rootCls,
hashId,
);
const checkboxClass = classNames(
@ -141,7 +144,7 @@ const InternalCheckbox: React.ForwardRefRenderFunction<CheckboxRef, CheckboxProp
hashId,
);
const ariaChecked = indeterminate ? 'mixed' : undefined;
return wrapSSR(
return wrapCSSVar(
<Wave component="Checkbox" disabled={mergedDisabled}>
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
<label

View File

@ -3,6 +3,7 @@ import classNames from 'classnames';
import omit from 'rc-util/lib/omit';
import { ConfigContext } from '../config-provider';
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
import type { CheckboxChangeEvent } from './Checkbox';
import Checkbox from './Checkbox';
import GroupContext from './GroupContext';
@ -110,7 +111,8 @@ const InternalGroup: React.ForwardRefRenderFunction<HTMLDivElement, CheckboxGrou
const prefixCls = getPrefixCls('checkbox', customizePrefixCls);
const groupPrefixCls = `${prefixCls}-group`;
const [wrapSSR, hashId] = useStyle(prefixCls);
const rootCls = useCSSVarCls(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls, rootCls);
const domProps = omit(restProps, ['value', 'disabled']);
@ -151,9 +153,10 @@ const InternalGroup: React.ForwardRefRenderFunction<HTMLDivElement, CheckboxGrou
},
className,
rootClassName,
rootCls,
hashId,
);
return wrapSSR(
return wrapCSSVar(
<div className={classString} style={style} {...domProps} ref={ref}>
<GroupContext.Provider value={context}>{childrenNode}</GroupContext.Provider>
</div>,

View File

@ -1,6 +1,8 @@
import { unit } from '@ant-design/cssinjs';
import { genFocusOutline, resetComponent } from '../../style';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
export interface ComponentToken {}
@ -102,7 +104,7 @@ export const genCheckboxStyle: GenerateStyle<CheckboxToken> = (token) => {
height: token.checkboxSize,
direction: 'ltr',
backgroundColor: token.colorBgContainer,
border: `${token.lineWidth}px ${token.lineType} ${token.colorBorder}`,
border: `${unit(token.lineWidth)} ${token.lineType} ${token.colorBorder}`,
borderRadius: token.borderRadiusSM,
borderCollapse: 'separate',
transition: `all ${token.motionDurationSlow}`,
@ -113,9 +115,9 @@ export const genCheckboxStyle: GenerateStyle<CheckboxToken> = (token) => {
top: '50%',
insetInlineStart: '21.5%',
display: 'table',
width: (token.checkboxSize / 14) * 5,
height: (token.checkboxSize / 14) * 8,
border: `${token.lineWidthBold}px solid ${token.colorWhite}`,
width: token.calc(token.checkboxSize).div(14).mul(5).equal(),
height: token.calc(token.checkboxSize).div(14).mul(8).equal(),
border: `${unit(token.lineWidthBold)} solid ${token.colorWhite}`,
borderTop: 0,
borderInlineStart: 0,
transform: 'rotate(45deg) scale(0) translate(-50%,-50%)',
@ -195,8 +197,8 @@ export const genCheckboxStyle: GenerateStyle<CheckboxToken> = (token) => {
'&:after': {
top: '50%',
insetInlineStart: '50%',
width: token.fontSizeLG / 2,
height: token.fontSizeLG / 2,
width: token.calc(token.fontSizeLG).div(2).equal(),
height: token.calc(token.fontSizeLG).div(2).equal(),
backgroundColor: token.colorPrimary,
border: 0,
transform: 'translate(-50%, -50%) scale(1)',
@ -261,6 +263,4 @@ export function getStyle(prefixCls: string, token: FullToken<'Checkbox'>) {
return [genCheckboxStyle(checkboxToken)];
}
export default genComponentStyleHook('Checkbox', (token, { prefixCls }) => [
getStyle(prefixCls, token),
]);
export default genStyleHooks('Checkbox', (token, { prefixCls }) => [getStyle(prefixCls, token)]);

View File

@ -76,7 +76,7 @@ const Collapse = React.forwardRef<HTMLDivElement, CollapseProps>((props, ref) =>
const mergedSize = useSize((ctx) => customizeSize ?? ctx ?? 'middle');
const prefixCls = getPrefixCls('collapse', customizePrefixCls);
const rootPrefixCls = getPrefixCls();
const [wrapSSR, hashId] = useStyle(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls);
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning('Collapse');
@ -153,7 +153,7 @@ const Collapse = React.forwardRef<HTMLDivElement, CollapseProps>((props, ref) =>
[children],
);
return wrapSSR(
return wrapCSSVar(
<RcCollapse
ref={ref}
openMotion={openMotion}

View File

@ -1,8 +1,10 @@
import type { CSSProperties } from 'react';
import { unit } from '@ant-design/cssinjs';
import { resetComponent, resetIcon } from '../../style';
import { genCollapseMotion } from '../../style/motion';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
/** Component only token. Which will handle additional calculation of alias token */
export interface ComponentToken {
@ -52,9 +54,9 @@ export const genBaseStyle: GenerateStyle<CollapseToken> = (token) => {
colorText,
colorTextHeading,
colorTextDisabled,
fontSize,
fontSizeLG,
lineHeight,
lineHeightLG,
marginSM,
paddingSM,
paddingLG,
@ -62,9 +64,11 @@ export const genBaseStyle: GenerateStyle<CollapseToken> = (token) => {
motionDurationSlow,
fontSizeIcon,
contentPadding,
fontHeight,
fontHeightLG,
} = token;
const borderBase = `${lineWidth}px ${lineType} ${colorBorder}`;
const borderBase = `${unit(lineWidth)} ${lineType} ${colorBorder}`;
return {
[componentCls]: {
@ -72,7 +76,7 @@ export const genBaseStyle: GenerateStyle<CollapseToken> = (token) => {
backgroundColor: headerBg,
border: borderBase,
borderBottom: 0,
borderRadius: `${collapsePanelBorderRadius}px`,
borderRadius: collapsePanelBorderRadius,
[`&-rtl`]: {
direction: 'rtl',
@ -84,7 +88,9 @@ export const genBaseStyle: GenerateStyle<CollapseToken> = (token) => {
[`
&,
& > ${componentCls}-header`]: {
borderRadius: `0 0 ${collapsePanelBorderRadius}px ${collapsePanelBorderRadius}px`,
borderRadius: `0 0 ${unit(collapsePanelBorderRadius)} ${unit(
collapsePanelBorderRadius,
)}`,
},
},
@ -109,7 +115,7 @@ export const genBaseStyle: GenerateStyle<CollapseToken> = (token) => {
// >>>>> Arrow
[`${componentCls}-expand-icon`]: {
height: fontSize * lineHeight,
height: fontHeight,
display: 'flex',
alignItems: 'center',
paddingInlineEnd: marginSM,
@ -161,7 +167,7 @@ export const genBaseStyle: GenerateStyle<CollapseToken> = (token) => {
[`> ${componentCls}-expand-icon`]: {
// Arrow offset
marginInlineStart: paddingSM - paddingXS,
marginInlineStart: token.calc(paddingSM).sub(paddingXS).equal(),
},
},
[`> ${componentCls}-content > ${componentCls}-content-box`]: {
@ -173,15 +179,15 @@ export const genBaseStyle: GenerateStyle<CollapseToken> = (token) => {
[`&-large`]: {
[`> ${componentCls}-item`]: {
fontSize: fontSizeLG,
lineHeight: lineHeightLG,
[`> ${componentCls}-header`]: {
padding: collapseHeaderPaddingLG,
paddingInlineStart: padding,
[`> ${componentCls}-expand-icon`]: {
height: fontSizeLG * lineHeight,
height: fontHeightLG,
// Arrow offset
marginInlineStart: paddingLG - padding,
marginInlineStart: token.calc(paddingLG).sub(padding).equal(),
},
},
[`> ${componentCls}-content > ${componentCls}-content-box`]: {
@ -192,7 +198,7 @@ export const genBaseStyle: GenerateStyle<CollapseToken> = (token) => {
[`${componentCls}-item:last-child`]: {
[`> ${componentCls}-content`]: {
borderRadius: `0 0 ${collapsePanelBorderRadius}px ${collapsePanelBorderRadius}px`,
borderRadius: `0 0 ${unit(collapsePanelBorderRadius)} ${unit(collapsePanelBorderRadius)}`,
},
},
@ -298,12 +304,19 @@ const genGhostStyle: GenerateStyle<CollapseToken> = (token) => {
};
};
export default genComponentStyleHook(
export const prepareComponentToken: GetDefaultToken<'Collapse'> = (token) => ({
headerPadding: `${token.paddingSM}px ${token.padding}px`,
headerBg: token.colorFillAlter,
contentPadding: `${token.padding}px 16px`, // Fixed Value
contentBg: token.colorBgContainer,
});
export default genStyleHooks(
'Collapse',
(token) => {
const collapseToken = mergeToken<CollapseToken>(token, {
collapseHeaderPaddingSM: `${token.paddingXS}px ${token.paddingSM}px`,
collapseHeaderPaddingLG: `${token.padding}px ${token.paddingLG}px`,
collapseHeaderPaddingSM: `${unit(token.paddingXS)} ${unit(token.paddingSM)}`,
collapseHeaderPaddingLG: `${unit(token.padding)} ${unit(token.paddingLG)}`,
collapsePanelBorderRadius: token.borderRadiusLG,
});
@ -315,10 +328,5 @@ export default genComponentStyleHook(
genCollapseMotion(collapseToken),
];
},
(token) => ({
headerPadding: `${token.paddingSM}px ${token.padding}px`,
headerBg: token.colorFillAlter,
contentPadding: `${token.padding}px 16px`, // Fixed Value
contentBg: token.colorBgContainer,
}),
prepareComponentToken,
);

View File

@ -12,6 +12,7 @@ import { getStatusClassNames } from '../_util/statusUtils';
import { devUseWarning } from '../_util/warning';
import type { ConfigConsumerProps } from '../config-provider/context';
import { ConfigContext } from '../config-provider/context';
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
import DisabledContext from '../config-provider/DisabledContext';
import useSize from '../config-provider/hooks/useSize';
import type { SizeType } from '../config-provider/SizeContext';
@ -31,7 +32,7 @@ import type {
TriggerPlacement,
TriggerType,
} from './interface';
import useStyle from './style/index';
import useStyle from './style';
import { customizePrefixCls, genAlphaColor, generateColor, getAlphaColor } from './util';
export type ColorPickerProps = Omit<
@ -135,9 +136,10 @@ const ColorPicker: CompoundedComponent = (props) => {
// ===================== Style =====================
const mergedSize = useSize(customizeSize);
const [wrapSSR, hashId] = useStyle(prefixCls);
const rootCls = useCSSVarCls(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls, rootCls);
const rtlCls = { [`${prefixCls}-rtl`]: direction };
const mergeRootCls = classNames(rootClassName, rtlCls);
const mergeRootCls = classNames(rootClassName, rootCls, rtlCls);
const mergeCls = classNames(
getStatusClassNames(prefixCls, contextStatus),
{
@ -149,7 +151,7 @@ const ColorPicker: CompoundedComponent = (props) => {
className,
hashId,
);
const mergePopupCls = classNames(prefixCls, rtlCls);
const mergePopupCls = classNames(prefixCls, mergeRootCls);
const popupAllowCloseRef = useRef(true);
@ -234,7 +236,7 @@ const ColorPicker: CompoundedComponent = (props) => {
// ============================ zIndex ============================
return wrapSSR(
return wrapCSSVar(
<Popover
style={styles?.popup}
overlayInnerStyle={styles?.popupOverlayInner}

View File

@ -1,4 +1,5 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { unit, type CSSObject } from '@ant-design/cssinjs';
import type { ColorPickerToken } from './index';
/**
@ -23,7 +24,7 @@ const genColorBlockStyle = (token: ColorPickerToken, size: number): CSSObject =>
[`${componentCls}-color-block-inner`]: {
width: '100%',
height: '100%',
border: `${lineWidth}px solid ${colorFillSecondary}`,
border: `${unit(lineWidth)} solid ${colorFillSecondary}`,
borderRadius: 'inherit',
},
},

View File

@ -1,6 +1,7 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { type CSSObject, unit } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
import genColorBlockStyle from './color-block';
import genInputStyle from './input';
import genPickerStyle from './picker';
@ -27,7 +28,7 @@ export const genActiveStyle = (
) => ({
borderInlineEndWidth: token.lineWidth,
borderColor,
boxShadow: `0 0 0 ${token.controlOutlineWidth}px ${outlineColor}`,
boxShadow: `0 0 0 ${unit(token.controlOutlineWidth)} ${outlineColor}`,
outline: 0,
});
@ -61,7 +62,7 @@ const genClearStyle = (
width: size,
height: size,
borderRadius: borderRadiusSM,
border: `${lineWidth}px solid ${colorSplit}`,
border: `${unit(lineWidth)} solid ${colorSplit}`,
position: 'relative',
cursor: 'pointer',
overflow: 'hidden',
@ -188,7 +189,7 @@ const genColorPickerStyle: GenerateStyle<ColorPickerToken> = (token) => {
width: colorPickerWidth,
'&-divider': {
margin: `${marginSM}px 0 ${marginXS}px`,
margin: `${unit(marginSM)} 0 ${unit(marginXS)}`,
},
[`${componentCls}-panel`]: {
...genPickerStyle(token),
@ -206,17 +207,20 @@ const genColorPickerStyle: GenerateStyle<ColorPickerToken> = (token) => {
minWidth: controlHeight,
height: controlHeight,
borderRadius,
border: `${lineWidth}px solid ${colorBorder}`,
border: `${unit(lineWidth)} solid ${colorBorder}`,
cursor: 'pointer',
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
transition: `all ${motionDurationMid}`,
background: colorBgElevated,
padding: paddingXXS - lineWidth,
padding: token.calc(paddingXXS).sub(lineWidth).equal(),
[`${componentCls}-trigger-text`]: {
marginInlineStart: marginXS,
marginInlineEnd: marginXS - (paddingXXS - lineWidth),
marginInlineEnd: token
.calc(marginXS)
.sub(token.calc(paddingXXS).sub(lineWidth))
.equal(),
fontSize,
color: colorText,
},
@ -248,7 +252,7 @@ const genColorPickerStyle: GenerateStyle<ColorPickerToken> = (token) => {
];
};
export default genComponentStyleHook('ColorPicker', (token) => {
export default genStyleHooks('ColorPicker', (token) => {
const { colorTextQuaternary, marginSM } = token;
const colorPickerSliderHeight = 8;
@ -262,7 +266,11 @@ export default genComponentStyleHook('ColorPicker', (token) => {
colorPickerPresetColorSize: 18,
colorPickerInsetShadow: `inset 0 0 1px 0 ${colorTextQuaternary}`,
colorPickerSliderHeight,
colorPickerPreviewSize: colorPickerSliderHeight * 2 + marginSM,
colorPickerPreviewSize: token
.calc(colorPickerSliderHeight)
.mul(2)
.add(marginSM)
.equal() as number,
});
return [genColorPickerStyle(colorPickerToken)];

View File

@ -1,4 +1,5 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { unit, type CSSObject } from '@ant-design/cssinjs';
import type { GenerateStyle } from '../../theme/internal';
import type { ColorPickerToken } from './index';
@ -36,7 +37,7 @@ const genInputStyle: GenerateStyle<ColorPickerToken, CSSObject> = (token) => {
},
[`${componentCls}-steppers${componentCls}-alpha-input`]: {
flex: `0 0 ${colorPickerAlphaInputWidth}px`,
flex: `0 0 ${unit(colorPickerAlphaInputWidth)}`,
marginInlineStart: marginXXS,
},
@ -52,9 +53,9 @@ const genInputStyle: GenerateStyle<ColorPickerToken, CSSObject> = (token) => {
insetInlineEnd: 0,
},
[`${antCls}-select-selection-item`]: {
paddingInlineEnd: fontSizeIcon + marginXXS,
paddingInlineEnd: token.calc(fontSizeIcon).add(marginXXS).equal(),
fontSize: fontSizeSM,
lineHeight: `${controlHeightSM}px`,
lineHeight: `${unit(controlHeightSM)}`,
},
[`${antCls}-select-item-option-content`]: {
fontSize: fontSizeSM,
@ -83,11 +84,11 @@ const genInputStyle: GenerateStyle<ColorPickerToken, CSSObject> = (token) => {
},
[`${componentCls}-hex-input${antCls}-input-affix-wrapper`]: {
flex: 1,
padding: `0 ${paddingXS}px`,
padding: `0 ${unit(paddingXS)}`,
[`${antCls}-input`]: {
fontSize: fontSizeSM,
textTransform: 'uppercase',
lineHeight: `${controlHeightSM - 2 * lineWidth}px`,
lineHeight: unit(token.calc(controlHeightSM).sub(token.calc(lineWidth).mul(2)).equal()),
},
[`${antCls}-input-prefix`]: {
color: colorTextPlaceholder,

View File

@ -1,4 +1,5 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { unit, type CSSObject } from '@ant-design/cssinjs';
import type { GenerateStyle } from '../../theme/internal';
import { getTransBg } from './color-block';
import type { ColorPickerToken } from './index';
@ -21,7 +22,7 @@ const genPickerStyle: GenerateStyle<ColorPickerToken, CSSObject> = (token) => {
return {
[`${componentCls}-select`]: {
[`${componentCls}-palette`]: {
minHeight: controlHeightLG * 4,
minHeight: token.calc(controlHeightLG).mul(4).equal(),
overflow: 'hidden',
borderRadius: borderRadiusSM,
},
@ -37,7 +38,7 @@ const genPickerStyle: GenerateStyle<ColorPickerToken, CSSObject> = (token) => {
[`${componentCls}-handler`]: {
width: colorPickerHandlerSize,
height: colorPickerHandlerSize,
border: `${lineWidthBold}px solid ${colorBgElevated}`,
border: `${unit(lineWidthBold)} solid ${colorBgElevated}`,
position: 'relative',
borderRadius: '50%',
cursor: 'pointer',
@ -49,15 +50,15 @@ const genPickerStyle: GenerateStyle<ColorPickerToken, CSSObject> = (token) => {
},
[`${componentCls}-slider`]: {
borderRadius: colorPickerSliderHeight / 2,
borderRadius: token.calc(colorPickerSliderHeight).div(2).equal(),
[`${componentCls}-palette`]: {
height: colorPickerSliderHeight,
},
[`${componentCls}-gradient`]: {
borderRadius: colorPickerSliderHeight / 2,
borderRadius: token.calc(colorPickerSliderHeight).div(2).equal(),
boxShadow: colorPickerInsetShadow,
},
'&-alpha': getTransBg(`${colorPickerSliderHeight}px`, token.colorFillSecondary),
'&-alpha': getTransBg(`${unit(colorPickerSliderHeight)}`, token.colorFillSecondary),
'&-hue': { marginBottom: marginSM },
},

View File

@ -1,4 +1,5 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { unit, type CSSObject } from '@ant-design/cssinjs';
import type { GenerateStyle } from '../../theme/internal';
import type { ColorPickerToken } from './index';
@ -18,6 +19,7 @@ const genPresetsStyle: GenerateStyle<ColorPickerToken, CSSObject> = (token) => {
colorWhite,
marginXXS,
paddingXS,
fontHeightSM,
} = token;
return {
@ -25,7 +27,7 @@ const genPresetsStyle: GenerateStyle<ColorPickerToken, CSSObject> = (token) => {
[`${antCls}-collapse-item > ${antCls}-collapse-header`]: {
padding: 0,
[`${antCls}-collapse-expand-icon`]: {
height: fontSizeSM * lineHeightSM,
height: fontHeightSM,
color: colorTextQuaternary,
paddingInlineEnd: paddingXXS,
},
@ -36,7 +38,7 @@ const genPresetsStyle: GenerateStyle<ColorPickerToken, CSSObject> = (token) => {
gap: marginXXS,
},
[`${antCls}-collapse-item > ${antCls}-collapse-content > ${antCls}-collapse-content-box`]: {
padding: `${paddingXS}px 0`,
padding: `${unit(paddingXS)} 0`,
},
'&-label': {
fontSize: fontSizeSM,
@ -46,7 +48,7 @@ const genPresetsStyle: GenerateStyle<ColorPickerToken, CSSObject> = (token) => {
'&-items': {
display: 'flex',
flexWrap: 'wrap',
gap: marginXXS * 1.5,
gap: token.calc(marginXXS).mul(1.5).equal(),
[`${componentCls}-presets-color`]: {
position: 'relative',
cursor: 'pointer',
@ -56,13 +58,16 @@ const genPresetsStyle: GenerateStyle<ColorPickerToken, CSSObject> = (token) => {
'&::before': {
content: '""',
pointerEvents: 'none',
width: colorPickerPresetColorSize + 4 * lineWidth,
height: colorPickerPresetColorSize + 4 * lineWidth,
width: token.calc(colorPickerPresetColorSize).add(token.calc(lineWidth).mul(4)).equal(),
height: token
.calc(colorPickerPresetColorSize)
.add(token.calc(lineWidth).mul(4))
.equal(),
position: 'absolute',
top: -2 * lineWidth,
insetInlineStart: -2 * lineWidth,
top: token.calc(lineWidth).mul(-2).equal(),
insetInlineStart: token.calc(lineWidth).mul(-2).equal(),
borderRadius,
border: `${lineWidth}px solid transparent`,
border: `${unit(lineWidth)} solid transparent`,
transition: `border-color ${token.motionDurationMid} ${token.motionEaseInBack}`,
},
'&:hover::before': {
@ -75,9 +80,9 @@ const genPresetsStyle: GenerateStyle<ColorPickerToken, CSSObject> = (token) => {
top: '50%',
insetInlineStart: '21.5%',
display: 'table',
width: (colorPickerPresetColorSize / 13) * 5,
height: (colorPickerPresetColorSize / 13) * 8,
border: `${token.lineWidthBold}px solid ${token.colorWhite}`,
width: token.calc(colorPickerPresetColorSize).div(13).mul(5).equal(),
height: token.calc(colorPickerPresetColorSize).div(13).mul(8).equal(),
border: `${unit(token.lineWidthBold)} solid ${token.colorWhite}`,
borderTop: 0,
borderInlineStart: 0,
transform: 'rotate(45deg) scale(0) translate(-50%,-50%)',

View File

@ -3,9 +3,9 @@ import kebabCase from 'lodash/kebabCase';
import canUseDom from 'rc-util/lib/Dom/canUseDom';
import ConfigProvider from '..';
import { InputNumber } from '../..';
import { resetWarned } from '../../_util/warning';
import { InputNumber, Button, Select } from '../..';
import { render } from '../../../tests/utils';
import { resetWarned } from '../../_util/warning';
import theme from '../../theme';
import { useToken } from '../../theme/internal';
@ -197,4 +197,75 @@ describe('ConfigProvider.Theme', () => {
);
expect(tokenRef?.colorPrimaryText).toBe('#1677ff');
});
describe('cssVar', () => {
it('should work', () => {
const { container } = render(
<ConfigProvider theme={{ cssVar: { key: 'foo' } }}>
<Button>Button</Button>
</ConfigProvider>,
);
const button = container.querySelector('button')!;
expect(button).toHaveClass('foo');
expect(button).toHaveStyle({
'--ant-color-text': 'rgba(0, 0, 0, 0.88)',
boxShadow: 'var(--ant-button-default-shadow)',
'line-height': 'var(--ant-line-height)',
});
});
it('prefix', () => {
const { container } = render(
<>
<ConfigProvider theme={{ cssVar: { key: 'foo' }, hashed: true }}>
<Button className="button-foo">Button</Button>
</ConfigProvider>
<ConfigProvider theme={{ cssVar: { key: 'bar', prefix: 'bar' }, hashed: true }}>
<Button className="button-bar">Button</Button>
</ConfigProvider>
</>,
);
const fooBtn = container.querySelector('.button-foo')!;
const barBtn = container.querySelector('.button-bar')!;
expect(fooBtn).toHaveClass('foo');
expect(fooBtn).toHaveStyle({
'--ant-color-text': 'rgba(0, 0, 0, 0.88)',
boxShadow: 'var(--ant-button-default-shadow)',
'line-height': 'var(--ant-line-height)',
});
expect(barBtn).toHaveClass('bar');
expect(barBtn).toHaveStyle({
'--bar-color-text': 'rgba(0, 0, 0, 0.88)',
boxShadow: 'var(--bar-button-default-shadow)',
'line-height': 'var(--bar-line-height)',
});
});
it('component token should work', () => {
const { container } = render(
<ConfigProvider
theme={{
cssVar: { key: 'foo' },
hashed: true,
components: { Select: { colorPrimary: '#1890ff', optionSelectedColor: '#000' } },
}}
>
<Select className="select-foo" />
</ConfigProvider>,
);
const select = container.querySelector('.select-foo')!;
expect(select).toHaveStyle({
'--ant-color-primary': '#1890ff',
'--ant-select-option-selected-color': '#000',
'--ant-select-option-selected-font-weight': '600',
'--ant-select-z-index-popup': '1050',
});
});
});
});

View File

@ -47,6 +47,18 @@ export interface ThemeConfig {
algorithm?: MappingAlgorithm | MappingAlgorithm[];
hashed?: boolean;
inherit?: boolean;
cssVar?:
| {
/**
* Prefix for css variable, default to `antd`.
*/
prefix?: string;
/**
* Unique key for theme, should be set manually < react@18.
*/
key?: string;
}
| boolean;
}
export interface ComponentStyleConfig {

View File

@ -0,0 +1,9 @@
import { useToken } from '../../theme/internal';
const useCSSVarCls = (prefixCls: string) => {
const [, , , , cssVar] = useToken();
return cssVar ? `${prefixCls}-css-var` : '';
};
export default useCSSVarCls;

View File

@ -3,15 +3,34 @@ import isEqual from 'rc-util/lib/isEqual';
import type { OverrideToken } from '../../theme/interface';
import type { ThemeConfig } from '../context';
import { defaultConfig } from '../../theme/internal';
import useThemeKey from './useThemeKey';
import { devUseWarning } from '../../_util/warning';
export default function useTheme(
theme?: ThemeConfig,
parentTheme?: ThemeConfig,
): ThemeConfig | undefined {
const warning = devUseWarning('ConfigProvider');
const themeConfig = theme || {};
const parentThemeConfig: ThemeConfig =
themeConfig.inherit === false || !parentTheme ? defaultConfig : parentTheme;
const themeKey = useThemeKey();
if (process.env.NODE_ENV !== 'production') {
const cssVarEnabled = themeConfig.cssVar || parentThemeConfig.cssVar;
const validKey = !!(
(typeof themeConfig.cssVar === 'object' && themeConfig.cssVar?.key) ||
themeKey
);
warning(
!cssVarEnabled || validKey,
'breaking',
'Missing key in `cssVar` config. Please upgrade to React 18 or set `cssVar.key` manually in each ConfigProvider inside `cssVar` enabled ConfigProvider.',
);
}
return useMemo<ThemeConfig | undefined>(
() => {
if (!theme) {
@ -30,6 +49,14 @@ export default function useTheme(
} as any;
});
const cssVarKey = `css-var-${themeKey.replace(/:/g, '')}`;
const mergedCssVar = (themeConfig.cssVar ?? parentThemeConfig.cssVar) && {
prefix: 'ant', // Default to ant
...(typeof parentThemeConfig.cssVar === 'object' ? parentThemeConfig.cssVar : {}),
...(typeof themeConfig.cssVar === 'object' ? themeConfig.cssVar : {}),
key: (typeof themeConfig.cssVar === 'object' && themeConfig.cssVar?.key) || cssVarKey,
};
// Base token
return {
...parentThemeConfig,
@ -40,6 +67,7 @@ export default function useTheme(
...themeConfig.token,
},
components: mergedComponents,
cssVar: mergedCssVar,
};
},
[themeConfig, parentThemeConfig],

View File

@ -0,0 +1,7 @@
import { useId } from 'react';
const useEmptyId = () => '';
const useThemeKey = typeof useId === 'undefined' ? useEmptyId : useId;
export default useThemeKey;

View File

@ -528,7 +528,7 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
// ================================ Dynamic theme ================================
const memoTheme = React.useMemo(() => {
const { algorithm, token, components, ...rest } = mergedTheme || {};
const { algorithm, token, components, cssVar, ...rest } = mergedTheme || {};
const themeObj =
algorithm && (!Array.isArray(algorithm) || algorithm.length > 0)
? createTheme(algorithm)
@ -568,6 +568,7 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
override: mergedToken,
...parsedComponents,
},
cssVar: cssVar as Exclude<ThemeConfig['cssVar'], boolean>,
};
}, [mergedTheme]);

View File

@ -28,6 +28,7 @@ import {
import Components from './Components';
import type { CommonPickerMethods, PickerComponentClass } from './interface';
import { useZIndex } from '../../_util/hooks/useZIndex';
import useCSSVarCls from '../../config-provider/hooks/useCSSVarCls';
export default function generateRangePicker<DateType>(generateConfig: GenerateConfig<DateType>) {
type InternalRangePickerProps = RangePickerProps<DateType> & {};
@ -71,7 +72,8 @@ export default function generateRangePicker<DateType>(generateConfig: GenerateCo
const { format, showTime, picker } = props as any;
const rootPrefixCls = getPrefixCls();
const [wrapSSR, hashId] = useStyle(prefixCls);
const cssVarCls = useCSSVarCls(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls, cssVarCls);
const additionalOverrideProps: any = {
...(showTime ? getTimeProps({ format, picker, ...showTime }) : {}),
@ -115,7 +117,7 @@ export default function generateRangePicker<DateType>(generateConfig: GenerateCo
// ============================ zIndex ============================
const [zIndex] = useZIndex('DatePicker', props.popupStyle?.zIndex as number);
return wrapSSR(
return wrapCSSVar(
<RCRangePicker<DateType>
separator={
<span aria-label="to" className={`${prefixCls}-separator`}>
@ -144,6 +146,7 @@ export default function generateRangePicker<DateType>(generateConfig: GenerateCo
compactItemClassnames,
className,
rangePicker?.className,
cssVarCls,
rootClassName,
)}
style={{ ...rangePicker?.style, ...style }}
@ -153,7 +156,12 @@ export default function generateRangePicker<DateType>(generateConfig: GenerateCo
generateConfig={generateConfig}
components={Components}
direction={direction}
dropdownClassName={classNames(hashId, popupClassName || dropdownClassName, rootClassName)}
dropdownClassName={classNames(
hashId,
popupClassName || dropdownClassName,
cssVarCls,
rootClassName,
)}
popupStyle={{
...props.popupStyle,
zIndex,

View File

@ -29,6 +29,7 @@ import {
import Components from './Components';
import type { CommonPickerMethods, DatePickRef, PickerComponentClass } from './interface';
import { useZIndex } from '../../_util/hooks/useZIndex';
import useCSSVarCls from '../../config-provider/hooks/useCSSVarCls';
export default function generatePicker<DateType>(generateConfig: GenerateConfig<DateType>) {
type CustomPickerProps = {
@ -79,7 +80,8 @@ export default function generatePicker<DateType>(generateConfig: GenerateConfig<
const innerRef = React.useRef<RCPicker<DateType>>(null);
const { format, showTime } = props as any;
const [wrapSSR, hashId] = useStyle(prefixCls);
const cssVarCls = useCSSVarCls(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls, cssVarCls);
useImperativeHandle(ref, () => ({
focus: () => innerRef.current?.focus(),
@ -142,7 +144,7 @@ export default function generatePicker<DateType>(generateConfig: GenerateConfig<
// ============================ zIndex ============================
const [zIndex] = useZIndex('DatePicker', props.popupStyle?.zIndex as number);
return wrapSSR(
return wrapCSSVar(
<RCPicker<DateType>
ref={innerRef}
placeholder={getPlaceholder(locale, mergedPicker, placeholder)}
@ -171,6 +173,7 @@ export default function generatePicker<DateType>(generateConfig: GenerateConfig<
compactItemClassnames,
consumerStyle?.className,
className,
cssVarCls,
rootClassName,
)}
style={{ ...consumerStyle?.style, ...style }}
@ -182,6 +185,7 @@ export default function generatePicker<DateType>(generateConfig: GenerateConfig<
disabled={mergedDisabled}
dropdownClassName={classNames(
hashId,
cssVarCls,
rootClassName,
popupClassName || dropdownClassName,
)}

View File

@ -1,4 +1,5 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { unit } from '@ant-design/cssinjs';
import { TinyColor } from '@ctrl/tinycolor';
import type { SharedComponentToken, SharedInputToken } from '../../input/style';
@ -9,7 +10,7 @@ import {
initComponentToken,
initInputToken,
} from '../../input/style';
import { resetComponent, roundedArrow, textEllipsis } from '../../style';
import { resetComponent, textEllipsis } from '../../style';
import { genCompactItemStyle } from '../../style/compact-item';
import {
initMoveMotion,
@ -20,9 +21,11 @@ import {
slideUpOut,
} from '../../style/motion';
import type { GlobalToken } from '../../theme/interface';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
import type { TokenWithCommonCls } from '../../theme/util/genComponentStyleHook';
import type { ArrowToken } from '../../style/roundedArrow';
import { genRoundedArrow, getArrowToken } from '../../style/roundedArrow';
export interface PanelComponentToken {
/**
@ -89,7 +92,8 @@ export interface PanelComponentToken {
export interface ComponentToken
extends Exclude<SharedComponentToken, 'addonBg'>,
PanelComponentToken {
PanelComponentToken,
ArrowToken {
/**
* @desc
* @descEN Width of preset area
@ -110,12 +114,13 @@ export interface ComponentToken
export type PickerPanelToken = {
pickerCellCls: string;
pickerCellInnerCls: string;
pickerDatePanelPaddingHorizontal: number;
pickerYearMonthCellWidth: number;
pickerCellPaddingVertical: number;
pickerQuarterPanelContentHeight: number;
pickerDatePanelPaddingHorizontal: number | string;
pickerYearMonthCellWidth: number | string;
pickerCellPaddingVertical: number | string;
pickerQuarterPanelContentHeight: number | string;
pickerCellBorderGap: number;
pickerControlIconSize: number;
pickerControlIconMargin: number;
pickerControlIconBorderWidth: number;
};
@ -126,17 +131,15 @@ type SharedPickerToken = TokenWithCommonCls<GlobalToken> & PickerPanelToken & Pa
const genPikerPadding = (
token: PickerToken,
inputHeight: number,
fontSize: number,
fontHeight: number,
paddingHorizontal: number,
): CSSObject => {
const { lineHeight } = token;
const fontHeight = Math.floor(fontSize * lineHeight) + 2;
const paddingTop = Math.max((inputHeight - fontHeight) / 2, 0);
const paddingBottom = Math.max(inputHeight - fontHeight - paddingTop, 0);
const height = token.calc(fontHeight).add(2).equal();
const paddingTop = token.max(token.calc(inputHeight).sub(height).div(2).equal(), 0);
const paddingBottom = token.max(token.calc(inputHeight).sub(height).sub(paddingTop).equal(), 0);
return {
padding: `${paddingTop}px ${paddingHorizontal}px ${paddingBottom}px`,
padding: `${unit(paddingTop)} ${unit(paddingHorizontal)} ${unit(paddingBottom)}`,
};
};
@ -184,7 +187,7 @@ const genPickerCellInnerStyle = (token: SharedPickerToken): CSSObject => {
display: 'inline-block',
minWidth: cellHeight,
height: cellHeight,
lineHeight: `${cellHeight}px`,
lineHeight: unit(cellHeight),
borderRadius: borderRadiusSM,
transition: `background ${motionDurationMid}, border ${motionDurationMid}`,
},
@ -213,7 +216,7 @@ const genPickerCellInnerStyle = (token: SharedPickerToken): CSSObject => {
bottom: 0,
insetInlineStart: 0,
zIndex: 1,
border: `${lineWidth}px ${lineType} ${colorPrimary}`,
border: `${unit(lineWidth)} ${lineType} ${colorPrimary}`,
borderRadius: borderRadiusSM,
content: '""',
},
@ -264,8 +267,8 @@ const genPickerCellInnerStyle = (token: SharedPickerToken): CSSObject => {
top: '50%',
zIndex: 0,
height: controlHeightSM,
borderTop: `${lineWidth}px dashed ${cellRangeBorderColor}`,
borderBottom: `${lineWidth}px dashed ${cellRangeBorderColor}`,
borderTop: `${unit(lineWidth)} dashed ${cellRangeBorderColor}`,
borderBottom: `${unit(lineWidth)} dashed ${cellRangeBorderColor}`,
transform: 'translateY(-50%)',
transition: `all ${motionDurationSlow}`,
content: '""',
@ -325,8 +328,8 @@ const genPickerCellInnerStyle = (token: SharedPickerToken): CSSObject => {
&-in-view${pickerCellCls}-start${pickerCellCls}-range-hover-edge-start${pickerCellCls}-range-hover-edge-start-near-range::after,
&-in-view${pickerCellCls}-range-hover-edge-start:not(${pickerCellCls}-range-hover-edge-start-near-range)::after,
&-in-view${pickerCellCls}-range-hover-start::after`]: {
insetInlineStart: (cellWidth - cellHeight) / 2,
borderInlineStart: `${lineWidth}px dashed ${cellRangeBorderColor}`,
insetInlineStart: token.calc(cellWidth).sub(cellHeight).div(2).equal(),
borderInlineStart: `${unit(lineWidth)} dashed ${cellRangeBorderColor}`,
borderStartStartRadius: borderRadiusSM,
borderEndStartRadius: borderRadiusSM,
},
@ -337,8 +340,8 @@ const genPickerCellInnerStyle = (token: SharedPickerToken): CSSObject => {
&-in-view${pickerCellCls}-end${pickerCellCls}-range-hover-edge-end${pickerCellCls}-range-hover-edge-end-near-range::after,
&-in-view${pickerCellCls}-range-hover-edge-end:not(${pickerCellCls}-range-hover-edge-end-near-range)::after,
&-in-view${pickerCellCls}-range-hover-end::after`]: {
insetInlineEnd: (cellWidth - cellHeight) / 2,
borderInlineEnd: `${lineWidth}px dashed ${cellRangeBorderColor}`,
insetInlineEnd: token.calc(cellWidth).sub(cellHeight).div(2).equal(),
borderInlineEnd: `${unit(lineWidth)} dashed ${cellRangeBorderColor}`,
borderStartEndRadius: borderRadiusSM,
borderEndEndRadius: borderRadiusSM,
},
@ -408,14 +411,27 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
controlItemBgActive,
marginXXS,
pickerDatePanelPaddingHorizontal,
pickerControlIconMargin,
} = token;
const pickerPanelWidth = cellWidth * 7 + pickerDatePanelPaddingHorizontal * 2;
const commonHoverCellFixedDistance =
(pickerPanelWidth - paddingXS * 2) / 3 - pickerYearMonthCellWidth - paddingSM;
const quarterHoverCellFixedDistance =
(pickerPanelWidth - paddingXS * 2) / 4 - pickerYearMonthCellWidth;
const pickerPanelWidth = token
.calc(cellWidth)
.mul(7)
.add(token.calc(pickerDatePanelPaddingHorizontal).mul(2))
.equal();
const commonHoverCellFixedDistance = token
.calc(pickerPanelWidth)
.sub(token.calc(paddingXS).mul(2))
.div(3)
.sub(token.pickerYearMonthCellWidth)
.sub(paddingSM)
.equal();
const quarterHoverCellFixedDistance = token
.calc(pickerPanelWidth)
.sub(token.calc(paddingXS).mul(2))
.div(4)
.sub(token.pickerYearMonthCellWidth)
.equal();
return {
[componentCls]: {
@ -424,7 +440,7 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
flexDirection: 'column',
textAlign: 'center',
background: colorBgContainer,
border: `${lineWidth}px ${lineType} ${colorSplit}`,
border: `${unit(lineWidth)} ${lineType} ${colorSplit}`,
borderRadius: borderRadiusLG,
outline: 'none',
@ -465,9 +481,9 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
// ======================= Header =======================
'&-header': {
display: 'flex',
padding: `0 ${paddingXS}px`,
padding: `0 ${unit(paddingXS)}`,
color: colorTextHeading,
borderBottom: `${lineWidth}px ${lineType} ${colorSplit}`,
borderBottom: `${unit(lineWidth)} ${lineType} ${colorSplit}`,
'> *': {
flex: 'none',
@ -476,7 +492,7 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
button: {
padding: 0,
color: colorIcon,
lineHeight: `${textHeight}px`,
lineHeight: unit(textHeight),
background: 'transparent',
border: 0,
cursor: 'pointer',
@ -496,7 +512,7 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
'&-view': {
flex: 'auto',
fontWeight: fontWeightStrong,
lineHeight: `${textHeight}px`,
lineHeight: unit(textHeight),
button: {
color: 'inherit',
@ -543,8 +559,8 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
&-super-next-icon`]: {
'&::after': {
position: 'absolute',
top: Math.ceil(pickerControlIconSize / 2),
insetInlineStart: Math.ceil(pickerControlIconSize / 2),
top: pickerControlIconMargin,
insetInlineStart: pickerControlIconMargin,
display: 'inline-block',
width: pickerControlIconSize,
height: pickerControlIconSize,
@ -580,14 +596,14 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
},
th: {
height: cellHeight + pickerCellPaddingVertical * 2,
height: token.calc(cellHeight).add(token.calc(pickerCellPaddingVertical).mul(2)).equal(),
color: colorText,
verticalAlign: 'middle',
},
},
'&-cell': {
padding: `${pickerCellPaddingVertical}px 0`,
padding: `${unit(pickerCellPaddingVertical)} 0`,
color: colorTextDisabled,
cursor: 'pointer',
@ -617,14 +633,14 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
[`&-date-panel
${componentCls}-cell-in-view${componentCls}-cell-in-range${componentCls}-cell-range-hover-start
${pickerCellInnerCls}::after`]: {
insetInlineEnd: -(cellWidth - cellHeight) / 2,
insetInlineEnd: token.calc(cellWidth).sub(cellHeight).mul(-1).div(2).equal(),
insetInlineStart: 0,
},
[`&-date-panel ${componentCls}-cell-in-view${componentCls}-cell-in-range${componentCls}-cell-range-hover-end ${pickerCellInnerCls}::after`]:
{
insetInlineEnd: 0,
insetInlineStart: -(cellWidth - cellHeight) / 2,
insetInlineStart: token.calc(cellWidth).sub(cellHeight).mul(-1).div(2).equal(),
},
// Hover with range start & end
@ -637,11 +653,11 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
&-quarter-panel,
&-month-panel`]: {
[`${componentCls}-content`]: {
height: withoutTimeCellHeight * 4,
height: token.calc(withoutTimeCellHeight).mul(4).equal(),
},
[pickerCellInnerCls]: {
padding: `0 ${paddingXS}px`,
padding: `0 ${unit(paddingXS)}`,
},
},
@ -653,42 +669,42 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
// Quarter Panel Special Style
[`${componentCls}-cell-range-hover-start::after`]: {
insetInlineStart: quarterHoverCellFixedDistance,
borderInlineStart: `${lineWidth}px dashed ${cellRangeBorderColor}`,
borderInlineStart: `${unit(lineWidth)} dashed ${cellRangeBorderColor}`,
[`${componentCls}-panel-rtl &`]: {
insetInlineEnd: quarterHoverCellFixedDistance,
borderInlineEnd: `${lineWidth}px dashed ${cellRangeBorderColor}`,
borderInlineEnd: `${unit(lineWidth)} dashed ${cellRangeBorderColor}`,
},
},
[`${componentCls}-cell-range-hover-end::after`]: {
insetInlineEnd: quarterHoverCellFixedDistance,
borderInlineEnd: `${lineWidth}px dashed ${cellRangeBorderColor}`,
borderInlineEnd: `${unit(lineWidth)} dashed ${cellRangeBorderColor}`,
[`${componentCls}-panel-rtl &`]: {
insetInlineStart: quarterHoverCellFixedDistance,
borderInlineStart: `${lineWidth}px dashed ${cellRangeBorderColor}`,
borderInlineStart: `${unit(lineWidth)} dashed ${cellRangeBorderColor}`,
},
},
},
// ======================== Footer ========================
[`&-panel ${componentCls}-footer`]: {
borderTop: `${lineWidth}px ${lineType} ${colorSplit}`,
borderTop: `${unit(lineWidth)} ${lineType} ${colorSplit}`,
},
'&-footer': {
width: 'min-content',
minWidth: '100%',
lineHeight: `${textHeight - 2 * lineWidth}px`,
lineHeight: unit(token.calc(textHeight).sub(token.calc(lineWidth).mul(2)).equal()),
textAlign: 'center',
'&-extra': {
padding: `0 ${paddingSM}px`,
lineHeight: `${textHeight - 2 * lineWidth}px`,
padding: `0 ${unit(paddingSM)}`,
lineHeight: unit(token.calc(textHeight).sub(token.calc(lineWidth).mul(2)).equal()),
textAlign: 'start',
'&:not(:last-child)': {
borderBottom: `${lineWidth}px ${lineType} ${colorSplit}`,
borderBottom: `${unit(lineWidth)} ${lineType} ${colorSplit}`,
},
},
},
@ -721,7 +737,7 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
// ===================== Decade Panel =====================
'&-decade-panel': {
[pickerCellInnerCls]: {
padding: `0 ${paddingXS / 2}px`,
padding: `0 ${unit(token.calc(paddingXS).div(2).equal())}`,
},
[`${componentCls}-cell::before`]: {
@ -734,7 +750,7 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
&-quarter-panel,
&-month-panel`]: {
[`${componentCls}-body`]: {
padding: `0 ${paddingXS}px`,
padding: `0 ${unit(paddingXS)}`,
},
[pickerCellInnerCls]: {
@ -773,20 +789,20 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
&-month-panel`]: {
[`${componentCls}-cell-range-hover-start::after`]: {
insetInlineStart: commonHoverCellFixedDistance,
borderInlineStart: `${lineWidth}px dashed ${cellRangeBorderColor}`,
borderInlineStart: `${unit(lineWidth)} dashed ${cellRangeBorderColor}`,
[`${componentCls}-panel-rtl &`]: {
insetInlineEnd: commonHoverCellFixedDistance,
borderInlineEnd: `${lineWidth}px dashed ${cellRangeBorderColor}`,
borderInlineEnd: `${unit(lineWidth)} dashed ${cellRangeBorderColor}`,
},
},
[`${componentCls}-cell-range-hover-end::after`]: {
insetInlineEnd: commonHoverCellFixedDistance,
borderInlineEnd: `${lineWidth}px dashed ${cellRangeBorderColor}`,
borderInlineEnd: `${unit(lineWidth)} dashed ${cellRangeBorderColor}`,
[`${componentCls}-panel-rtl &`]: {
insetInlineStart: commonHoverCellFixedDistance,
borderInlineStart: `${lineWidth}px dashed ${cellRangeBorderColor}`,
borderInlineStart: `${unit(lineWidth)} dashed ${cellRangeBorderColor}`,
},
},
},
@ -794,7 +810,7 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
// ====================== Week Panel ======================
'&-week-panel': {
[`${componentCls}-body`]: {
padding: `${paddingXS}px ${paddingSM}px`,
padding: `${unit(paddingXS)} ${unit(paddingSM)}`,
},
// Clear cell style
@ -857,11 +873,11 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
// ====================== Date Panel ======================
'&-date-panel': {
[`${componentCls}-body`]: {
padding: `${paddingXS}px ${pickerDatePanelPaddingHorizontal}px`,
padding: `${unit(paddingXS)} ${unit(pickerDatePanelPaddingHorizontal)}`,
},
[`${componentCls}-content`]: {
width: cellWidth * 7,
width: token.calc(cellWidth).mul(7).equal(),
th: {
width: cellWidth,
@ -876,7 +892,7 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
display: 'flex',
[`${componentCls}-time-panel`]: {
borderInlineStart: `${lineWidth}px ${lineType} ${colorSplit}`,
borderInlineStart: `${unit(lineWidth)} ${lineType} ${colorSplit}`,
},
[`${componentCls}-date-panel,
@ -912,7 +928,7 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
'&-column': {
flex: '1 0 auto',
width: timeColumnWidth,
margin: `${paddingXXS}px 0`,
margin: `${unit(paddingXXS)} 0`,
padding: 0,
overflowY: 'hidden',
textAlign: 'start',
@ -938,12 +954,12 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
'&::after': {
display: 'block',
height: timeColumnHeight - timeCellHeight,
height: token.calc(timeColumnHeight).sub(timeCellHeight).equal(),
content: '""',
},
'&:not(:first-child)': {
borderInlineStart: `${lineWidth}px ${lineType} ${colorSplit}`,
borderInlineStart: `${unit(lineWidth)} ${lineType} ${colorSplit}`,
},
'&-active': {
@ -962,14 +978,14 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
marginInline: marginXXS,
[`${componentCls}-time-panel-cell-inner`]: {
display: 'block',
width: timeColumnWidth - 2 * marginXXS,
width: token.calc(timeColumnWidth).sub(token.calc(marginXXS).mul(2)).equal(),
height: timeCellHeight,
margin: 0,
paddingBlock: 0,
paddingInlineEnd: 0,
paddingInlineStart: (timeColumnWidth - timeCellHeight) / 2,
paddingInlineStart: token.calc(timeColumnWidth).sub(timeCellHeight).div(2).equal(),
color: colorText,
lineHeight: `${timeCellHeight}px`,
lineHeight: unit(timeCellHeight),
borderRadius: borderRadiusSM,
cursor: 'pointer',
transition: `background ${motionDurationMid}`,
@ -998,7 +1014,11 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
},
// https://github.com/ant-design/ant-design/issues/39227
[`&-datetime-panel ${componentCls}-time-panel-column:after`]: {
height: timeColumnHeight - timeCellHeight + paddingXXS * 2,
height: token
.calc(timeColumnHeight)
.sub(timeCellHeight)
.add(token.calc(paddingXXS).mul(2))
.equal(),
},
},
};
@ -1070,7 +1090,6 @@ const genPickerStyle: GenerateStyle<PickerToken> = (token) => {
componentCls,
antCls,
controlHeight,
fontSize,
paddingInline,
colorBgContainer,
lineWidth,
@ -1089,7 +1108,6 @@ const genPickerStyle: GenerateStyle<PickerToken> = (token) => {
marginXS,
colorTextDescription,
lineWidthBold,
lineHeight,
colorPrimary,
motionDurationSlow,
zIndexPopup,
@ -1099,8 +1117,6 @@ const genPickerStyle: GenerateStyle<PickerToken> = (token) => {
cellActiveWithRangeBg,
colorPrimaryBorder,
sizePopupArrow,
borderRadiusXS,
borderRadiusOuter,
colorBgElevated,
borderRadiusLG,
boxShadowSecondary,
@ -1111,19 +1127,22 @@ const genPickerStyle: GenerateStyle<PickerToken> = (token) => {
presetsMaxWidth,
boxShadowPopoverArrow,
colorTextQuaternary,
fontHeight,
fontHeightLG,
lineHeightLG,
} = token;
return [
{
[componentCls]: {
...resetComponent(token),
...genPikerPadding(token, controlHeight, fontSize, paddingInline),
...genPikerPadding(token, controlHeight, fontHeight, paddingInline),
position: 'relative',
display: 'inline-flex',
alignItems: 'center',
background: colorBgContainer,
lineHeight: 1,
border: `${lineWidth}px ${lineType} ${colorBorder}`,
border: `${unit(lineWidth)} ${lineType} ${colorBorder}`,
borderRadius,
transition: `border ${motionDurationMid}, box-shadow ${motionDurationMid}`,
@ -1196,22 +1215,23 @@ const genPickerStyle: GenerateStyle<PickerToken> = (token) => {
// Size
'&-large': {
...genPikerPadding(token, controlHeightLG, fontSizeLG, paddingInline),
...genPikerPadding(token, controlHeightLG, fontHeightLG, paddingInline),
[`${componentCls}-input > input`]: {
fontSize: fontSizeLG,
lineHeight: lineHeightLG,
},
},
'&-small': {
...genPikerPadding(token, controlHeightSM, fontSize, paddingInlineSM),
...genPikerPadding(token, controlHeightSM, fontHeight, paddingInlineSM),
},
[`${componentCls}-suffix`]: {
display: 'flex',
flex: 'none',
alignSelf: 'center',
marginInlineStart: paddingXS / 2,
marginInlineStart: token.calc(paddingXS).div(2).equal(),
color: colorTextDisabled,
lineHeight: 1,
pointerEvents: 'none',
@ -1285,7 +1305,7 @@ const genPickerStyle: GenerateStyle<PickerToken> = (token) => {
// Active bar
[`${componentCls}-active-bar`]: {
bottom: -lineWidth,
bottom: token.calc(lineWidth).mul(-1).equal(),
height: lineWidthBold,
marginInlineStart: paddingInline,
background: colorPrimary,
@ -1302,7 +1322,7 @@ const genPickerStyle: GenerateStyle<PickerToken> = (token) => {
[`${componentCls}-range-separator`]: {
alignItems: 'center',
padding: `0 ${paddingXS}px`,
padding: `0 ${unit(paddingXS)}`,
lineHeight: 1,
},
@ -1387,9 +1407,15 @@ const genPickerStyle: GenerateStyle<PickerToken> = (token) => {
// ======================== Ranges ========================
[`${componentCls}-ranges`]: {
marginBottom: 0,
padding: `${paddingXXS}px ${paddingSM}px`,
padding: `${unit(paddingXXS)} ${unit(paddingSM)}`,
overflow: 'hidden',
lineHeight: `${textHeight - 2 * lineWidth - paddingXS / 2}px`,
lineHeight: unit(
token
.calc(textHeight)
.sub(token.calc(lineWidth).mul(2))
.sub(token.calc(paddingXS).div(2))
.equal(),
),
textAlign: 'start',
listStyle: 'none',
display: 'flex',
@ -1421,15 +1447,9 @@ const genPickerStyle: GenerateStyle<PickerToken> = (token) => {
position: 'absolute',
zIndex: 1,
display: 'none',
marginInlineStart: paddingInline * 1.5,
marginInlineStart: token.calc(paddingInline).mul(1.5).equal(),
transition: `left ${motionDurationSlow} ease-out`,
...roundedArrow(
sizePopupArrow,
borderRadiusXS,
borderRadiusOuter,
colorBgElevated,
boxShadowPopoverArrow,
),
...genRoundedArrow(token, colorBgElevated, boxShadowPopoverArrow),
},
[`${componentCls}-panel-container`]: {
@ -1461,13 +1481,13 @@ const genPickerStyle: GenerateStyle<PickerToken> = (token) => {
overflow: 'auto',
margin: 0,
padding: paddingXS,
borderInlineEnd: `${lineWidth}px ${lineType} ${colorSplit}`,
borderInlineEnd: `${unit(lineWidth)} ${lineType} ${colorSplit}`,
li: {
...textEllipsis,
borderRadius: borderRadiusSM,
paddingInline: paddingXS,
paddingBlock: (controlHeightSM - Math.round(fontSize * lineHeight)) / 2,
paddingBlock: token.calc(controlHeightSM).sub(fontHeight).div(2).equal(),
cursor: 'pointer',
transition: `all ${motionDurationSlow}`,
@ -1489,7 +1509,7 @@ const genPickerStyle: GenerateStyle<PickerToken> = (token) => {
direction: 'ltr',
[`${componentCls}-panel`]: {
borderWidth: `0 0 ${lineWidth}px`,
borderWidth: `0 0 ${unit(lineWidth)}`,
},
'&:last-child': {
@ -1518,7 +1538,7 @@ const genPickerStyle: GenerateStyle<PickerToken> = (token) => {
},
'&-dropdown-range': {
padding: `${(sizePopupArrow * 2) / 3}px 0`,
padding: `${unit(token.calc(sizePopupArrow).mul(2).div(3).equal())} 0`,
'&-hidden': {
display: 'none',
@ -1555,13 +1575,17 @@ export const initPickerPanelToken = (token: TokenWithCommonCls<GlobalToken>): Pi
return {
pickerCellCls: `${componentCls}-cell`,
pickerCellInnerCls: `${componentCls}-cell-inner`,
pickerYearMonthCellWidth: controlHeightLG * 1.5,
pickerQuarterPanelContentHeight: controlHeightLG * 1.4,
pickerCellPaddingVertical: paddingXXS + paddingXXS / 2,
pickerYearMonthCellWidth: token.calc(controlHeightLG).mul(1.5).equal(),
pickerQuarterPanelContentHeight: token.calc(controlHeightLG).mul(1.4).equal(),
pickerCellPaddingVertical: token.calc(paddingXXS).add(token.calc(paddingXXS).div(2)).equal(),
pickerCellBorderGap: 2, // Magic for gap between cells
pickerControlIconSize: 7,
pickerControlIconMargin: 4,
pickerControlIconBorderWidth: 1.5,
pickerDatePanelPaddingHorizontal: padding + paddingXXS / 2, // 18 in normal
pickerDatePanelPaddingHorizontal: token
.calc(padding)
.add(token.calc(paddingXXS).div(2))
.equal(), // 18 in normal
};
};
@ -1580,8 +1604,17 @@ export const initPanelComponentToken = (token: GlobalToken): PanelComponentToken
withoutTimeCellHeight: token.controlHeightLG * 1.65,
});
export const prepareComponentToken: GetDefaultToken<'DatePicker'> = (token) => ({
...initComponentToken(token),
...initPanelComponentToken(token),
...getArrowToken(token),
presetsWidth: 120,
presetsMaxWidth: 200,
zIndexPopup: token.zIndexPopupBase + 50,
});
// ============================== Export ==============================
export default genComponentStyleHook(
export default genStyleHooks(
'DatePicker',
(token) => {
const pickerToken = mergeToken<PickerToken>(initInputToken(token), initPickerPanelToken(token));
@ -1596,11 +1629,5 @@ export default genComponentStyleHook(
}),
];
},
(token) => ({
...initComponentToken(token),
...initPanelComponentToken(token),
presetsWidth: 120,
presetsMaxWidth: 200,
zIndexPopup: token.zIndexPopupBase + 50,
}),
prepareComponentToken,
);

View File

@ -92,7 +92,7 @@ const Descriptions: React.FC<DescriptionsProps> & CompoundedComponent = (props)
const mergedSize = useSize(customizeSize);
const rows = useRow(mergedColumn, mergedItems);
const [wrapSSR, hashId] = useStyle(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls);
// ======================== Render ========================
const contextValue = React.useMemo(
@ -100,7 +100,7 @@ const Descriptions: React.FC<DescriptionsProps> & CompoundedComponent = (props)
[labelStyle, contentStyle],
);
return wrapSSR(
return wrapCSSVar(
<DescriptionsContext.Provider value={contextValue}>
<div
className={classNames(

View File

@ -1,8 +1,8 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { type CSSObject, unit } from '@ant-design/cssinjs';
import { resetComponent, textEllipsis } from '../../style';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
/** Component only token. Which will handle additional calculation of alias token */
export interface ComponentToken {
@ -56,19 +56,19 @@ const genBorderedStyle = (token: DescriptionsToken): CSSObject => {
return {
[`&${componentCls}-bordered`]: {
[`> ${componentCls}-view`]: {
border: `${token.lineWidth}px ${token.lineType} ${token.colorSplit}`,
border: `${unit(token.lineWidth)} ${token.lineType} ${token.colorSplit}`,
'> table': {
tableLayout: 'auto',
borderCollapse: 'collapse',
},
[`${componentCls}-row`]: {
borderBottom: `${token.lineWidth}px ${token.lineType} ${token.colorSplit}`,
borderBottom: `${unit(token.lineWidth)} ${token.lineType} ${token.colorSplit}`,
'&:last-child': {
borderBottom: 'none',
},
[`> ${componentCls}-item-label, > ${componentCls}-item-content`]: {
padding: `${token.padding}px ${token.paddingLG}px`,
borderInlineEnd: `${token.lineWidth}px ${token.lineType} ${token.colorSplit}`,
padding: `${unit(token.padding)} ${unit(token.paddingLG)}`,
borderInlineEnd: `${unit(token.lineWidth)} ${token.lineType} ${token.colorSplit}`,
'&:last-child': {
borderInlineEnd: 'none',
},
@ -85,14 +85,14 @@ const genBorderedStyle = (token: DescriptionsToken): CSSObject => {
[`&${componentCls}-middle`]: {
[`${componentCls}-row`]: {
[`> ${componentCls}-item-label, > ${componentCls}-item-content`]: {
padding: `${token.paddingSM}px ${token.paddingLG}px`,
padding: `${unit(token.paddingSM)} ${unit(token.paddingLG)}`,
},
},
},
[`&${componentCls}-small`]: {
[`${componentCls}-row`]: {
[`> ${componentCls}-item-label, > ${componentCls}-item-content`]: {
padding: `${token.paddingXS}px ${token.padding}px`,
padding: `${unit(token.paddingXS)} ${unit(token.padding)}`,
},
},
},
@ -161,7 +161,7 @@ const genDescriptionStyles: GenerateStyle<DescriptionsToken> = (token) => {
content: '":"',
position: 'relative',
top: -0.5, // magic for position
marginInline: `${colonMarginLeft}px ${colonMarginRight}px`,
marginInline: `${unit(colonMarginLeft)} ${unit(colonMarginRight)}`,
},
[`&${componentCls}-item-no-colon::after`]: {
@ -215,14 +215,8 @@ const genDescriptionStyles: GenerateStyle<DescriptionsToken> = (token) => {
},
};
};
// ============================== Export ==============================
export default genComponentStyleHook(
'Descriptions',
(token) => {
const descriptionToken = mergeToken<DescriptionsToken>(token, {});
return [genDescriptionStyles(descriptionToken)];
},
(token) => ({
export const prepareComponentToken: GetDefaultToken<'Descriptions'> = (token) => ({
labelBg: token.colorFillAlter,
titleColor: token.colorText,
titleMarginBottom: token.fontSizeSM * token.lineHeightSM,
@ -231,5 +225,14 @@ export default genComponentStyleHook(
colonMarginLeft: token.marginXXS / 2,
contentColor: token.colorText,
extraColor: token.colorText,
}),
});
// ============================== Export ==============================
export default genStyleHooks(
'Descriptions',
(token) => {
const descriptionToken = mergeToken<DescriptionsToken>(token, {});
return genDescriptionStyles(descriptionToken);
},
prepareComponentToken,
);

View File

@ -35,7 +35,8 @@ const Divider: React.FC<DividerProps> = (props) => {
...restProps
} = props;
const prefixCls = getPrefixCls('divider', customizePrefixCls);
const [wrapSSR, hashId] = useStyle(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls);
const orientationPrefix = orientation.length > 0 ? `-${orientation}` : orientation;
const hasChildren = !!children;
@ -85,7 +86,7 @@ const Divider: React.FC<DividerProps> = (props) => {
);
}
return wrapSSR(
return wrapCSSVar(
<div
className={classString}
style={{ ...divider?.style, ...style }}

View File

@ -1,8 +1,10 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { CSSProperties } from 'react';
import type { CSSObject } from '@ant-design/cssinjs';
import { unit } from '@ant-design/cssinjs';
import { resetComponent } from '../../style';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
/** Component only token. Which will handle additional calculation of alias token */
export interface ComponentToken {
@ -24,9 +26,9 @@ export interface ComponentToken {
}
interface DividerToken extends FullToken<'Divider'> {
sizePaddingEdgeHorizontal: number;
dividerHorizontalWithTextGutterMargin: number;
dividerHorizontalGutterMargin: number;
sizePaddingEdgeHorizontal: number | string;
dividerHorizontalWithTextGutterMargin: number | string;
dividerHorizontalGutterMargin: number | string;
}
// ============================== Shared ==============================
@ -44,7 +46,7 @@ const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject =>
return {
[componentCls]: {
...resetComponent(token),
borderBlockStart: `${lineWidth}px solid ${colorSplit}`,
borderBlockStart: `${unit(lineWidth)} solid ${colorSplit}`,
// vertical
'&-vertical': {
@ -56,7 +58,7 @@ const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject =>
marginBlock: 0,
verticalAlign: 'middle',
borderTop: 0,
borderInlineStart: `${lineWidth}px solid ${colorSplit}`,
borderInlineStart: `${unit(lineWidth)} solid ${colorSplit}`,
},
'&-horizontal': {
@ -64,13 +66,13 @@ const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject =>
clear: 'both',
width: '100%',
minWidth: '100%', // Fix https://github.com/ant-design/ant-design/issues/10914
margin: `${token.dividerHorizontalGutterMargin}px 0`,
margin: `${unit(token.dividerHorizontalGutterMargin)} 0`,
},
[`&-horizontal${componentCls}-with-text`]: {
display: 'flex',
alignItems: 'center',
margin: `${token.dividerHorizontalWithTextGutterMargin}px 0`,
margin: `${unit(token.dividerHorizontalWithTextGutterMargin)} 0`,
color: token.colorTextHeading,
fontWeight: 500,
fontSize: token.fontSizeLG,
@ -81,7 +83,7 @@ const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject =>
'&::before, &::after': {
position: 'relative',
width: '50%',
borderBlockStart: `${lineWidth}px solid transparent`,
borderBlockStart: `${unit(lineWidth)} solid transparent`,
// Chrome not accept `inherit` in `border-top`
borderBlockStartColor: 'inherit',
borderBlockEnd: 0,
@ -92,21 +94,19 @@ const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject =>
[`&-horizontal${componentCls}-with-text-left`]: {
'&::before': {
width: `${orientationMargin * 100}%`,
width: `calc(${orientationMargin} * 100%)`,
},
'&::after': {
width: `${100 - orientationMargin * 100}%`,
width: `calc(100% - ${orientationMargin} * 100%)`,
},
},
[`&-horizontal${componentCls}-with-text-right`]: {
'&::before': {
width: `${100 - orientationMargin * 100}%`,
width: `calc(100% - ${orientationMargin} * 100%)`,
},
'&::after': {
width: `${orientationMargin * 100}%`,
width: `calc(${orientationMargin} * 100%)`,
},
},
@ -120,7 +120,7 @@ const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject =>
background: 'none',
borderColor: colorSplit,
borderStyle: 'dashed',
borderWidth: `${lineWidth}px 0 0`,
borderWidth: `${unit(lineWidth)} 0 0`,
},
[`&-horizontal${componentCls}-with-text${componentCls}-dashed`]: {
@ -175,8 +175,14 @@ const genSharedDividerStyle: GenerateStyle<DividerToken> = (token): CSSObject =>
};
};
export const prepareComponentToken: GetDefaultToken<'Divider'> = (token) => ({
textPaddingInline: '1em',
orientationMargin: 0.05,
verticalMarginInline: token.marginXS,
});
// ============================== Export ==============================
export default genComponentStyleHook(
export default genStyleHooks(
'Divider',
(token) => {
const dividerToken = mergeToken<DividerToken>(token, {
@ -186,9 +192,10 @@ export default genComponentStyleHook(
});
return [genSharedDividerStyle(dividerToken)];
},
(token) => ({
textPaddingInline: '1em',
orientationMargin: 0.05,
verticalMarginInline: token.marginXS,
}),
prepareComponentToken,
{
unitless: {
orientationMargin: true,
},
},
);

View File

@ -1,6 +1,7 @@
import * as React from 'react';
import classNames from 'classnames';
import type { DrawerProps as RCDrawerProps } from 'rc-drawer';
import * as React from 'react';
import useClosable from '../_util/hooks/useClosable';
import { ConfigContext } from '../config-provider';

View File

@ -5,7 +5,7 @@ import type { DrawerClassNames, DrawerStyles } from '../DrawerPanel';
const useStyle = createStyles(({ token }) => ({
'my-drawer-body': {
background: token['blue-1'],
background: token.blue1,
},
'my-drawer-mask': {
boxShadow: `inset 0 0 15px #fff`,

View File

@ -8,18 +8,17 @@ import type { CSSMotionProps } from 'rc-motion';
import { useZIndex } from '../_util/hooks/useZIndex';
import { getTransitionName } from '../_util/motion';
import { devUseWarning } from '../_util/warning';
import zIndexContext from '../_util/zindexContext';
import { ConfigContext } from '../config-provider';
import { NoFormStyle } from '../form/context';
// CSSINJS
import { NoCompactStyle } from '../space/Compact';
import { usePanelRef } from '../watermark/context';
import type { DrawerClassNames, DrawerPanelProps, DrawerStyles } from './DrawerPanel';
import DrawerPanel from './DrawerPanel';
import useStyle from './style';
import zIndexContext from '../_util/zindexContext';
const SizeTypes = ['default', 'large'] as const;
type sizeType = typeof SizeTypes[number];
type sizeType = (typeof SizeTypes)[number];
export interface PushState {
distance: string | number;
@ -70,10 +69,10 @@ const Drawer: React.FC<DrawerProps> & {
} = props;
const { getPopupContainer, getPrefixCls, direction, drawer } = React.useContext(ConfigContext);
const prefixCls = getPrefixCls('drawer', customizePrefixCls);
// Style
const [wrapSSR, hashId] = useStyle(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls);
const getContainer =
// 有可能为 false所以不能直接判断
@ -149,7 +148,7 @@ const Drawer: React.FC<DrawerProps> & {
const [zIndex, contextZIndex] = useZIndex('Drawer', rest.zIndex);
// =========================== Render ===========================
return wrapSSR(
return wrapCSSVar(
<NoCompactStyle>
<NoFormStyle status override>
<zIndexContext.Provider value={contextZIndex}>
@ -214,8 +213,7 @@ const PurePanel: React.FC<Omit<DrawerPanelProps, 'prefixCls'> & PurePanelInterfa
const prefixCls = getPrefixCls('drawer', customizePrefixCls);
// Style
const [wrapSSR, hashId] = useStyle(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls);
const cls = classNames(
prefixCls,
@ -225,7 +223,7 @@ const PurePanel: React.FC<Omit<DrawerPanelProps, 'prefixCls'> & PurePanelInterfa
className,
);
return wrapSSR(
return wrapCSSVar(
<div className={cls} style={style}>
<DrawerPanel prefixCls={prefixCls} {...restProps} />
</div>,

View File

@ -1,5 +1,7 @@
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { unit } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
import genMotionStyle from './motion';
export interface ComponentToken {
@ -23,7 +25,7 @@ export interface ComponentToken {
export interface DrawerToken extends FullToken<'Drawer'> {}
// =============================== Base ===============================
const genDrawerStyle: GenerateStyle<DrawerToken> = (token: DrawerToken) => {
const genDrawerStyle: GenerateStyle<DrawerToken> = (token) => {
const {
componentCls,
zIndexPopup,
@ -150,10 +152,10 @@ const genDrawerStyle: GenerateStyle<DrawerToken> = (token: DrawerToken) => {
display: 'flex',
flex: 0,
alignItems: 'center',
padding: `${padding}px ${paddingLG}px`,
padding: `${unit(padding)} ${unit(paddingLG)}`,
fontSize: fontSizeLG,
lineHeight: lineHeightLG,
borderBottom: `${lineWidth}px ${lineType} ${colorSplit}`,
borderBottom: `${unit(lineWidth)} ${lineType} ${colorSplit}`,
'&-title': {
display: 'flex',
@ -213,8 +215,8 @@ const genDrawerStyle: GenerateStyle<DrawerToken> = (token: DrawerToken) => {
// Footer
[`${componentCls}-footer`]: {
flexShrink: 0,
padding: `${footerPaddingBlock}px ${footerPaddingInline}px`,
borderTop: `${lineWidth}px ${lineType} ${colorSplit}`,
padding: `${unit(footerPaddingBlock)} ${unit(footerPaddingInline)}`,
borderTop: `${unit(lineWidth)} ${lineType} ${colorSplit}`,
},
// ====================== RTL =======================
@ -225,17 +227,18 @@ const genDrawerStyle: GenerateStyle<DrawerToken> = (token: DrawerToken) => {
};
};
// ============================== Export ==============================
export default genComponentStyleHook(
'Drawer',
(token) => {
const drawerToken = mergeToken<DrawerToken>(token, {});
return [genDrawerStyle(drawerToken), genMotionStyle(drawerToken)];
},
(token) => ({
export const prepareComponentToken: GetDefaultToken<'Drawer'> = (token) => ({
zIndexPopup: token.zIndexPopupBase,
footerPaddingBlock: token.paddingXS,
footerPaddingInline: token.padding,
}),
});
// ============================== Export ==============================
export default genStyleHooks(
'Drawer',
(token) => {
const drawerToken = mergeToken<DrawerToken>(token, {});
return [genDrawerStyle(drawerToken), genMotionStyle(drawerToken)];
},
prepareComponentToken,
);

View File

@ -1,7 +1,7 @@
import type { DrawerToken } from '.';
import type { GenerateStyle } from '../../theme/internal';
const genMotionStyle: GenerateStyle<DrawerToken> = (token: DrawerToken) => {
const genMotionStyle: GenerateStyle<DrawerToken> = (token) => {
const { componentCls, motionDurationSlow } = token;
const sharedPanelMotion = {

View File

@ -6,7 +6,6 @@ import { ConfigContext } from '../config-provider';
import Space from '../space';
import { useCompactItemContext } from '../space/Compact';
import Dropdown from './dropdown';
import useStyle from './style';
import type { ButtonProps, ButtonHTMLType } from '../button';
import type { ButtonGroupProps } from '../button/button-group';
@ -75,7 +74,6 @@ const DropdownButton: CompoundedComponent = (props) => {
const prefixCls = getPrefixCls('dropdown', customizePrefixCls);
const buttonPrefixCls = `${prefixCls}-button`;
const [wrapSSR, hashId] = useStyle(prefixCls);
const dropdownProps: DropdownProps = {
menu,
@ -96,7 +94,7 @@ const DropdownButton: CompoundedComponent = (props) => {
const { compactSize, compactItemClassnames } = useCompactItemContext(prefixCls, direction);
const classes = classNames(buttonPrefixCls, compactItemClassnames, className, hashId);
const classes = classNames(buttonPrefixCls, compactItemClassnames, className);
if ('overlay' in props) {
dropdownProps.overlay = overlay;
@ -131,11 +129,11 @@ const DropdownButton: CompoundedComponent = (props) => {
const [leftButtonToRender, rightButtonToRender] = buttonsRender([leftButton, rightButton]);
return wrapSSR(
return (
<Space.Compact className={classes} size={compactSize} block {...restProps}>
{leftButtonToRender}
<Dropdown {...dropdownProps}>{rightButtonToRender}</Dropdown>
</Space.Compact>,
</Space.Compact>
);
};

View File

@ -20,6 +20,7 @@ import Menu from '../menu';
import { OverrideProvider } from '../menu/OverrideContext';
import { useToken } from '../theme/internal';
import useStyle from './style';
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
const Placements = [
'topLeft',
@ -32,7 +33,7 @@ const Placements = [
'bottom',
] as const;
type Placement = typeof Placements[number];
type Placement = (typeof Placements)[number];
type DropdownPlacement = Exclude<Placement, 'topCenter' | 'bottomCenter'>;
type OverlayFunc = () => React.ReactElement;
@ -169,7 +170,8 @@ const Dropdown: CompoundedComponent = (props) => {
}
const prefixCls = getPrefixCls('dropdown', customizePrefixCls);
const [wrapSSR, hashId] = useStyle(prefixCls);
const rootCls = useCSSVarCls(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls, rootCls);
const [, token] = useToken();
@ -208,6 +210,7 @@ const Dropdown: CompoundedComponent = (props) => {
overlayClassName,
rootClassName,
hashId,
rootCls,
dropdown?.className,
{ [`${prefixCls}-rtl`]: direction === 'rtl' },
);
@ -250,6 +253,7 @@ const Dropdown: CompoundedComponent = (props) => {
return (
<OverrideProvider
prefixCls={`${prefixCls}-menu`}
rootClassName={rootCls}
expandIcon={
<span className={`${prefixCls}-menu-submenu-arrow`}>
<RightOutlined className={`${prefixCls}-menu-submenu-arrow-icon`} />
@ -305,7 +309,7 @@ const Dropdown: CompoundedComponent = (props) => {
);
}
return wrapSSR(renderNode);
return wrapCSSVar(renderNode);
};
function postPureProps(props: DropdownProps) {

View File

@ -8,24 +8,31 @@ import {
slideUpIn,
slideUpOut,
} from '../../style/motion';
import getArrowStyle, { getArrowOffset } from '../../style/placementArrow';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import type { ArrowOffsetToken } from '../../style/placementArrow';
import getArrowStyle, { getArrowOffsetToken } from '../../style/placementArrow';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
import genStatusStyle from './status';
import type { ArrowToken } from '../../style/roundedArrow';
import { getArrowToken } from '../../style/roundedArrow';
import type { CSSProperties } from 'react';
import { unit } from '@ant-design/cssinjs';
export interface ComponentToken {
export interface ComponentToken extends ArrowToken, ArrowOffsetToken {
/**
* @desc z-index
* @descEN z-index of dropdown
*/
zIndexPopup: number;
/**
* @desc
* @descEN Vertical padding of dropdown
*/
paddingBlock: CSSProperties['paddingBlock'];
}
export interface DropdownToken extends FullToken<'Dropdown'> {
rootPrefixCls: string;
dropdownArrowDistance: number;
dropdownArrowOffset: number;
dropdownPaddingVertical: number;
dropdownArrowDistance: number | string;
dropdownEdgeChildPadding: number;
menuCls: string;
}
@ -41,7 +48,7 @@ const genBaseStyle: GenerateStyle<DropdownToken> = (token) => {
antCls,
iconCls,
motionDurationMid,
dropdownPaddingVertical,
paddingBlock,
fontSize,
dropdownEdgeChildPadding,
colorTextDisabled,
@ -67,7 +74,7 @@ const genBaseStyle: GenerateStyle<DropdownToken> = (token) => {
// A placeholder out of dropdown visible range to avoid close when user moving
'&::before': {
position: 'absolute',
insetBlock: -dropdownArrowDistance + sizePopupArrow / 2,
insetBlock: token.calc(sizePopupArrow).div(2).sub(dropdownArrowDistance).equal(),
// insetInlineStart: -7, // FIXME: Seems not work for hidden element
zIndex: -9999,
opacity: 0.0001,
@ -150,9 +157,7 @@ const genBaseStyle: GenerateStyle<DropdownToken> = (token) => {
// =============================================================
// == Arrow style ==
// =============================================================
getArrowStyle<DropdownToken>(token, {
colorBg: colorBgElevated,
limitVerticalRadius: true,
getArrowStyle<DropdownToken>(token, colorBgElevated, {
arrowPlacement: { top: true, bottom: true },
}),
@ -190,7 +195,7 @@ const genBaseStyle: GenerateStyle<DropdownToken> = (token) => {
...genFocusStyle(token),
[`${menuCls}-item-group-title`]: {
padding: `${dropdownPaddingVertical}px ${controlPaddingHorizontal}px`,
padding: `${unit(paddingBlock!)} ${unit(controlPaddingHorizontal)}`,
color: token.colorTextDescription,
transition: `all ${motionDurationMid}`,
},
@ -231,7 +236,7 @@ const genBaseStyle: GenerateStyle<DropdownToken> = (token) => {
[`${menuCls}-item, ${menuCls}-submenu-title`]: {
clear: 'both',
margin: 0,
padding: `${dropdownPaddingVertical}px ${controlPaddingHorizontal}px`,
padding: `${unit(paddingBlock!)} ${unit(controlPaddingHorizontal)}`,
color: token.colorText,
fontWeight: 'normal',
fontSize,
@ -271,7 +276,7 @@ const genBaseStyle: GenerateStyle<DropdownToken> = (token) => {
'&-divider': {
height: 1, // By design
margin: `${token.marginXXS}px 0`,
margin: `${unit(token.marginXXS)} 0`,
overflow: 'hidden',
lineHeight: 0,
backgroundColor: token.colorSplit,
@ -291,13 +296,13 @@ const genBaseStyle: GenerateStyle<DropdownToken> = (token) => {
},
[`${menuCls}-item-group-list`]: {
margin: `0 ${token.marginXS}px`,
margin: `0 ${unit(token.marginXS)}`,
padding: 0,
listStyle: 'none',
},
[`${menuCls}-submenu-title`]: {
paddingInlineEnd: controlPaddingHorizontal + token.fontSizeSM,
paddingInlineEnd: token.calc(controlPaddingHorizontal).add(token.fontSizeSM).equal(),
},
[`${menuCls}-submenu-vertical`]: {
@ -332,36 +337,27 @@ const genBaseStyle: GenerateStyle<DropdownToken> = (token) => {
};
// ============================== Export ==============================
export default genComponentStyleHook(
'Dropdown',
(token, { rootPrefixCls }) => {
const {
marginXXS,
sizePopupArrow,
controlHeight,
fontSize,
lineHeight,
paddingXXS,
componentCls,
borderRadiusLG,
} = token;
export const prepareComponentToken: GetDefaultToken<'Dropdown'> = (token) => ({
zIndexPopup: token.zIndexPopupBase + 50,
paddingBlock: (token.controlHeight - token.fontSize * token.lineHeight) / 2,
...getArrowOffsetToken({
contentRadius: token.borderRadiusLG,
limitVerticalRadius: true,
}),
...getArrowToken(token),
});
const dropdownPaddingVertical = (controlHeight - fontSize * lineHeight) / 2;
const { dropdownArrowOffset } = getArrowOffset({
contentRadius: borderRadiusLG,
});
export default genStyleHooks(
'Dropdown',
(token) => {
const { marginXXS, sizePopupArrow, paddingXXS, componentCls } = token;
const dropdownToken = mergeToken<DropdownToken>(token, {
menuCls: `${componentCls}-menu`,
rootPrefixCls,
dropdownArrowDistance: sizePopupArrow / 2 + marginXXS,
dropdownArrowOffset,
dropdownPaddingVertical,
dropdownArrowDistance: token.calc(sizePopupArrow).div(2).add(marginXXS).equal(),
dropdownEdgeChildPadding: paddingXXS,
});
return [genBaseStyle(dropdownToken), genStatusStyle(dropdownToken)];
},
(token) => ({
zIndexPopup: token.zIndexPopupBase + 50,
}),
prepareComponentToken,
);

View File

@ -45,7 +45,7 @@ const Empty: CompoundedComponent = ({
const { getPrefixCls, direction, empty } = React.useContext(ConfigContext);
const prefixCls = getPrefixCls('empty', customizePrefixCls);
const [wrapSSR, hashId] = useStyle(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls);
const [locale] = useLocale('Empty');
@ -60,7 +60,7 @@ const Empty: CompoundedComponent = ({
imageNode = image;
}
return wrapSSR(
return wrapCSSVar(
<div
className={classNames(
hashId,

View File

@ -1,14 +1,14 @@
import type { CSSObject } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
/** Component only token. Which will handle additional calculation of alias token */
export interface ComponentToken {}
interface EmptyToken extends FullToken<'Empty'> {
emptyImgCls: string;
emptyImgHeight: number;
emptyImgHeightSM: number;
emptyImgHeight: number | string;
emptyImgHeightSM: number | string;
emptyImgHeightMD: number;
}
@ -75,14 +75,14 @@ const genSharedEmptyStyle: GenerateStyle<EmptyToken> = (token): CSSObject => {
};
// ============================== Export ==============================
export default genComponentStyleHook('Empty', (token) => {
const { componentCls, controlHeightLG } = token;
export default genStyleHooks('Empty', (token) => {
const { componentCls, controlHeightLG, calc } = token;
const emptyToken: EmptyToken = mergeToken<EmptyToken>(token, {
emptyImgCls: `${componentCls}-img`,
emptyImgHeight: controlHeightLG * 2.5,
emptyImgHeight: calc(controlHeightLG).mul(2.5).equal(),
emptyImgHeightMD: controlHeightLG,
emptyImgHeightSM: controlHeightLG * 0.875,
emptyImgHeightSM: calc(controlHeightLG).mul(0.875).equal(),
});
return [genSharedEmptyStyle(emptyToken)];

View File

@ -31,7 +31,7 @@ const Flex = React.forwardRef<HTMLElement, FlexProps>((props, ref) => {
const prefixCls = getPrefixCls('flex', customizePrefixCls);
const [wrapSSR, hashId] = useStyle(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls);
const mergedVertical = vertical ?? ctxFlex?.vertical;
@ -59,7 +59,7 @@ const Flex = React.forwardRef<HTMLElement, FlexProps>((props, ref) => {
mergedStyle.gap = gap;
}
return wrapSSR(
return wrapCSSVar(
<Component
ref={ref}
className={mergedCls}

View File

@ -1,7 +1,7 @@
import type { CSSInterpolation } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
import { alignItemsValues, flexWrapValues, justifyContentValues } from '../utils';
/** Component only token. Which will handle additional calculation of alias token */
@ -95,11 +95,16 @@ const genJustifyContentStyle: GenerateStyle<FlexToken> = (token) => {
return justifyStyle;
};
export default genComponentStyleHook<'Flex'>('Flex', (token) => {
export const prepareComponentToken: GetDefaultToken<'Flex'> = () => ({});
export default genStyleHooks(
'Flex',
(token) => {
const { paddingXS, padding, paddingLG } = token;
const flexToken = mergeToken<FlexToken>(token, {
flexGapSM: token.paddingXS,
flexGap: token.padding,
flexGapLG: token.paddingLG,
flexGapSM: paddingXS,
flexGap: padding,
flexGapLG: paddingLG,
});
return [
genFlexStyle(flexToken),
@ -108,4 +113,6 @@ export default genComponentStyleHook<'Flex'>('Flex', (token) => {
genAlignItemsStyle(flexToken),
genJustifyContentStyle(flexToken),
];
});
},
prepareComponentToken,
);

View File

@ -17,7 +17,6 @@ import type {
FloatButtonRef,
FloatButtonShape,
} from './interface';
import useStyle from './style';
const BackTop = React.forwardRef<FloatButtonRef, BackTopProps>((props, ref) => {
const {
@ -73,7 +72,6 @@ const BackTop = React.forwardRef<FloatButtonRef, BackTopProps>((props, ref) => {
const prefixCls = getPrefixCls(floatButtonPrefixCls, customizePrefixCls);
const rootPrefixCls = getPrefixCls();
const [wrapSSR] = useStyle(prefixCls);
const groupShape = useContext<FloatButtonShape | undefined>(FloatButtonGroupContext);
@ -81,7 +79,7 @@ const BackTop = React.forwardRef<FloatButtonRef, BackTopProps>((props, ref) => {
const contentProps: FloatButtonProps = { prefixCls, icon, type, shape: mergeShape, ...restProps };
return wrapSSR(
return (
<CSSMotion visible={visible} motionName={`${rootPrefixCls}-fade`}>
{({ className: motionClassName }) => (
<FloatButton
@ -91,7 +89,7 @@ const BackTop = React.forwardRef<FloatButtonRef, BackTopProps>((props, ref) => {
className={classNames(className, motionClassName)}
/>
)}
</CSSMotion>,
</CSSMotion>
);
});

View File

@ -18,6 +18,7 @@ import type {
FloatButtonShape,
} from './interface';
import useStyle from './style';
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
export const floatButtonPrefixCls = 'float-btn';
@ -37,12 +38,14 @@ const FloatButton = React.forwardRef<FloatButtonElement, FloatButtonProps>((prop
const { getPrefixCls, direction } = useContext<ConfigConsumerProps>(ConfigContext);
const groupShape = useContext<FloatButtonShape | undefined>(FloatButtonGroupContext);
const prefixCls = getPrefixCls(floatButtonPrefixCls, customizePrefixCls);
const [wrapSSR, hashId] = useStyle(prefixCls);
const rootCls = useCSSVarCls(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls, rootCls);
const mergeShape = groupShape || shape;
const classString = classNames(
hashId,
rootCls,
prefixCls,
className,
rootClassName,
@ -92,7 +95,7 @@ const FloatButton = React.forwardRef<FloatButtonElement, FloatButtonProps>((prop
);
}
return wrapSSR(
return wrapCSSVar(
props.href ? (
<a ref={ref} {...restProps} className={classString}>
{buttonNode}

View File

@ -12,6 +12,7 @@ import { FloatButtonGroupProvider } from './context';
import FloatButton, { floatButtonPrefixCls } from './FloatButton';
import type { FloatButtonGroupProps, FloatButtonRef } from './interface';
import useStyle from './style';
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
const FloatButtonGroup: React.FC<FloatButtonGroupProps> = (props) => {
const {
@ -32,10 +33,11 @@ const FloatButtonGroup: React.FC<FloatButtonGroupProps> = (props) => {
const { direction, getPrefixCls } = useContext<ConfigConsumerProps>(ConfigContext);
const prefixCls = getPrefixCls(floatButtonPrefixCls, customizePrefixCls);
const [wrapSSR, hashId] = useStyle(prefixCls);
const rootCls = useCSSVarCls(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls, rootCls);
const groupPrefixCls = `${prefixCls}-group`;
const groupCls = classNames(groupPrefixCls, hashId, className, {
const groupCls = classNames(groupPrefixCls, hashId, rootCls, className, {
[`${groupPrefixCls}-rtl`]: direction === 'rtl',
[`${groupPrefixCls}-${shape}`]: shape,
[`${groupPrefixCls}-${shape}-shadow`]: !trigger,
@ -104,7 +106,7 @@ const FloatButtonGroup: React.FC<FloatButtonGroupProps> = (props) => {
);
}
return wrapSSR(
return wrapCSSVar(
<FloatButtonGroupProvider value={shape}>
<div ref={floatButtonGroupRef} className={groupCls} style={style} {...hoverAction}>
{trigger && ['click', 'hover'].includes(trigger) ? (

View File

@ -1,15 +1,24 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { Keyframes } from '@ant-design/cssinjs';
import { Keyframes, unit } from '@ant-design/cssinjs';
import { resetComponent } from '../../style';
import { initFadeMotion } from '../../style/motion/fade';
import { initMotion } from '../../style/motion/motion';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
import getOffset from '../util';
/** Component only token. Which will handle additional calculation of alias token */
export interface ComponentToken {
zIndexPopup: number;
/**
* Offset of the badge dot in a circular button
* @internal
*/
dotOffsetInCircle: number;
/**
* Offset of the badge dot in a square button
* @internal
*/
dotOffsetInSquare: number;
}
type FloatButtonToken = FullToken<'FloatButton'> & {
@ -18,12 +27,10 @@ type FloatButtonToken = FullToken<'FloatButton'> & {
floatButtonHoverBackgroundColor: string;
floatButtonFontSize: number;
floatButtonSize: number;
floatButtonIconSize: number;
floatButtonBodySize: number;
floatButtonIconSize: number | string;
floatButtonBodySize: number | string;
floatButtonBodyPadding: number;
badgeOffset: number;
dotOffsetInCircle: number;
dotOffsetInSquare: number;
badgeOffset: number | string;
// Position
floatButtonInsetBlockEnd: number;
@ -35,7 +42,7 @@ const initFloatButtonGroupMotion = (token: FloatButtonToken) => {
const groupPrefixCls = `${componentCls}-group`;
const moveDownIn = new Keyframes('antFloatButtonMoveDownIn', {
'0%': {
transform: `translate3d(0, ${floatButtonSize}px, 0)`,
transform: `translate3d(0, ${unit(floatButtonSize)}, 0)`,
transformOrigin: '0 0',
opacity: 0,
},
@ -53,7 +60,7 @@ const initFloatButtonGroupMotion = (token: FloatButtonToken) => {
opacity: 1,
},
'100%': {
transform: `translate3d(0, ${floatButtonSize}px, 0)`,
transform: `translate3d(0, ${unit(floatButtonSize)}, 0)`,
transformOrigin: '0 0',
opacity: 0,
},
@ -93,6 +100,7 @@ const floatButtonGroupStyle: GenerateStyle<FloatButtonToken, CSSObject> = (token
borderRadiusSM,
badgeOffset,
floatButtonBodyPadding,
calc,
} = token;
const groupPrefixCls = `${componentCls}-group`;
return {
@ -146,12 +154,12 @@ const floatButtonGroupStyle: GenerateStyle<FloatButtonToken, CSSObject> = (token
borderEndEndRadius: borderRadiusLG,
},
'&:not(:last-child)': {
borderBottom: `${token.lineWidth}px ${token.lineType} ${token.colorSplit}`,
borderBottom: `${unit(token.lineWidth)} ${token.lineType} ${token.colorSplit}`,
},
[`${antCls}-badge`]: {
[`${antCls}-badge-count`]: {
top: -(floatButtonBodyPadding + badgeOffset),
insetInlineEnd: -(floatButtonBodyPadding + badgeOffset),
top: calc(calc(floatButtonBodyPadding).add(badgeOffset)).mul(-1).equal(),
insetInlineEnd: calc(calc(floatButtonBodyPadding).add(badgeOffset)).mul(-1).equal(),
},
},
},
@ -173,7 +181,7 @@ const floatButtonGroupStyle: GenerateStyle<FloatButtonToken, CSSObject> = (token
borderEndEndRadius: borderRadiusLG,
},
'&:not(:last-child)': {
borderBottom: `${token.lineWidth}px ${token.lineType} ${token.colorSplit}`,
borderBottom: `${unit(token.lineWidth)} ${token.lineType} ${token.colorSplit}`,
},
[`${componentCls}-body`]: {
width: token.floatButtonBodySize,
@ -212,6 +220,7 @@ const sharedFloatButtonStyle: GenerateStyle<FloatButtonToken, CSSObject> = (toke
badgeOffset,
dotOffsetInSquare,
dotOffsetInCircle,
calc,
} = token;
return {
[componentCls]: {
@ -243,8 +252,8 @@ const sharedFloatButtonStyle: GenerateStyle<FloatButtonToken, CSSObject> = (toke
[`${antCls}-badge-count`]: {
transform: 'translate(0, 0)',
transformOrigin: 'center',
top: -badgeOffset,
insetInlineEnd: -badgeOffset,
top: calc(badgeOffset).mul(-1).equal(),
insetInlineEnd: calc(badgeOffset).mul(-1).equal(),
},
},
[`${componentCls}-body`]: {
@ -262,7 +271,9 @@ const sharedFloatButtonStyle: GenerateStyle<FloatButtonToken, CSSObject> = (toke
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
padding: `${floatButtonBodyPadding / 2}px ${floatButtonBodyPadding}px`,
padding: `${unit(calc(floatButtonBodyPadding).div(2).equal())} ${unit(
floatButtonBodyPadding,
)}`,
[`${componentCls}-icon`]: {
textAlign: 'center',
margin: 'auto',
@ -321,7 +332,7 @@ const sharedFloatButtonStyle: GenerateStyle<FloatButtonToken, CSSObject> = (toke
[`${componentCls}-description`]: {
display: 'flex',
alignItems: 'center',
lineHeight: `${token.fontSizeLG}px`,
lineHeight: unit(token.fontSizeLG),
color: token.colorText,
fontSize: token.fontSizeSM,
},
@ -343,7 +354,7 @@ const sharedFloatButtonStyle: GenerateStyle<FloatButtonToken, CSSObject> = (toke
[`${componentCls}-description`]: {
display: 'flex',
alignItems: 'center',
lineHeight: `${token.fontSizeLG}px`,
lineHeight: unit(token.fontSizeLG),
color: token.colorTextLightSolid,
fontSize: token.fontSizeSM,
},
@ -354,7 +365,14 @@ const sharedFloatButtonStyle: GenerateStyle<FloatButtonToken, CSSObject> = (toke
};
// ============================== Export ==============================
export default genComponentStyleHook<'FloatButton'>('FloatButton', (token) => {
export const prepareComponentToken: GetDefaultToken<'FloatButton'> = (token) => ({
dotOffsetInCircle: getOffset(token.controlHeightLG / 2),
dotOffsetInSquare: getOffset(token.borderRadiusLG),
});
export default genStyleHooks(
'FloatButton',
(token) => {
const {
colorTextLightSolid,
colorBgElevated,
@ -365,7 +383,7 @@ export default genComponentStyleHook<'FloatButton'>('FloatButton', (token) => {
fontSizeIcon,
controlItemBgHover,
paddingXXS,
borderRadiusLG,
calc,
} = token;
const floatButtonToken = mergeToken<FloatButtonToken>(token, {
@ -373,16 +391,14 @@ export default genComponentStyleHook<'FloatButton'>('FloatButton', (token) => {
floatButtonColor: colorTextLightSolid,
floatButtonHoverBackgroundColor: controlItemBgHover,
floatButtonFontSize: fontSize,
floatButtonIconSize: fontSizeIcon * 1.5,
floatButtonIconSize: calc(fontSizeIcon).mul(1.5).equal(),
floatButtonSize: controlHeightLG,
floatButtonInsetBlockEnd: marginXXL,
floatButtonInsetInlineEnd: marginLG,
floatButtonBodySize: controlHeightLG - paddingXXS * 2,
floatButtonBodySize: calc(controlHeightLG).sub(calc(paddingXXS).mul(2)).equal(),
// 这里的 paddingXXS 是简写,完整逻辑是 (controlHeightLG - (controlHeightLG - paddingXXS * 2)) / 2,
floatButtonBodyPadding: paddingXXS,
badgeOffset: paddingXXS * 1.5,
dotOffsetInCircle: getOffset(controlHeightLG / 2),
dotOffsetInSquare: getOffset(borderRadiusLG),
badgeOffset: calc(paddingXXS).mul(1.5).equal(),
});
return [
@ -391,4 +407,6 @@ export default genComponentStyleHook<'FloatButton'>('FloatButton', (token) => {
initFadeMotion(token),
initFloatButtonGroupMotion(floatButtonToken),
];
});
},
prepareComponentToken,
);

View File

@ -9,6 +9,7 @@ import type { ValidateStatus } from './FormItem';
import useDebounce from './hooks/useDebounce';
import useStyle from './style';
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
const EMPTY_LIST: React.ReactNode[] = [];
@ -54,7 +55,8 @@ const ErrorList: React.FC<ErrorListProps> = ({
const baseClassName = `${prefixCls}-item-explain`;
const [, hashId] = useStyle(prefixCls);
const cssVarCls = useCSSVarCls(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls, cssVarCls);
const collapseMotion: CSSMotionProps = useMemo(() => initCollapseMotion(prefixCls), [prefixCls]);
@ -82,7 +84,7 @@ const ErrorList: React.FC<ErrorListProps> = ({
helpProps.id = `${fieldId}_help`;
}
return (
return wrapCSSVar(
<CSSMotion
motionDeadline={collapseMotion.motionDeadline}
motionName={`${prefixCls}-show-help`}
@ -95,7 +97,7 @@ const ErrorList: React.FC<ErrorListProps> = ({
return (
<div
{...helpProps}
className={classNames(baseClassName, holderClassName, rootClassName, hashId)}
className={classNames(baseClassName, holderClassName, cssVarCls, rootClassName, hashId)}
style={holderStyle}
role="alert"
>
@ -130,7 +132,7 @@ const ErrorList: React.FC<ErrorListProps> = ({
</div>
);
}}
</CSSMotion>
</CSSMotion>,
);
};

View File

@ -19,6 +19,7 @@ import type { FormLabelAlign } from './interface';
import useStyle from './style';
import ValidateMessagesContext from './validateMessagesContext';
import type { FeedbackIcons } from './FormItem';
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
export type RequiredMark =
| boolean
@ -103,7 +104,8 @@ const InternalForm: React.ForwardRefRenderFunction<FormInstance, FormProps> = (p
const prefixCls = getPrefixCls('form', customizePrefixCls);
// Style
const [wrapSSR, hashId] = useStyle(prefixCls);
const cssVarCls = useCSSVarCls(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls, cssVarCls);
const formClassName = classNames(
prefixCls,
@ -113,6 +115,7 @@ const InternalForm: React.ForwardRefRenderFunction<FormInstance, FormProps> = (p
[`${prefixCls}-rtl`]: direction === 'rtl',
[`${prefixCls}-${mergedSize}`]: mergedSize,
},
cssVarCls,
hashId,
contextForm?.className,
className,
@ -177,7 +180,7 @@ const InternalForm: React.ForwardRefRenderFunction<FormInstance, FormProps> = (p
}
};
return wrapSSR(
return wrapCSSVar(
<DisabledContextProvider disabled={disabled}>
<SizeContext.Provider value={mergedSize}>
<FormProvider

View File

@ -21,6 +21,7 @@ import useStyle from '../style';
import { getFieldId, toArray } from '../util';
import ItemHolder from './ItemHolder';
import StatusProvider from './StatusProvider';
import useCSSVarCls from '../../config-provider/hooks/useCSSVarCls';
const NAME_SPLIT = '__SPLIT__';
@ -30,7 +31,7 @@ interface FieldError {
}
const ValidateStatuses = ['success', 'warning', 'error', 'validating', ''] as const;
export type ValidateStatus = typeof ValidateStatuses[number];
export type ValidateStatus = (typeof ValidateStatuses)[number];
type RenderChildren<Values = any> = (form: FormInstance<Values>) => React.ReactNode;
type RcFieldProps<Values = any> = Omit<FieldProps<Values>, 'children'>;
@ -126,7 +127,8 @@ function InternalFormItem<Values = any>(props: FormItemProps<Values>): React.Rea
const prefixCls = getPrefixCls('form', customizePrefixCls);
// Style
const [wrapSSR, hashId] = useStyle(prefixCls);
const cssVarCls = useCSSVarCls(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls, cssVarCls);
// ========================= Warn =========================
const warning = devUseWarning('Form.Item');
@ -240,7 +242,7 @@ function InternalFormItem<Values = any>(props: FormItemProps<Values>): React.Rea
<ItemHolder
key="row"
{...props}
className={classNames(className, hashId)}
className={classNames(className, cssVarCls, hashId)}
prefixCls={prefixCls}
fieldId={fieldId}
isRequired={isRequired}
@ -255,7 +257,7 @@ function InternalFormItem<Values = any>(props: FormItemProps<Values>): React.Rea
}
if (!hasName && !isRenderProps && !dependencies) {
return wrapSSR(renderLayout(mergedChildren) as JSX.Element);
return wrapCSSVar(renderLayout(mergedChildren) as JSX.Element);
}
let variables: Record<string, string> = {};
@ -269,7 +271,7 @@ function InternalFormItem<Values = any>(props: FormItemProps<Values>): React.Rea
}
// >>>>> With Field
return wrapSSR(
return wrapCSSVar(
<Field
{...props}
messageVariables={variables}

View File

@ -19530,6 +19530,9 @@ Array [
<pre>
Name Value:
</pre>
<pre>
Custom Value: name:
</pre>
</article>,
]
`;

View File

@ -8272,6 +8272,9 @@ Array [
<pre>
Name Value:
</pre>
<pre>
Custom Value:
</pre>
</article>,
]
`;

View File

@ -2108,4 +2108,44 @@ describe('Form', () => {
expect(container.querySelector('.ant-input-number-suffix')).toBeTruthy();
expect(container.querySelector('.ant-input-number-focused')).toBeTruthy();
});
// https://github.com/ant-design/ant-design/issues/20803#issuecomment-601626759
it('without explicitly passing `valuePropName`', async () => {
const submit = jest.fn();
const Demo = () => (
<Form
initialValues={{
foo: true,
}}
onFinish={submit}
>
<Form.Item label="Switch" name="foo">
<Switch />
</Form.Item>
<button type="submit">Submit</button>
</Form>
);
const { getByRole } = render(<Demo />);
await waitFakeTimer();
const switchNode = getByRole('switch');
expect(switchNode).toBeTruthy();
expect(switchNode).toBeChecked();
fireEvent.click(switchNode);
expect(switchNode).not.toBeChecked();
const submitButton = getByRole('button');
expect(submitButton).toBeTruthy();
fireEvent.click(submitButton);
await waitFakeTimer();
expect(submit).toHaveBeenCalledWith({
foo: false,
});
});
});

View File

@ -4,6 +4,8 @@ import { Form, Input, InputNumber, Typography } from 'antd';
const Demo: React.FC = () => {
const [form] = Form.useForm<{ name: string; age: number }>();
const nameValue = Form.useWatch('name', form);
// The selector is static and does not support closures.
const customValue = Form.useWatch((values) => `name: ${values.name || ''}`, form);
return (
<>
@ -18,6 +20,7 @@ const Demo: React.FC = () => {
<Typography>
<pre>Name Value: {nameValue}</pre>
<pre>Custom Value: {customValue}</pre>
</Typography>
</>
);

View File

@ -387,7 +387,9 @@ export default () => {
### Form.useWatch
`type Form.useWatch = (namePath: NamePath, formInstance?: FormInstance | WatchOptions): Value`
`type Form.useWatch = (namePath: NamePath | (selector: (values: Store) => any), formInstance?: FormInstance | WatchOptions): Value`
`5.12.0` add `selector`
Watch the value of a field. You can use this to interact with other hooks like `useSWR` to reduce development costs:

View File

@ -386,7 +386,9 @@ export default () => {
### Form.useWatch
`type Form.useWatch = (namePath: NamePath, formInstance?: FormInstance | WatchOptions): Value`
`type Form.useWatch = (namePath: NamePath | (selector: (values: Store)) => any, formInstance?: FormInstance | WatchOptions): Value`
`5.12.0` 新增 `selector`
用于直接获取 form 中字段对应的值。通过该 Hooks 可以与诸如 `useSWR` 进行联动从而降低维护成本:

View File

@ -1,10 +1,11 @@
import type { CSSProperties } from 'react';
import type { CSSObject } from '@ant-design/cssinjs';
import { unit } from '@ant-design/cssinjs';
import { resetComponent } from '../../style';
import { genCollapseMotion, zoomIn } from '../../style/motion';
import type { AliasToken, FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import type { AliasToken, FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
import type { GenStyleFn } from '../../theme/util/genComponentStyleHook';
import genFormValidateMotionStyle from './explain';
@ -71,7 +72,7 @@ const resetForm = (token: AliasToken): CSSObject => ({
fontSize: token.fontSizeLG,
lineHeight: 'inherit',
border: 0,
borderBottom: `${token.lineWidth}px ${token.lineType} ${token.colorBorder}`,
borderBottom: `${unit(token.lineWidth)} ${token.lineType} ${token.colorBorder}`,
},
label: {
@ -107,7 +108,7 @@ const resetForm = (token: AliasToken): CSSObject => ({
input[type='radio']:focus,
input[type='checkbox']:focus`]: {
outline: 0,
boxShadow: `0 0 0 ${token.controlOutlineWidth}px ${token.controlOutline}`,
boxShadow: `0 0 0 ${unit(token.controlOutlineWidth)} ${token.controlOutline}`,
},
// Adjust output element
@ -223,7 +224,7 @@ const genFormItemStyle: GenerateStyle<FormToken> = (token) => {
'&-wrap': {
overflow: 'unset',
lineHeight: `${token.lineHeight} - 0.25em`,
lineHeight: token.lineHeight,
whiteSpace: 'unset',
},
@ -515,7 +516,7 @@ const genVerticalStyle: GenerateStyle<FormToken> = (token) => {
.${rootPrefixCls}-col-24${formItemCls}-label,
.${rootPrefixCls}-col-xl-24${formItemCls}-label`]: makeVerticalLayoutLabel(token),
[`@media (max-width: ${token.screenXSMax}px)`]: [
[`@media (max-width: ${unit(token.screenXSMax)})`]: [
makeVerticalLayout(token),
{
[componentCls]: {
@ -524,19 +525,19 @@ const genVerticalStyle: GenerateStyle<FormToken> = (token) => {
},
],
[`@media (max-width: ${token.screenSMMax}px)`]: {
[`@media (max-width: ${unit(token.screenSMMax)})`]: {
[componentCls]: {
[`.${rootPrefixCls}-col-sm-24${formItemCls}-label`]: makeVerticalLayoutLabel(token),
},
},
[`@media (max-width: ${token.screenMDMax}px)`]: {
[`@media (max-width: ${unit(token.screenMDMax)})`]: {
[componentCls]: {
[`.${rootPrefixCls}-col-md-24${formItemCls}-label`]: makeVerticalLayoutLabel(token),
},
},
[`@media (max-width: ${token.screenLGMax}px)`]: {
[`@media (max-width: ${unit(token.screenLGMax)})`]: {
[componentCls]: {
[`.${rootPrefixCls}-col-lg-24${formItemCls}-label`]: makeVerticalLayoutLabel(token),
},
@ -545,6 +546,18 @@ const genVerticalStyle: GenerateStyle<FormToken> = (token) => {
};
// ============================== Export ==============================
export const prepareComponentToken: GetDefaultToken<'Form'> = (token) => ({
labelRequiredMarkColor: token.colorError,
labelColor: token.colorTextHeading,
labelFontSize: token.fontSize,
labelHeight: token.controlHeight,
labelColonMarginInlineStart: token.marginXXS / 2,
labelColonMarginInlineEnd: token.marginXS,
itemMarginBottom: token.marginLG,
verticalLabelPadding: `0 0 ${token.paddingXS}px`,
verticalLabelMargin: 0,
});
export const prepareToken: (
token: Parameters<GenStyleFn<'Form'>>[0],
rootPrefixCls: string,
@ -557,7 +570,7 @@ export const prepareToken: (
return formToken;
};
export default genComponentStyleHook(
export default genStyleHooks(
'Form',
(token, { rootPrefixCls }) => {
const formToken = prepareToken(token, rootPrefixCls);
@ -573,17 +586,7 @@ export default genComponentStyleHook(
zoomIn,
];
},
(token) => ({
labelRequiredMarkColor: token.colorError,
labelColor: token.colorTextHeading,
labelFontSize: token.fontSize,
labelHeight: token.controlHeight,
labelColonMarginInlineStart: token.marginXXS / 2,
labelColonMarginInlineEnd: token.marginXS,
itemMarginBottom: token.marginLG,
verticalLabelPadding: `0 0 ${token.paddingXS}px`,
verticalLabelMargin: 0,
}),
prepareComponentToken,
{
// Let From style before the Grid
// ref https://github.com/ant-design/ant-design/issues/44386

View File

@ -67,7 +67,8 @@ const Col = React.forwardRef<HTMLDivElement, ColProps>((props, ref) => {
} = props;
const prefixCls = getPrefixCls('col', customizePrefixCls);
const [wrapSSR, hashId] = useColStyle(prefixCls);
const [wrapCSSVar, hashId] = useColStyle(prefixCls);
let sizeClassObj = {};
sizes.forEach((size) => {
@ -126,7 +127,7 @@ const Col = React.forwardRef<HTMLDivElement, ColProps>((props, ref) => {
}
}
return wrapSSR(
return wrapCSSVar(
<div {...others} style={{ ...mergedStyle, ...style }} className={classes} ref={ref}>
{children}
</div>,

View File

@ -26,12 +26,12 @@ type ResponsiveLike<T> = {
type Gap = number | undefined;
export type Gutter = number | undefined | Partial<Record<Breakpoint, number>>;
type ResponsiveAligns = ResponsiveLike<typeof RowAligns[number]>;
type ResponsiveJustify = ResponsiveLike<typeof RowJustify[number]>;
type ResponsiveAligns = ResponsiveLike<(typeof RowAligns)[number]>;
type ResponsiveJustify = ResponsiveLike<(typeof RowJustify)[number]>;
export interface RowProps extends React.HTMLAttributes<HTMLDivElement> {
gutter?: Gutter | [Gutter, Gutter];
align?: typeof RowAligns[number] | ResponsiveAligns;
justify?: typeof RowJustify[number] | ResponsiveJustify;
align?: (typeof RowAligns)[number] | ResponsiveAligns;
justify?: (typeof RowJustify)[number] | ResponsiveJustify;
prefixCls?: string;
wrap?: boolean;
}
@ -146,7 +146,9 @@ const Row = React.forwardRef<HTMLDivElement, RowProps>((props, ref) => {
};
const prefixCls = getPrefixCls('row', customizePrefixCls);
const [wrapSSR, hashId] = useRowStyle(prefixCls);
const [wrapCSSVar, hashId] = useRowStyle(prefixCls);
const gutters = getGutter();
const classes = classNames(
prefixCls,
@ -180,7 +182,7 @@ const Row = React.forwardRef<HTMLDivElement, RowProps>((props, ref) => {
[gutterH, gutterV, wrap],
);
return wrapSSR(
return wrapCSSVar(
<RowContext.Provider value={rowContext}>
<div {...others} className={classes} style={{ ...rowStyle, ...style }} ref={ref}>
{children}

View File

@ -1,9 +1,15 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { type CSSObject, unit } from '@ant-design/cssinjs';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
interface GridRowToken extends FullToken<'Grid'> {}
export interface ComponentToken {
//
}
interface GridRowToken extends FullToken<'Grid'> {
//
}
interface GridColToken extends FullToken<'Grid'> {
gridColumns: number;
@ -156,35 +162,40 @@ const genGridMediaStyle = (
screenSize: number,
sizeCls: string,
): CSSObject => ({
[`@media (min-width: ${screenSize}px)`]: {
[`@media (min-width: ${unit(screenSize)})`]: {
...genGridStyle(token, sizeCls),
},
});
// ============================== Export ==============================
export const useRowStyle = genComponentStyleHook('Grid', (token) => [genGridRowStyle(token)]);
export const prepareRowComponentToken: GetDefaultToken<'Grid'> = () => ({});
export const useColStyle = genComponentStyleHook('Grid', (token) => {
export const prepareColComponentToken: GetDefaultToken<'Grid'> = () => ({});
// ============================== Export ==============================
export const useRowStyle = genStyleHooks('Grid', genGridRowStyle, prepareRowComponentToken);
export const useColStyle = genStyleHooks(
'Grid',
(token) => {
const gridToken: GridColToken = mergeToken<GridColToken>(token, {
gridColumns: 24, // Row is divided into 24 parts in Grid
});
const gridMediaSizesMap = {
'-sm': gridToken.screenSMMin,
'-md': gridToken.screenMDMin,
'-lg': gridToken.screenLGMin,
'-xl': gridToken.screenXLMin,
'-xxl': gridToken.screenXXLMin,
};
} as const;
type GridMediaSize = keyof typeof gridMediaSizesMap;
return [
genGridColStyle(gridToken),
genGridStyle(gridToken, ''),
genGridStyle(gridToken, '-xs'),
Object.keys(gridMediaSizesMap)
.map((key: keyof typeof gridMediaSizesMap) =>
genGridMediaStyle(gridToken, gridMediaSizesMap[key], key),
)
.map((key: GridMediaSize) => genGridMediaStyle(gridToken, gridMediaSizesMap[key], key))
.reduce((pre, cur) => ({ ...pre, ...cur }), {}),
];
});
},
prepareColComponentToken,
);

View File

@ -1,3 +1,4 @@
import * as React from 'react';
import CloseOutlined from '@ant-design/icons/CloseOutlined';
import LeftOutlined from '@ant-design/icons/LeftOutlined';
import RightOutlined from '@ant-design/icons/RightOutlined';
@ -6,16 +7,15 @@ import RotateRightOutlined from '@ant-design/icons/RotateRightOutlined';
import SwapOutlined from '@ant-design/icons/SwapOutlined';
import ZoomInOutlined from '@ant-design/icons/ZoomInOutlined';
import ZoomOutOutlined from '@ant-design/icons/ZoomOutOutlined';
import classNames from 'classnames';
import RcImage from 'rc-image';
import type { GroupConsumerProps } from 'rc-image/lib/PreviewGroup';
import * as React from 'react';
import classNames from 'classnames';
import { ConfigContext } from '../config-provider';
import { getTransitionName } from '../_util/motion';
// CSSINJS
import useStyle from './style';
import { useZIndex } from '../_util/hooks/useZIndex';
import { getTransitionName } from '../_util/motion';
import { ConfigContext } from '../config-provider';
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
import useStyle from './style';
export const icons = {
rotateLeft: <RotateLeftOutlined />,
@ -39,19 +39,20 @@ const InternalPreviewGroup: React.FC<GroupConsumerProps> = ({
const previewPrefixCls = `${prefixCls}-preview`;
const rootPrefixCls = getPrefixCls();
const [wrapSSR, hashId] = useStyle(prefixCls);
const rootCls = useCSSVarCls(prefixCls);
const [wrapCSSVar, hashId] = useStyle(prefixCls, rootCls);
const [zIndex] = useZIndex(
'ImagePreview',
typeof preview === 'object' ? preview.zIndex : undefined,
);
const mergedPreview = React.useMemo(() => {
const mergedPreview = React.useMemo<GroupConsumerProps['preview']>(() => {
if (preview === false) {
return preview;
}
const _preview = typeof preview === 'object' ? preview : {};
const mergedRootClassName = classNames(hashId, _preview.rootClassName ?? '');
const mergedRootClassName = classNames(hashId, rootCls, _preview.rootClassName ?? '');
return {
..._preview,
@ -62,7 +63,7 @@ const InternalPreviewGroup: React.FC<GroupConsumerProps> = ({
};
}, [preview]);
return wrapSSR(
return wrapCSSVar(
<RcImage.PreviewGroup
preview={mergedPreview}
previewPrefixCls={previewPrefixCls}

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