Browse Source

Merge pull request #28401 from ant-design/merge

chore: merge master info feature
pull/28402/head
偏右 4 years ago
committed by GitHub
parent
commit
e3c5581555
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      .eslintignore
  2. 22
      .github/workflows/test.yml
  3. 2
      components/affix/demo/target.md
  4. 2
      components/alert/__tests__/__snapshots__/demo.test.ts.snap
  5. 2
      components/alert/demo/error-boundary.md
  6. 2
      components/auto-complete/demo/non-case-sensitive.md
  7. 2
      components/auto-complete/demo/uncertain-category.md
  8. 4
      components/drawer/demo/config-provider.md
  9. 2
      components/drawer/index.zh-CN.md
  10. 2
      components/form/demo/advanced-search.md
  11. 4
      components/form/demo/basic.md
  12. 4
      components/form/demo/control-hooks.md
  13. 14
      components/form/demo/control-ref.md
  14. 18
      components/form/demo/customized-form-controls.md
  15. 2
      components/form/demo/dynamic-rule.md
  16. 14
      components/form/demo/form-context.md
  17. 2
      components/form/demo/form-in-modal.md
  18. 14
      components/form/demo/global-state.md
  19. 6
      components/form/demo/inline-login.md
  20. 6
      components/form/demo/layout.md
  21. 2
      components/form/demo/nest-messages.md
  22. 2
      components/form/demo/normal-login.md
  23. 9
      components/form/demo/register.md
  24. 6
      components/form/demo/required-mark.md
  25. 10
      components/form/demo/size.md
  26. 6
      components/form/demo/time-related-controls.md
  27. 4
      components/form/demo/validate-other.md
  28. 14
      components/form/demo/without-form-create.md
  29. 6
      components/mentions/demo/form.md
  30. 10
      components/message/index.zh-CN.md
  31. 40
      components/table/__tests__/__snapshots__/demo.test.js.snap
  32. 50
      components/table/demo/edit-cell.md
  33. 8
      components/table/demo/edit-row.md
  34. 18
      components/table/demo/row-selection.md
  35. 30
      components/table/demo/virtual-list.md
  36. 2
      components/table/index.en-US.md
  37. 2
      components/table/index.zh-CN.md
  38. 12
      components/tree/demo/basic-controlled.md
  39. 4
      components/tree/demo/basic.md
  40. 4
      components/tree/demo/directory.md
  41. 4
      components/tree/demo/dynamic.md
  42. 14
      components/tree/demo/line.md
  43. 1
      components/upload/Upload.tsx
  44. 15
      components/upload/interface.tsx
  45. 2
      docs/spec/illustration.en-US.md
  46. 2
      docs/spec/illustration.zh-CN.md
  47. 6
      package.json
  48. 88
      scripts/check-ts-demo.js
  49. 2
      typings/custom-typings.d.ts

3
.eslintignore

@ -3,6 +3,7 @@ components/**/*.jsx
!components/*/__tests__/**/*.js
!components/*/demo/*
!.*.js
~*
# Docs templates
site/theme/template/Color/ColorPicker.jsx
site/theme/template/IconDisplay/*.js
@ -27,4 +28,4 @@ coverage
**/*.d.ts
# Scripts
scripts/previewEditor/**/*
jest-stare
jest-stare

22
.github/workflows/test.yml

@ -95,6 +95,28 @@ jobs:
run: npm run lint
needs: setup
tsx-demo:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
- name: restore cache from package-lock.json
uses: actions/cache@v2
with:
path: package-temp-dir
key: lock-${{ github.sha }}
- name: restore cache from node_modules
uses: actions/cache@v2
with:
path: node_modules
key: node_modules-${{ hashFiles('**/package-temp-dir/package-lock.json') }}
- name: tsx-demo
run: npm run check-ts-demo
needs: setup
check_metadata:
runs-on: ubuntu-latest
steps:

2
components/affix/demo/target.md

