Merge branch 'feature' into merge

This commit is contained in:
Tom Xu 2020-10-24 20:53:34 +08:00
commit 7be4339806
28 changed files with 459 additions and 42 deletions

View File

@ -14643,7 +14643,7 @@ exports[`ConfigProvider components Input configProvider componentSize large 1`]
</span>
</span>
<textarea
class="config-input"
class="config-input config-input-lg"
/>
</div>
`;

View File

@ -0,0 +1,247 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ConfigProvider.Form form requiredMark set requiredMark optional 1`] = `
<ConfigProvider
form={
Object {
"requiredMark": "optional",
}
}
>
<LocaleReceiver
componentName="global"
>
<SizeContextProvider>
<LocaleProvider
_ANT_MARK__="internalMark"
locale={Object {}}
>
<ForwardRef(InternalForm)
initialValues={
Object {
"age": 18,
}
}
>
<SizeContextProvider>
<ForwardRef(Form)
className="ant-form ant-form-horizontal"
form={
Object {
"__INTERNAL__": Object {
"itemRef": [Function],
"name": undefined,
},
"getFieldError": [Function],
"getFieldInstance": [Function],
"getFieldValue": [Function],
"getFieldsError": [Function],
"getFieldsValue": [Function],
"getInternalHooks": [Function],
"isFieldTouched": [Function],
"isFieldValidating": [Function],
"isFieldsTouched": [Function],
"isFieldsValidating": [Function],
"resetFields": [Function],
"scrollToField": [Function],
"setFields": [Function],
"setFieldsValue": [Function],
"submit": [Function],
"validateFields": [Function],
}
}
initialValues={
Object {
"age": 18,
}
}
onFinishFailed={[Function]}
>
<form
className="ant-form ant-form-horizontal"
onSubmit={[Function]}
>
<FormItem
label="年龄"
name="age"
rules={
Array [
Object {
"len": 17,
"type": "number",
},
]
}
>
<WrapperField
label="年龄"
messageVariables={
Object {
"label": "年龄",
}
}
name="age"
onReset={[Function]}
rules={
Array [
Object {
"len": 17,
"type": "number",
},
]
}
trigger="onChange"
validateTrigger="onChange"
>
<Field
key="_age"
label="年龄"
messageVariables={
Object {
"label": "年龄",
}
}
name={
Array [
"age",
]
}
onReset={[Function]}
rules={
Array [
Object {
"len": 17,
"type": "number",
},
]
}
trigger="onChange"
validateTrigger="onChange"
valuePropName="value"
>
<Row
className="ant-form-item"
key="row"
>
<div
className="ant-row ant-form-item"
style={Object {}}
>
<FormItemLabel
htmlFor="age"
label="年龄"
name="age"
prefixCls="ant-form"
required={false}
requiredMark="optional"
rules={
Array [
Object {
"len": 17,
"type": "number",
},
]
}
>
<Col
className="ant-form-item-label"
>
<div
className="ant-col ant-form-item-label"
style={Object {}}
>
<label
className="ant-form-item-required-mark-optional"
htmlFor="age"
title="年龄"
>
年龄
<span
className="ant-form-item-optional"
>
(optional)
</span>
</label>
</div>
</Col>
</FormItemLabel>
<FormItemInput
errors={Array []}
label="年龄"
name={
Array [
"age",
]
}
onDomErrorVisibleChange={[Function]}
prefixCls="ant-form"
rules={
Array [
Object {
"len": 17,
"type": "number",
},
]
}
status=""
touched={false}
validateStatus=""
validating={false}
>
<Col
className="ant-form-item-control"
>
<div
className="ant-col ant-form-item-control"
style={Object {}}
>
<div
className="ant-form-item-control-input"
>
<div
className="ant-form-item-control-input-content"
>
<Component
update={1}
value={18}
>
<input
id="age"
onChange={[Function]}
value={18}
/>
</Component>
</div>
</div>
<ErrorList
errors={Array []}
onDomErrorVisibleChange={[Function]}
>
<CSSMotion
motionAppear={true}
motionDeadline={500}
motionName="show-help"
onLeaveEnd={[Function]}
removeOnLeave={true}
visible={false}
>
<DomWrapper />
</CSSMotion>
</ErrorList>
</div>
</Col>
</FormItemInput>
</div>
</Row>
</Field>
</WrapperField>
</FormItem>
</form>
</ForwardRef(Form)>
</SizeContextProvider>
</ForwardRef(InternalForm)>
</LocaleProvider>
</SizeContextProvider>
</LocaleReceiver>
</ConfigProvider>
`;

