index.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. import { unit } from '@ant-design/cssinjs';
  2. import { FastColor } from '@ant-design/fast-color';
  3. import { genFocusStyle, resetComponent } from '../../style';
  4. import { genStyleHooks, mergeToken } from '../../theme/internal';
  5. const genSwitchSmallStyle = token => {
  6. const {
  7. componentCls,
  8. trackHeightSM,
  9. trackPadding,
  10. trackMinWidthSM,
  11. innerMinMarginSM,
  12. innerMaxMarginSM,
  13. handleSizeSM,
  14. calc
  15. } = token;
  16. const switchInnerCls = `${componentCls}-inner`;
  17. const trackPaddingCalc = unit(calc(handleSizeSM).add(calc(trackPadding).mul(2)).equal());
  18. const innerMaxMarginCalc = unit(calc(innerMaxMarginSM).mul(2).equal());
  19. return {
  20. [componentCls]: {
  21. [`&${componentCls}-small`]: {
  22. minWidth: trackMinWidthSM,
  23. height: trackHeightSM,
  24. lineHeight: unit(trackHeightSM),
  25. [`${componentCls}-inner`]: {
  26. paddingInlineStart: innerMaxMarginSM,
  27. paddingInlineEnd: innerMinMarginSM,
  28. [`${switchInnerCls}-checked, ${switchInnerCls}-unchecked`]: {
  29. minHeight: trackHeightSM
  30. },
  31. [`${switchInnerCls}-checked`]: {
  32. marginInlineStart: `calc(-100% + ${trackPaddingCalc} - ${innerMaxMarginCalc})`,
  33. marginInlineEnd: `calc(100% - ${trackPaddingCalc} + ${innerMaxMarginCalc})`
  34. },
  35. [`${switchInnerCls}-unchecked`]: {
  36. marginTop: calc(trackHeightSM).mul(-1).equal(),
  37. marginInlineStart: 0,
  38. marginInlineEnd: 0
  39. }
  40. },
  41. [`${componentCls}-handle`]: {
  42. width: handleSizeSM,
  43. height: handleSizeSM
  44. },
  45. [`${componentCls}-loading-icon`]: {
  46. top: calc(calc(handleSizeSM).sub(token.switchLoadingIconSize)).div(2).equal(),
  47. fontSize: token.switchLoadingIconSize
  48. },
  49. [`&${componentCls}-checked`]: {
  50. [`${componentCls}-inner`]: {
  51. paddingInlineStart: innerMinMarginSM,
  52. paddingInlineEnd: innerMaxMarginSM,
  53. [`${switchInnerCls}-checked`]: {
  54. marginInlineStart: 0,
  55. marginInlineEnd: 0
  56. },
  57. [`${switchInnerCls}-unchecked`]: {
  58. marginInlineStart: `calc(100% - ${trackPaddingCalc} + ${innerMaxMarginCalc})`,
  59. marginInlineEnd: `calc(-100% + ${trackPaddingCalc} - ${innerMaxMarginCalc})`
  60. }
  61. },
  62. [`${componentCls}-handle`]: {
  63. insetInlineStart: `calc(100% - ${unit(calc(handleSizeSM).add(trackPadding).equal())})`
  64. }
  65. },
  66. [`&:not(${componentCls}-disabled):active`]: {
  67. [`&:not(${componentCls}-checked) ${switchInnerCls}`]: {
  68. [`${switchInnerCls}-unchecked`]: {
  69. marginInlineStart: calc(token.marginXXS).div(2).equal(),
  70. marginInlineEnd: calc(token.marginXXS).mul(-1).div(2).equal()
  71. }
  72. },
  73. [`&${componentCls}-checked ${switchInnerCls}`]: {
  74. [`${switchInnerCls}-checked`]: {
  75. marginInlineStart: calc(token.marginXXS).mul(-1).div(2).equal(),
  76. marginInlineEnd: calc(token.marginXXS).div(2).equal()
  77. }
  78. }
  79. }
  80. }
  81. }
  82. };
  83. };
  84. const genSwitchLoadingStyle = token => {
  85. const {
  86. componentCls,
  87. handleSize,
  88. calc
  89. } = token;
  90. return {
  91. [componentCls]: {
  92. [`${componentCls}-loading-icon${token.iconCls}`]: {
  93. position: 'relative',
  94. top: calc(calc(handleSize).sub(token.fontSize)).div(2).equal(),
  95. color: token.switchLoadingIconColor,
  96. verticalAlign: 'top'
  97. },
  98. [`&${componentCls}-checked ${componentCls}-loading-icon`]: {
  99. color: token.switchColor
  100. }
  101. }
  102. };
  103. };
  104. const genSwitchHandleStyle = token => {
  105. const {
  106. componentCls,
  107. trackPadding,
  108. handleBg,
  109. handleShadow,
  110. handleSize,
  111. calc
  112. } = token;
  113. const switchHandleCls = `${componentCls}-handle`;
  114. return {
  115. [componentCls]: {
  116. [switchHandleCls]: {
  117. position: 'absolute',
  118. top: trackPadding,
  119. insetInlineStart: trackPadding,
  120. width: handleSize,
  121. height: handleSize,
  122. transition: `all ${token.switchDuration} ease-in-out`,
  123. '&::before': {
  124. position: 'absolute',
  125. top: 0,
  126. insetInlineEnd: 0,
  127. bottom: 0,
  128. insetInlineStart: 0,
  129. backgroundColor: handleBg,
  130. borderRadius: calc(handleSize).div(2).equal(),
  131. boxShadow: handleShadow,
  132. transition: `all ${token.switchDuration} ease-in-out`,
  133. content: '""'
  134. }
  135. },
  136. [`&${componentCls}-checked ${switchHandleCls}`]: {
  137. insetInlineStart: `calc(100% - ${unit(calc(handleSize).add(trackPadding).equal())})`
  138. },
  139. [`&:not(${componentCls}-disabled):active`]: {
  140. [`${switchHandleCls}::before`]: {
  141. insetInlineEnd: token.switchHandleActiveInset,
  142. insetInlineStart: 0
  143. },
  144. [`&${componentCls}-checked ${switchHandleCls}::before`]: {
  145. insetInlineEnd: 0,
  146. insetInlineStart: token.switchHandleActiveInset
  147. }
  148. }
  149. }
  150. };
  151. };
  152. const genSwitchInnerStyle = token => {
  153. const {
  154. componentCls,
  155. trackHeight,
  156. trackPadding,
  157. innerMinMargin,
  158. innerMaxMargin,
  159. handleSize,
  160. calc
  161. } = token;
  162. const switchInnerCls = `${componentCls}-inner`;
  163. const trackPaddingCalc = unit(calc(handleSize).add(calc(trackPadding).mul(2)).equal());
  164. const innerMaxMarginCalc = unit(calc(innerMaxMargin).mul(2).equal());
  165. return {
  166. [componentCls]: {
  167. [switchInnerCls]: {
  168. display: 'block',
  169. overflow: 'hidden',
  170. borderRadius: 100,
  171. height: '100%',
  172. paddingInlineStart: innerMaxMargin,
  173. paddingInlineEnd: innerMinMargin,
  174. transition: `padding-inline-start ${token.switchDuration} ease-in-out, padding-inline-end ${token.switchDuration} ease-in-out`,
  175. [`${switchInnerCls}-checked, ${switchInnerCls}-unchecked`]: {
  176. display: 'block',
  177. color: token.colorTextLightSolid,
  178. fontSize: token.fontSizeSM,
  179. transition: `margin-inline-start ${token.switchDuration} ease-in-out, margin-inline-end ${token.switchDuration} ease-in-out`,
  180. pointerEvents: 'none',
  181. minHeight: trackHeight
  182. },
  183. [`${switchInnerCls}-checked`]: {
  184. marginInlineStart: `calc(-100% + ${trackPaddingCalc} - ${innerMaxMarginCalc})`,
  185. marginInlineEnd: `calc(100% - ${trackPaddingCalc} + ${innerMaxMarginCalc})`
  186. },
  187. [`${switchInnerCls}-unchecked`]: {
  188. marginTop: calc(trackHeight).mul(-1).equal(),
  189. marginInlineStart: 0,
  190. marginInlineEnd: 0
  191. }
  192. },
  193. [`&${componentCls}-checked ${switchInnerCls}`]: {
  194. paddingInlineStart: innerMinMargin,
  195. paddingInlineEnd: innerMaxMargin,
  196. [`${switchInnerCls}-checked`]: {
  197. marginInlineStart: 0,
  198. marginInlineEnd: 0
  199. },
  200. [`${switchInnerCls}-unchecked`]: {
  201. marginInlineStart: `calc(100% - ${trackPaddingCalc} + ${innerMaxMarginCalc})`,
  202. marginInlineEnd: `calc(-100% + ${trackPaddingCalc} - ${innerMaxMarginCalc})`
  203. }
  204. },
  205. [`&:not(${componentCls}-disabled):active`]: {
  206. [`&:not(${componentCls}-checked) ${switchInnerCls}`]: {
  207. [`${switchInnerCls}-unchecked`]: {
  208. marginInlineStart: calc(trackPadding).mul(2).equal(),
  209. marginInlineEnd: calc(trackPadding).mul(-1).mul(2).equal()
  210. }
  211. },
  212. [`&${componentCls}-checked ${switchInnerCls}`]: {
  213. [`${switchInnerCls}-checked`]: {
  214. marginInlineStart: calc(trackPadding).mul(-1).mul(2).equal(),
  215. marginInlineEnd: calc(trackPadding).mul(2).equal()
  216. }
  217. }
  218. }
  219. }
  220. };
  221. };
  222. const genSwitchStyle = token => {
  223. const {
  224. componentCls,
  225. trackHeight,
  226. trackMinWidth
  227. } = token;
  228. return {
  229. [componentCls]: Object.assign(Object.assign(Object.assign(Object.assign({}, resetComponent(token)), {
  230. position: 'relative',
  231. display: 'inline-block',
  232. boxSizing: 'border-box',
  233. minWidth: trackMinWidth,
  234. height: trackHeight,
  235. lineHeight: unit(trackHeight),
  236. verticalAlign: 'middle',
  237. background: token.colorTextQuaternary,
  238. border: '0',
  239. borderRadius: 100,
  240. cursor: 'pointer',
  241. transition: `all ${token.motionDurationMid}`,
  242. userSelect: 'none',
  243. [`&:hover:not(${componentCls}-disabled)`]: {
  244. background: token.colorTextTertiary
  245. }
  246. }), genFocusStyle(token)), {
  247. [`&${componentCls}-checked`]: {
  248. background: token.switchColor,
  249. [`&:hover:not(${componentCls}-disabled)`]: {
  250. background: token.colorPrimaryHover
  251. }
  252. },
  253. [`&${componentCls}-loading, &${componentCls}-disabled`]: {
  254. cursor: 'not-allowed',
  255. opacity: token.switchDisabledOpacity,
  256. '*': {
  257. boxShadow: 'none',
  258. cursor: 'not-allowed'
  259. }
  260. },
  261. // rtl style
  262. [`&${componentCls}-rtl`]: {
  263. direction: 'rtl'
  264. }
  265. })
  266. };
  267. };
  268. // ============================== Export ==============================
  269. export const prepareComponentToken = token => {
  270. const {
  271. fontSize,
  272. lineHeight,
  273. controlHeight,
  274. colorWhite
  275. } = token;
  276. const height = fontSize * lineHeight;
  277. const heightSM = controlHeight / 2;
  278. const padding = 2; // Fixed value
  279. const handleSize = height - padding * 2;
  280. const handleSizeSM = heightSM - padding * 2;
  281. return {
  282. trackHeight: height,
  283. trackHeightSM: heightSM,
  284. trackMinWidth: handleSize * 2 + padding * 4,
  285. trackMinWidthSM: handleSizeSM * 2 + padding * 2,
  286. trackPadding: padding,
  287. // Fixed value
  288. handleBg: colorWhite,
  289. handleSize,
  290. handleSizeSM,
  291. handleShadow: `0 2px 4px 0 ${new FastColor('#00230b').setA(0.2).toRgbString()}`,
  292. innerMinMargin: handleSize / 2,
  293. innerMaxMargin: handleSize + padding + padding * 2,
  294. innerMinMarginSM: handleSizeSM / 2,
  295. innerMaxMarginSM: handleSizeSM + padding + padding * 2
  296. };
  297. };
  298. export default genStyleHooks('Switch', token => {
  299. const switchToken = mergeToken(token, {
  300. switchDuration: token.motionDurationMid,
  301. switchColor: token.colorPrimary,
  302. switchDisabledOpacity: token.opacityLoading,
  303. switchLoadingIconSize: token.calc(token.fontSizeIcon).mul(0.75).equal(),
  304. switchLoadingIconColor: `rgba(0, 0, 0, ${token.opacityLoading})`,
  305. switchHandleActiveInset: '-30%'
  306. });
  307. return [genSwitchStyle(switchToken),
  308. // inner style
  309. genSwitchInnerStyle(switchToken),
  310. // handle style
  311. genSwitchHandleStyle(switchToken),
  312. // loading style
  313. genSwitchLoadingStyle(switchToken),
  314. // small style
  315. genSwitchSmallStyle(switchToken)];
  316. }, prepareComponentToken);