feat: fix support options (#38968)

* feat: fix support options

* feat: update package
This commit is contained in:
黑雨 2022-11-25 11:12:59 +08:00 committed by GitHub
parent d989a4e53b
commit 8fd6ae54e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 228 additions and 112 deletions

View File

@ -84,4 +84,24 @@ describe('Mentions', () => {
expect(wrapper.container.querySelectorAll('li.ant-mentions-dropdown-menu-item').length).toBe(1);
expect(wrapper.container.querySelectorAll('.bamboo-light').length).toBeTruthy();
});
it('do not lose label when use children Option', () => {
const wrapper = render(
<Mentions style={{ width: '100%' }}>
<Mentions.Option value="afc163">Afc163</Mentions.Option>
<Mentions.Option value="zombieJ">ZombieJ</Mentions.Option>
<Mentions.Option value="yesmeck">Yesmeck</Mentions.Option>
</Mentions>,
);
simulateInput(wrapper, '@');
const { container } = wrapper;
fireEvent.mouseEnter(container.querySelector('li.ant-mentions-dropdown-menu-item:last-child')!);
fireEvent.focus(container.querySelector('textarea')!);
act(() => {
jest.runAllTimers();
});
expect(
wrapper.container.querySelector('.ant-mentions-dropdown-menu-item-active')?.textContent,
).toBe('Yesmeck');
});
});

View File

@ -2,7 +2,6 @@ import React, { useCallback, useRef, useState } from 'react';
import { Mentions } from 'antd';
import debounce from 'lodash/debounce';
const { Option } = Mentions;
const App: React.FC = () => {
const [loading, setLoading] = useState(false);
const [users, setUsers] = useState<{ login: string; avatar_url: string }[]>([]);
@ -36,14 +35,22 @@ const App: React.FC = () => {
};
return (
<Mentions style={{ width: '100%' }} loading={loading} onSearch={onSearch}>
{users.map(({ login, avatar_url: avatar }) => (
<Option key={login} value={login} className="antd-demo-dynamic-option">
<img src={avatar} alt={login} />
<span>{login}</span>
</Option>
))}
</Mentions>
<Mentions
style={{ width: '100%' }}
loading={loading}
onSearch={onSearch}
options={users.map(({ login, avatar_url: avatar }) => ({
key: login,
value: login,
className: 'antd-demo-dynamic-option',
label: (
<>
<img src={avatar} alt={login} />
<span>{login}</span>
</>
),
}))}
/>
);
};

View File

@ -1,14 +1,25 @@
import React from 'react';
import { Mentions } from 'antd';
const { Option } = Mentions;
const App: React.FC = () => (
<Mentions autoSize style={{ width: '100%' }}>
<Option value="afc163">afc163</Option>
<Option value="zombieJ">zombieJ</Option>
<Option value="yesmeck">yesmeck</Option>
</Mentions>
<Mentions
autoSize
style={{ width: '100%' }}
options={[
{
value: 'afc163',
label: 'afc163',
},
{
value: 'zombieJ',
label: 'zombieJ',
},
{
value: 'yesmeck',
label: 'yesmeck',
},
]}
/>
);
export default App;

View File