View File

@ -5,7 +5,7 @@ import ConfigProvider from '..';
import zhCN from '../../locale/zh_CN';
import Form from '../../form';
describe('ConfigProvider.Form.Locale', () => {
describe('ConfigProvider.Form', () => {
describe('form validateMessages', () => {
const wrapperComponent = ({ validateMessages }) => {
const formRef = React.createRef();
@ -75,4 +75,20 @@ describe('ConfigProvider.Form.Locale', () => {
expect(wrapper.find('.ant-form-item-explain').last().text()).toEqual('年龄必须等于17');
});
});
describe('form requiredMark', () => {
it('set requiredMark optional', async () => {
const wrapper = mount(
<ConfigProvider form={{ requiredMark: 'optional' }}>
<Form initialValues={{ age: 18 }}>
<Form.Item name="age" label="年龄" rules={[{ type: 'number', len: 17 }]}>
<input />
</Form.Item>
</Form>
</ConfigProvider>,
);
expect(wrapper).toMatchSnapshot();
});
});
});

View File

@ -2,6 +2,7 @@ import * as React from 'react';
import defaultRenderEmpty, { RenderEmptyHandler } from './renderEmpty';
import { Locale } from '../locale-provider';
import { SizeType } from './SizeContext';
import { RequiredMark } from '../form/Form';
export interface CSPConfig {
nonce?: string;
@ -28,6 +29,9 @@ export interface ConfigConsumerProps {
};
virtual?: boolean;
dropdownMatchSelectWidth?: boolean;
form?: {
requiredMark?: RequiredMark;
};
}
export const ConfigContext = React.createContext<ConfigConsumerProps>({

View File

@ -49,6 +49,9 @@ const FormSizeDemo = () => {
<div className="example">
<Input.Search allowClear />
</div>
<div className="example">
<Input.TextArea allowClear />
</div>
<div className="example">
<Select defaultValue="demo" options={[{ value: 'demo' }]} />
</div>

View File

@ -43,7 +43,7 @@ Some components use dynamic style to support wave effect. You can config `csp` p
| csp | Set [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) config | { nonce: string } | - | |
| direction | Set direction of layout. See [demo](#components-config-provider-demo-direction) | `ltr` \| `rtl` | `ltr` | |
| dropdownMatchSelectWidth | Determine whether the dropdown menu and the select input are the same width. Default set `min-width` same as input. Will ignore when value less than select width. `false` will disable virtual scroll | boolean \| number | - | 4.3.0 |
| form | Set Form common props | { validateMessages?: [ValidateMessages](/components/form/#validateMessages) } | - | |
| form | Set Form common props | { validateMessages?: [ValidateMessages](/components/form/#validateMessages), requiredMark?: boolean \| `optional` } | - | requiredMark: 4.8.0 |
| getPopupContainer | To set the container of the popup element. The default is to create a `div` element in `body` | function(triggerNode) | () => document.body | |
| getTargetContainer | Config Affix, Anchor scroll target container | () => HTMLElement | () => window | 4.2.0 |
| input | Set Input common props | { autoComplete?: string } | - | 4.2.0 |

View File

@ -11,6 +11,7 @@ import { ConfigConsumer, ConfigContext, CSPConfig, ConfigConsumerProps } from '.
import { SizeType, SizeContextProvider } from './SizeContext';
import message from '../message';
import notification from '../notification';
import { RequiredMark } from '../form/Form';
export { RenderEmptyHandler, ConfigContext, ConfigConsumer, CSPConfig, ConfigConsumerProps };
@ -36,6 +37,7 @@ export interface ConfigProviderProps {
autoInsertSpaceInButton?: boolean;
form?: {
validateMessages?: ValidateMessages;
requiredMark?: RequiredMark;
};
input?: {
autoComplete?: string;
@ -130,8 +132,11 @@ const ConfigProvider: React.FC<ConfigProviderProps> & {
config.input = input;
}
let childNode = children;
if (form) {
config.form = form;
}
let childNode = children;
// Additional Form provider
let validateMessages: ValidateMessages = {};

View File

@ -44,7 +44,7 @@ export default () => (
| csp | 设置 [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) 配置 | { nonce: string } | - | |
| direction | 设置文本展示方向。 [示例](#components-config-provider-demo-direction) | `ltr` \| `rtl` | `ltr` | |
| dropdownMatchSelectWidth | 下拉菜单和选择器同宽。默认将设置 `min-width`,当值小于选择框宽度时会被忽略。`false` 时会关闭虚拟滚动 | boolean \| number | - | 4.3.0 |
| form | 设置 Form 组件的通用属性 | { validateMessages?: [ValidateMessages](/components/form/#validateMessages) } | - | |
| form | 设置 Form 组件的通用属性 | { validateMessages?: [ValidateMessages](/components/form/#validateMessages), requiredMark?: boolean \| `optional` } | - | requiredMark: 4.8.0 |
| getPopupContainer | 弹出框Select, Tooltip, Menu 等等)渲染父节点,默认渲染到 body 上。 | function(triggerNode) | () => document.body | |
| getTargetContainer | 配置 Affix、Anchor 滚动监听容器。 | () => HTMLElement | () => window | 4.2.0 |
| input | 设置 Input 组件的通用属性 | { autoComplete?: string } | - | 4.2.0 |

View File

@ -5,7 +5,7 @@ import FieldForm, { List } from 'rc-field-form';
import { FormProps as RcFormProps } from 'rc-field-form/lib/Form';
import { ValidateErrorEntity } from 'rc-field-form/lib/interface';
import { ColProps } from '../grid/col';
import { ConfigContext, ConfigConsumerProps } from '../config-provider';
import { ConfigContext } from '../config-provider';
import { FormContext, FormContextProps } from './context';
import { FormLabelAlign } from './interface';
import useForm, { FormInstance } from './hooks/useForm';
@ -32,7 +32,7 @@ export interface FormProps<Values = any> extends Omit<RcFormProps<Values>, 'form
const InternalForm: React.ForwardRefRenderFunction<unknown, FormProps> = (props, ref) => {
const contextSize = React.useContext(SizeContext);
const { getPrefixCls, direction }: ConfigConsumerProps = React.useContext(ConfigContext);
const { getPrefixCls, direction, form: contextForm } = React.useContext(ConfigContext);
const { name } = props;
@ -58,12 +58,16 @@ const InternalForm: React.ForwardRefRenderFunction<unknown, FormProps> = (props,
return requiredMark;
}
if (contextForm && contextForm.requiredMark !== undefined) {
return contextForm.requiredMark;
}
if (hideRequiredMark) {
return false;
}
return true;
}, [hideRequiredMark, requiredMark]);
}, [hideRequiredMark, requiredMark, contextForm]);
const prefixCls = getPrefixCls('form', customizePrefixCls);

View File

@ -31,6 +31,7 @@ Previewable image.
{
visible?: boolean;
onVisibleChange?: (visible, prevVisible) => void;
getContainer?: string | HTMLElement | (() => HTMLElement); // V4.8.0
}
```

View File

@ -32,6 +32,7 @@ cover: https://gw.alipayobjects.com/zos/antfincdn/D1dXz9PZqa/image.svg
{
visible?: boolean;
onVisibleChange?: (visible, prevVisible) => void;
getContainer: string | HTMLElement | (() => HTMLElement); // V4.8.0
}
```

View File

@ -5,12 +5,14 @@ import classNames from 'classnames';
import ClearableLabeledInput from './ClearableLabeledInput';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import { fixControlledValue, resolveOnChange } from './Input';
import SizeContext, { SizeType } from '../config-provider/SizeContext';
export interface TextAreaProps extends RcTextAreaProps {
allowClear?: boolean;
bordered?: boolean;
showCount?: boolean;
maxLength?: number;
size?: SizeType;
}
export interface TextAreaState {
@ -76,15 +78,17 @@ class TextArea extends React.Component<TextAreaProps, TextAreaState> {
resolveOnChange(this.resizableTextArea.textArea, e, this.props.onChange);
};
renderTextArea = (prefixCls: string, bordered: boolean) => {
const { showCount, className, style } = this.props;
renderTextArea = (prefixCls: string, bordered: boolean, size?: SizeType) => {
const { showCount, className, style, size: customizeSize } = this.props;
return (
<RcTextArea
{...omit(this.props, ['allowClear', 'bordered', 'showCount'])}
{...omit(this.props, ['allowClear', 'bordered', 'showCount', 'size'])}
className={classNames({
[`${prefixCls}-borderless`]: !bordered,
[className!]: className && !showCount,
[`${prefixCls}-sm`]: size === 'small' || customizeSize === 'small',
[`${prefixCls}-lg`]: size === 'large' || customizeSize === 'large',
})}
style={showCount ? null : style}
prefixCls={prefixCls}
@ -112,14 +116,14 @@ class TextArea extends React.Component<TextAreaProps, TextAreaState> {
value = hasMaxLength ? value.slice(0, maxLength) : value;
// TextArea
let textareaNode = (
const textareaNode = (size?: SizeType) => (
<ClearableLabeledInput
{...this.props}
prefixCls={prefixCls}
direction={direction}
inputType="text"
value={value}
element={this.renderTextArea(prefixCls, bordered)}
element={this.renderTextArea(prefixCls, bordered, size)}
handleReset={this.handleReset}
ref={this.saveClearableInput}
triggerFocus={this.focus}
@ -132,25 +136,29 @@ class TextArea extends React.Component<TextAreaProps, TextAreaState> {
const valueLength = [...value].length;
const dataCount = `${valueLength}${hasMaxLength ? ` / ${maxLength}` : ''}`;
textareaNode = (
<div
className={classNames(
`${prefixCls}-textarea`,
{
[`${prefixCls}-textarea-rtl`]: direction === 'rtl',
},
`${prefixCls}-textarea-show-count`,
className,
return (
<SizeContext.Consumer>
{(size?: SizeType) => (
<div
className={classNames(
`${prefixCls}-textarea`,
{
[`${prefixCls}-textarea-rtl`]: direction === 'rtl',
},
`${prefixCls}-textarea-show-count`,
className,
)}
style={style}
data-count={dataCount}
>
{textareaNode(size)}
</div>
)}
style={style}
data-count={dataCount}
>
{textareaNode}
</div>
</SizeContext.Consumer>
);
}
return textareaNode;
return <SizeContext.Consumer>{textareaNode}</SizeContext.Consumer>;
};
render() {

View File

@ -263,3 +263,9 @@ exports[`TextArea should support maxLength 1`] = `
maxlength="10"
/>
`;
exports[`TextArea should support size 1`] = `
<textarea
class="ant-input ant-input-lg"
/>
`;

View File

@ -155,6 +155,12 @@ describe('TextArea', () => {
expect(wrapper.find('.ant-input').props().style.background).toBeFalsy();
});
});
it('should support size', async () => {
const wrapper = mount(<TextArea size="large" />);
expect(wrapper.find('textarea').hasClass('ant-input-lg')).toBe(true);
expect(wrapper.render()).toMatchSnapshot();
});
});
describe('TextArea allowClear', () => {

View File

@ -31,6 +31,7 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
direction,
prefixCls,
rootPrefixCls,
bodyStyle,
} = props;
devWarning(
@ -95,7 +96,7 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
getContainer={getContainer}
>
<div className={`${contentPrefixCls}-body-wrapper`}>
<div className={`${contentPrefixCls}-body`}>
<div className={`${contentPrefixCls}-body`} style={bodyStyle}>
{icon}
{props.title === undefined ? null : (
<span className={`${contentPrefixCls}-title`}>{props.title}</span>

View File

@ -114,6 +114,7 @@ export interface ModalFuncProps {
transitionName?: string;
maskTransitionName?: string;
direction?: string;
bodyStyle?: React.CSSProperties;
}
export interface ModalLocale {

View File

@ -244,7 +244,7 @@ describe('Modal.confirm triggers callbacks correctly', () => {
jest.useRealTimers();
});
it('could be update', () => {
it('could be update by new config', () => {
jest.useFakeTimers();
['info', 'success', 'warning', 'error'].forEach(type => {
const instance = Modal[type]({
@ -273,6 +273,49 @@ describe('Modal.confirm triggers callbacks correctly', () => {
jest.useRealTimers();
});
it('could be update by call function', () => {
jest.useFakeTimers();
['info', 'success', 'warning', 'error'].forEach(type => {
const instance = Modal[type]({
title: 'title',
okButtonProps: {
loading: true,
style: {
color: 'red',
},
},
});
act(() => {
jest.runAllTimers();
});
expect($$(`.ant-modal-confirm-${type}`)).toHaveLength(1);
expect($$('.ant-modal-confirm-title')[0].innerHTML).toBe('title');
expect($$('.ant-modal-confirm-btns .ant-btn-primary')[0].classList).toContain(
'ant-btn-loading',
);
expect($$('.ant-modal-confirm-btns .ant-btn-primary')[0].style.color).toBe('red');
instance.update(prevConfig => ({
...prevConfig,
okButtonProps: {
...prevConfig.okButtonProps,
loading: false,
},
}));
act(() => {
jest.runAllTimers();
});
expect($$(`.ant-modal-confirm-${type}`)).toHaveLength(1);
expect($$('.ant-modal-confirm-title')[0].innerHTML).toBe('title');
expect($$('.ant-modal-confirm-btns .ant-btn-primary')[0].classList).not.toContain(
'ant-btn-loading',
);
expect($$('.ant-modal-confirm-btns .ant-btn-primary')[0].style.color).toBe('red');
instance.destroy();
jest.runAllTimers();
});
jest.useRealTimers();
});
it('could be destroy', () => {
jest.useFakeTimers();
['info', 'success', 'warning', 'error'].forEach(type => {

View File

@ -14,11 +14,13 @@ function getRootPrefixCls() {
return defaultRootPrefixCls;
}
type ConfigUpdate = ModalFuncProps | ((prevConfig: ModalFuncProps) => ModalFuncProps);
export type ModalFunc = (
props: ModalFuncProps,
) => {
destroy: () => void;
update: (newConfig: ModalFuncProps) => void;
update: (configUpdate: ConfigUpdate) => void;
};
export interface ModalStaticFunctions {
@ -84,11 +86,15 @@ export default function confirm(config: ModalFuncProps) {
render(currentConfig);
}
function update(newConfig: ModalFuncProps) {
currentConfig = {
...currentConfig,
...newConfig,
};
function update(configUpdate: ConfigUpdate) {
if (typeof configUpdate === 'function') {
currentConfig = configUpdate(currentConfig);
} else {
currentConfig = {
...currentConfig,
...configUpdate,
};
}
render(currentConfig);
}

View File

@ -65,6 +65,7 @@ The items listed above are all functions, expecting a settings object as paramet
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| autoFocusButton | Specify which button to autofocus | null \| `ok` \| `cancel` | `ok` | |
| bodyStyle | Body style for modal body element. Such as height, padding etc | CSSProperties | | 4.8.0 |
| cancelButtonProps | The cancel button props | [ButtonProps](/components/button/#API) | - | |
| cancelText | Text of the Cancel button with Modal.confirm | string | `Cancel` | |
| centered | Centered Modal | boolean | false | |
@ -96,6 +97,12 @@ modal.update({
content: 'Updated content',
});
// on 4.8.0 or above, you can pass a function to update modal
modal.update(prevConfig => ({
...prevConfig,
title: `${prevConfig.title} (New)`,
}));
modal.destroy();
```

View File

@ -68,6 +68,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/3StSdUlSH/Modal.svg
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| autoFocusButton | 指定自动获得焦点的按钮 | null \| `ok` \| `cancel` | `ok` | |
| bodyStyle | Modal body 样式 | CSSProperties | | 4.8.0 |
| cancelButtonProps | cancel 按钮 props | [ButtonProps](/components/button/#API) | - | |
| cancelText | 设置 Modal.confirm 取消按钮文字 | string | `取消` | |
| centered | 垂直居中展示 Modal | boolean | false | |
@ -99,6 +100,12 @@ modal.update({
content: '修改的内容',
});
// 在 4.8.0 或更高版本中,可以通过传入函数的方式更新弹窗
modal.update(prevConfig => ({
...prevConfig,
title: `${prevConfig.title}(新)`,
}));
modal.destroy();
```

View File

@ -3,6 +3,7 @@ import classNames from 'classnames';
import { ConfigConsumerProps } from '../config-provider';
import { withConfigConsumer } from '../config-provider/context';
import Skeleton from '../skeleton';
import StatisticNumber from './Number';
import Countdown from './Countdown';
import { valueType, FormatConfig } from './utils';
@ -21,6 +22,7 @@ export interface StatisticProps extends FormatConfig {
title?: React.ReactNode;
prefix?: React.ReactNode;
suffix?: React.ReactNode;
loading?: boolean;
onMouseEnter?: React.MouseEventHandler<HTMLDivElement>;
onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;
}
@ -36,6 +38,7 @@ const Statistic: React.FC<StatisticProps & ConfigConsumerProps> = props => {
valueRender,
prefix,
suffix,
loading,
direction,
onMouseEnter,
onMouseLeave,
@ -51,11 +54,13 @@ const Statistic: React.FC<StatisticProps & ConfigConsumerProps> = props => {
return (
<div className={cls} style={style} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>
{title && <div className={`${prefixCls}-title`}>{title}</div>}
<div style={valueStyle} className={`${prefixCls}-content`}>
{prefix && <span className={`${prefixCls}-content-prefix`}>{prefix}</span>}
{valueRender ? valueRender(valueNode) : valueNode}
{suffix && <span className={`${prefixCls}-content-suffix`}>{suffix}</span>}
</div>
<Skeleton paragraph={false} loading={loading}>
<div style={valueStyle} className={`${prefixCls}-content`}>
{prefix && <span className={`${prefixCls}-content-prefix`}>{prefix}</span>}
{valueRender ? valueRender(valueNode) : valueNode}
{suffix && <span className={`${prefixCls}-content-suffix`}>{suffix}</span>}
</div>
</Skeleton>
</div>
);
};
@ -63,6 +68,7 @@ const Statistic: React.FC<StatisticProps & ConfigConsumerProps> = props => {
Statistic.defaultProps = {
decimalSeparator: '.',
groupSeparator: ',',
loading: false,
};
const WrapperStatistic = withConfigConsumer<StatisticProps>({

View File

@ -73,6 +73,31 @@ exports[`renders ./components/statistic/demo/basic.md correctly 1`] = `
</span>
</button>
</div>
<div
class="ant-col ant-col-12"
style="padding-left:8px;padding-right:8px"
>
<div
class="ant-statistic"
>
<div
class="ant-statistic-title"
>
Active Users
</div>
<div
class="ant-skeleton"
>
<div
class="ant-skeleton-content"
>
<h3
class="ant-skeleton-title"
/>
</div>
</div>
</div>
</div>
</div>
`;

View File

@ -50,6 +50,18 @@ describe('Statistic', () => {
expect(wrapper.render()).toMatchSnapshot();
});
it('loading with skeleton', async () => {
let loading = false;
const wrapper = mount(<Statistic title="Active Users" value={112112} loading={loading} />);
expect(wrapper.find('.ant-skeleton')).toHaveLength(0);
expect(wrapper.find('.ant-statistic-content')).toHaveLength(1);
loading = true;
wrapper.setProps({ loading });
expect(wrapper.find('.ant-skeleton')).toHaveLength(1);
expect(wrapper.find('.ant-statistic-content')).toHaveLength(0);
});
describe('Countdown', () => {
it('render correctly', () => {
const now = moment().add(2, 'd').add(11, 'h').add(28, 'm').add(9, 's').add(3, 'ms');

View File

@ -27,6 +27,9 @@ ReactDOM.render(
Recharge
</Button>
</Col>
<Col span={12}>
<Statistic title="Active Users" value={112893} loading />
</Col>
</Row>,
mountNode,
);

View File

@ -21,6 +21,7 @@ Display statistic number.
| decimalSeparator | The decimal separator | string | `.` | |
| formatter | Customize value display logic | (value) => ReactNode | - | |
| groupSeparator | Group separator | string | `,` | |
| loading | Loading status of Statistic | boolean | false | 4.8.0 |
| precision | The precision of input value | number | - | |
| prefix | The prefix node of value | ReactNode | - | |
| suffix | The suffix node of value | ReactNode | - | |

View File

@ -22,6 +22,7 @@ cover: https://gw.alipayobjects.com/zos/antfincdn/rcBNhLBrKbE/Statistic.svg
| decimalSeparator | 设置小数点 | string | `.` | |
| formatter | 自定义数值展示 | (value) => ReactNode | - | |
| groupSeparator | 设置千分位标识符 | string | `,` | |
| loading | 数值是否加载中 | boolean | false | 4.8.0 |
| precision | 数值精度 | number | - | |
| prefix | 设置数值的前缀 | ReactNode | - | |
| suffix | 设置数值的后缀 | ReactNode | - | |

View File

@ -1,2 +1,5 @@
import '../../style/index.less';
import './index.less';
// style dependencies
import '../../skeleton/style';

View File

@ -126,7 +126,7 @@
"rc-drawer": "~4.1.0",
"rc-dropdown": "~3.2.0",
"rc-field-form": "~1.13.0",
"rc-image": "~3.2.1",
"rc-image": "~4.0.0",
"rc-input-number": "~6.1.0",
"rc-mentions": "~1.5.0",
"rc-menu": "~8.8.2",