From 5ebac5f9d689c834aec092d794cf5dc5773a463d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Fri, 3 Jan 2020 13:38:16 +0800 Subject: [PATCH] feat: Form & ConfigProvider support component size (#20570) * feat: Support form & ConfigProvider set component size * update snapshot * fix lint * rm only * update doc * Table & Card support sizing * Update snapshot * fix lint * update snapshot * flush rest snapshot --- components/button/button-group.tsx | 4 +- components/button/button.tsx | 181 +++--- components/button/index.tsx | 3 +- components/calendar/Header.tsx | 6 +- .../__tests__/__snapshots__/demo.test.js.snap | 6 +- .../__snapshots__/index.test.js.snap | 4 +- components/card/index.tsx | 45 +- components/cascader/index.tsx | 337 +++++------ components/config-provider/SizeContext.tsx | 19 + .../__snapshots__/components.test.js.snap | 12 +- components/config-provider/demo/size.md | 89 +++ components/config-provider/index.en-US.md | 1 + components/config-provider/index.tsx | 15 +- components/config-provider/index.zh-CN.md | 1 + components/date-picker/generatePicker.tsx | 66 ++- components/form/Form.tsx | 29 +- .../__tests__/__snapshots__/demo.test.js.snap | 556 ++++++++++++++++++ components/form/demo/size.md | 99 ++++ components/form/index.en-US.md | 1 + components/form/index.zh-CN.md | 1 + components/input-number/index.tsx | 43 +- components/input/ClearableLabeledInput.tsx | 5 +- components/input/Input.tsx | 46 +- components/radio/group.tsx | 54 +- components/radio/interface.tsx | 3 +- components/select/index.tsx | 59 +- components/switch/index.tsx | 46 +- components/table/Table.tsx | 14 +- components/table/interface.tsx | 2 - components/tree-select/index.tsx | 85 +-- 30 files changed, 1355 insertions(+), 477 deletions(-) create mode 100644 components/config-provider/SizeContext.tsx create mode 100644 components/config-provider/demo/size.md create mode 100644 components/form/demo/size.md diff --git a/components/button/button-group.tsx b/components/button/button-group.tsx index a4285a3d24..0549a6f899 100644 --- a/components/button/button-group.tsx +++ b/components/button/button-group.tsx @@ -1,10 +1,10 @@ import * as React from 'react'; import classNames from 'classnames'; -import { ButtonSize } from './button'; +import { SizeType } from '../config-provider/SizeContext'; import { ConfigConsumer, ConfigConsumerProps } from '../config-provider'; export interface ButtonGroupProps { - size?: ButtonSize; + size?: SizeType; style?: React.CSSProperties; className?: string; prefixCls?: string; diff --git a/components/button/button.tsx b/components/button/button.tsx index 149acf37b0..798ea4ba8a 100644 --- a/components/button/button.tsx +++ b/components/button/button.tsx @@ -9,6 +9,7 @@ import { ConfigConsumer, ConfigConsumerProps } from '../config-provider'; import Wave from '../_util/wave'; import { Omit, tuple } from '../_util/type'; import warning from '../_util/warning'; +import SizeContext, { SizeType } from '../config-provider/SizeContext'; const rxTwoCNChar = /^[\u4e00-\u9fa5]{2}$/; const isTwoCNChar = rxTwoCNChar.test.bind(rxTwoCNChar); @@ -68,8 +69,6 @@ const ButtonTypes = tuple('default', 'primary', 'ghost', 'dashed', 'danger', 'li export type ButtonType = typeof ButtonTypes[number]; const ButtonShapes = tuple('circle', 'circle-outline', 'round'); export type ButtonShape = typeof ButtonShapes[number]; -const ButtonSizes = tuple('large', 'default', 'small'); -export type ButtonSize = typeof ButtonSizes[number]; const ButtonHTMLTypes = tuple('submit', 'button', 'reset'); export type ButtonHTMLType = typeof ButtonHTMLTypes[number]; @@ -77,7 +76,7 @@ export interface BaseButtonProps { type?: ButtonType; icon?: React.ReactNode; shape?: ButtonShape; - size?: ButtonSize; + size?: SizeType; loading?: boolean | { delay?: number }; prefixCls?: string; className?: string; @@ -201,103 +200,107 @@ class Button extends React.Component { return React.Children.count(children) === 1 && !icon && type !== 'link'; } - renderButton = ({ getPrefixCls, autoInsertSpaceInButton, direction }: ConfigConsumerProps) => { - const { - prefixCls: customizePrefixCls, - type, - danger, - shape, - size, - className, - children, - icon, - ghost, - block, - ...rest - } = this.props; - const { loading, hasTwoCNChar } = this.state; + renderButton = ({ getPrefixCls, autoInsertSpaceInButton, direction }: ConfigConsumerProps) => ( + + {size => { + const { + prefixCls: customizePrefixCls, + type, + danger, + shape, + size: customizeSize, + className, + children, + icon, + ghost, + block, + ...rest + } = this.props; + const { loading, hasTwoCNChar } = this.state; - warning( - !(typeof icon === 'string' && icon.length > 2), - 'Button', - `\`icon\` is using ReactNode instead of string naming in v4. Please check \`${icon}\` at https://ant.design/components/icon`, - ); + warning( + !(typeof icon === 'string' && icon.length > 2), + 'Button', + `\`icon\` is using ReactNode instead of string naming in v4. Please check \`${icon}\` at https://ant.design/components/icon`, + ); - const prefixCls = getPrefixCls('btn', customizePrefixCls); - const autoInsertSpace = autoInsertSpaceInButton !== false; + const prefixCls = getPrefixCls('btn', customizePrefixCls); + const autoInsertSpace = autoInsertSpaceInButton !== false; - // large => lg - // small => sm - let sizeCls = ''; - switch (size) { - case 'large': - sizeCls = 'lg'; - break; - case 'small': - sizeCls = 'sm'; - break; - default: - break; - } + // large => lg + // small => sm + let sizeCls = ''; + switch (customizeSize || size) { + case 'large': + sizeCls = 'lg'; + break; + case 'small': + sizeCls = 'sm'; + break; + default: + break; + } - const iconType = loading ? 'loading' : icon; + const iconType = loading ? 'loading' : icon; - const classes = classNames(prefixCls, className, { - [`${prefixCls}-${type}`]: type, - [`${prefixCls}-${shape}`]: shape, - [`${prefixCls}-${sizeCls}`]: sizeCls, - [`${prefixCls}-icon-only`]: !children && children !== 0 && iconType, - [`${prefixCls}-loading`]: !!loading, - [`${prefixCls}-background-ghost`]: ghost, - [`${prefixCls}-two-chinese-chars`]: hasTwoCNChar && autoInsertSpace, - [`${prefixCls}-block`]: block, - [`${prefixCls}-dangerous`]: !!danger, - [`${prefixCls}-rtl`]: direction === 'rtl', - }); + const classes = classNames(prefixCls, className, { + [`${prefixCls}-${type}`]: type, + [`${prefixCls}-${shape}`]: shape, + [`${prefixCls}-${sizeCls}`]: sizeCls, + [`${prefixCls}-icon-only`]: !children && children !== 0 && iconType, + [`${prefixCls}-loading`]: !!loading, + [`${prefixCls}-background-ghost`]: ghost, + [`${prefixCls}-two-chinese-chars`]: hasTwoCNChar && autoInsertSpace, + [`${prefixCls}-block`]: block, + [`${prefixCls}-dangerous`]: !!danger, + [`${prefixCls}-rtl`]: direction === 'rtl', + }); - const iconNode = loading ? : icon || null; - const kids = - children || children === 0 - ? spaceChildren(children, this.isNeedInserted() && autoInsertSpace) - : null; + const iconNode = loading ? : icon || null; + const kids = + children || children === 0 + ? spaceChildren(children, this.isNeedInserted() && autoInsertSpace) + : null; - const linkButtonRestProps = omit(rest as AnchorButtonProps, ['htmlType', 'loading']); - if (linkButtonRestProps.href !== undefined) { - return ( - - {iconNode} - {kids} - - ); - } + const linkButtonRestProps = omit(rest as AnchorButtonProps, ['htmlType', 'loading']); + if (linkButtonRestProps.href !== undefined) { + return ( + + {iconNode} + {kids} + + ); + } - // React does not recognize the `htmlType` prop on a DOM element. Here we pick it out of `rest`. - const { htmlType, ...otherProps } = rest as NativeButtonProps; + // React does not recognize the `htmlType` prop on a DOM element. Here we pick it out of `rest`. + const { htmlType, ...otherProps } = rest as NativeButtonProps; - const buttonNode = ( - - ); + const buttonNode = ( + + ); - if (type === 'link') { - return buttonNode; - } + if (type === 'link') { + return buttonNode; + } - return {buttonNode}; - }; + return {buttonNode}; + }} + + ); render() { return {this.renderButton}; diff --git a/components/button/index.tsx b/components/button/index.tsx index f5e9fed97f..1f3b6d5996 100644 --- a/components/button/index.tsx +++ b/components/button/index.tsx @@ -1,8 +1,9 @@ import Button from './button'; import ButtonGroup from './button-group'; -export { ButtonProps, ButtonShape, ButtonSize, ButtonType } from './button'; +export { ButtonProps, ButtonShape, ButtonType } from './button'; export { ButtonGroupProps } from './button-group'; +export { SizeType as ButtonSize } from '../config-provider/SizeContext'; Button.Group = ButtonGroup; export default Button; diff --git a/components/calendar/Header.tsx b/components/calendar/Header.tsx index ecfc0ca828..49c78b0f63 100644 --- a/components/calendar/Header.tsx +++ b/components/calendar/Header.tsx @@ -49,7 +49,7 @@ function YearSelect(props: SharedProps) { return ( (props: ModeSwitchProps) { onModeChange(value); }} value={mode} - size={fullscreen ? 'default' : 'small'} + size={fullscreen ? undefined : 'small'} className={`${prefixCls}-mode-switch`} > diff --git a/components/calendar/__tests__/__snapshots__/demo.test.js.snap b/components/calendar/__tests__/__snapshots__/demo.test.js.snap index 7601b08d80..2f918e72cc 100644 --- a/components/calendar/__tests__/__snapshots__/demo.test.js.snap +++ b/components/calendar/__tests__/__snapshots__/demo.test.js.snap @@ -122,7 +122,7 @@ exports[`renders ./components/calendar/demo/basic.md correctly 1`] = `
+ +
+
+ +
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+ +
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+ +
+
+
+ + + + + + + +
+
+
+
+
+ +
+
+
+
+
+ + + + + + +
+
+
+
+
+
+
+ +
+
+
+
+
+ + + + + + + + + + +
+
+ +
+
+
+
+
+
+
+ +
+
+
+ +
+
+
+
+
+ +
+
+
+ +
+
+
+ + +`; + exports[`renders ./components/form/demo/time-related-controls.md correctly 1`] = `
{ + const [componentSize, setComponentSize] = React.useState('small'); + const onFormLayoutChange = ({ size }) => { + setComponentSize(size); + }; + return ( +
+ + + + Small + Middle + Large + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ ); +}; +ReactDOM.render(, mountNode); +``` diff --git a/components/form/index.en-US.md b/components/form/index.en-US.md index e6981b353f..6d47d1372e 100644 --- a/components/form/index.en-US.md +++ b/components/form/index.en-US.md @@ -28,6 +28,7 @@ High performance Form component with data scope management. Including data colle | labelCol | label layout, like `` component. Set `span` `offset` value like `{span: 3, offset: 12}` or `sm: {span: 3, offset: 12}` | [object](https://ant.design/components/grid/#Col) | - | | layout | Form layout | 'horizontal'\|'vertical'\|'inline' | 'horizontal' | | name | Form name. Will be the prefix of Field `id` | string | - | +| size | Set field component size (antd components only) | `small | middle | large` | - | | validateMessages | 验证提示模板,说明[见下](#validateMessages) | [ValidateMessages](https://github.com/react-component/field-form/blob/master/src/utils/messages.ts) | - | | wrapperCol | The layout for input controls, same as `labelCol` | [object](https://ant.design/components/grid/#Col) | - | | onFinish | Trigger after submitting the form and verifying data successfully | Function(values) | - | diff --git a/components/form/index.zh-CN.md b/components/form/index.zh-CN.md index b953ad86b5..378fea19f2 100644 --- a/components/form/index.zh-CN.md +++ b/components/form/index.zh-CN.md @@ -29,6 +29,7 @@ title: Form | labelCol | label 标签布局,同 `` 组件,设置 `span` `offset` 值,如 `{span: 3, offset: 12}` 或 `sm: {span: 3, offset: 12}` | [object](https://ant.design/components/grid/#Col) | - | | layout | 表单布局 | 'horizontal'\|'vertical'\|'inline' | 'horizontal' | | name | 表单名称,会作为表单字段 `id` 前缀使用 | string | - | +| size | 设置字段组件的尺寸(仅限 antd 组件) | `small | middle | large` | - | | validateMessages | 验证提示模板,说明[见下](#validateMessages) | [ValidateMessages](https://github.com/react-component/field-form/blob/master/src/utils/messages.ts) | - | | wrapperCol | 需要为输入控件设置布局样式时,使用该属性,用法同 labelCol | [object](https://ant.design/components/grid/#Col) | - | | onFinish | 提交表单且数据验证成功后回调事件 | Function(values) | - | diff --git a/components/input-number/index.tsx b/components/input-number/index.tsx index b96db6e04a..1683b700e8 100644 --- a/components/input-number/index.tsx +++ b/components/input-number/index.tsx @@ -5,6 +5,7 @@ import { UpOutlined, DownOutlined } from '@ant-design/icons'; import { ConfigConsumer, ConfigConsumerProps } from '../config-provider'; import { Omit } from '../_util/type'; +import SizeContext, { SizeType } from '../config-provider/SizeContext'; // omitting this attrs because they conflicts with the ones defined in InputNumberProps export type OmitAttrs = 'defaultValue' | 'onChange' | 'size'; @@ -20,7 +21,7 @@ export interface InputNumberProps tabIndex?: number; onChange?: (value: number | undefined) => void; disabled?: boolean; - size?: 'large' | 'small' | 'default'; + size?: SizeType; formatter?: (value: number | string | undefined) => string; parser?: (displayValue: string | undefined) => number | string; decimalSeparator?: string; @@ -53,27 +54,35 @@ export default class InputNumber extends React.Component } renderInputNumber = ({ getPrefixCls }: ConfigConsumerProps) => { - const { className, size, prefixCls: customizePrefixCls, ...others } = this.props; + const { className, size: customizeSize, prefixCls: customizePrefixCls, ...others } = this.props; const prefixCls = getPrefixCls('input-number', customizePrefixCls); - const inputNumberClass = classNames( - { - [`${prefixCls}-lg`]: size === 'large', - [`${prefixCls}-sm`]: size === 'small', - }, - className, - ); const upIcon = ; const downIcon = ; return ( - + + {size => { + const mergeSize = customizeSize || size; + const inputNumberClass = classNames( + { + [`${prefixCls}-lg`]: mergeSize === 'large', + [`${prefixCls}-sm`]: mergeSize === 'small', + }, + className, + ); + + return ( + + ); + }} + ); }; diff --git a/components/input/ClearableLabeledInput.tsx b/components/input/ClearableLabeledInput.tsx index 667df70740..3b082d62d8 100644 --- a/components/input/ClearableLabeledInput.tsx +++ b/components/input/ClearableLabeledInput.tsx @@ -2,7 +2,8 @@ import * as React from 'react'; import classNames from 'classnames'; import { CloseCircleFilled } from '@ant-design/icons'; import { tuple } from '../_util/type'; -import { InputProps, InputSizes, getInputClassName } from './Input'; +import { InputProps, getInputClassName } from './Input'; +import { SizeType } from '../config-provider/SizeContext'; const ClearableInputType = tuple('text', 'input'); @@ -31,7 +32,7 @@ interface BasicProps { * This props only for input. */ interface ClearableInputProps extends BasicProps { - size?: typeof InputSizes[number]; + size?: SizeType; suffix?: React.ReactNode; prefix?: React.ReactNode; addonBefore?: React.ReactNode; diff --git a/components/input/Input.tsx b/components/input/Input.tsx index 6e479496fc..b3fbc71662 100644 --- a/components/input/Input.tsx +++ b/components/input/Input.tsx @@ -5,17 +5,16 @@ import Group from './Group'; import Search from './Search'; import TextArea from './TextArea'; import Password from './Password'; -import { Omit, tuple } from '../_util/type'; +import { Omit } from '../_util/type'; import ClearableLabeledInput, { hasPrefixSuffix } from './ClearableLabeledInput'; import { ConfigConsumer, ConfigConsumerProps } from '../config-provider'; +import SizeContext, { SizeType } from '../config-provider/SizeContext'; import warning from '../_util/warning'; -export const InputSizes = tuple('small', 'default', 'large'); - export interface InputProps extends Omit, 'size' | 'prefix'> { prefixCls?: string; - size?: typeof InputSizes[number]; + size?: SizeType; onPressEnter?: React.KeyboardEventHandler; addonBefore?: React.ReactNode; addonAfter?: React.ReactNode; @@ -59,7 +58,7 @@ export function resolveOnChange( export function getInputClassName( prefixCls: string, - size?: typeof InputSizes[number], + size?: SizeType, disabled?: boolean, direction?: any, ) { @@ -171,8 +170,8 @@ class Input extends React.Component { resolveOnChange(this.input, e, this.props.onChange); }; - renderInput = (prefixCls: string) => { - const { className, addonBefore, addonAfter, size, disabled } = this.props; + renderInput = (prefixCls: string, size?: SizeType) => { + const { className, addonBefore, addonAfter, size: customizeSize, disabled } = this.props; // Fix https://fb.me/react-unknown-prop const otherProps = omit(this.props, [ 'prefixCls', @@ -193,9 +192,12 @@ class Input extends React.Component { {...otherProps} onChange={this.handleChange} onKeyDown={this.handleKeyDown} - className={classNames(getInputClassName(prefixCls, size, disabled, this.direction), { - [className!]: className && !addonBefore && !addonAfter, - })} + className={classNames( + getInputClassName(prefixCls, customizeSize || size, disabled, this.direction), + { + [className!]: className && !addonBefore && !addonAfter, + }, + )} ref={this.saveInput} /> ); @@ -235,16 +237,20 @@ class Input extends React.Component { const prefixCls = getPrefixCls('input', customizePrefixCls); this.direction = direction; return ( - + + {size => ( + + )} + ); }; diff --git a/components/radio/group.tsx b/components/radio/group.tsx index f918f538ec..4ba20cd0f4 100644 --- a/components/radio/group.tsx +++ b/components/radio/group.tsx @@ -10,6 +10,7 @@ import { RadioGroupButtonStyle, } from './interface'; import { ConfigConsumer, ConfigConsumerProps } from '../config-provider'; +import SizeContext from '../config-provider/SizeContext'; function getCheckedValue(children: React.ReactNode) { let value = null; @@ -96,19 +97,15 @@ class RadioGroup extends React.Component { renderGroup = ({ getPrefixCls, direction }: ConfigConsumerProps) => { const { props } = this; - const { prefixCls: customizePrefixCls, className = '', options, buttonStyle } = props; + const { + prefixCls: customizePrefixCls, + className = '', + options, + buttonStyle, + size: customizeSize, + } = props; const prefixCls = getPrefixCls('radio', customizePrefixCls); const groupPrefixCls = `${prefixCls}-group`; - const classString = classNames( - groupPrefixCls, - `${groupPrefixCls}-${buttonStyle}`, - { - [`${groupPrefixCls}-${props.size}`]: props.size, - [`${groupPrefixCls}-rtl`]: direction === 'rtl', - }, - className, - ); - let { children } = props; // 如果存在 options, 优先使用 @@ -144,15 +141,32 @@ class RadioGroup extends React.Component { } return ( -
- {children} -
+ + {size => { + const mergedSize = customizeSize || size; + const classString = classNames( + groupPrefixCls, + `${groupPrefixCls}-${buttonStyle}`, + { + [`${groupPrefixCls}-${mergedSize}`]: mergedSize, + [`${groupPrefixCls}-rtl`]: direction === 'rtl', + }, + className, + ); + + return ( +
+ {children} +
+ ); + }} +
); }; diff --git a/components/radio/interface.tsx b/components/radio/interface.tsx index 5cdb581ff2..6042131e39 100644 --- a/components/radio/interface.tsx +++ b/components/radio/interface.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { AbstractCheckboxGroupProps } from '../checkbox/Group'; import { AbstractCheckboxProps } from '../checkbox/Checkbox'; +import { SizeType } from '../config-provider/SizeContext'; export type RadioGroupButtonStyle = 'outline' | 'solid'; @@ -8,7 +9,7 @@ export interface RadioGroupProps extends AbstractCheckboxGroupProps { defaultValue?: any; value?: any; onChange?: (e: RadioChangeEvent) => void; - size?: 'large' | 'default' | 'small'; + size?: SizeType; onMouseEnter?: React.MouseEventHandler; onMouseLeave?: React.MouseEventHandler; name?: string; diff --git a/components/select/index.tsx b/components/select/index.tsx index fa7dfb3bd2..9bd85fc736 100755 --- a/components/select/index.tsx +++ b/components/select/index.tsx @@ -6,11 +6,10 @@ import classNames from 'classnames'; import RcSelect, { Option, OptGroup, SelectProps as RcSelectProps } from 'rc-select'; import { ConfigConsumer, ConfigConsumerProps } from '../config-provider'; import getIcons from './utils/iconUtil'; +import SizeContext, { SizeType } from '../config-provider/SizeContext'; type RawValue = string | number; -export type Size = 'large' | 'default' | 'small'; - export type OptionType = typeof Option; export interface LabeledValue { @@ -23,7 +22,7 @@ export type SelectValue = RawValue | RawValue[] | LabeledValue | LabeledValue[]; export interface InternalSelectProps extends Omit, 'mode'> { suffixIcon?: React.ReactNode; - size?: Size; + size?: SizeType; mode?: 'multiple' | 'tags' | 'SECRET_COMBOBOX_MODE_DO_NOT_USE'; } @@ -85,7 +84,7 @@ class Select extends React.Componen prefixCls: customizePrefixCls, notFoundContent, className, - size, + size: customizeSize, listHeight = 256, listItemHeight = 32, getPopupContainer, @@ -98,7 +97,7 @@ class Select extends React.Componen const isMultiple = mode === 'multiple' || mode === 'tags'; // ===================== Empty ===================== - let mergedNotFound; + let mergedNotFound: React.ReactNode; if (notFoundContent !== undefined) { mergedNotFound = notFoundContent; } else if (mode === 'combobox') { @@ -122,31 +121,39 @@ class Select extends React.Componen 'size', ]); - const mergedClassName = classNames(className, { - [`${prefixCls}-lg`]: size === 'large', - [`${prefixCls}-sm`]: size === 'small', - [`${prefixCls}-rtl`]: direction === 'rtl', - }); const rcSelectRtlDropDownClassName = classNames(dropdownClassName, { [`${prefixCls}-dropdown-${direction}`]: direction === 'rtl', }); return ( - - ref={this.selectRef} - {...selectProps} - listHeight={listHeight} - listItemHeight={listItemHeight} - mode={mode} - prefixCls={prefixCls} - inputIcon={suffixIcon} - menuItemSelectedIcon={itemIcon} - removeIcon={removeIcon} - clearIcon={clearIcon} - notFoundContent={mergedNotFound} - className={mergedClassName} - getPopupContainer={getPopupContainer || getContextPopupContainer} - dropdownClassName={rcSelectRtlDropDownClassName} - /> + + {size => { + const mergedSize = customizeSize || size; + const mergedClassName = classNames(className, { + [`${prefixCls}-lg`]: mergedSize === 'large', + [`${prefixCls}-sm`]: mergedSize === 'small', + [`${prefixCls}-rtl`]: direction === 'rtl', + }); + + return ( + + ref={this.selectRef} + {...selectProps} + listHeight={listHeight} + listItemHeight={listItemHeight} + mode={mode} + prefixCls={prefixCls} + inputIcon={suffixIcon} + menuItemSelectedIcon={itemIcon} + removeIcon={removeIcon} + clearIcon={clearIcon} + notFoundContent={mergedNotFound} + className={mergedClassName} + getPopupContainer={getPopupContainer || getContextPopupContainer} + dropdownClassName={rcSelectRtlDropDownClassName} + /> + ); + }} + ); }; diff --git a/components/switch/index.tsx b/components/switch/index.tsx index 2840c5b10f..fe2c57c4e0 100755 --- a/components/switch/index.tsx +++ b/components/switch/index.tsx @@ -7,6 +7,7 @@ import { LoadingOutlined } from '@ant-design/icons'; import Wave from '../_util/wave'; import { ConfigConsumer, ConfigConsumerProps } from '../config-provider'; import warning from '../_util/warning'; +import SizeContext from '../config-provider/SizeContext'; export type SwitchSize = 'small' | 'default'; export type SwitchChangeEventHandler = (checked: boolean, event: MouseEvent) => void; @@ -57,27 +58,40 @@ export default class Switch extends React.Component { } renderSwitch = ({ getPrefixCls, direction }: ConfigConsumerProps) => { - const { prefixCls: customizePrefixCls, size, loading, className = '', disabled } = this.props; + const { + prefixCls: customizePrefixCls, + size: customizeSize, + loading, + className = '', + disabled, + } = this.props; const prefixCls = getPrefixCls('switch', customizePrefixCls); - const classes = classNames(className, { - [`${prefixCls}-small`]: size === 'small', - [`${prefixCls}-loading`]: loading, - [`${prefixCls}-rtl`]: direction === 'rtl', - }); const loadingIcon = loading ? ( ) : null; return ( - - - + + {size => { + const classes = classNames(className, { + [`${prefixCls}-small`]: (customizeSize || size) === 'small', + [`${prefixCls}-loading`]: loading, + [`${prefixCls}-rtl`]: direction === 'rtl', + }); + + return ( + + + + ); + }} + ); }; diff --git a/components/table/Table.tsx b/components/table/Table.tsx index 53aec6c908..82db0971e4 100644 --- a/components/table/Table.tsx +++ b/components/table/Table.tsx @@ -15,7 +15,6 @@ import { SorterResult, Key, GetPopupContainer, - TableSize, ExpandableConfig, ExpandType, TablePaginationConfig, @@ -29,6 +28,7 @@ import useTitleColumns from './hooks/useTitleColumns'; import renderExpandIcon from './ExpandIcon'; import scrollTo from '../_util/scrollTo'; import defaultLocale from '../locale/en_US'; +import SizeContext, { SizeType } from '../config-provider/SizeContext'; export { ColumnsType, TablePaginationConfig }; @@ -65,7 +65,7 @@ export interface TableProps columns?: ColumnsType; pagination?: false | TablePaginationConfig; loading?: boolean | SpinProps; - size?: TableSize; + size?: SizeType; bordered?: boolean; locale?: TableLocale; @@ -88,7 +88,7 @@ function Table(props: TableProps) { const { prefixCls: customizePrefixCls, className, - size, + size: customizeSize, bordered, dropdownPrefixCls, dataSource, @@ -109,9 +109,11 @@ function Table(props: TableProps) { sortDirections, locale, } = props; + const size = React.useContext(SizeContext); const { locale: contextLocale = defaultLocale, renderEmpty, direction } = React.useContext( ConfigContext, ); + const mergedSize = customizeSize || size; const tableLocale = locale || contextLocale.Table; const rawData: RecordType[] = dataSource || EMPTY_LIST; @@ -354,7 +356,7 @@ function Table(props: TableProps) { if (mergedPagination.size) { paginationSize = mergedPagination.size; } else { - paginationSize = size === 'small' || size === 'middle' ? 'small' : undefined; + paginationSize = mergedSize === 'small' || mergedSize === 'middle' ? 'small' : undefined; } const renderPagination = () => ( @@ -407,8 +409,8 @@ function Table(props: TableProps) { expandable={mergedExpandable} prefixCls={prefixCls} className={classNames(className, { - [`${prefixCls}-middle`]: size === 'middle', - [`${prefixCls}-small`]: size === 'small', + [`${prefixCls}-middle`]: mergedSize === 'middle', + [`${prefixCls}-small`]: mergedSize === 'small', [`${prefixCls}-bordered`]: bordered, [`${prefixCls}-rtl`]: direction === 'rtl', })} diff --git a/components/table/interface.tsx b/components/table/interface.tsx index d6e9b0d10d..9206fa5c39 100644 --- a/components/table/interface.tsx +++ b/components/table/interface.tsx @@ -10,8 +10,6 @@ export type RowSelectionType = 'checkbox' | 'radio'; export type SelectionItemSelectFn = (currentRowKeys: Key[]) => void; -export type TableSize = 'default' | 'middle' | 'small'; - export type ExpandType = null | 'row' | 'nest'; export interface TableLocale { diff --git a/components/tree-select/index.tsx b/components/tree-select/index.tsx index d9ea690214..6a1f5fe3b9 100644 --- a/components/tree-select/index.tsx +++ b/components/tree-select/index.tsx @@ -12,9 +12,9 @@ import { ConfigConsumer, ConfigConsumerProps } from '../config-provider'; import collapseMotion from '../_util/motion'; import warning from '../_util/warning'; import { AntTreeNodeProps } from '../tree'; -import { Size } from '../select'; import getIcons from '../select/utils/iconUtil'; import renderSwitcherIcon from '../tree/utils/iconUtil'; +import SizeContext, { SizeType } from '../config-provider/SizeContext'; type RawValue = string | number; @@ -31,7 +31,7 @@ export interface TreeSelectProps RcTreeSelectProps, 'showTreeIcon' | 'treeMotion' | 'inputIcon' | 'mode' | 'getInputElement' | 'backfill' > { - size?: Size; + size?: SizeType; } class TreeSelect extends React.Component, {}> { @@ -80,7 +80,7 @@ class TreeSelect extends React.Component, {}> { }: ConfigConsumerProps) => { const { prefixCls: customizePrefixCls, - size, + size: customizeSize, className, treeCheckable, multiple, @@ -97,16 +97,6 @@ class TreeSelect extends React.Component, {}> { const treePrefixCls = getPrefixCls('select-tree', customizePrefixCls); const treeSelectPrefixCls = getPrefixCls('tree-select', customizePrefixCls); - const mergedClassName = classNames( - !customizePrefixCls && treeSelectPrefixCls, - { - [`${prefixCls}-lg`]: size === 'large', - [`${prefixCls}-sm`]: size === 'small', - [`${prefixCls}-rtl`]: direction === 'rtl', - }, - className, - ); - const mergedDropdownClassName = classNames( dropdownClassName, `${treeSelectPrefixCls}-dropdown`, @@ -124,7 +114,7 @@ class TreeSelect extends React.Component, {}> { }); // ===================== Empty ===================== - let mergedNotFound; + let mergedNotFound: React.ReactNode; if (notFoundContent !== undefined) { mergedNotFound = notFoundContent; } else { @@ -143,29 +133,50 @@ class TreeSelect extends React.Component, {}> { ]); return ( - : treeCheckable - } - inputIcon={suffixIcon} - menuItemSelectedIcon={itemIcon} - removeIcon={removeIcon} - clearIcon={clearIcon} - switcherIcon={(nodeProps: AntTreeNodeProps) => - renderSwitcherIcon(treePrefixCls, switcherIcon, treeLine, nodeProps) - } - showTreeIcon={false} - notFoundContent={mergedNotFound} - getPopupContainer={getPopupContainer || getContextPopupContainer} - treeMotion={collapseMotion} - dropdownClassName={mergedDropdownClassName} - /> + + {size => { + const mergedSize = customizeSize || size; + const mergedClassName = classNames( + !customizePrefixCls && treeSelectPrefixCls, + { + [`${prefixCls}-lg`]: mergedSize === 'large', + [`${prefixCls}-sm`]: mergedSize === 'small', + [`${prefixCls}-rtl`]: direction === 'rtl', + }, + className, + ); + + return ( + + ) : ( + treeCheckable + ) + } + inputIcon={suffixIcon} + menuItemSelectedIcon={itemIcon} + removeIcon={removeIcon} + clearIcon={clearIcon} + switcherIcon={(nodeProps: AntTreeNodeProps) => + renderSwitcherIcon(treePrefixCls, switcherIcon, treeLine, nodeProps) + } + showTreeIcon={false} + notFoundContent={mergedNotFound} + getPopupContainer={getPopupContainer || getContextPopupContainer} + treeMotion={collapseMotion} + dropdownClassName={mergedDropdownClassName} + /> + ); + }} + ); };