Browse Source

chore: Add demo tsx check (#28389)

* chore: Add demo tsx check

* chore: Prettier

* chore: Fix lint

* fix: Upload ts definition

* chore: Demo onlt

* docs: Fix demo

* chore: Add CI action

* chore: Use real name

* chore: fix ts define

* chore: fix more ts

* chore: fix more ts

* chore: More ts

* chore: More ts

* chore: More ts

* chore: More ts

* chore: More ts

* chore: More ts

* chore: More ts

* chore: Update all rest TS demo

* fix test case
pull/28400/head
二货机器人 4 years ago
committed by GitHub
parent
commit
55e0d13234
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/form/demo/advanced-search.md
  10. 4
      components/form/demo/basic.md
  11. 4
      components/form/demo/control-hooks.md
  12. 14
      components/form/demo/control-ref.md
  13. 18
      components/form/demo/customized-form-controls.md
  14. 2
      components/form/demo/dynamic-rule.md
  15. 14
      components/form/demo/form-context.md
  16. 2
      components/form/demo/form-in-modal.md
  17. 14
      components/form/demo/global-state.md
  18. 6
      components/form/demo/inline-login.md
  19. 6
      components/form/demo/layout.md
  20. 2
      components/form/demo/nest-messages.md
  21. 2
      components/form/demo/normal-login.md
  22. 9
      components/form/demo/register.md
  23. 6
      components/form/demo/required-mark.md
  24. 10
      components/form/demo/size.md
  25. 6
      components/form/demo/time-related-controls.md
  26. 4
      components/form/demo/validate-other.md
  27. 14
      components/form/demo/without-form-create.md
  28. 6
      components/mentions/demo/form.md
  29. 40
      components/table/__tests__/__snapshots__/demo.test.js.snap
  30. 50
      components/table/demo/edit-cell.md
  31. 8
      components/table/demo/edit-row.md
  32. 18
      components/table/demo/row-selection.md
  33. 30
      components/table/demo/virtual-list.md
  34. 12
      components/tree/demo/basic-controlled.md
  35. 4
      components/tree/demo/basic.md
  36. 4
      components/tree/demo/directory.md
  37. 4
      components/tree/demo/dynamic.md
  38. 14
      components/tree/demo/line.md
  39. 1
      components/upload/Upload.tsx
  40. 15
      components/upload/interface.tsx
  41. 6
      package.json
  42. 88
      scripts/check-ts-demo.js
  43. 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/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>

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>

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

@ -231,6 +231,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;

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.2.0",
"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