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
This commit is contained in:
二货机器人 2020-01-03 13:38:16 +08:00 committed by GitHub
parent b6450ce84a
commit 5ebac5f9d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 1355 additions and 477 deletions

View File

@ -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;

View File

@ -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,13 +200,15 @@ class Button extends React.Component<ButtonProps, ButtonState> {
return React.Children.count(children) === 1 && !icon && type !== 'link';
}
renderButton = ({ getPrefixCls, autoInsertSpaceInButton, direction }: ConfigConsumerProps) => {
renderButton = ({ getPrefixCls, autoInsertSpaceInButton, direction }: ConfigConsumerProps) => (
<SizeContext.Consumer>
{size => {
const {
prefixCls: customizePrefixCls,
type,
danger,
shape,
size,
size: customizeSize,
className,
children,
icon,
@ -229,7 +230,7 @@ class Button extends React.Component<ButtonProps, ButtonState> {
// large => lg
// small => sm
let sizeCls = '';
switch (size) {
switch (customizeSize || size) {
case 'large':
sizeCls = 'lg';
break;
@ -297,7 +298,9 @@ class Button extends React.Component<ButtonProps, ButtonState> {
}
return <Wave>{buttonNode}</Wave>;
};
}}
</SizeContext.Consumer>
);
render() {
return <ConfigConsumer>{this.renderButton}</ConfigConsumer>;

View File

@ -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;

View File

@ -49,7 +49,7 @@ function YearSelect<DateType>(props: SharedProps<DateType>) {
return (
<Select
size={fullscreen ? 'default' : 'small'}
size={fullscreen ? undefined : 'small'}
options={options}
value={year}
className={`${prefixCls}-year-select`}
@ -119,7 +119,7 @@ function MonthSelect<DateType>(props: SharedProps<DateType>) {
return (
<Select
size={fullscreen ? 'default' : 'small'}
size={fullscreen ? undefined : 'small'}
dropdownMatchSelectWidth={100}
className={`${prefixCls}-month-select`}
value={month}
@ -145,7 +145,7 @@ function ModeSwitch<DateType>(props: ModeSwitchProps<DateType>) {
onModeChange(value);
}}
value={mode}
size={fullscreen ? 'default' : 'small'}
size={fullscreen ? undefined : 'small'}
className={`${prefixCls}-mode-switch`}
>
<Button value="month">{locale.month}</Button>

View File

@ -122,7 +122,7 @@ exports[`renders ./components/calendar/demo/basic.md correctly 1`] = `
</span>
</div>
<div
class="ant-radio-group ant-radio-group-outline ant-radio-group-default ant-picker-calendar-mode-switch"
class="ant-radio-group ant-radio-group-outline ant-picker-calendar-mode-switch"
>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"
@ -3005,7 +3005,7 @@ exports[`renders ./components/calendar/demo/notice-calendar.md correctly 1`] = `
</span>
</div>
<div
class="ant-radio-group ant-radio-group-outline ant-radio-group-default ant-picker-calendar-mode-switch"
class="ant-radio-group ant-radio-group-outline ant-picker-calendar-mode-switch"
>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"
@ -4366,7 +4366,7 @@ exports[`renders ./components/calendar/demo/select.md correctly 1`] = `
</span>
</div>
<div
class="ant-radio-group ant-radio-group-outline ant-radio-group-default ant-picker-calendar-mode-switch"
class="ant-radio-group ant-radio-group-outline ant-picker-calendar-mode-switch"
>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"

View File

@ -124,7 +124,7 @@ exports[`Calendar Calendar should support locale 1`] = `
</span>
</div>
<div
class="ant-radio-group ant-radio-group-outline ant-radio-group-default ant-picker-calendar-mode-switch"
class="ant-radio-group ant-radio-group-outline ant-picker-calendar-mode-switch"
>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"
@ -1074,7 +1074,7 @@ exports[`Calendar rtl render component should be rendered correctly in RTL direc
</span>
</div>
<div
class="ant-radio-group ant-radio-group-outline ant-radio-group-default ant-radio-group-rtl ant-picker-calendar-mode-switch"
class="ant-radio-group ant-radio-group-outline ant-radio-group-rtl ant-picker-calendar-mode-switch"
>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked ant-radio-button-wrapper-rtl"

View File

@ -8,6 +8,7 @@ import Row from '../row';
import Col from '../col';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import { Omit } from '../_util/type';
import SizeContext from '../config-provider/SizeContext';
function getAction(actions: React.ReactNode[]) {
const actionList = actions.map((action, index) => (
@ -86,7 +87,7 @@ export default class Card extends React.Component<CardProps, {}> {
title,
loading,
bordered = true,
size = 'default',
size: customizeSize,
type,
cover,
actions,
@ -100,16 +101,6 @@ export default class Card extends React.Component<CardProps, {}> {
} = this.props;
const prefixCls = getPrefixCls('card', customizePrefixCls);
const classString = classNames(prefixCls, className, {
[`${prefixCls}-loading`]: loading,
[`${prefixCls}-bordered`]: bordered,
[`${prefixCls}-hoverable`]: hoverable,
[`${prefixCls}-contain-grid`]: this.isContainGrid(),
[`${prefixCls}-contain-tabs`]: tabList && tabList.length,
[`${prefixCls}-${size}`]: size !== 'default',
[`${prefixCls}-type-${type}`]: !!type,
[`${prefixCls}-rtl`]: direction === 'rtl',
});
const loadingBlockStyle =
bodyStyle.padding === 0 || bodyStyle.padding === '0px' ? { padding: 24 } : undefined;
@ -167,7 +158,7 @@ export default class Card extends React.Component<CardProps, {}> {
tabBarExtraContent,
};
let head;
let head: React.ReactNode;
const tabs =
tabList && tabList.length ? (
<Tabs
@ -203,6 +194,21 @@ export default class Card extends React.Component<CardProps, {}> {
<ul className={`${prefixCls}-actions`}>{getAction(actions)}</ul>
) : null;
const divProps = omit(others, ['onTabChange']);
return (
<SizeContext.Consumer>
{size => {
const mergedSize = customizeSize || size;
const classString = classNames(prefixCls, className, {
[`${prefixCls}-loading`]: loading,
[`${prefixCls}-bordered`]: bordered,
[`${prefixCls}-hoverable`]: hoverable,
[`${prefixCls}-contain-grid`]: this.isContainGrid(),
[`${prefixCls}-contain-tabs`]: tabList && tabList.length,
[`${prefixCls}-${mergedSize}`]: mergedSize,
[`${prefixCls}-type-${type}`]: !!type,
[`${prefixCls}-rtl`]: direction === 'rtl',
});
return (
<div {...divProps} className={classString}>
{head}
@ -211,6 +217,9 @@ export default class Card extends React.Component<CardProps, {}> {
{actionDom}
</div>
);
}}
</SizeContext.Consumer>
);
};
render() {

View File

@ -16,6 +16,7 @@ import Input from '../input';
import { ConfigConsumer, ConfigConsumerProps, RenderEmptyHandler } from '../config-provider';
import LocaleReceiver from '../locale-provider/LocaleReceiver';
import warning from '../_util/warning';
import SizeContext, { SizeType } from '../config-provider/SizeContext';
export interface CascaderOptionType {
value?: string;
@ -81,7 +82,7 @@ export interface CascaderProps {
/** 输入框占位文本 */
placeholder?: string;
/** 输入框大小,可选 `large` `default` `small` */
size?: string;
size?: SizeType;
/** 禁用 */
disabled?: boolean;
/** 是否支持清除 */
@ -435,14 +436,16 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
direction,
}: ConfigConsumerProps,
locale: CascaderLocale,
) => {
) => (
<SizeContext.Consumer>
{size => {
const { props, state } = this;
const {
prefixCls: customizePrefixCls,
inputPrefixCls: customizeInputPrefixCls,
children,
placeholder = locale.placeholder || 'Please select',
size,
size: customizeSize,
disabled,
className,
style,
@ -453,6 +456,7 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
popupClassName,
...otherProps
} = props;
const mergedSize = customizeSize || size;
const { value, inputFocused } = state;
@ -462,12 +466,15 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
const inputPrefixCls = getPrefixCls('input', customizeInputPrefixCls);
const sizeCls = classNames({
[`${inputPrefixCls}-lg`]: size === 'large',
[`${inputPrefixCls}-sm`]: size === 'small',
[`${inputPrefixCls}-lg`]: mergedSize === 'large',
[`${inputPrefixCls}-sm`]: mergedSize === 'small',
});
const clearIcon =
(allowClear && !disabled && value.length > 0) || state.inputValue ? (
<CloseCircleFilled className={`${prefixCls}-picker-clear`} onClick={this.clearSelection} />
<CloseCircleFilled
className={`${prefixCls}-picker-clear`}
onClick={this.clearSelection}
/>
) : null;
const arrowCls = classNames({
[`${prefixCls}-picker-arrow`]: true,
@ -477,7 +484,7 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
[`${prefixCls}-picker-rtl`]: isRtlLayout,
[`${prefixCls}-picker-with-value`]: state.inputValue,
[`${prefixCls}-picker-disabled`]: disabled,
[`${prefixCls}-picker-${size}`]: !!size,
[`${prefixCls}-picker-${mergedSize}`]: !!mergedSize,
[`${prefixCls}-picker-show-search`]: !!showSearch,
[`${prefixCls}-picker-focused`]: inputFocused,
});
@ -609,7 +616,9 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
{input}
</RcCascader>
);
};
}}
</SizeContext.Consumer>
);
render() {
return (

View File

@ -0,0 +1,19 @@
import * as React from 'react';
export type SizeType = 'small' | 'middle' | 'large' | undefined;
const SizeContext = React.createContext<SizeType>(undefined);
export interface SizeContextProps {
size?: SizeType;
}
export const SizeContextProvider: React.FC<SizeContextProps> = ({ children, size }) => (
<SizeContext.Consumer>
{originSize => (
<SizeContext.Provider value={size || originSize}>{children}</SizeContext.Provider>
)}
</SizeContext.Consumer>
);
export default SizeContext;

View File

@ -1173,7 +1173,7 @@ exports[`ConfigProvider components Calendar configProvider 1`] = `
</span>
</div>
<div
class="config-radio-group config-radio-group-outline config-radio-group-default config-picker-calendar-mode-switch"
class="config-radio-group config-radio-group-outline config-picker-calendar-mode-switch"
>
<label
class="config-radio-button-wrapper config-radio-button-wrapper-checked"
@ -2063,7 +2063,7 @@ exports[`ConfigProvider components Calendar configProvider 1`] = `
</span>
</div>
<div
class="config-radio-group config-radio-group-outline config-radio-group-default config-picker-calendar-mode-switch"
class="config-radio-group config-radio-group-outline config-picker-calendar-mode-switch"
>
<label
class="config-radio-button-wrapper"
@ -2464,7 +2464,7 @@ exports[`ConfigProvider components Calendar normal 1`] = `
</span>
</div>
<div
class="ant-radio-group ant-radio-group-outline ant-radio-group-default ant-picker-calendar-mode-switch"
class="ant-radio-group ant-radio-group-outline ant-picker-calendar-mode-switch"
>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"
@ -3354,7 +3354,7 @@ exports[`ConfigProvider components Calendar normal 1`] = `
</span>
</div>
<div
class="ant-radio-group ant-radio-group-outline ant-radio-group-default ant-picker-calendar-mode-switch"
class="ant-radio-group ant-radio-group-outline ant-picker-calendar-mode-switch"
>
<label
class="ant-radio-button-wrapper"
@ -3755,7 +3755,7 @@ exports[`ConfigProvider components Calendar prefixCls 1`] = `
</span>
</div>
<div
class="ant-radio-group ant-radio-group-outline ant-radio-group-default prefix-Calendar-calendar-mode-switch"
class="ant-radio-group ant-radio-group-outline prefix-Calendar-calendar-mode-switch"
>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"
@ -4645,7 +4645,7 @@ exports[`ConfigProvider components Calendar prefixCls 1`] = `
</span>
</div>
<div
class="ant-radio-group ant-radio-group-outline ant-radio-group-default prefix-Calendar-calendar-mode-switch"
class="ant-radio-group ant-radio-group-outline prefix-Calendar-calendar-mode-switch"
>
<label
class="ant-radio-button-wrapper"

View File

@ -0,0 +1,89 @@
---
order: 2
title:
zh-CN: 组件尺寸
en-US: Component size
---
## zh-CN
修改默认组件尺寸。
## en-US
Config component default size.
```jsx
import {
ConfigProvider,
Radio,
Input,
Button,
Select,
DatePicker,
Divider,
Table,
Card,
} from 'antd';
const FormSizeDemo = () => {
const [componentSize, setComponentSize] = React.useState('small');
return (
<div>
<Radio.Group
value={componentSize}
onChange={e => {
setComponentSize(e.target.value);
}}
>
<Radio.Button value="small">Small</Radio.Button>
<Radio.Button value="middle">Middle</Radio.Button>
<Radio.Button value="large">Large</Radio.Button>
</Radio.Group>
<Divider />
<ConfigProvider componentSize={componentSize}>
<div className="example">
<Input />
</div>
<div className="example">
<Select defaultValue="demo" options={[{ value: 'demo' }]} />
</div>
<div className="example">
<DatePicker />
</div>
<div className="example">
<Button>Button</Button>
</div>
<div className="example">
<Card title="Card">
<Table
columns={[
{ title: 'Name', dataIndex: 'name' },
{ title: 'Age', dataIndex: 'age' },
]}
dataSource={[
{
key: '1',
name: 'John Brown',
age: 32,
},
{
key: '2',
name: 'Jim Green',
age: 42,
},
{
key: '3',
name: 'Joe Black',
age: 32,
},
]}
/>
</Card>
</div>
</ConfigProvider>
</div>
);
};
ReactDOM.render(<FormSizeDemo />, mountNode);
```

View File

@ -38,6 +38,7 @@ Some components use dynamic style to support wave effect. You can config `csp` p
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| autoInsertSpaceInButton | Set `false` to remove space between 2 chinese characters on Button | boolean | true | |
| componentSize | Config antd component size | `small | middle | large` | - | |
| csp | Set [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) config | { nonce: string } | - | |
| form | Set Form common props | { validateMessages?: [ValidateMessages](/components/form/#validateMessages) } | - | |
| renderEmpty | set empty content of components. Ref [Empty](/components/empty/) | Function(componentName: string): ReactNode | - | |

View File

@ -8,6 +8,7 @@ import { RenderEmptyHandler } from './renderEmpty';
import LocaleProvider, { Locale, ANT_MARK } from '../locale-provider';
import LocaleReceiver from '../locale-provider/LocaleReceiver';
import { ConfigConsumer, ConfigContext, CSPConfig, ConfigConsumerProps } from './context';
import { SizeType, SizeContextProvider } from './SizeContext';
export { RenderEmptyHandler, ConfigContext, ConfigConsumer, CSPConfig, ConfigConsumerProps };
@ -36,6 +37,7 @@ export interface ConfigProviderProps {
pageHeader?: {
ghost: boolean;
};
componentSize?: SizeType;
direction?: 'ltr' | 'rtl';
}
@ -58,6 +60,7 @@ class ConfigProvider extends React.Component<ConfigProviderProps> {
form,
locale,
pageHeader,
componentSize,
direction,
} = this.props;
@ -92,11 +95,13 @@ class ConfigProvider extends React.Component<ConfigProviderProps> {
}
return (
<SizeContextProvider size={componentSize}>
<ConfigContext.Provider value={config}>
<LocaleProvider locale={locale || legacyLocale} _ANT_MARK__={ANT_MARK}>
{childNode}
</LocaleProvider>
</ConfigContext.Provider>
</SizeContextProvider>
);
};

View File

@ -39,6 +39,7 @@ return (
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| autoInsertSpaceInButton | 设置为 `false` 时,移除按钮中 2 个汉字之间的空格 | boolean | true | |
| componentSize | 设置 antd 组件大小 | `small | middle | large` | - | |
| csp | 设置 [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) 配置 | { nonce: string } | - | |
| form | 设置 Form 组件的通用属性 | { validateMessages?: [ValidateMessages](/components/form/#validateMessages) } | - | |
| renderEmpty | 自定义组件空状态。参考 [空状态](/components/empty/) | Function(componentName: string): ReactNode | - | |

View File

@ -21,6 +21,7 @@ import enUS from './locale/en_US';
import { getPlaceholder, getRangePlaceholder } from './util';
import PickerButton from './PickerButton';
import PickerTag from './PickerTag';
import SizeContext, { SizeType } from '../config-provider/SizeContext';
const Components = { button: PickerButton, rangeItem: PickerTag };
@ -76,7 +77,7 @@ type InjectDefaultProps<Props> = Omit<
| 'components'
> & {
locale?: typeof enUS;
size?: 'large' | 'default' | 'small';
size?: SizeType;
};
// Picker Props
@ -143,7 +144,12 @@ function generatePicker<DateType>(generateConfig: GenerateConfig<DateType>) {
renderPicker = (locale: any) => {
const { getPrefixCls, direction } = this.context;
const { prefixCls: customizePrefixCls, className, size, ...restProps } = this.props;
const {
prefixCls: customizePrefixCls,
className,
size: customizeSize,
...restProps
} = this.props;
const { format, showTime } = this.props as any;
const prefixCls = getPrefixCls('picker', customizePrefixCls);
@ -165,11 +171,18 @@ function generatePicker<DateType>(generateConfig: GenerateConfig<DateType>) {
: {}),
};
return (
<SizeContext.Consumer>
{size => {
const mergedSize = customizeSize || size;
return (
<RCPicker<DateType>
ref={this.pickerRef}
placeholder={getPlaceholder(mergedPicker, locale)}
suffixIcon={mergedPicker === 'time' ? <ClockCircleOutlined /> : <CalendarOutlined />}
suffixIcon={
mergedPicker === 'time' ? <ClockCircleOutlined /> : <CalendarOutlined />
}
clearIcon={<CloseCircleFilled />}
allowClear
transitionName="slide-up"
@ -178,7 +191,7 @@ function generatePicker<DateType>(generateConfig: GenerateConfig<DateType>) {
{...additionalOverrideProps}
locale={locale!.lang}
className={classNames(className, {
[`${prefixCls}-${size}`]: size,
[`${prefixCls}-${mergedSize}`]: mergedSize,
})}
prefixCls={prefixCls}
generateConfig={generateConfig}
@ -190,6 +203,9 @@ function generatePicker<DateType>(generateConfig: GenerateConfig<DateType>) {
direction={direction}
/>
);
}}
</SizeContext.Consumer>
);
};
render() {

View File

@ -8,6 +8,7 @@ import { ConfigContext, ConfigConsumerProps } from '../config-provider';
import { FormContext } from './context';
import { FormLabelAlign } from './interface';
import { useForm, FormInstance } from './util';
import { SizeType, SizeContextProvider } from '../config-provider/SizeContext';
export type FormLayout = 'horizontal' | 'inline' | 'vertical';
@ -21,6 +22,7 @@ export interface FormProps extends Omit<RcFormProps, 'form'> {
labelCol?: ColProps;
wrapperCol?: ColProps;
form?: FormInstance;
size?: SizeType;
}
const InternalForm: React.FC<FormProps> = (props, ref) => {
@ -37,6 +39,7 @@ const InternalForm: React.FC<FormProps> = (props, ref) => {
hideRequiredMark,
className = '',
layout = 'horizontal',
size,
} = props;
const prefixCls = getPrefixCls('form', customizePrefixCls);
@ -67,6 +70,7 @@ const InternalForm: React.FC<FormProps> = (props, ref) => {
React.useImperativeHandle(ref, () => wrapForm);
return (
<SizeContextProvider size={size}>
<FormContext.Provider
value={{
name,
@ -79,6 +83,7 @@ const InternalForm: React.FC<FormProps> = (props, ref) => {
>
<FieldForm id={name} {...formProps} form={wrapForm} className={formClassName} />
</FormContext.Provider>
</SizeContextProvider>
);
};

View File

@ -2496,6 +2496,562 @@ exports[`renders ./components/form/demo/register.md correctly 1`] = `
</form>
`;
exports[`renders ./components/form/demo/size.md correctly 1`] = `
<div>
<form
class="ant-form ant-form-horizontal"
>
<div
class="ant-row ant-form-item"
>
<div
class="ant-col ant-col-4 ant-form-item-label"
>
<label
class=""
for="size"
title="Form Size"
>
Form Size
</label>
</div>
<div
class="ant-col ant-col-14 ant-form-item-control"
>
<div
class="ant-form-item-control-input"
>
<div
class="ant-radio-group ant-radio-group-outline ant-radio-group-small"
id="size"
>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"
>
<span
class="ant-radio-button ant-radio-button-checked"
>
<input
checked=""
class="ant-radio-button-input"
type="radio"
value="small"
/>
<span
class="ant-radio-button-inner"
/>
</span>
<span>
Small
</span>
</label>
<label
class="ant-radio-button-wrapper"
>
<span
class="ant-radio-button"
>
<input
class="ant-radio-button-input"
type="radio"
value="middle"
/>
<span
class="ant-radio-button-inner"
/>
</span>
<span>
Middle
</span>
</label>
<label
class="ant-radio-button-wrapper"
>
<span
class="ant-radio-button"
>
<input
class="ant-radio-button-input"
type="radio"
value="large"
/>
<span
class="ant-radio-button-inner"
/>
</span>
<span>
Large
</span>
</label>
</div>
</div>
</div>
</div>
<div
class="ant-row ant-form-item"
>
<div
class="ant-col ant-col-4 ant-form-item-label"
>
<label
class=""
title="Input"
>
Input
</label>
</div>
<div
class="ant-col ant-col-14 ant-form-item-control"
>
<div
class="ant-form-item-control-input"
>
<input
class="ant-input ant-input-sm"
type="text"
value=""
/>
</div>
</div>
</div>
<div
class="ant-row ant-form-item"
>
<div
class="ant-col ant-col-4 ant-form-item-label"
>
<label
class=""
title="Select"
>
Select
</label>
</div>
<div
class="ant-col ant-col-14 ant-form-item-control"
>
<div
class="ant-form-item-control-input"
>
<div
class="ant-select ant-select-sm ant-select-single ant-select-show-arrow"
>
<div
class="ant-select-selector"
>
<span
class="ant-select-selection-search"
>
<input
aria-activedescendant="undefined_list_0"
aria-autocomplete="list"
aria-controls="undefined_list"
aria-haspopup="listbox"
aria-owns="undefined_list"
autocomplete="off"
class="ant-select-selection-search-input"
readonly=""
role="combobox"
style="opacity:0"
value=""
/>
</span>
<span
class="ant-select-selection-placeholder"
/>
</div>
<span
aria-hidden="true"
class="ant-select-arrow"
style="user-select:none;-webkit-user-select:none"
unselectable="on"
>
<span
aria-label="down"
class="anticon anticon-down"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
/>
</svg>
</span>
</span>
</div>
</div>
</div>
</div>
<div
class="ant-row ant-form-item"
>
<div
class="ant-col ant-col-4 ant-form-item-label"
>
<label
class=""
title="TreeSelect"
>
TreeSelect
</label>
</div>
<div
class="ant-col ant-col-14 ant-form-item-control"
>
<div
class="ant-form-item-control-input"
>
<div
class="ant-select ant-tree-select ant-select-sm ant-select-single ant-select-show-arrow"
>
<div
class="ant-select-selector"
>
<span
class="ant-select-selection-search"
>
<input
aria-activedescendant="undefined_list_0"
aria-autocomplete="list"
aria-controls="undefined_list"
aria-haspopup="listbox"
aria-owns="undefined_list"
autocomplete="off"
class="ant-select-selection-search-input"
readonly=""
role="combobox"
style="opacity:0"
value=""
/>
</span>
<span
class="ant-select-selection-placeholder"
/>
</div>
<span
aria-hidden="true"
class="ant-select-arrow"
style="user-select:none;-webkit-user-select:none"
unselectable="on"
>
<span
aria-label="down"
class="anticon anticon-down"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
/>
</svg>
</span>
</span>
</div>
</div>
</div>
</div>
<div
class="ant-row ant-form-item"
>
<div
class="ant-col ant-col-4 ant-form-item-label"
>
<label
class=""
title="Cascader"
>
Cascader
</label>
</div>
<div
class="ant-col ant-col-14 ant-form-item-control"
>
<div
class="ant-form-item-control-input"
>
<span
class="ant-cascader-picker ant-cascader-picker-small"
tabindex="0"
>
<span
class="ant-cascader-picker-label"
/>
<input
autocomplete="off"
class="ant-input ant-input-sm ant-cascader-input ant-input-sm"
placeholder="Please select"
readonly=""
tabindex="-1"
type="text"
value=""
/>
<span
aria-label="down"
class="anticon anticon-down ant-cascader-picker-arrow"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
/>
</svg>
</span>
</span>
</div>
</div>
</div>
<div
class="ant-row ant-form-item"
>
<div
class="ant-col ant-col-4 ant-form-item-label"
>
<label
class=""
title="DatePicker"
>
DatePicker
</label>
</div>
<div
class="ant-col ant-col-14 ant-form-item-control"
>
<div
class="ant-form-item-control-input"
>
<div
class="ant-picker ant-picker-small"
>
<div
class="ant-picker-input"
>
<input
placeholder="Select date"
readonly=""
size="12"
value=""
/>
<span
class="ant-picker-suffix"
>
<span
aria-label="calendar"
class="anticon anticon-calendar"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="calendar"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M880 184H712v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H384v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H144c-17.7 0-32 14.3-32 32v664c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V216c0-17.7-14.3-32-32-32zm-40 656H184V460h656v380zM184 392V256h128v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h256v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h128v136H184z"
/>
</svg>
</span>
</span>
</div>
</div>
</div>
</div>
</div>
<div
class="ant-row ant-form-item"
>
<div
class="ant-col ant-col-4 ant-form-item-label"
>
<label
class=""
title="InputNumber"
>
InputNumber
</label>
</div>
<div
class="ant-col ant-col-14 ant-form-item-control"
>
<div
class="ant-form-item-control-input"
>
<div
class="ant-input-number ant-input-number-sm"
>
<div
class="ant-input-number-handler-wrap"
>
<span
aria-disabled="false"
aria-label="Increase Value"
class="ant-input-number-handler ant-input-number-handler-up "
role="button"
unselectable="unselectable"
>
<span
aria-label="up"
class="anticon anticon-up ant-input-number-handler-up-inner"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="up"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M890.5 755.3L537.9 269.2c-12.8-17.6-39-17.6-51.7 0L133.5 755.3A8 8 0 00140 768h75c5.1 0 9.9-2.5 12.9-6.6L512 369.8l284.1 391.6c3 4.1 7.8 6.6 12.9 6.6h75c6.5 0 10.3-7.4 6.5-12.7z"
/>
</svg>
</span>
</span>
<span
aria-disabled="false"
aria-label="Decrease Value"
class="ant-input-number-handler ant-input-number-handler-down "
role="button"
unselectable="unselectable"
>
<span
aria-label="down"
class="anticon anticon-down ant-input-number-handler-down-inner"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
/>
</svg>
</span>
</span>
</div>
<div
class="ant-input-number-input-wrap"
>
<input
aria-valuemin="-9007199254740991"
autocomplete="off"
class="ant-input-number-input"
min="-9007199254740991"
role="spinbutton"
step="1"
value=""
/>
</div>
</div>
</div>
</div>
</div>
<div
class="ant-row ant-form-item"
>
<div
class="ant-col ant-col-4 ant-form-item-label"
>
<label
class=""
title="Switch"
>
Switch
</label>
</div>
<div
class="ant-col ant-col-14 ant-form-item-control"
>
<div
class="ant-form-item-control-input"
>
<button
aria-checked="false"
class="ant-switch-small ant-switch"
role="switch"
type="button"
>
<span
class="ant-switch-inner"
/>
</button>
</div>
</div>
</div>
<div
class="ant-row ant-form-item"
>
<div
class="ant-col ant-col-4 ant-form-item-label"
>
<label
class=""
title="Button"
>
Button
</label>
</div>
<div
class="ant-col ant-col-14 ant-form-item-control"
>
<div
class="ant-form-item-control-input"
>
<button
class="ant-btn ant-btn-sm"
type="button"
>
<span>
Button
</span>
</button>
</div>
</div>
</div>
</form>
</div>
`;
exports[`renders ./components/form/demo/time-related-controls.md correctly 1`] = `
<form
class="ant-form ant-form-horizontal"

View File

@ -0,0 +1,99 @@
---
order: 3.1
title:
zh-CN: 表单尺寸
en-US: Form size
---
## zh-CN
设置表单组件尺寸,仅对 antd 组件有效。
## en-US
Set component size, only works for antd components.
```tsx
import {
Form,
Input,
Button,
Radio,
Select,
Cascader,
DatePicker,
InputNumber,
TreeSelect,
Switch,
} from 'antd';
const FormSizeDemo = () => {
const [componentSize, setComponentSize] = React.useState('small');
const onFormLayoutChange = ({ size }) => {
setComponentSize(size);
};
return (
<div>
<Form
labelCol={{ span: 4 }}
wrapperCol={{ span: 14 }}
layout="horizontal"
initialValues={{ size: componentSize }}
onValuesChange={onFormLayoutChange}
size={componentSize}
>
<Form.Item label="Form Size" name="size">
<Radio.Group>
<Radio.Button value="small">Small</Radio.Button>
<Radio.Button value="middle">Middle</Radio.Button>
<Radio.Button value="large">Large</Radio.Button>
</Radio.Group>
</Form.Item>
<Form.Item label="Input">
<Input />
</Form.Item>
<Form.Item label="Select">
<Select>
<Select.Option value="demo">Demo</Select.Option>
</Select>
</Form.Item>
<Form.Item label="TreeSelect">
<TreeSelect
treeData={[
{ title: 'Light', value: 'light', children: [{ title: 'Bamboo', value: 'bamboo' }] },
]}
/>
</Form.Item>
<Form.Item label="Cascader">
<Cascader
options={[
{
value: 'zhejiang',
label: 'Zhejiang',
children: [
{
value: 'hangzhou',
label: 'Hangzhou',
},
],
},
]}
/>
</Form.Item>
<Form.Item label="DatePicker">
<DatePicker />
</Form.Item>
<Form.Item label="InputNumber">
<InputNumber />
</Form.Item>
<Form.Item label="Switch">
<Switch />
</Form.Item>
<Form.Item label="Button">
<Button>Button</Button>
</Form.Item>
</Form>
</div>
);
};
ReactDOM.render(<FormSizeDemo />, mountNode);
```

View File

@ -28,6 +28,7 @@ High performance Form component with data scope management. Including data colle
| labelCol | label layout, like `<Col>` 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) | - |

View File

@ -29,6 +29,7 @@ title: Form
| labelCol | label 标签布局,同 `<Col>` 组件,设置 `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) | - |

View File

@ -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,17 +54,22 @@ export default class InputNumber extends React.Component<InputNumberProps, any>
}
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 upIcon = <UpOutlined className={`${prefixCls}-handler-up-inner`} />;
const downIcon = <DownOutlined className={`${prefixCls}-handler-down-inner`} />;
return (
<SizeContext.Consumer>
{size => {
const mergeSize = customizeSize || size;
const inputNumberClass = classNames(
{
[`${prefixCls}-lg`]: size === 'large',
[`${prefixCls}-sm`]: size === 'small',
[`${prefixCls}-lg`]: mergeSize === 'large',
[`${prefixCls}-sm`]: mergeSize === 'small',
},
className,
);
const upIcon = <UpOutlined className={`${prefixCls}-handler-up-inner`} />;
const downIcon = <DownOutlined className={`${prefixCls}-handler-down-inner`} />;
return (
<RcInputNumber
@ -75,6 +81,9 @@ export default class InputNumber extends React.Component<InputNumberProps, any>
{...others}
/>
);
}}
</SizeContext.Consumer>
);
};
render() {

View File

@ -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;

View File

@ -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<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'prefix'> {
prefixCls?: string;
size?: typeof InputSizes[number];
size?: SizeType;
onPressEnter?: React.KeyboardEventHandler<HTMLInputElement>;
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<InputProps, InputState> {
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<InputProps, InputState> {
{...otherProps}
onChange={this.handleChange}
onKeyDown={this.handleKeyDown}
className={classNames(getInputClassName(prefixCls, size, disabled, this.direction), {
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<InputProps, InputState> {
const prefixCls = getPrefixCls('input', customizePrefixCls);
this.direction = direction;
return (
<SizeContext.Consumer>
{size => (
<ClearableLabeledInput
{...this.props}
prefixCls={prefixCls}
inputType="input"
value={fixControlledValue(value)}
element={this.renderInput(prefixCls)}
element={this.renderInput(prefixCls, size)}
handleReset={this.handleReset}
ref={this.saveClearableInput}
direction={direction}
/>
)}
</SizeContext.Consumer>
);
};

View File

@ -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<RadioGroupProps, RadioGroupState> {
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, 优先使用
@ -143,6 +140,20 @@ class RadioGroup extends React.Component<RadioGroupProps, RadioGroupState> {
});
}
return (
<SizeContext.Consumer>
{size => {
const mergedSize = customizeSize || size;
const classString = classNames(
groupPrefixCls,
`${groupPrefixCls}-${buttonStyle}`,
{
[`${groupPrefixCls}-${mergedSize}`]: mergedSize,
[`${groupPrefixCls}-rtl`]: direction === 'rtl',
},
className,
);
return (
<div
className={classString}
@ -154,6 +165,9 @@ class RadioGroup extends React.Component<RadioGroupProps, RadioGroupState> {
{children}
</div>
);
}}
</SizeContext.Consumer>
);
};
render() {

View File

@ -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<HTMLDivElement>;
onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;
name?: string;

View File

@ -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<VT> extends Omit<RcSelectProps<VT>, 'mode'> {
suffixIcon?: React.ReactNode;
size?: Size;
size?: SizeType;
mode?: 'multiple' | 'tags' | 'SECRET_COMBOBOX_MODE_DO_NOT_USE';
}
@ -85,7 +84,7 @@ class Select<ValueType extends SelectValue = SelectValue> extends React.Componen
prefixCls: customizePrefixCls,
notFoundContent,
className,
size,
size: customizeSize,
listHeight = 256,
listItemHeight = 32,
getPopupContainer,
@ -98,7 +97,7 @@ class Select<ValueType extends SelectValue = SelectValue> 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,14 +121,19 @@ class Select<ValueType extends SelectValue = SelectValue> 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 (
<SizeContext.Consumer>
{size => {
const mergedSize = customizeSize || size;
const mergedClassName = classNames(className, {
[`${prefixCls}-lg`]: mergedSize === 'large',
[`${prefixCls}-sm`]: mergedSize === 'small',
[`${prefixCls}-rtl`]: direction === 'rtl',
});
return (
<RcSelect<ValueType>
ref={this.selectRef}
@ -148,6 +152,9 @@ class Select<ValueType extends SelectValue = SelectValue> extends React.Componen
dropdownClassName={rcSelectRtlDropDownClassName}
/>
);
}}
</SizeContext.Consumer>
);
};
render() {

View File

@ -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,16 +58,26 @@ export default class Switch extends React.Component<SwitchProps, {}> {
}
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 ? (
<LoadingOutlined className={`${prefixCls}-loading-icon`} />
) : null;
return (
<SizeContext.Consumer>
{size => {
const classes = classNames(className, {
[`${prefixCls}-small`]: (customizeSize || size) === 'small',
[`${prefixCls}-loading`]: loading,
[`${prefixCls}-rtl`]: direction === 'rtl',
});
return (
<Wave insertExtraNode>
<RcSwitch
@ -79,6 +90,9 @@ export default class Switch extends React.Component<SwitchProps, {}> {
/>
</Wave>
);
}}
</SizeContext.Consumer>
);
};
render() {

View File

@ -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<RecordType>
columns?: ColumnsType<RecordType>;
pagination?: false | TablePaginationConfig;
loading?: boolean | SpinProps;
size?: TableSize;
size?: SizeType;
bordered?: boolean;
locale?: TableLocale;
@ -88,7 +88,7 @@ function Table<RecordType extends object = any>(props: TableProps<RecordType>) {
const {
prefixCls: customizePrefixCls,
className,
size,
size: customizeSize,
bordered,
dropdownPrefixCls,
dataSource,
@ -109,9 +109,11 @@ function Table<RecordType extends object = any>(props: TableProps<RecordType>) {
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<RecordType extends object = any>(props: TableProps<RecordType>) {
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<RecordType extends object = any>(props: TableProps<RecordType>) {
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',
})}

View File

@ -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 {

View File

@ -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<T>
RcTreeSelectProps<T>,
'showTreeIcon' | 'treeMotion' | 'inputIcon' | 'mode' | 'getInputElement' | 'backfill'
> {
size?: Size;
size?: SizeType;
}
class TreeSelect<T> extends React.Component<TreeSelectProps<T>, {}> {
@ -80,7 +80,7 @@ class TreeSelect<T> extends React.Component<TreeSelectProps<T>, {}> {
}: ConfigConsumerProps) => {
const {
prefixCls: customizePrefixCls,
size,
size: customizeSize,
className,
treeCheckable,
multiple,
@ -97,16 +97,6 @@ class TreeSelect<T> extends React.Component<TreeSelectProps<T>, {}> {
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<T> extends React.Component<TreeSelectProps<T>, {}> {
});
// ===================== Empty =====================
let mergedNotFound;
let mergedNotFound: React.ReactNode;
if (notFoundContent !== undefined) {
mergedNotFound = notFoundContent;
} else {
@ -142,6 +132,20 @@ class TreeSelect<T> extends React.Component<TreeSelectProps<T>, {}> {
'size',
]);
return (
<SizeContext.Consumer>
{size => {
const mergedSize = customizeSize || size;
const mergedClassName = classNames(
!customizePrefixCls && treeSelectPrefixCls,
{
[`${prefixCls}-lg`]: mergedSize === 'large',
[`${prefixCls}-sm`]: mergedSize === 'small',
[`${prefixCls}-rtl`]: direction === 'rtl',
},
className,
);
return (
<RcTreeSelect
{...selectProps}
@ -151,7 +155,11 @@ class TreeSelect<T> extends React.Component<TreeSelectProps<T>, {}> {
listHeight={listHeight}
listItemHeight={listItemHeight}
treeCheckable={
treeCheckable ? <span className={`${prefixCls}-tree-checkbox-inner`} /> : treeCheckable
treeCheckable ? (
<span className={`${prefixCls}-tree-checkbox-inner`} />
) : (
treeCheckable
)
}
inputIcon={suffixIcon}
menuItemSelectedIcon={itemIcon}
@ -167,6 +175,9 @@ class TreeSelect<T> extends React.Component<TreeSelectProps<T>, {}> {
dropdownClassName={mergedDropdownClassName}
/>
);
}}
</SizeContext.Consumer>
);
};
render() {