index.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. import _extends from "@babel/runtime/helpers/esm/extends";
  2. import { genCollapseMotion, zoomIn } from '../../style/motion';
  3. import { genComponentStyleHook, mergeToken } from '../../theme/internal';
  4. import { resetComponent } from '../../style';
  5. import genFormValidateMotionStyle from './explain';
  6. const resetForm = token => ({
  7. legend: {
  8. display: 'block',
  9. width: '100%',
  10. marginBottom: token.marginLG,
  11. padding: 0,
  12. color: token.colorTextDescription,
  13. fontSize: token.fontSizeLG,
  14. lineHeight: 'inherit',
  15. border: 0,
  16. borderBottom: `${token.lineWidth}px ${token.lineType} ${token.colorBorder}`
  17. },
  18. label: {
  19. fontSize: token.fontSize
  20. },
  21. 'input[type="search"]': {
  22. boxSizing: 'border-box'
  23. },
  24. // Position radios and checkboxes better
  25. 'input[type="radio"], input[type="checkbox"]': {
  26. lineHeight: 'normal'
  27. },
  28. 'input[type="file"]': {
  29. display: 'block'
  30. },
  31. // Make range inputs behave like textual form controls
  32. 'input[type="range"]': {
  33. display: 'block',
  34. width: '100%'
  35. },
  36. // Make multiple select elements height not fixed
  37. 'select[multiple], select[size]': {
  38. height: 'auto'
  39. },
  40. // Focus for file, radio, and checkbox
  41. [`input[type='file']:focus,
  42. input[type='radio']:focus,
  43. input[type='checkbox']:focus`]: {
  44. outline: 0,
  45. boxShadow: `0 0 0 ${token.controlOutlineWidth}px ${token.controlOutline}`
  46. },
  47. // Adjust output element
  48. output: {
  49. display: 'block',
  50. paddingTop: 15,
  51. color: token.colorText,
  52. fontSize: token.fontSize,
  53. lineHeight: token.lineHeight
  54. }
  55. });
  56. const genFormSize = (token, height) => {
  57. const {
  58. formItemCls
  59. } = token;
  60. return {
  61. [formItemCls]: {
  62. [`${formItemCls}-label > label`]: {
  63. height
  64. },
  65. [`${formItemCls}-control-input`]: {
  66. minHeight: height
  67. }
  68. }
  69. };
  70. };
  71. const genFormStyle = token => {
  72. const {
  73. componentCls
  74. } = token;
  75. return {
  76. [token.componentCls]: _extends(_extends(_extends({}, resetComponent(token)), resetForm(token)), {
  77. [`${componentCls}-text`]: {
  78. display: 'inline-block',
  79. paddingInlineEnd: token.paddingSM
  80. },
  81. // ================================================================
  82. // = Size =
  83. // ================================================================
  84. '&-small': _extends({}, genFormSize(token, token.controlHeightSM)),
  85. '&-large': _extends({}, genFormSize(token, token.controlHeightLG))
  86. })
  87. };
  88. };
  89. const genFormItemStyle = token => {
  90. const {
  91. formItemCls,
  92. iconCls,
  93. componentCls,
  94. rootPrefixCls
  95. } = token;
  96. return {
  97. [formItemCls]: _extends(_extends({}, resetComponent(token)), {
  98. marginBottom: token.marginLG,
  99. verticalAlign: 'top',
  100. '&-with-help': {
  101. transition: 'none'
  102. },
  103. [`&-hidden,
  104. &-hidden.${rootPrefixCls}-row`]: {
  105. // https://github.com/ant-design/ant-design/issues/26141
  106. display: 'none'
  107. },
  108. '&-has-warning': {
  109. [`${formItemCls}-split`]: {
  110. color: token.colorError
  111. }
  112. },
  113. '&-has-error': {
  114. [`${formItemCls}-split`]: {
  115. color: token.colorWarning
  116. }
  117. },
  118. // ==============================================================
  119. // = Label =
  120. // ==============================================================
  121. [`${formItemCls}-label`]: {
  122. display: 'inline-block',
  123. flexGrow: 0,
  124. overflow: 'hidden',
  125. whiteSpace: 'nowrap',
  126. textAlign: 'end',
  127. verticalAlign: 'middle',
  128. '&-left': {
  129. textAlign: 'start'
  130. },
  131. '&-wrap': {
  132. overflow: 'unset',
  133. lineHeight: `${token.lineHeight} - 0.25em`,
  134. whiteSpace: 'unset'
  135. },
  136. '> label': {
  137. position: 'relative',
  138. display: 'inline-flex',
  139. alignItems: 'center',
  140. maxWidth: '100%',
  141. height: token.controlHeight,
  142. color: token.colorTextHeading,
  143. fontSize: token.fontSize,
  144. [`> ${iconCls}`]: {
  145. fontSize: token.fontSize,
  146. verticalAlign: 'top'
  147. },
  148. // Required mark
  149. [`&${formItemCls}-required:not(${formItemCls}-required-mark-optional)::before`]: {
  150. display: 'inline-block',
  151. marginInlineEnd: token.marginXXS,
  152. color: token.colorError,
  153. fontSize: token.fontSize,
  154. fontFamily: 'SimSun, sans-serif',
  155. lineHeight: 1,
  156. content: '"*"',
  157. [`${componentCls}-hide-required-mark &`]: {
  158. display: 'none'
  159. }
  160. },
  161. // Optional mark
  162. [`${formItemCls}-optional`]: {
  163. display: 'inline-block',
  164. marginInlineStart: token.marginXXS,
  165. color: token.colorTextDescription,
  166. [`${componentCls}-hide-required-mark &`]: {
  167. display: 'none'
  168. }
  169. },
  170. // Optional mark
  171. [`${formItemCls}-tooltip`]: {
  172. color: token.colorTextDescription,
  173. cursor: 'help',
  174. writingMode: 'horizontal-tb',
  175. marginInlineStart: token.marginXXS
  176. },
  177. '&::after': {
  178. content: '":"',
  179. position: 'relative',
  180. marginBlock: 0,
  181. marginInlineStart: token.marginXXS / 2,
  182. marginInlineEnd: token.marginXS
  183. },
  184. [`&${formItemCls}-no-colon::after`]: {
  185. content: '" "'
  186. }
  187. }
  188. },
  189. // ==============================================================
  190. // = Input =
  191. // ==============================================================
  192. [`${formItemCls}-control`]: {
  193. display: 'flex',
  194. flexDirection: 'column',
  195. flexGrow: 1,
  196. [`&:first-child:not([class^="'${rootPrefixCls}-col-'"]):not([class*="' ${rootPrefixCls}-col-'"])`]: {
  197. width: '100%'
  198. },
  199. '&-input': {
  200. position: 'relative',
  201. display: 'flex',
  202. alignItems: 'center',
  203. minHeight: token.controlHeight,
  204. '&-content': {
  205. flex: 'auto',
  206. maxWidth: '100%'
  207. }
  208. }
  209. },
  210. // ==============================================================
  211. // = Explain =
  212. // ==============================================================
  213. [formItemCls]: {
  214. '&-explain, &-extra': {
  215. clear: 'both',
  216. color: token.colorTextDescription,
  217. fontSize: token.fontSize,
  218. lineHeight: token.lineHeight
  219. },
  220. '&-explain-connected': {
  221. width: '100%'
  222. },
  223. '&-extra': {
  224. minHeight: token.controlHeightSM,
  225. transition: `color ${token.motionDurationMid} ${token.motionEaseOut}` // sync input color transition
  226. },
  227. '&-explain': {
  228. '&-error': {
  229. color: token.colorError
  230. },
  231. '&-warning': {
  232. color: token.colorWarning
  233. }
  234. }
  235. },
  236. [`&-with-help ${formItemCls}-explain`]: {
  237. height: 'auto',
  238. opacity: 1
  239. },
  240. // ==============================================================
  241. // = Feedback Icon =
  242. // ==============================================================
  243. [`${formItemCls}-feedback-icon`]: {
  244. fontSize: token.fontSize,
  245. textAlign: 'center',
  246. visibility: 'visible',
  247. animationName: zoomIn,
  248. animationDuration: token.motionDurationMid,
  249. animationTimingFunction: token.motionEaseOutBack,
  250. pointerEvents: 'none',
  251. '&-success': {
  252. color: token.colorSuccess
  253. },
  254. '&-error': {
  255. color: token.colorError
  256. },
  257. '&-warning': {
  258. color: token.colorWarning
  259. },
  260. '&-validating': {
  261. color: token.colorPrimary
  262. }
  263. }
  264. })
  265. };
  266. };
  267. const genHorizontalStyle = token => {
  268. const {
  269. componentCls,
  270. formItemCls,
  271. rootPrefixCls
  272. } = token;
  273. return {
  274. [`${componentCls}-horizontal`]: {
  275. [`${formItemCls}-label`]: {
  276. flexGrow: 0
  277. },
  278. [`${formItemCls}-control`]: {
  279. flex: '1 1 0',
  280. // https://github.com/ant-design/ant-design/issues/32777
  281. // https://github.com/ant-design/ant-design/issues/33773
  282. minWidth: 0
  283. },
  284. // https://github.com/ant-design/ant-design/issues/32980
  285. [`${formItemCls}-label.${rootPrefixCls}-col-24 + ${formItemCls}-control`]: {
  286. minWidth: 'unset'
  287. }
  288. }
  289. };
  290. };
  291. const genInlineStyle = token => {
  292. const {
  293. componentCls,
  294. formItemCls
  295. } = token;
  296. return {
  297. [`${componentCls}-inline`]: {
  298. display: 'flex',
  299. flexWrap: 'wrap',
  300. [formItemCls]: {
  301. flex: 'none',
  302. flexWrap: 'nowrap',
  303. marginInlineEnd: token.margin,
  304. marginBottom: 0,
  305. '&-with-help': {
  306. marginBottom: token.marginLG
  307. },
  308. [`> ${formItemCls}-label,
  309. > ${formItemCls}-control`]: {
  310. display: 'inline-block',
  311. verticalAlign: 'top'
  312. },
  313. [`> ${formItemCls}-label`]: {
  314. flex: 'none'
  315. },
  316. [`${componentCls}-text`]: {
  317. display: 'inline-block'
  318. },
  319. [`${formItemCls}-has-feedback`]: {
  320. display: 'inline-block'
  321. }
  322. }
  323. }
  324. };
  325. };
  326. const makeVerticalLayoutLabel = token => ({
  327. margin: 0,
  328. padding: `0 0 ${token.paddingXS}px`,
  329. whiteSpace: 'initial',
  330. textAlign: 'start',
  331. '> label': {
  332. margin: 0,
  333. '&::after': {
  334. display: 'none'
  335. }
  336. }
  337. });
  338. const makeVerticalLayout = token => {
  339. const {
  340. componentCls,
  341. formItemCls
  342. } = token;
  343. return {
  344. [`${formItemCls} ${formItemCls}-label`]: makeVerticalLayoutLabel(token),
  345. [componentCls]: {
  346. [formItemCls]: {
  347. flexWrap: 'wrap',
  348. [`${formItemCls}-label,
  349. ${formItemCls}-control`]: {
  350. flex: '0 0 100%',
  351. maxWidth: '100%'
  352. }
  353. }
  354. }
  355. };
  356. };
  357. const genVerticalStyle = token => {
  358. const {
  359. componentCls,
  360. formItemCls,
  361. rootPrefixCls
  362. } = token;
  363. return {
  364. [`${componentCls}-vertical`]: {
  365. [formItemCls]: {
  366. '&-row': {
  367. flexDirection: 'column'
  368. },
  369. '&-label > label': {
  370. height: 'auto'
  371. },
  372. [`${componentCls}-item-control`]: {
  373. width: '100%'
  374. }
  375. }
  376. },
  377. [`${componentCls}-vertical ${formItemCls}-label,
  378. .${rootPrefixCls}-col-24${formItemCls}-label,
  379. .${rootPrefixCls}-col-xl-24${formItemCls}-label`]: makeVerticalLayoutLabel(token),
  380. [`@media (max-width: ${token.screenXSMax}px)`]: [makeVerticalLayout(token), {
  381. [componentCls]: {
  382. [`.${rootPrefixCls}-col-xs-24${formItemCls}-label`]: makeVerticalLayoutLabel(token)
  383. }
  384. }],
  385. [`@media (max-width: ${token.screenSMMax}px)`]: {
  386. [componentCls]: {
  387. [`.${rootPrefixCls}-col-sm-24${formItemCls}-label`]: makeVerticalLayoutLabel(token)
  388. }
  389. },
  390. [`@media (max-width: ${token.screenMDMax}px)`]: {
  391. [componentCls]: {
  392. [`.${rootPrefixCls}-col-md-24${formItemCls}-label`]: makeVerticalLayoutLabel(token)
  393. }
  394. },
  395. [`@media (max-width: ${token.screenLGMax}px)`]: {
  396. [componentCls]: {
  397. [`.${rootPrefixCls}-col-lg-24${formItemCls}-label`]: makeVerticalLayoutLabel(token)
  398. }
  399. }
  400. };
  401. };
  402. // ============================== Export ==============================
  403. export default genComponentStyleHook('Form', (token, _ref) => {
  404. let {
  405. rootPrefixCls
  406. } = _ref;
  407. const formToken = mergeToken(token, {
  408. formItemCls: `${token.componentCls}-item`,
  409. rootPrefixCls
  410. });
  411. return [genFormStyle(formToken), genFormItemStyle(formToken), genFormValidateMotionStyle(formToken), genHorizontalStyle(formToken), genInlineStyle(formToken), genVerticalStyle(formToken), genCollapseMotion(formToken), zoomIn];
  412. });