@ -1,14 +1,12 @@
import React from 'react';
import { Mentions } from 'antd';
import type { OptionProps } from 'antd/es/mentions';
const { Option } = Mentions;
import type { MentionsOptionProps } from 'antd/es/mentions';
const onChange = (value: string) => {
console.log('Change:', value);
};
const onSelect = (option: OptionProps) => {
const onSelect = (option: MentionsOptionProps) => {
console.log('select', option);
};
@ -18,11 +16,21 @@ const App: React.FC = () => (
onChange={onChange}
onSelect={onSelect}
defaultValue="@afc163"
>
<Option value="afc163">afc163</Option>
<Option value="zombieJ">zombieJ</Option>
<Option value="yesmeck">yesmeck</Option>
</Mentions>
options={[
{
value: 'afc163',
label: 'afc163',
},
{
value: 'zombieJ',
label: 'zombieJ',
},
{
value: 'yesmeck',
label: 'yesmeck',
},
]}
/>
);
export default App;

View File

@ -1,7 +1,7 @@
import React from 'react';
import { Button, Form, Mentions } from 'antd';
const { Option, getMentions } = Mentions;
const { getMentions } = Mentions;
const App: React.FC = () => {
const [form] = Form.useForm();
@ -36,11 +36,23 @@ const App: React.FC = () => {
wrapperCol={{ span: 16 }}
rules={[{ validator: checkMention }]}
>
<Mentions rows={1}>
<Option value="afc163">afc163</Option>
<Option value="zombieJ">zombieJ</Option>
<Option value="yesmeck">yesmeck</Option>
</Mentions>
<Mentions
rows={1}
options={[
{
value: 'afc163',
label: 'afc163',
},
{
value: 'zombieJ',
label: 'zombieJ',
},
{
value: 'yesmeck',
label: 'yesmeck',
},
]}
/>
</Form.Item>
<Form.Item
name="bio"
@ -49,11 +61,24 @@ const App: React.FC = () => {
wrapperCol={{ span: 16 }}
rules={[{ required: true }]}
>
<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>
</Mentions>
<Mentions
rows={3}
placeholder="You can use @ to ref user here"
options={[
{
value: 'afc163',
label: 'afc163',
},
{
value: 'zombieJ',
label: 'zombieJ',
},
{
value: 'yesmeck',
label: 'yesmeck',
},
]}
/>
</Form.Item>
<Form.Item wrapperCol={{ span: 14, offset: 6 }}>
<Button htmlType="submit" type="primary">

View File

@ -1,14 +1,25 @@
import React from 'react';
import { Mentions } from 'antd';
const { Option } = Mentions;
const App: React.FC = () => (
<Mentions style={{ width: '100%' }} placement="top">
<Option value="afc163">afc163</Option>
<Option value="zombieJ">zombieJ</Option>
<Option value="yesmeck">yesmeck</Option>
</Mentions>
<Mentions
style={{ width: '100%' }}
placement="top"
options={[
{
value: 'afc163',
label: 'afc163',
},
{
value: 'zombieJ',
label: 'zombieJ',
},
{
value: 'yesmeck',
label: 'yesmeck',
},
]}
/>
);
export default App;

View File

@ -1,8 +1,6 @@
import React, { useState } from 'react';
import { Mentions } from 'antd';
const { Option } = Mentions;
const MOCK_DATA = {
'@': ['afc163', 'zombiej', 'yesmeck'],
'#': ['1.0', '2.0', '3.0'],
@ -23,13 +21,12 @@ const App: React.FC = () => {
placeholder="input @ to mention people, # to mention tag"
prefix={['@', '#']}
onSearch={onSearch}
>
{(MOCK_DATA[prefix] || []).map((value) => (
<Option key={value} value={value}>
{value}
</Option>
))}
</Mentions>
options={(MOCK_DATA[prefix] || []).map((value) => ({
key: value,
value,
label: value,
}))}
/>
);
};

View File

@ -1,25 +1,28 @@
import React from 'react';
import { Mentions } from 'antd';
const { Option } = Mentions;
const getOptions = () =>
['afc163', 'zombiej', 'yesmeck'].map((value) => (
<Option key={value} value={value}>
{value}
</Option>
));
const options = ['afc163', 'zombiej', 'yesmeck'].map((value) => ({
value,
key: value,
label: value,
}));
const App: React.FC = () => (
<>
<div style={{ marginBottom: 10 }}>
<Mentions style={{ width: '100%' }} placeholder="this is disabled Mentions" disabled>
{getOptions()}
</Mentions>
<Mentions
style={{ width: '100%' }}
placeholder="this is disabled Mentions"
disabled
options={options}
/>
</div>
<Mentions style={{ width: '100%' }} placeholder="this is readOnly Mentions" readOnly>
{getOptions()}
</Mentions>
<Mentions
style={{ width: '100%' }}
placeholder="this is readOnly Mentions"
readOnly
options={options}
/>
</>
);

View File

@ -1,15 +1,21 @@
import React from 'react';
import { Mentions } from 'antd';
const { Option } = Mentions;
const { _InternalPanelDoNotUseOrYouWillBeFired: InternalMentions } = Mentions;
const options = [
{
value: 'afc163',
label: 'afc163',
},
{
value: 'zombieJ',
label: 'zombieJ',
},
];
const App: React.FC = () => (
<InternalMentions style={{ width: '100%' }} value="@">
<Option value="afc163">afc163</Option>
<Option value="zombieJ">zombieJ</Option>
</InternalMentions>
<InternalMentions style={{ width: '100%' }} value="@" options={options} />
);
export default App;

View File

@ -1,34 +1,47 @@
import React from 'react';
import { Mentions, Space } from 'antd';
import type { OptionProps } from 'antd/es/mentions';
const { Option } = Mentions;
import type { MentionsOptionProps } from 'antd/es/mentions';
const onChange = (value: string) => {
console.log('Change:', value);
};
const onSelect = (option: OptionProps) => {
const onSelect = (option: MentionsOptionProps) => {
console.log('select', option);
};
const App: React.FC = () => {
const options = (
<>
<Option value="afc163">afc163</Option>
<Option value="zombieJ">zombieJ</Option>
<Option value="yesmeck">yesmeck</Option>
</>
);
const options = [
{
value: 'afc163',
label: 'afc163',
},
{
value: 'zombieJ',
label: 'zombieJ',
},
{
value: 'yesmeck',
label: 'yesmeck',
},
];
return (
<Space direction="vertical">
<Mentions onChange={onChange} onSelect={onSelect} defaultValue="@afc163" status="error">
{options}
</Mentions>
<Mentions onChange={onChange} onSelect={onSelect} defaultValue="@afc163" status="warning">
{options}
</Mentions>
<Mentions
onChange={onChange}
onSelect={onSelect}
defaultValue="@afc163"
status="error"
options={options}
/>
<Mentions
onChange={onChange}
onSelect={onSelect}
defaultValue="@afc163"
status="warning"
options={options}
/>
</Space>
);
};

View File

@ -28,12 +28,6 @@ When you need to mention someone or something.
## API
```jsx
<Mentions onChange={onChange}>
<Mentions.Option value="sample">Sample</Mentions.Option>
</Mentions>
```
### Mention
| Property | Description | Type | Default | Version |
@ -56,6 +50,7 @@ When you need to mention someone or something.
| onResize | The callback function that is triggered when textarea resize | function({ width, height }) | - | |
| onSearch | Trigger when prefix hit | (text: string, prefix: string) => void | - | |
| onSelect | Trigger when user select the option | (option: OptionProps, prefix: string) => void | - | |
| options | Option Configuration | [Options](#Option) | \[] | 5.1.0 |
### Mention methods
@ -66,7 +61,10 @@ When you need to mention someone or something.
### Option
| Property | Description | Type | Default |
| --- | --- | --- | --- |
| children | Suggestion content | ReactNode | - |
| value | The value of suggestion, the value will insert into input filed while selected | string | - |
| Property | Description | Type | Default |
| --------- | --------------------------- | ------------------- | ------- |
| label | Title of the option | React.ReactNode | - |
| key | The key value of the option | string | - |
| disabled | Optional | boolean | - |
| className | className | string | - |
| style | The style of the option | React.CSSProperties | - |

View File

@ -3,6 +3,7 @@ import RcMentions from 'rc-mentions';
import type {
MentionsProps as RcMentionsProps,
MentionsRef as RcMentionsRef,
DataDrivenOptionProps as MentionsOptionProps,
} from 'rc-mentions/lib/Mentions';
import { composeRef } from 'rc-util/lib/ref';
// eslint-disable-next-line import/no-named-as-default
@ -25,6 +26,10 @@ function loadingFilterOption() {
export type MentionPlacement = 'top' | 'bottom';
export type {
DataDrivenOptionProps as MentionsOptionProps,
} from 'rc-mentions/lib/Mentions';
export interface OptionProps {
value: string;
children: React.ReactNode;
@ -34,6 +39,7 @@ export interface OptionProps {
export interface MentionProps extends RcMentionsProps {
loading?: boolean;
status?: InputStatus;
options?: MentionsOptionProps[];
popupClassName?: string;
}
@ -70,6 +76,7 @@ const InternalMentions: React.ForwardRefRenderFunction<MentionsRef, MentionProps
filterOption,
children,
notFoundContent,
options,
status: customStatus,
popupClassName,
...restProps
@ -122,6 +129,16 @@ const InternalMentions: React.ForwardRefRenderFunction<MentionsRef, MentionProps
return children;
};
const mergedOptions = loading
? [
{
value: 'ANTD_SEARCHING',
disabled: true,
label: <Spin size="small" />,
},
]
: options;
const getFilterOption = (): any => {
if (loading) {
return loadingFilterOption;
@ -158,6 +175,7 @@ const InternalMentions: React.ForwardRefRenderFunction<MentionsRef, MentionProps
onBlur={onBlur}
dropdownClassName={classNames(popupClassName, hashId)}
ref={mergedRef as any}
options={mergedOptions}
>
{getOptions()}
</RcMentions>

View File

@ -29,12 +29,6 @@ demo:
## API
```jsx
<Mentions onChange={onChange}>
<Mentions.Option value="sample">Sample</Mentions.Option>
</Mentions>
```
### Mentions
| 参数 | 说明 | 类型 | 默认值 | 版本 |
@ -57,6 +51,7 @@ demo:
| onResize | resize 回调 | function({ width, height }) | - | |
| onSearch | 搜索时触发 | (text: string, prefix: string) => void | - | |
| onSelect | 选择选项时触发 | (option: OptionProps, prefix: string) => void | - | |
| options | 选项配置 | [Options](#Option) | [] | 5.1.0 |
### Mentions 方法
@ -67,7 +62,11 @@ demo:
### Option
| 参数 | 说明 | 类型 | 默认值 |
| -------- | -------------- | --------- | ------ |
| children | 选项内容 | ReactNode | - |
| value | 选择时填充的值 | string | - |
| 参数 | 说明 | 类型 | 默认值 |
| --------- | -------------- | ------------------- | ------ |
| value | 选择时填充的值 | string | - |
| label | 选项的标题 | React.ReactNode | - |
| key | 选项的 key 值 | string | - |
| disabled | 是否可选 | boolean | - |
| className | css 类名 | string | - |
| style | 选项样式 | React.CSSProperties | - |

View File

@ -129,8 +129,8 @@
"rc-image": "~5.12.0",
"rc-input": "~0.1.4",
"rc-input-number": "~7.3.9",
"rc-mentions": "~1.11.0",
"rc-menu": "~9.7.2",
"rc-mentions": "~1.13.1",
"rc-menu": "~9.8.0",
"rc-motion": "^2.6.1",
"rc-notification": "~5.0.0-alpha.9",
"rc-pagination": "~3.2.0",
@ -144,7 +144,7 @@
"rc-steps": "~6.0.0-alpha.2",
"rc-switch": "~4.0.0",
"rc-table": "~7.26.0",
"rc-tabs": "~12.3.0",
"rc-tabs": "~12.4.1",
"rc-textarea": "~0.4.5",
"rc-tooltip": "~5.2.0",
"rc-tree": "~5.7.0",