index.js 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. import { Keyframes, unit } from '@ant-design/cssinjs';
  2. import { genStyleHooks, mergeToken } from '../../theme/internal';
  3. const skeletonClsLoading = new Keyframes(`ant-skeleton-loading`, {
  4. '0%': {
  5. backgroundPosition: '100% 50%'
  6. },
  7. '100%': {
  8. backgroundPosition: '0 50%'
  9. }
  10. });
  11. const genSkeletonElementCommonSize = size => ({
  12. height: size,
  13. lineHeight: unit(size)
  14. });
  15. const genSkeletonElementAvatarSize = size => Object.assign({
  16. width: size
  17. }, genSkeletonElementCommonSize(size));
  18. const genSkeletonColor = token => ({
  19. background: token.skeletonLoadingBackground,
  20. backgroundSize: '400% 100%',
  21. animationName: skeletonClsLoading,
  22. animationDuration: token.skeletonLoadingMotionDuration,
  23. animationTimingFunction: 'ease',
  24. animationIterationCount: 'infinite'
  25. });
  26. const genSkeletonElementInputSize = (size, calc) => Object.assign({
  27. width: calc(size).mul(5).equal(),
  28. minWidth: calc(size).mul(5).equal()
  29. }, genSkeletonElementCommonSize(size));
  30. const genSkeletonElementAvatar = token => {
  31. const {
  32. skeletonAvatarCls,
  33. gradientFromColor,
  34. controlHeight,
  35. controlHeightLG,
  36. controlHeightSM
  37. } = token;
  38. return {
  39. [skeletonAvatarCls]: Object.assign({
  40. display: 'inline-block',
  41. verticalAlign: 'top',
  42. background: gradientFromColor
  43. }, genSkeletonElementAvatarSize(controlHeight)),
  44. [`${skeletonAvatarCls}${skeletonAvatarCls}-circle`]: {
  45. borderRadius: '50%'
  46. },
  47. [`${skeletonAvatarCls}${skeletonAvatarCls}-lg`]: Object.assign({}, genSkeletonElementAvatarSize(controlHeightLG)),
  48. [`${skeletonAvatarCls}${skeletonAvatarCls}-sm`]: Object.assign({}, genSkeletonElementAvatarSize(controlHeightSM))
  49. };
  50. };
  51. const genSkeletonElementInput = token => {
  52. const {
  53. controlHeight,
  54. borderRadiusSM,
  55. skeletonInputCls,
  56. controlHeightLG,
  57. controlHeightSM,
  58. gradientFromColor,
  59. calc
  60. } = token;
  61. return {
  62. [skeletonInputCls]: Object.assign({
  63. display: 'inline-block',
  64. verticalAlign: 'top',
  65. background: gradientFromColor,
  66. borderRadius: borderRadiusSM
  67. }, genSkeletonElementInputSize(controlHeight, calc)),
  68. [`${skeletonInputCls}-lg`]: Object.assign({}, genSkeletonElementInputSize(controlHeightLG, calc)),
  69. [`${skeletonInputCls}-sm`]: Object.assign({}, genSkeletonElementInputSize(controlHeightSM, calc))
  70. };
  71. };
  72. const genSkeletonElementImageSize = size => Object.assign({
  73. width: size
  74. }, genSkeletonElementCommonSize(size));
  75. const genSkeletonElementImage = token => {
  76. const {
  77. skeletonImageCls,
  78. imageSizeBase,
  79. gradientFromColor,
  80. borderRadiusSM,
  81. calc
  82. } = token;
  83. return {
  84. [skeletonImageCls]: Object.assign(Object.assign({
  85. display: 'inline-flex',
  86. alignItems: 'center',
  87. justifyContent: 'center',
  88. verticalAlign: 'middle',
  89. background: gradientFromColor,
  90. borderRadius: borderRadiusSM
  91. }, genSkeletonElementImageSize(calc(imageSizeBase).mul(2).equal())), {
  92. [`${skeletonImageCls}-path`]: {
  93. fill: '#bfbfbf'
  94. },
  95. [`${skeletonImageCls}-svg`]: Object.assign(Object.assign({}, genSkeletonElementImageSize(imageSizeBase)), {
  96. maxWidth: calc(imageSizeBase).mul(4).equal(),
  97. maxHeight: calc(imageSizeBase).mul(4).equal()
  98. }),
  99. [`${skeletonImageCls}-svg${skeletonImageCls}-svg-circle`]: {
  100. borderRadius: '50%'
  101. }
  102. }),
  103. [`${skeletonImageCls}${skeletonImageCls}-circle`]: {
  104. borderRadius: '50%'
  105. }
  106. };
  107. };
  108. const genSkeletonElementButtonShape = (token, size, buttonCls) => {
  109. const {
  110. skeletonButtonCls
  111. } = token;
  112. return {
  113. [`${buttonCls}${skeletonButtonCls}-circle`]: {
  114. width: size,
  115. minWidth: size,
  116. borderRadius: '50%'
  117. },
  118. [`${buttonCls}${skeletonButtonCls}-round`]: {
  119. borderRadius: size
  120. }
  121. };
  122. };
  123. const genSkeletonElementButtonSize = (size, calc) => Object.assign({
  124. width: calc(size).mul(2).equal(),
  125. minWidth: calc(size).mul(2).equal()
  126. }, genSkeletonElementCommonSize(size));
  127. const genSkeletonElementButton = token => {
  128. const {
  129. borderRadiusSM,
  130. skeletonButtonCls,
  131. controlHeight,
  132. controlHeightLG,
  133. controlHeightSM,
  134. gradientFromColor,
  135. calc
  136. } = token;
  137. return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({
  138. [skeletonButtonCls]: Object.assign({
  139. display: 'inline-block',
  140. verticalAlign: 'top',
  141. background: gradientFromColor,
  142. borderRadius: borderRadiusSM,
  143. width: calc(controlHeight).mul(2).equal(),
  144. minWidth: calc(controlHeight).mul(2).equal()
  145. }, genSkeletonElementButtonSize(controlHeight, calc))
  146. }, genSkeletonElementButtonShape(token, controlHeight, skeletonButtonCls)), {
  147. [`${skeletonButtonCls}-lg`]: Object.assign({}, genSkeletonElementButtonSize(controlHeightLG, calc))
  148. }), genSkeletonElementButtonShape(token, controlHeightLG, `${skeletonButtonCls}-lg`)), {
  149. [`${skeletonButtonCls}-sm`]: Object.assign({}, genSkeletonElementButtonSize(controlHeightSM, calc))
  150. }), genSkeletonElementButtonShape(token, controlHeightSM, `${skeletonButtonCls}-sm`));
  151. };
  152. // =============================== Base ===============================
  153. const genBaseStyle = token => {
  154. const {
  155. componentCls,
  156. skeletonAvatarCls,
  157. skeletonTitleCls,
  158. skeletonParagraphCls,
  159. skeletonButtonCls,
  160. skeletonInputCls,
  161. skeletonImageCls,
  162. controlHeight,
  163. controlHeightLG,
  164. controlHeightSM,
  165. gradientFromColor,
  166. padding,
  167. marginSM,
  168. borderRadius,
  169. titleHeight,
  170. blockRadius,
  171. paragraphLiHeight,
  172. controlHeightXS,
  173. paragraphMarginTop
  174. } = token;
  175. return {
  176. [componentCls]: {
  177. display: 'table',
  178. width: '100%',
  179. [`${componentCls}-header`]: {
  180. display: 'table-cell',
  181. paddingInlineEnd: padding,
  182. verticalAlign: 'top',
  183. // Avatar
  184. [skeletonAvatarCls]: Object.assign({
  185. display: 'inline-block',
  186. verticalAlign: 'top',
  187. background: gradientFromColor
  188. }, genSkeletonElementAvatarSize(controlHeight)),
  189. [`${skeletonAvatarCls}-circle`]: {
  190. borderRadius: '50%'
  191. },
  192. [`${skeletonAvatarCls}-lg`]: Object.assign({}, genSkeletonElementAvatarSize(controlHeightLG)),
  193. [`${skeletonAvatarCls}-sm`]: Object.assign({}, genSkeletonElementAvatarSize(controlHeightSM))
  194. },
  195. [`${componentCls}-content`]: {
  196. display: 'table-cell',
  197. width: '100%',
  198. verticalAlign: 'top',
  199. // Title
  200. [skeletonTitleCls]: {
  201. width: '100%',
  202. height: titleHeight,
  203. background: gradientFromColor,
  204. borderRadius: blockRadius,
  205. [`+ ${skeletonParagraphCls}`]: {
  206. marginBlockStart: controlHeightSM
  207. }
  208. },
  209. // paragraph
  210. [skeletonParagraphCls]: {
  211. padding: 0,
  212. '> li': {
  213. width: '100%',
  214. height: paragraphLiHeight,
  215. listStyle: 'none',
  216. background: gradientFromColor,
  217. borderRadius: blockRadius,
  218. '+ li': {
  219. marginBlockStart: controlHeightXS
  220. }
  221. }
  222. },
  223. [`${skeletonParagraphCls}> li:last-child:not(:first-child):not(:nth-child(2))`]: {
  224. width: '61%'
  225. }
  226. },
  227. [`&-round ${componentCls}-content`]: {
  228. [`${skeletonTitleCls}, ${skeletonParagraphCls} > li`]: {
  229. borderRadius
  230. }
  231. }
  232. },
  233. [`${componentCls}-with-avatar ${componentCls}-content`]: {
  234. // Title
  235. [skeletonTitleCls]: {
  236. marginBlockStart: marginSM,
  237. [`+ ${skeletonParagraphCls}`]: {
  238. marginBlockStart: paragraphMarginTop
  239. }
  240. }
  241. },
  242. // Skeleton element
  243. [`${componentCls}${componentCls}-element`]: Object.assign(Object.assign(Object.assign(Object.assign({
  244. display: 'inline-block',
  245. width: 'auto'
  246. }, genSkeletonElementButton(token)), genSkeletonElementAvatar(token)), genSkeletonElementInput(token)), genSkeletonElementImage(token)),
  247. // Skeleton Block Button, Input
  248. [`${componentCls}${componentCls}-block`]: {
  249. width: '100%',
  250. [skeletonButtonCls]: {
  251. width: '100%'
  252. },
  253. [skeletonInputCls]: {
  254. width: '100%'
  255. }
  256. },
  257. // With active animation
  258. [`${componentCls}${componentCls}-active`]: {
  259. [`
  260. ${skeletonTitleCls},
  261. ${skeletonParagraphCls} > li,
  262. ${skeletonAvatarCls},
  263. ${skeletonButtonCls},
  264. ${skeletonInputCls},
  265. ${skeletonImageCls}
  266. `]: Object.assign({}, genSkeletonColor(token))
  267. }
  268. };
  269. };
  270. // ============================== Export ==============================
  271. export const prepareComponentToken = token => {
  272. const {
  273. colorFillContent,
  274. colorFill
  275. } = token;
  276. const gradientFromColor = colorFillContent;
  277. const gradientToColor = colorFill;
  278. return {
  279. color: gradientFromColor,
  280. colorGradientEnd: gradientToColor,
  281. gradientFromColor,
  282. gradientToColor,
  283. titleHeight: token.controlHeight / 2,
  284. blockRadius: token.borderRadiusSM,
  285. paragraphMarginTop: token.marginLG + token.marginXXS,
  286. paragraphLiHeight: token.controlHeight / 2
  287. };
  288. };
  289. export default genStyleHooks('Skeleton', token => {
  290. const {
  291. componentCls,
  292. calc
  293. } = token;
  294. const skeletonToken = mergeToken(token, {
  295. skeletonAvatarCls: `${componentCls}-avatar`,
  296. skeletonTitleCls: `${componentCls}-title`,
  297. skeletonParagraphCls: `${componentCls}-paragraph`,
  298. skeletonButtonCls: `${componentCls}-button`,
  299. skeletonInputCls: `${componentCls}-input`,
  300. skeletonImageCls: `${componentCls}-image`,
  301. imageSizeBase: calc(token.controlHeight).mul(1.5).equal(),
  302. borderRadius: 100,
  303. // Large number to make capsule shape
  304. skeletonLoadingBackground: `linear-gradient(90deg, ${token.gradientFromColor} 25%, ${token.gradientToColor} 37%, ${token.gradientFromColor} 63%)`,
  305. skeletonLoadingMotionDuration: '1.4s'
  306. });
  307. return genBaseStyle(skeletonToken);
  308. }, prepareComponentToken, {
  309. deprecatedTokens: [['color', 'gradientFromColor'], ['colorGradientEnd', 'gradientToColor']]
  310. });