index.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. import _extends from "@babel/runtime/helpers/esm/extends";
  2. import '../../_util/cssinjs';
  3. import { TinyColor } from '@ctrl/tinycolor';
  4. import { genModalMaskStyle } from '../../modal/style';
  5. import { initZoomMotion, initFadeMotion } from '../../style/motion';
  6. import { genComponentStyleHook, mergeToken } from '../../theme/internal';
  7. import { resetComponent, textEllipsis } from '../../style';
  8. export const genBoxStyle = position => ({
  9. position: position || 'absolute',
  10. inset: 0
  11. });
  12. export const genImageMaskStyle = token => {
  13. const {
  14. iconCls,
  15. motionDurationSlow,
  16. paddingXXS,
  17. marginXXS,
  18. prefixCls
  19. } = token;
  20. return {
  21. position: 'absolute',
  22. inset: 0,
  23. display: 'flex',
  24. alignItems: 'center',
  25. justifyContent: 'center',
  26. color: '#fff',
  27. background: new TinyColor('#000').setAlpha(0.5).toRgbString(),
  28. cursor: 'pointer',
  29. opacity: 0,
  30. transition: `opacity ${motionDurationSlow}`,
  31. [`.${prefixCls}-mask-info`]: _extends(_extends({}, textEllipsis), {
  32. padding: `0 ${paddingXXS}px`,
  33. [iconCls]: {
  34. marginInlineEnd: marginXXS,
  35. svg: {
  36. verticalAlign: 'baseline'
  37. }
  38. }
  39. })
  40. };
  41. };
  42. export const genPreviewOperationsStyle = token => {
  43. const {
  44. previewCls,
  45. modalMaskBg,
  46. paddingSM,
  47. previewOperationColorDisabled,
  48. motionDurationSlow
  49. } = token;
  50. const operationBg = new TinyColor(modalMaskBg).setAlpha(0.1);
  51. const operationBgHover = operationBg.clone().setAlpha(0.2);
  52. return {
  53. [`${previewCls}-operations`]: _extends(_extends({}, resetComponent(token)), {
  54. display: 'flex',
  55. flexDirection: 'row-reverse',
  56. alignItems: 'center',
  57. color: token.previewOperationColor,
  58. listStyle: 'none',
  59. background: operationBg.toRgbString(),
  60. pointerEvents: 'auto',
  61. '&-operation': {
  62. marginInlineStart: paddingSM,
  63. padding: paddingSM,
  64. cursor: 'pointer',
  65. transition: `all ${motionDurationSlow}`,
  66. userSelect: 'none',
  67. '&:hover': {
  68. background: operationBgHover.toRgbString()
  69. },
  70. '&-disabled': {
  71. color: previewOperationColorDisabled,
  72. pointerEvents: 'none'
  73. },
  74. '&:last-of-type': {
  75. marginInlineStart: 0
  76. }
  77. },
  78. '&-progress': {
  79. position: 'absolute',
  80. left: {
  81. _skip_check_: true,
  82. value: '50%'
  83. },
  84. transform: 'translateX(-50%)'
  85. },
  86. '&-icon': {
  87. fontSize: token.previewOperationSize
  88. }
  89. })
  90. };
  91. };
  92. export const genPreviewSwitchStyle = token => {
  93. const {
  94. modalMaskBg,
  95. iconCls,
  96. previewOperationColorDisabled,
  97. previewCls,
  98. zIndexPopup,
  99. motionDurationSlow
  100. } = token;
  101. const operationBg = new TinyColor(modalMaskBg).setAlpha(0.1);
  102. const operationBgHover = operationBg.clone().setAlpha(0.2);
  103. return {
  104. [`${previewCls}-switch-left, ${previewCls}-switch-right`]: {
  105. position: 'fixed',
  106. insetBlockStart: '50%',
  107. zIndex: zIndexPopup + 1,
  108. display: 'flex',
  109. alignItems: 'center',
  110. justifyContent: 'center',
  111. width: token.imagePreviewSwitchSize,
  112. height: token.imagePreviewSwitchSize,
  113. marginTop: -token.imagePreviewSwitchSize / 2,
  114. color: token.previewOperationColor,
  115. background: operationBg.toRgbString(),
  116. borderRadius: '50%',
  117. transform: `translateY(-50%)`,
  118. cursor: 'pointer',
  119. transition: `all ${motionDurationSlow}`,
  120. pointerEvents: 'auto',
  121. userSelect: 'none',
  122. '&:hover': {
  123. background: operationBgHover.toRgbString()
  124. },
  125. [`&-disabled`]: {
  126. '&, &:hover': {
  127. color: previewOperationColorDisabled,
  128. background: 'transparent',
  129. cursor: 'not-allowed',
  130. [`> ${iconCls}`]: {
  131. cursor: 'not-allowed'
  132. }
  133. }
  134. },
  135. [`> ${iconCls}`]: {
  136. fontSize: token.previewOperationSize
  137. }
  138. },
  139. [`${previewCls}-switch-left`]: {
  140. insetInlineStart: token.marginSM
  141. },
  142. [`${previewCls}-switch-right`]: {
  143. insetInlineEnd: token.marginSM
  144. }
  145. };
  146. };
  147. export const genImagePreviewStyle = token => {
  148. const {
  149. motionEaseOut,
  150. previewCls,
  151. motionDurationSlow,
  152. componentCls
  153. } = token;
  154. return [{
  155. [`${componentCls}-preview-root`]: {
  156. [previewCls]: {
  157. height: '100%',
  158. textAlign: 'center',
  159. pointerEvents: 'none'
  160. },
  161. [`${previewCls}-body`]: _extends(_extends({}, genBoxStyle()), {
  162. overflow: 'hidden'
  163. }),
  164. [`${previewCls}-img`]: {
  165. maxWidth: '100%',
  166. maxHeight: '100%',
  167. verticalAlign: 'middle',
  168. transform: 'scale3d(1, 1, 1)',
  169. cursor: 'grab',
  170. transition: `transform ${motionDurationSlow} ${motionEaseOut} 0s`,
  171. userSelect: 'none',
  172. pointerEvents: 'auto',
  173. '&-wrapper': _extends(_extends({}, genBoxStyle()), {
  174. transition: `transform ${motionDurationSlow} ${motionEaseOut} 0s`,
  175. // https://github.com/ant-design/ant-design/issues/39913
  176. // TailwindCSS will reset img default style.
  177. // Let's set back.
  178. display: 'flex',
  179. justifyContent: 'center',
  180. alignItems: 'center',
  181. '&::before': {
  182. display: 'inline-block',
  183. width: 1,
  184. height: '50%',
  185. marginInlineEnd: -1,
  186. content: '""'
  187. }
  188. })
  189. },
  190. [`${previewCls}-moving`]: {
  191. [`${previewCls}-preview-img`]: {
  192. cursor: 'grabbing',
  193. '&-wrapper': {
  194. transitionDuration: '0s'
  195. }
  196. }
  197. }
  198. }
  199. },
  200. // Override
  201. {
  202. [`${componentCls}-preview-root`]: {
  203. [`${previewCls}-wrap`]: {
  204. zIndex: token.zIndexPopup
  205. }
  206. }
  207. },
  208. // Preview operations & switch
  209. {
  210. [`${componentCls}-preview-operations-wrapper`]: {
  211. position: 'fixed',
  212. insetBlockStart: 0,
  213. insetInlineEnd: 0,
  214. zIndex: token.zIndexPopup + 1,
  215. width: '100%'
  216. },
  217. '&': [genPreviewOperationsStyle(token), genPreviewSwitchStyle(token)]
  218. }];
  219. };
  220. const genImageStyle = token => {
  221. const {
  222. componentCls
  223. } = token;
  224. return {
  225. // ============================== image ==============================
  226. [componentCls]: {
  227. position: 'relative',
  228. display: 'inline-block',
  229. [`${componentCls}-img`]: {
  230. width: '100%',
  231. height: 'auto',
  232. verticalAlign: 'middle'
  233. },
  234. [`${componentCls}-img-placeholder`]: {
  235. backgroundColor: token.colorBgContainerDisabled,
  236. backgroundImage: "url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMTQuNSAyLjVoLTEzQS41LjUgMCAwIDAgMSAzdjEwYS41LjUgMCAwIDAgLjUuNWgxM2EuNS41IDAgMCAwIC41LS41VjNhLjUuNSAwIDAgMC0uNS0uNXpNNS4yODEgNC43NWExIDEgMCAwIDEgMCAyIDEgMSAwIDAgMSAwLTJ6bTguMDMgNi44M2EuMTI3LjEyNyAwIDAgMS0uMDgxLjAzSDIuNzY5YS4xMjUuMTI1IDAgMCAxLS4wOTYtLjIwN2wyLjY2MS0zLjE1NmEuMTI2LjEyNiAwIDAgMSAuMTc3LS4wMTZsLjAxNi4wMTZMNy4wOCAxMC4wOWwyLjQ3LTIuOTNhLjEyNi4xMjYgMCAwIDEgLjE3Ny0uMDE2bC4wMTUuMDE2IDMuNTg4IDQuMjQ0YS4xMjcuMTI3IDAgMCAxLS4wMi4xNzV6IiBmaWxsPSIjOEM4QzhDIiBmaWxsLXJ1bGU9Im5vbnplcm8iLz48L3N2Zz4=')",
  237. backgroundRepeat: 'no-repeat',
  238. backgroundPosition: 'center center',
  239. backgroundSize: '30%'
  240. },
  241. [`${componentCls}-mask`]: _extends({}, genImageMaskStyle(token)),
  242. [`${componentCls}-mask:hover`]: {
  243. opacity: 1
  244. },
  245. [`${componentCls}-placeholder`]: _extends({}, genBoxStyle())
  246. }
  247. };
  248. };
  249. const genPreviewMotion = token => {
  250. const {
  251. previewCls
  252. } = token;
  253. return {
  254. [`${previewCls}-root`]: initZoomMotion(token, 'zoom'),
  255. [`&`]: initFadeMotion(token, true)
  256. };
  257. };
  258. // ============================== Export ==============================
  259. export default genComponentStyleHook('Image', token => {
  260. const previewCls = `${token.componentCls}-preview`;
  261. const imageToken = mergeToken(token, {
  262. previewCls,
  263. modalMaskBg: new TinyColor('#000').setAlpha(0.45).toRgbString(),
  264. imagePreviewSwitchSize: token.controlHeightLG
  265. });
  266. return [genImageStyle(imageToken), genImagePreviewStyle(imageToken), genModalMaskStyle(mergeToken(imageToken, {
  267. componentCls: previewCls
  268. })), genPreviewMotion(imageToken)];
  269. }, token => ({
  270. zIndexPopup: token.zIndexPopupBase + 80,
  271. previewOperationColor: new TinyColor(token.colorTextLightSolid).toRgbString(),
  272. previewOperationColorDisabled: new TinyColor(token.colorTextLightSolid).setAlpha(0.25).toRgbString(),
  273. previewOperationSize: token.fontSizeIcon * 1.5 // FIXME: fontSizeIconLG
  274. }));