@ -18,7 +18,7 @@ import React, { useState } from 'react';
import { Affix, Button } from 'antd';
const Demo: React.FC = () => {
const [container, setContainer] = useState(null);
const [container, setContainer] = useState<HTMLDivElement | null>(null);
return (
<div className="scrollable-container" ref={setContainer}>
<div className="background">

2
components/alert/__tests__/__snapshots__/demo.test.ts.snap

@ -996,7 +996,7 @@ Array [
exports[`renders ./components/alert/demo/error-boundary.md correctly 1`] = `
<button
class="ant-btn ant-btn-danger"
class="ant-btn ant-btn-dangerous"
type="button"
>
<span>

2
components/alert/demo/error-boundary.md

@ -28,7 +28,7 @@ const ThrowError: React.FC = () => {
throw error;
}
return (
<Button type="danger" onClick={onClick}>
<Button danger onClick={onClick}>
Click me to throw a error
</Button>
);

2
components/auto-complete/demo/non-case-sensitive.md

@ -28,7 +28,7 @@ const Complete: React.FC = () => (
options={options}
placeholder="try to type `b`"
filterOption={(inputValue, option) =>
option.value.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1
option!.value.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1
}
/>
);

2
components/auto-complete/demo/uncertain-category.md

@ -26,7 +26,7 @@ const searchResult = (query: string) => {
return new Array(getRandomInt(5))
.join('.')
.split('.')
.map((item, idx) => {
.map((_, idx) => {
const category = `${query}${idx}`;
return {
value: category,

4
components/drawer/demo/config-provider.md

@ -19,7 +19,7 @@ import React, { useState, useRef } from 'react';
import { Drawer, ConfigProvider, Button } from 'antd';
const App: React.FC = () => {
const domRef = useRef();
const domRef = useRef<HTMLDivElement>(null);
const [visible, setVisible] = useState(false);
const showDrawer = () => {
setVisible(true);
@ -30,7 +30,7 @@ const App: React.FC = () => {
return (
<ConfigProvider
getPopupContainer={() => {
return domRef.current;
return domRef.current!;
}}
>
<div ref={domRef} className="site-drawer-render-in-current-wrapper">

2
components/drawer/index.zh-CN.md

@ -10,7 +10,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/7z8NJQhFb/Drawer.svg
## 何时使用
抽屉从父窗体边缘滑入,覆盖住部分父窗体内容。用户在抽屉内操作时不必离开当前任务,操作完成后,可以平滑地回到原任务。
抽屉从父窗体边缘滑入,覆盖住部分父窗体内容。用户在抽屉内操作时不必离开当前任务,操作完成后,可以平滑地回到原任务。
- 当需要一个附加的面板来控制父窗体内容,这个面板在需要时呼出。比如,控制界面展示样式,往界面中添加内容。
- 当需要在当前任务流中插入临时任务,创建或预览附加内容。比如展示协议条款,创建子对象。

2
components/form/demo/advanced-search.md

@ -52,7 +52,7 @@ const AdvancedSearchForm = () => {
return children;
};
const onFinish = values => {
const onFinish = (values: any) => {
console.log('Received values of form: ', values);
};

4
components/form/demo/basic.md

@ -25,11 +25,11 @@ const tailLayout = {
};
const Demo = () => {
const onFinish = values => {
const onFinish = (values: any) => {
console.log('Success:', values);
};
const onFinishFailed = errorInfo => {
const onFinishFailed = (errorInfo: any) => {
console.log('Failed:', errorInfo);
};

4
components/form/demo/control-hooks.md

@ -33,7 +33,7 @@ const tailLayout = {
const Demo = () => {
const [form] = Form.useForm();
const onGenderChange = value => {
const onGenderChange = (value: string) => {
switch (value) {
case 'male':
form.setFieldsValue({ note: 'Hi, man!' });
@ -47,7 +47,7 @@ const Demo = () => {
}
};
const onFinish = values => {
const onFinish = (values: any) => {
console.log(values);
};

14
components/form/demo/control-ref.md

@ -30,30 +30,30 @@ const tailLayout = {
class Demo extends React.Component {
formRef = React.createRef<FormInstance>();
onGenderChange = value => {
onGenderChange = (value: string) => {
switch (value) {
case 'male':
this.formRef.current.setFieldsValue({ note: 'Hi, man!' });
this.formRef.current!.setFieldsValue({ note: 'Hi, man!' });
return;
case 'female':
this.formRef.current.setFieldsValue({ note: 'Hi, lady!' });
this.formRef.current!.setFieldsValue({ note: 'Hi, lady!' });
return;
case 'other':
this.formRef.current.setFieldsValue({ note: 'Hi there!' });
this.formRef.current!.setFieldsValue({ note: 'Hi there!' });
return;
}
};
onFinish = values => {
onFinish = (values: any) => {
console.log(values);
};
onReset = () => {
this.formRef.current.resetFields();
this.formRef.current!.resetFields();
};
onFill = () => {
this.formRef.current.setFieldsValue({
this.formRef.current!.setFieldsValue({
note: 'Hello world!',
gender: 'male',
});

18
components/form/demo/customized-form-controls.md

@ -25,9 +25,11 @@ import { Form, Input, Select, Button } from 'antd';
const { Option } = Select;
type Currency = 'rmb' | 'dollar';
interface PriceValue {
number?: number;
currency?: 'rmb' | 'dollar';
currency?: Currency;
}
interface PriceInputProps {
@ -37,16 +39,16 @@ interface PriceInputProps {
const PriceInput: React.FC<PriceInputProps> = ({ value = {}, onChange }) => {
const [number, setNumber] = useState(0);
const [currency, setCurrency] = useState('rmb');
const [currency, setCurrency] = useState<Currency>('rmb');
const triggerChange = changedValue => {
const triggerChange = (changedValue: { number?: number; currency?: Currency }) => {
if (onChange) {
onChange({ number, currency, ...value, ...changedValue });
}
};
const onNumberChange = e => {
const newNumber = parseInt(e.target.value || 0, 10);
const onNumberChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newNumber = parseInt(e.target.value || '0', 10);
if (Number.isNaN(number)) {
return;
}
@ -56,7 +58,7 @@ const PriceInput: React.FC<PriceInputProps> = ({ value = {}, onChange }) => {
triggerChange({ number: newNumber });
};
const onCurrencyChange = newCurrency => {
const onCurrencyChange = (newCurrency: Currency) => {
if (!('currency' in value)) {
setCurrency(newCurrency);
}
@ -84,11 +86,11 @@ const PriceInput: React.FC<PriceInputProps> = ({ value = {}, onChange }) => {
};
const Demo = () => {
const onFinish = values => {
const onFinish = (values: any) => {
console.log('Received values from form: ', values);
};
const checkPrice = (rule, value) => {
const checkPrice = (_: any, value: { number: number }) => {
if (value.number > 0) {
return Promise.resolve();
}

2
components/form/demo/dynamic-rule.md

@ -34,7 +34,7 @@ const DynamicRule = () => {
form.validateFields(['nickname']);
}, [checkNick]);
const onCheckboxChange = e => {
const onCheckboxChange = (e: { target: { checked: boolean } }) => {
setCheckNick(e.target.checked);
};

14
components/form/demo/form-context.md

@ -17,6 +17,7 @@ Use `Form.Provider` to process data between forms. In this case, submit button i
import React, { useState, useEffect, useRef } from 'react';
import { Form, Input, InputNumber, Modal, Button, Avatar, Typography } from 'antd';
import { SmileOutlined, UserOutlined } from '@ant-design/icons';
import { FormInstance } from 'antd/lib/form';
const layout = {
labelCol: { span: 8 },
@ -26,14 +27,19 @@ const tailLayout = {
wrapperCol: { offset: 8, span: 16 },
};
interface UserType {
name: string;
age: string;
}
interface ModalFormProps {
visible: boolean;
onCancel: () => void;
}
// reset form fields when modal is form, closed
const useResetFormOnCloseModal = ({ form, visible }) => {
const prevVisibleRef = useRef();
const useResetFormOnCloseModal = ({ form, visible }: { form: FormInstance; visible: boolean }) => {
const prevVisibleRef = useRef<boolean>();
useEffect(() => {
prevVisibleRef.current = visible;
}, [visible]);
@ -83,7 +89,7 @@ const Demo = () => {
setVisible(false);
};
const onFinish = values => {
const onFinish = (values: any) => {
console.log('Finish:', values);
};
@ -108,7 +114,7 @@ const Demo = () => {
shouldUpdate={(prevValues, curValues) => prevValues.users !== curValues.users}
>
{({ getFieldValue }) => {
const users = getFieldValue('users') || [];
const users: UserType[] = getFieldValue('users') || [];
return users.length ? (
<ul>
{users.map((user, index) => (

2
components/form/demo/form-in-modal.md

@ -86,7 +86,7 @@ const CollectionCreateForm: React.FC<CollectionCreateFormProps> = ({
const CollectionsPage = () => {
const [visible, setVisible] = useState(false);
const onCreate = values => {
const onCreate = (values: any) => {
console.log('Received values of form: ', values);
setVisible(false);
};

14
components/form/demo/global-state.md

@ -22,11 +22,11 @@ import React, { useState } from 'react';
import { Form, Input } from 'antd';
interface FieldData {
name: string[];
value: any;
touched: boolean;
validating: boolean;
errors: string[];
name: string | number | (string | number)[];
value?: any;
touched?: boolean;
validating?: boolean;
errors?: string[];
}
interface CustomizedFormProps {
@ -40,7 +40,7 @@ const CustomizedForm: React.FC<CustomizedFormProps> = ({ onChange, fields }) =>
name="global_state"
layout="inline"
fields={fields}
onFieldsChange={(changedFields, allFields) => {
onFieldsChange={(_, allFields) => {
onChange(allFields);
}}
>
@ -56,7 +56,7 @@ const CustomizedForm: React.FC<CustomizedFormProps> = ({ onChange, fields }) =>
};
const Demo = () => {
const [fields, setFields] = useState([{ name: ['username'], value: 'Ant Design' }]);
const [fields, setFields] = useState<FieldData[]>([{ name: ['username'], value: 'Ant Design' }]);
return (
<>

6
components/form/demo/inline-login.md

@ -20,14 +20,14 @@ import { UserOutlined, LockOutlined } from '@ant-design/icons';
const HorizontalLoginForm = () => {
const [form] = Form.useForm();
const [, forceUpdate] = useState();
const [, forceUpdate] = useState({});
// To disable submit button at the beginning.
useEffect(() => {
forceUpdate({});
}, []);
const onFinish = values => {
const onFinish = (values: any) => {
console.log('Finish:', values);
};
@ -56,7 +56,7 @@ const HorizontalLoginForm = () => {
htmlType="submit"
disabled={
!form.isFieldsTouched(true) ||
form.getFieldsError().filter(({ errors }) => errors.length).length
!!form.getFieldsError().filter(({ errors }) => errors.length).length
}
>
Log in

6
components/form/demo/layout.md

@ -17,11 +17,13 @@ There are three layout for form: `horizontal`, `vertical`, `inline`.
import React, { useState } from 'react';
import { Form, Input, Button, Radio } from 'antd';
type LayoutType = Parameters<typeof Form>[0]['layout'];
const FormLayoutDemo = () => {
const [form] = Form.useForm();
const [formLayout, setFormLayout] = useState('horizontal');
const [formLayout, setFormLayout] = useState<LayoutType>('horizontal');
const onFormLayoutChange = ({ layout }) => {
const onFormLayoutChange = ({ layout }: { layout: LayoutType }) => {
setFormLayout(layout);
};

2
components/form/demo/nest-messages.md

@ -33,7 +33,7 @@ const validateMessages = {
};
const Demo = () => {
const onFinish = values => {
const onFinish = (values: any) => {
console.log(values);
};

2
components/form/demo/normal-login.md

@ -20,7 +20,7 @@ import { Form, Input, Button, Checkbox } from 'antd';
import { UserOutlined, LockOutlined } from '@ant-design/icons';
const NormalLoginForm = () => {
const onFinish = values => {
const onFinish = (values: any) => {
console.log('Received values of form: ', values);
};

9
components/form/demo/register.md

@ -30,7 +30,6 @@ import {
import { QuestionCircleOutlined } from '@ant-design/icons';
const { Option } = Select;
const AutoCompleteOption = AutoComplete.Option;
const residences = [
{
@ -93,7 +92,7 @@ const tailFormItemLayout = {
const RegistrationForm = () => {
const [form] = Form.useForm();
const onFinish = values => {
const onFinish = (values: any) => {
console.log('Received values of form: ', values);
};
@ -106,9 +105,9 @@ const RegistrationForm = () => {
</Form.Item>
);
const [autoCompleteResult, setAutoCompleteResult] = useState([]);
const [autoCompleteResult, setAutoCompleteResult] = useState<string[]>([]);
const onWebsiteChange = value => {
const onWebsiteChange = (value: string) => {
if (!value) {
setAutoCompleteResult([]);
} else {
@ -175,7 +174,7 @@ const RegistrationForm = () => {
message: 'Please confirm your password!',
},
({ getFieldValue }) => ({
validator(rule, value) {
validator(_, value) {
if (!value || getFieldValue('password') === value) {
return Promise.resolve();
}

6
components/form/demo/required-mark.md

@ -18,11 +18,13 @@ import React, { useState } from 'react';
import { Form, Input, Button, Radio } from 'antd';
import { InfoCircleOutlined } from '@ant-design/icons';
type RequiredMark = boolean | 'optional';
const FormLayoutDemo = () => {
const [form] = Form.useForm();
const [requiredMark, setRequiredMarkType] = useState<boolean | 'optional'>('optional');
const [requiredMark, setRequiredMarkType] = useState<RequiredMark>('optional');
const onRequiredTypeChange = ({ requiredMark }) => {
const onRequiredTypeChange = ({ requiredMark }: { requiredMark: RequiredMark }) => {
setRequiredMarkType(requiredMark);
};

10
components/form/demo/size.md

@ -27,9 +27,12 @@ import {
TreeSelect,
Switch,
} from 'antd';
type SizeType = Parameters<typeof Form>[0]['size'];
const FormSizeDemo = () => {
const [componentSize, setComponentSize] = useState('default');
const onFormLayoutChange = ({ size }) => {
const [componentSize, setComponentSize] = useState<SizeType | 'default'>('default');
const onFormLayoutChange = ({ size }: { size: SizeType }) => {
setComponentSize(size);
};
return (
@ -40,7 +43,7 @@ const FormSizeDemo = () => {
layout="horizontal"
initialValues={{ size: componentSize }}
onValuesChange={onFormLayoutChange}
size={componentSize}
size={componentSize as SizeType}
>
<Form.Item label="Form Size" name="size">
<Radio.Group>
@ -96,5 +99,6 @@ const FormSizeDemo = () => {
</>
);
};
ReactDOM.render(<FormSizeDemo />, mountNode);
```

6
components/form/demo/time-related-controls.md

@ -29,14 +29,14 @@ const formItemLayout = {
},
};
const config = {
rules: [{ type: 'object', required: true, message: 'Please select time!' }],
rules: [{ type: 'object' as const, required: true, message: 'Please select time!' }],
};
const rangeConfig = {
rules: [{ type: 'array', required: true, message: 'Please select time!' }],
rules: [{ type: 'array' as const, required: true, message: 'Please select time!' }],
};
const TimeRelatedForm = () => {
const onFinish = fieldsValue => {
const onFinish = (fieldsValue: any) => {
// Should format date value before submit.
const rangeValue = fieldsValue['range-picker'];
const rangeTimeValue = fieldsValue['range-time-picker'];

4
components/form/demo/validate-other.md

@ -37,7 +37,7 @@ const formItemLayout = {
wrapperCol: { span: 14 },
};
const normFile = e => {
const normFile = (e: any) => {
console.log('Upload event:', e);
if (Array.isArray(e)) {
return e;
@ -46,7 +46,7 @@ const normFile = e => {
};
const Demo = () => {
const onFinish = values => {
const onFinish = (values: any) => {
console.log('Received values of form: ', values);
};

14
components/form/demo/without-form-create.md

@ -17,7 +17,11 @@ title:
import React, { useState } from 'react';
import { Form, InputNumber } from 'antd';
function validatePrimeNumber(number) {
type ValidateStatus = Parameters<typeof Form.Item>[0]['validateStatus'];
function validatePrimeNumber(
number: number,
): { validateStatus: ValidateStatus; errorMsg: string | null } {
if (number === 11) {
return {
validateStatus: 'success',
@ -36,14 +40,18 @@ const formItemLayout = {
};
const RawForm = () => {
const [number, setNumber] = useState({
const [number, setNumber] = useState<{
value: number;
validateStatus?: ValidateStatus;
errorMsg?: string | null;
}>({
value: 11,
});
const tips =
'A prime is a natural number greater than 1 that has no positive divisors other than 1 and itself.';
const onNumberChange = value => {
const onNumberChange = (value: number) => {
setNumber({
...validatePrimeNumber(value),
value,

6
components/mentions/demo/form.md

@ -34,7 +34,7 @@ const App = () => {
}
};
const checkMention = async (rule, value, callback) => {
const checkMention = async (_: any, value: string) => {
const mentions = getMentions(value);
if (mentions.length < 2) {
@ -51,7 +51,7 @@ const App = () => {
wrapperCol={{ span: 16 }}
rules={[{ validator: checkMention }]}
>
<Mentions rows="1">
<Mentions rows={1}>
<Option value="afc163">afc163</Option>
<Option value="zombieJ">zombieJ</Option>
<Option value="yesmeck">yesmeck</Option>
@ -64,7 +64,7 @@ const App = () => {
wrapperCol={{ span: 16 }}
rules={[{ required: true }]}
>
<Mentions rows="3" placeholder="You can use @ to ref user here">
<Mentions rows={3} placeholder="You can use @ to ref user here">
<Option value="afc163">afc163</Option>
<Option value="zombieJ">zombieJ</Option>
<Option value="yesmeck">yesmeck</Option>

10
components/message/index.zh-CN.md

@ -25,11 +25,11 @@ cover: https://gw.alipayobjects.com/zos/alicdn/hAkKTIW0K/Message.svg
- `message.warn(content, [duration], onClose)` // alias of warning
- `message.loading(content, [duration], onClose)`
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| content | 提示内容 | ReactNode \| config | - |
| duration | 自动关闭的延时,单位秒。设为 0 时不自动关闭 | number | 3 |
| onClose | 关闭时触发的回调函数 | function | - |
| 参数 | 说明 | 类型 | 默认值 |
| -------- | ------------------------------------------- | ------------------- | ------ |
| content | 提示内容 | ReactNode \| config | - |
| duration | 自动关闭的延时,单位秒。设为 0 时不自动关闭 | number | 3 |
| onClose | 关闭时触发的回调函数 | function | - |
组件同时提供 promise 接口。

40
components/table/__tests__/__snapshots__/demo.test.js.snap

@ -4166,7 +4166,9 @@ exports[`renders ./components/table/demo/edit-row.md correctly 1`] = `
<td
class="ant-table-cell"
>
<a>
<a
class="ant-typography"
>
Edit
</a>
</td>
@ -4193,7 +4195,9 @@ exports[`renders ./components/table/demo/edit-row.md correctly 1`] = `
<td
class="ant-table-cell"
>
<a>
<a
class="ant-typography"
>
Edit
</a>
</td>
@ -4220,7 +4224,9 @@ exports[`renders ./components/table/demo/edit-row.md correctly 1`] = `
<td
class="ant-table-cell"
>
<a>
<a
class="ant-typography"
>
Edit
</a>
</td>
@ -4247,7 +4253,9 @@ exports[`renders ./components/table/demo/edit-row.md correctly 1`] = `
<td
class="ant-table-cell"
>
<a>
<a
class="ant-typography"
>
Edit
</a>
</td>
@ -4274,7 +4282,9 @@ exports[`renders ./components/table/demo/edit-row.md correctly 1`] = `
<td
class="ant-table-cell"
>
<a>
<a
class="ant-typography"
>
Edit
</a>
</td>
@ -4301,7 +4311,9 @@ exports[`renders ./components/table/demo/edit-row.md correctly 1`] = `
<td
class="ant-table-cell"
>
<a>
<a
class="ant-typography"
>
Edit
</a>
</td>
@ -4328,7 +4340,9 @@ exports[`renders ./components/table/demo/edit-row.md correctly 1`] = `
<td
class="ant-table-cell"
>
<a>
<a
class="ant-typography"
>
Edit
</a>
</td>
@ -4355,7 +4369,9 @@ exports[`renders ./components/table/demo/edit-row.md correctly 1`] = `
<td
class="ant-table-cell"
>
<a>
<a
class="ant-typography"
>
Edit
</a>
</td>
@ -4382,7 +4398,9 @@ exports[`renders ./components/table/demo/edit-row.md correctly 1`] = `
<td
class="ant-table-cell"
>
<a>
<a
class="ant-typography"
>
Edit
</a>
</td>
@ -4409,7 +4427,9 @@ exports[`renders ./components/table/demo/edit-row.md correctly 1`] = `
<td
class="ant-table-cell"
>
<a>
<a
class="ant-typography"
>
Edit
</a>
</td>

50
components/table/demo/edit-cell.md

@ -16,8 +16,9 @@ Table with editable cells.
```tsx
import React, { useContext, useState, useEffect, useRef } from 'react';
import { Table, Input, Button, Popconfirm, Form } from 'antd';
import { FormInstance } from 'antd/lib/form';
const EditableContext = React.createContext<any>();
const EditableContext = React.createContext<FormInstance<any> | null>(null);
interface Item {
key: string;
@ -45,7 +46,7 @@ interface EditableCellProps {
title: React.ReactNode;
editable: boolean;
children: React.ReactNode;
dataIndex: string;
dataIndex: keyof Item;
record: Item;
handleSave: (record: Item) => void;
}
@ -60,12 +61,12 @@ const EditableCell: React.FC<EditableCellProps> = ({
...restProps
}) => {
const [editing, setEditing] = useState(false);
const inputRef = useRef();
const form = useContext(EditableContext);
const inputRef = useRef<Input>(null);
const form = useContext(EditableContext)!;
useEffect(() => {
if (editing) {
inputRef.current.focus();
inputRef.current!.focus();
}
}, [editing]);
@ -74,7 +75,7 @@ const EditableCell: React.FC<EditableCellProps> = ({
form.setFieldsValue({ [dataIndex]: record[dataIndex] });
};
const save = async e => {
const save = async () => {
try {
const values = await form.validateFields();
@ -111,9 +112,28 @@ const EditableCell: React.FC<EditableCellProps> = ({
return <td {...restProps}>{childNode}</td>;
};
class EditableTable extends React.Component {
constructor(props) {
type EditableTableProps = Parameters<typeof Table>[0];
interface DataType {
key: React.Key;
name: string;
age: string;
address: string;
}
interface EditableTableState {
dataSource: DataType[];
count: number;
}
type ColumnTypes = Exclude<EditableTableProps['columns'], undefined>;
class EditableTable extends React.Component<EditableTableProps, EditableTableState> {
columns: (ColumnTypes[number] & { editable?: boolean; dataIndex: string })[];
constructor(props: EditableTableProps) {
super(props);
this.columns = [
{
title: 'name',
@ -132,7 +152,7 @@ class EditableTable extends React.Component {
{
title: 'operation',
dataIndex: 'operation',
render: (text, record) =>
render: (_, record: { key: React.Key }) =>
this.state.dataSource.length >= 1 ? (
<Popconfirm title="Sure to delete?" onConfirm={() => this.handleDelete(record.key)}>
<a>Delete</a>
@ -160,17 +180,17 @@ class EditableTable extends React.Component {
};
}
handleDelete = key => {
handleDelete = (key: React.Key) => {
const dataSource = [...this.state.dataSource];
this.setState({ dataSource: dataSource.filter(item => item.key !== key) });
};
handleAdd = () => {
const { count, dataSource } = this.state;
const newData = {
const newData: DataType = {
key: count,
name: `Edward King ${count}`,
age: 32,
age: '32',
address: `London, Park Lane no. ${count}`,
};
this.setState({
@ -179,7 +199,7 @@ class EditableTable extends React.Component {
});
};
handleSave = row => {
handleSave = (row: DataType) => {
const newData = [...this.state.dataSource];
const index = newData.findIndex(item => row.key === item.key);
const item = newData[index];
@ -204,7 +224,7 @@ class EditableTable extends React.Component {
}
return {
...col,
onCell: record => ({
onCell: (record: DataType) => ({
record,
editable: col.editable,
dataIndex: col.dataIndex,
@ -223,7 +243,7 @@ class EditableTable extends React.Component {
rowClassName={() => 'editable-row'}
bordered
dataSource={dataSource}
columns={columns}
columns={columns as ColumnTypes}
/>
</div>
);

8
components/table/demo/edit-row.md

@ -17,7 +17,7 @@ Table with editable rows.
```tsx
import React, { useState } from 'react';
import { Table, Input, InputNumber, Popconfirm, Form } from 'antd';
import { Table, Input, InputNumber, Popconfirm, Form, Typography } from 'antd';
interface Item {
key: string;
@ -86,7 +86,7 @@ const EditableTable = () => {
const isEditing = (record: Item) => record.key === editingKey;
const edit = (record: Item) => {
const edit = (record: Partial<Item> & { key: React.Key }) => {
form.setFieldsValue({ name: '', age: '', address: '', ...record });
setEditingKey(record.key);
};
@ -153,9 +153,9 @@ const EditableTable = () => {
</Popconfirm>
</span>
) : (
<a disabled={editingKey !== ''} onClick={() => edit(record)}>
<Typography.Link disabled={editingKey !== ''} onClick={() => edit(record)}>
Edit
</a>
</Typography.Link>
);
},
},

18
components/table/demo/row-selection.md

@ -25,7 +25,7 @@ const columns = [
{
title: 'Name',
dataIndex: 'name',
render: text => <a>{text}</a>,
render: (text: string) => <a>{text}</a>,
},
{
title: 'Age',
@ -36,7 +36,15 @@ const columns = [
dataIndex: 'address',
},
];
const data = [
interface DataType {
key: React.Key;
name: string;
age: number;
address: string;
}
const data: DataType[] = [
{
key: '1',
name: 'John Brown',
@ -65,17 +73,17 @@ const data = [
// rowSelection object indicates the need for row selection
const rowSelection = {
onChange: (selectedRowKeys, selectedRows) => {
onChange: (selectedRowKeys: React.Key[], selectedRows: DataType[]) => {
console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
},
getCheckboxProps: record => ({
getCheckboxProps: (record: DataType) => ({
disabled: record.name === 'Disabled User', // Column configuration not to be checked
name: record.name,
}),
};
const Demo = () => {
const [selectionType, setSelectionType] = useState('checkbox');
const [selectionType, setSelectionType] = useState<'checkbox' | 'radio'>('checkbox');
return (
<div>

30
components/table/demo/virtual-list.md

@ -20,12 +20,12 @@ import ResizeObserver from 'rc-resize-observer';
import classNames from 'classnames';
import { Table } from 'antd';
function VirtualTable(props) {
function VirtualTable(props: Parameters<typeof Table>[0]) {
const { columns, scroll } = props;
const [tableWidth, setTableWidth] = useState(0);
const widthColumnCount = columns.filter(({ width }) => !width).length;
const mergedColumns = columns.map(column => {
const widthColumnCount = columns!.filter(({ width }) => !width).length;
const mergedColumns = columns!.map(column => {
if (column.width) {
return column;
}
@ -69,28 +69,36 @@ function VirtualTable(props) {
ref={gridRef}
className="virtual-grid"
columnCount={mergedColumns.length}
columnWidth={index => {
columnWidth={(index: number) => {
const { width } = mergedColumns[index];
return totalHeight > scroll.y && index === mergedColumns.length - 1
? width - scrollbarSize - 1
: width;
return totalHeight > scroll!.y! && index === mergedColumns.length - 1
? (width as number) - scrollbarSize - 1
: (width as number);
}}
height={scroll.y}
height={scroll!.y as number}
rowCount={rawData.length}
rowHeight={() => 54}
width={tableWidth}
onScroll={({ scrollLeft }) => {
onScroll={({ scrollLeft }: { scrollLeft: number }) => {
onScroll({ scrollLeft });
}}
>
{({ columnIndex, rowIndex, style }) => (
{({
columnIndex,
rowIndex,
style,
}: {
columnIndex: number;
rowIndex: number;
style: React.CSSProperties;
}) => (
<div
className={classNames('virtual-table-cell', {
'virtual-table-cell-last': columnIndex === mergedColumns.length - 1,
})}
style={style}
>
{rawData[rowIndex][mergedColumns[columnIndex].dataIndex]}
{(rawData[rowIndex] as any)[(mergedColumns as any)[columnIndex].dataIndex]}
</div>
)}
</Grid>

2
components/table/index.en-US.md

@ -166,7 +166,7 @@ More about pagination, please check [`Pagination`](/components/pagination/).
Properties for expandable.
| Property | Description | Type | Default |
| --- | --- | --- | --- |
| --- | --- | --- | --- | --- |
| columnWidth | Set the width of the expand column | string \| number | - | |
| childrenColumnName | The column contains children to display | string | children |
| defaultExpandAllRows | Expand all rows initially | boolean | false |

2
components/table/index.zh-CN.md

@ -173,7 +173,7 @@ const columns = [
展开功能的配置。
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| --- | --- | --- | --- | --- |
| columnWidth | 自定义展开列宽度 | string \| number | - | |
| childrenColumnName | 指定树形结构的列名 | string | children |
| defaultExpandAllRows | 初始时,是否展开所有行 | boolean | false |

12
components/tree/demo/basic-controlled.md

@ -62,12 +62,12 @@ const treeData = [
];
const Demo = () => {
const [expandedKeys, setExpandedKeys] = useState<string[]>(['0-0-0', '0-0-1']);
const [checkedKeys, setCheckedKeys] = useState<string[]>(['0-0-0']);
const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
const [expandedKeys, setExpandedKeys] = useState<React.Key[]>(['0-0-0', '0-0-1']);
const [checkedKeys, setCheckedKeys] = useState<React.Key[]>(['0-0-0']);
const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
const [autoExpandParent, setAutoExpandParent] = useState<boolean>(true);
const onExpand = expandedKeys => {
const onExpand = (expandedKeys: React.Key[]) => {
console.log('onExpand', expandedKeys);
// if not set autoExpandParent to false, if children expanded, parent can not collapse.
// or, you can remove all expanded children keys.
@ -75,12 +75,12 @@ const Demo = () => {
setAutoExpandParent(false);
};
const onCheck = checkedKeys => {
const onCheck = (checkedKeys: React.Key[]) => {
console.log('onCheck', checkedKeys);
setCheckedKeys(checkedKeys);
};
const onSelect = (selectedKeys, info) => {
const onSelect = (selectedKeys: React.Key[], info: any) => {
console.log('onSelect', info);
setSelectedKeys(selectedKeys);
};

4
components/tree/demo/basic.md

@ -47,11 +47,11 @@ const treeData = [
];
const Demo = () => {
const onSelect = (selectedKeys, info) => {
const onSelect = (selectedKeys: React.Key[], info: any) => {
console.log('selected', selectedKeys, info);
};
const onCheck = (checkedKeys, info) => {
const onCheck = (checkedKeys: React.Key[], info: any) => {
console.log('onCheck', checkedKeys, info);
};

4
components/tree/demo/directory.md

@ -38,8 +38,8 @@ const treeData = [
];
const Demo: React.FC<{}> = () => {
const onSelect = (keys, event) => {
console.log('Trigger Select', keys, event);
const onSelect = (keys: React.Key[], info: any) => {
console.log('Trigger Select', keys, info);
};
const onExpand = () => {

4
components/tree/demo/dynamic.md

@ -51,8 +51,8 @@ function updateTreeData(list: DataNode[], key: React.Key, children: DataNode[]):
const Demo: React.FC<{}> = () => {
const [treeData, setTreeData] = useState(initTreeDate);
function onLoadData({ key, children }) {
return new Promise(resolve => {
function onLoadData({ key, children }: any) {
return new Promise<void>(resolve => {
if (children) {
resolve();
return;

14
components/tree/demo/line.md

@ -84,20 +84,20 @@ const treeData = [
];
const Demo: React.FC<{}> = () => {
const [showLine, setShowLine] = useState(true);
const [showIcon, setShowIcon] = useState(false);
const [showLeafIcon, setShowLeafIcon] = useState(true);
const [showLine, setShowLine] = useState<boolean | { showLeafIcon: boolean }>(true);
const [showIcon, setShowIcon] = useState<boolean>(false);
const [showLeafIcon, setShowLeafIcon] = useState<boolean>(true);
const onSelect = (selectedKeys, info) => {
const onSelect = (selectedKeys: React.Key[], info: any) => {
console.log('selected', selectedKeys, info);
};
const onSetLeafIcon = checked => {
const onSetLeafIcon = (checked: boolean) => {
setShowLeafIcon(checked);
setShowLine({ showLeafIcon: checked });
};
const onSetShowLine = checked => {
const onSetShowLine = (checked: boolean) => {
if (checked) {
showLeafIcon ? setShowLine(checked) : setShowLine({ showLeafIcon });
} else {
@ -108,7 +108,7 @@ const Demo: React.FC<{}> = () => {
return (
<div>
<div style={{ marginBottom: 16 }}>
showLine: <Switch checked={showLine} onChange={onSetShowLine} />
showLine: <Switch checked={!!showLine} onChange={onSetShowLine} />
<br />
<br />
showIcon: <Switch checked={showIcon} onChange={setShowIcon} />

1
components/upload/Upload.tsx

@ -239,6 +239,7 @@ const InternalUpload: React.ForwardRefRenderFunction<unknown, UploadProps> = (pr
...props,
prefixCls,
beforeUpload,
onChange: undefined,
};
delete rcUploadProps.className;

15
components/upload/interface.tsx

@ -1,4 +1,5 @@
import * as React from 'react';
import { UploadRequestOption as RcCustomRequestOptions } from 'rc-upload/lib/interface';
import { ProgressProps } from '../progress';
export type UploadFileStatus = 'error' | 'success' | 'done' | 'uploading' | 'removed';
@ -13,18 +14,6 @@ export interface RcFile extends File {
readonly webkitRelativePath: string;
}
export interface RcCustomRequestOptions {
onProgress: (event: { percent: number }, file: RcFile) => void;
onError: (error: Error, response?: any, file?: RcFile) => void;
onSuccess: (response: object, file: RcFile) => void;
data: object;
filename: string;
file: RcFile;
withCredentials: boolean;
action: string;
headers: object;
}
export interface UploadFile<T = any> {
uid: string;
size: number;
@ -96,7 +85,7 @@ export interface UploadProps<T = any> {
showUploadList?: boolean | ShowUploadListInterface;
multiple?: boolean;
accept?: string;
beforeUpload?: (file: RcFile, FileList: RcFile[]) => boolean | PromiseLike<void | Blob | File>;
beforeUpload?: (file: RcFile, FileList: RcFile[]) => boolean | Promise<void | Blob | File>;
onChange?: (info: UploadChangeParam) => void;
listType?: UploadListType;
className?: string;

2
docs/spec/illustration.en-US.md

@ -51,7 +51,7 @@ Through research, we discovered blue and white accounts for a large proportion a
<img class="preview-img no-padding" align="right" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*U5L-RKWlmJcAAAAAAAAAAABkARQnAQ" />
Sea Hare's palette combined with Adobe's ternary color picker and mosaic ball, you can easily obtain the Dedult version of the basic color palette.
Sea Hare's palette combined with Adobe's ternary color picker and mosaic ball, you can easily obtain the default version of the basic color palette.
<br />

2
docs/spec/illustration.zh-CN.md

@ -51,7 +51,7 @@ title:
<img class="preview-img no-padding" align="right" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*U5L-RKWlmJcAAAAAAAAAAABkARQnAQ" />
基于 Adobe Color 的三元取色工具,和 3D 立体马赛克球,结合我们自己的海兔色板。可以轻松得到了我们 Dedult 版本的基础色板。
基于 Adobe Color 的三元取色工具,和 3D 立体马赛克球,结合我们自己的海兔色板。可以轻松得到了我们默认版本的基础色板。
<br />

6
package.json

@ -51,6 +51,7 @@
"build": "npm run compile && NODE_OPTIONS='--max-old-space-size=4096' npm run dist",
"bundlesize": "bundlesize",
"check-commit": "node ./scripts/check-commit",
"check-ts-demo": "node ./scripts/check-ts-demo",
"prestart": "npm run version",
"precompile": "npm run version",
"pretest": "npm run version",
@ -122,7 +123,7 @@
"rc-dialog": "~8.4.0",
"rc-drawer": "~4.1.0",
"rc-dropdown": "~3.2.0",
"rc-field-form": "~1.17.0",
"rc-field-form": "~1.17.3",
"rc-image": "~4.3.1",
"rc-input-number": "~6.1.0",
"rc-mentions": "~1.5.0",
@ -144,7 +145,7 @@
"rc-tooltip": "~5.0.0",
"rc-tree": "~4.0.0",
"rc-tree-select": "~4.2.0",
"rc-upload": "~3.3.1",
"rc-upload": "~3.3.4",
"rc-util": "^5.1.0",
"scroll-into-view-if-needed": "^2.2.25",
"warning": "^4.0.3"
@ -167,6 +168,7 @@
"@types/react-color": "^3.0.1",
"@types/react-copy-to-clipboard": "^5.0.0",
"@types/react-dom": "^17.0.0",
"@types/react-window": "^1.8.2",
"@types/warning": "^3.0.0",
"@typescript-eslint/eslint-plugin": "^4.1.1",
"@typescript-eslint/parser": "^4.1.1",

88
scripts/check-ts-demo.js

@ -0,0 +1,88 @@
/* eslint-disable no-await-in-loop, no-console */
const path = require('path');
const glob = require('glob');
const fs = require('fs-extra');
const chalk = require('chalk');
const { spawn } = require('child_process');
(async () => {
console.time('Execution...');
const demoFiles = glob.sync(path.join(process.cwd(), 'components/**/demo/*.md'));
const tmpFolder = path.resolve('components', '~tmp');
await fs.remove(tmpFolder);
await fs.ensureDir(tmpFolder);
function getTypescriptDemo(content, demoPath) {
const lines = content.split(/[\n\r]/);
const tsxStartLine = lines.findIndex(line =>
line.replace(/\s/g).toLowerCase().includes('```tsx'),
);
if (tsxStartLine < 0) {
return null;
}
const tsxEndLine = lines.findIndex(
(line, index) => index > tsxStartLine && line.trim() === '```',
);
let script = lines.slice(tsxStartLine + 1, tsxEndLine).join('\n');
// insert React & ReactDOM
if (!script.includes('import React') && !script.includes('import * as React')) {
script = `import React from 'react';\n${script}`;
}
script = `import ReactDOM from 'react-dom';\n${script}`;
// Replace mountNode
script = script.replace('mountNode', `document.getElementById('#root')`);
// Replace antd
script = script.replace(`from 'antd'`, `from '..'`);
// Add path
script = `/* eslint-disabled */\n// ${demoPath}\n${script}`;
return script;
}
for (let i = 0; i < demoFiles.length; i += 1) {
const demoPath = demoFiles[i];
const content = await fs.readFile(demoPath, 'utf8');
const script = getTypescriptDemo(content, demoPath);
const dirs = path.dirname(demoPath).split(path.sep);
// Parse TSX
if (script) {
const tmpFile = path.join(
tmpFolder,
`${dirs[dirs.length - 2]}-${path.basename(demoPath).replace(/\..*/, '')}.tsx`,
);
await fs.writeFile(tmpFile, script, 'utf8');
}
}
const child = spawn('npm', ['run', 'tsc']);
child.stdout.pipe(process.stdout);
child.stderr.pipe(process.stderr);
child.on('exit', async code => {
console.timeEnd('Execution...');
if (code) {
console.log(chalk.red('💥 OPS! Seems some tsx demo not pass tsc...'));
} else {
await fs.remove(tmpFolder);
console.log(chalk.green('🤪 All tsx demo passed. Congratulations!'));
}
process.exit(code);
});
})();

2
typings/custom-typings.d.ts

@ -50,8 +50,6 @@ declare module 'rc-steps';
declare module 'rc-switch';
declare module 'rc-upload';
declare module '*.json' {
const value: any;
export const version: string;

Loading…
Cancel
Save