ant-design/components/switch/style/index.ts
Dunqing 6759887c44
chore: migrate to vitest (#42506)
* chore: migrate to vitest

* chore: update ci

* fix: test correctly

* test: support puppeteer

* chore: update coverage

* chore: update include/exclude

* chore: update config

* test: update incorrect tests

* chore: update script

* chore: update

* fix: should close browser at the ended

* chore: improve

* fix: test cause tsc error

* fix: eslint error

* chore: exclude correctly

* test: update snap and fix some tests

* chore: update test config

* fix: countup.js

* fix: incorrect test

* chore: update reference

* test: update

* fix: countup.js

* fix: timeout

* chore: update site test

* fix: fixed countup version

* chore: remove unsed code

* test: update

* test: update demo timeout

* test: update timeout

* chore: update image test

* chore: update threads

* fix: image/svg+xml test failed

* chore: limits threads

* test: update test coverage include

* chore: remove jest files

* chore: rename jest to vi

* chore: update document

* chore: fix missing @types/jsdom

* chore: update coverage

* chore: update snap

* fix:watermark test cases are incorrect

* feat: update ignore comment

* test: fix test case

* test: reset body scrollTop

* test: clean up

* test: use vi

* test: update snapshot

* test: update snapshot

* test: fix dropdown test failed

* fix: toHaveStyle cause test fail

* test: improve test case

* test: fix

* fix: color failed, refer to https://github.com/jsdom/jsdom/pull/3560

* test: fix

* test: fix

* test: fix circular import

* test: revert

* ci: coverage failed

* test: fix c8 ignore comment

* chore: incorrect config

* chore: fix ignore ci

* test: revert svg+xml

* test: fix realTimers

* feat: rc-trigger should be remove

* test: fix some failed test

* chore: remove unused deps and configure eslint-plugin-vitest

* test: update snap

* chore: remove jest

* test: fix lint error

---------

Co-authored-by: 二货机器人 <smith3816@gmail.com>
Co-authored-by: afc163 <afc163@gmail.com>
2023-06-07 11:54:50 +08:00

357 lines
11 KiB
TypeScript

import type { CSSObject } from '@ant-design/cssinjs';
import { TinyColor } from '@ctrl/tinycolor';
import { genFocusStyle, resetComponent } from '../../style';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
interface SwitchToken extends FullToken<'Switch'> {
switchMinWidth: number;
switchHeight: number;
switchDuration: string;
switchColor: string;
switchDisabledOpacity: number;
switchInnerMarginMin: number;
switchInnerMarginMax: number;
switchPadding: number;
switchPinSize: number;
switchBg: string;
switchMinWidthSM: number;
switchHeightSM: number;
switchInnerMarginMinSM: number;
switchInnerMarginMaxSM: number;
switchPinSizeSM: number;
switchHandleShadow: string;
switchLoadingIconSize: number;
switchLoadingIconColor: string;
switchHandleActiveInset: string;
}
const genSwitchSmallStyle: GenerateStyle<SwitchToken, CSSObject> = (token) => {
const { componentCls } = token;
const switchInnerCls = `${componentCls}-inner`;
return {
[componentCls]: {
[`&${componentCls}-small`]: {
minWidth: token.switchMinWidthSM,
height: token.switchHeightSM,
lineHeight: `${token.switchHeightSM}px`,
[`${componentCls}-inner`]: {
paddingInlineStart: token.switchInnerMarginMaxSM,
paddingInlineEnd: token.switchInnerMarginMinSM,
[`${switchInnerCls}-checked`]: {
marginInlineStart: `calc(-100% + ${
token.switchPinSizeSM + token.switchPadding * 2
}px - ${token.switchInnerMarginMaxSM * 2}px)`,
marginInlineEnd: `calc(100% - ${token.switchPinSizeSM + token.switchPadding * 2}px + ${
token.switchInnerMarginMaxSM * 2
}px)`,
},
[`${switchInnerCls}-unchecked`]: {
marginTop: -token.switchHeightSM,
marginInlineStart: 0,
marginInlineEnd: 0,
},
},
[`${componentCls}-handle`]: {
width: token.switchPinSizeSM,
height: token.switchPinSizeSM,
},
[`${componentCls}-loading-icon`]: {
top: (token.switchPinSizeSM - token.switchLoadingIconSize) / 2,
fontSize: token.switchLoadingIconSize,
},
[`&${componentCls}-checked`]: {
[`${componentCls}-inner`]: {
paddingInlineStart: token.switchInnerMarginMinSM,
paddingInlineEnd: token.switchInnerMarginMaxSM,
[`${switchInnerCls}-checked`]: {
marginInlineStart: 0,
marginInlineEnd: 0,
},
[`${switchInnerCls}-unchecked`]: {
marginInlineStart: `calc(100% - ${
token.switchPinSizeSM + token.switchPadding * 2
}px + ${token.switchInnerMarginMaxSM * 2}px)`,
marginInlineEnd: `calc(-100% + ${
token.switchPinSizeSM + token.switchPadding * 2
}px - ${token.switchInnerMarginMaxSM * 2}px)`,
},
},
[`${componentCls}-handle`]: {
insetInlineStart: `calc(100% - ${token.switchPinSizeSM + token.switchPadding}px)`,
},
},
[`&:not(${componentCls}-disabled):active`]: {
[`&:not(${componentCls}-checked) ${switchInnerCls}`]: {
[`${switchInnerCls}-unchecked`]: {
marginInlineStart: token.marginXXS / 2,
marginInlineEnd: -token.marginXXS / 2,
},
},
[`&${componentCls}-checked ${switchInnerCls}`]: {
[`${switchInnerCls}-checked`]: {
marginInlineStart: -token.marginXXS / 2,
marginInlineEnd: token.marginXXS / 2,
},
},
},
},
},
};
};
const genSwitchLoadingStyle: GenerateStyle<SwitchToken, CSSObject> = (token) => {
const { componentCls } = token;
return {
[componentCls]: {
[`${componentCls}-loading-icon${token.iconCls}`]: {
position: 'relative',
top: (token.switchPinSize - token.fontSize) / 2,
color: token.switchLoadingIconColor,
verticalAlign: 'top',
},
[`&${componentCls}-checked ${componentCls}-loading-icon`]: {
color: token.switchColor,
},
},
};
};
const genSwitchHandleStyle: GenerateStyle<SwitchToken, CSSObject> = (token) => {
const { componentCls, motion } = token;
const switchHandleCls = `${componentCls}-handle`;
return {
[componentCls]: {
[switchHandleCls]: {
position: 'absolute',
top: token.switchPadding,
insetInlineStart: token.switchPadding,
width: token.switchPinSize,
height: token.switchPinSize,
transition: `all ${token.switchDuration} ease-in-out`,
'&::before': {
position: 'absolute',
top: 0,
insetInlineEnd: 0,
bottom: 0,
insetInlineStart: 0,
backgroundColor: token.colorWhite,
borderRadius: token.switchPinSize / 2,
boxShadow: token.switchHandleShadow,
transition: `all ${token.switchDuration} ease-in-out`,
content: '""',
},
},
[`&${componentCls}-checked ${switchHandleCls}`]: {
insetInlineStart: `calc(100% - ${token.switchPinSize + token.switchPadding}px)`,
},
[`&:not(${componentCls}-disabled):active`]: motion
? {
[`${switchHandleCls}::before`]: {
insetInlineEnd: token.switchHandleActiveInset,
insetInlineStart: 0,
},
[`&${componentCls}-checked ${switchHandleCls}::before`]: {
insetInlineEnd: 0,
insetInlineStart: token.switchHandleActiveInset,
},
}
: /* c8 ignore next */
{},
},
};
};
const genSwitchInnerStyle: GenerateStyle<SwitchToken, CSSObject> = (token) => {
const { componentCls } = token;
const switchInnerCls = `${componentCls}-inner`;
return {
[componentCls]: {
[switchInnerCls]: {
display: 'block',
overflow: 'hidden',
borderRadius: 100,
height: '100%',
paddingInlineStart: token.switchInnerMarginMax,
paddingInlineEnd: token.switchInnerMarginMin,
transition: `padding-inline-start ${token.switchDuration} ease-in-out, padding-inline-end ${token.switchDuration} ease-in-out`,
[`${switchInnerCls}-checked, ${switchInnerCls}-unchecked`]: {
display: 'block',
color: token.colorTextLightSolid,
fontSize: token.fontSizeSM,
transition: `margin-inline-start ${token.switchDuration} ease-in-out, margin-inline-end ${token.switchDuration} ease-in-out`,
pointerEvents: 'none',
},
[`${switchInnerCls}-checked`]: {
marginInlineStart: `calc(-100% + ${token.switchPinSize + token.switchPadding * 2}px - ${
token.switchInnerMarginMax * 2
}px)`,
marginInlineEnd: `calc(100% - ${token.switchPinSize + token.switchPadding * 2}px + ${
token.switchInnerMarginMax * 2
}px)`,
},
[`${switchInnerCls}-unchecked`]: {
marginTop: -token.switchHeight,
marginInlineStart: 0,
marginInlineEnd: 0,
},
},
[`&${componentCls}-checked ${switchInnerCls}`]: {
paddingInlineStart: token.switchInnerMarginMin,
paddingInlineEnd: token.switchInnerMarginMax,
[`${switchInnerCls}-checked`]: {
marginInlineStart: 0,
marginInlineEnd: 0,
},
[`${switchInnerCls}-unchecked`]: {
marginInlineStart: `calc(100% - ${token.switchPinSize + token.switchPadding * 2}px + ${
token.switchInnerMarginMax * 2
}px)`,
marginInlineEnd: `calc(-100% + ${token.switchPinSize + token.switchPadding * 2}px - ${
token.switchInnerMarginMax * 2
}px)`,
},
},
[`&:not(${componentCls}-disabled):active`]: {
[`&:not(${componentCls}-checked) ${switchInnerCls}`]: {
[`${switchInnerCls}-unchecked`]: {
marginInlineStart: token.switchPadding * 2,
marginInlineEnd: -token.switchPadding * 2,
},
},
[`&${componentCls}-checked ${switchInnerCls}`]: {
[`${switchInnerCls}-checked`]: {
marginInlineStart: -token.switchPadding * 2,
marginInlineEnd: token.switchPadding * 2,
},
},
},
},
};
};
const genSwitchStyle = (token: SwitchToken): CSSObject => {
const { componentCls } = token;
return {
[componentCls]: {
...resetComponent(token),
position: 'relative',
display: 'inline-block',
boxSizing: 'border-box',
minWidth: token.switchMinWidth,
height: token.switchHeight,
lineHeight: `${token.switchHeight}px`,
verticalAlign: 'middle',
background: token.colorTextQuaternary,
border: '0',
borderRadius: 100,
cursor: 'pointer',
transition: `all ${token.motionDurationMid}`,
userSelect: 'none',
[`&:hover:not(${componentCls}-disabled)`]: {
background: token.colorTextTertiary,
},
...genFocusStyle(token),
[`&${componentCls}-checked`]: {
background: token.switchColor,
[`&:hover:not(${componentCls}-disabled)`]: {
background: token.colorPrimaryHover,
},
},
[`&${componentCls}-loading, &${componentCls}-disabled`]: {
cursor: 'not-allowed',
opacity: token.switchDisabledOpacity,
'*': {
boxShadow: 'none',
cursor: 'not-allowed',
},
},
// rtl style
[`&${componentCls}-rtl`]: {
direction: 'rtl',
},
},
};
};
// ============================== Export ==============================
export default genComponentStyleHook('Switch', (token) => {
const switchHeight = token.fontSize * token.lineHeight;
const switchHeightSM = token.controlHeight / 2;
const switchPadding = 2; // This is magic
const switchPinSize = switchHeight - switchPadding * 2;
const switchPinSizeSM = switchHeightSM - switchPadding * 2;
const switchToken = mergeToken<SwitchToken>(token, {
switchMinWidth: switchPinSize * 2 + switchPadding * 4,
switchHeight,
switchDuration: token.motionDurationMid,
switchColor: token.colorPrimary,
switchDisabledOpacity: token.opacityLoading,
switchInnerMarginMin: switchPinSize / 2,
switchInnerMarginMax: switchPinSize + switchPadding + switchPadding * 2,
switchPadding,
switchPinSize,
switchBg: token.colorBgContainer,
switchMinWidthSM: switchPinSizeSM * 2 + switchPadding * 2,
switchHeightSM,
switchInnerMarginMinSM: switchPinSizeSM / 2,
switchInnerMarginMaxSM: switchPinSizeSM + switchPadding + switchPadding * 2,
switchPinSizeSM,
switchHandleShadow: `0 2px 4px 0 ${new TinyColor('#00230b').setAlpha(0.2).toRgbString()}`,
switchLoadingIconSize: token.fontSizeIcon * 0.75,
switchLoadingIconColor: `rgba(0, 0, 0, ${token.opacityLoading})`,
switchHandleActiveInset: '-30%',
});
return [
genSwitchStyle(switchToken),
// inner style
genSwitchInnerStyle(switchToken),
// handle style
genSwitchHandleStyle(switchToken),
// loading style
genSwitchLoadingStyle(switchToken),
// small style
genSwitchSmallStyle(switchToken),
];
});