chore: Remove LocaleProvider & Mention in export (#19935)

* chore: Clean up

* clean up test case

* clean up
This commit is contained in:
二货机器人 2019-11-26 14:21:05 +08:00 committed by GitHub
parent ee7a55380d
commit 5fc62314af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 1 additions and 4761 deletions

View File

@ -31,7 +31,6 @@ Array [
"InputNumber", "InputNumber",
"Layout", "Layout",
"List", "List",
"LocaleProvider",
"message", "message",
"Menu", "Menu",
"Mentions", "Mentions",
@ -63,7 +62,6 @@ Array [
"Timeline", "Timeline",
"Tooltip", "Tooltip",
"Typography", "Typography",
"Mention",
"Upload", "Upload",
"version", "version",
] ]

View File

@ -7758,180 +7758,6 @@ exports[`ConfigProvider components List prefixCls 1`] = `
</div> </div>
`; `;
exports[`ConfigProvider components Mention configProvider 1`] = `
<div
class="config-mention-wrapper"
>
<div
class="config-mention-editor oneline"
>
<div
class="config-mention-toolbar"
/>
<div
class="config-mention-editor-wrapper"
>
<div
class="DraftEditor-root"
>
<div
class="DraftEditor-editorContainer"
>
<div
aria-describedby="placeholder-123"
class="notranslate public-DraftEditor-content"
contenteditable="true"
role="textbox"
spellcheck="false"
style="outline:none;user-select:text;-webkit-user-select:text;white-space:pre-wrap;word-wrap:break-word"
>
<div
data-contents="true"
>
<div
class=""
data-block="true"
data-editor="123"
data-offset-key="123-0-0"
>
<div
class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr"
data-offset-key="123-0-0"
>
<span
data-offset-key="123-0-0"
>
<br
data-text="true"
/>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`ConfigProvider components Mention normal 1`] = `
<div
class="ant-mention-wrapper"
>
<div
class="ant-mention-editor oneline"
>
<div
class="ant-mention-toolbar"
/>
<div
class="ant-mention-editor-wrapper"
>
<div
class="DraftEditor-root"
>
<div
class="DraftEditor-editorContainer"
>
<div
aria-describedby="placeholder-123"
class="notranslate public-DraftEditor-content"
contenteditable="true"
role="textbox"
spellcheck="false"
style="outline:none;user-select:text;-webkit-user-select:text;white-space:pre-wrap;word-wrap:break-word"
>
<div
data-contents="true"
>
<div
class=""
data-block="true"
data-editor="123"
data-offset-key="123-0-0"
>
<div
class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr"
data-offset-key="123-0-0"
>
<span
data-offset-key="123-0-0"
>
<br
data-text="true"
/>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`ConfigProvider components Mention prefixCls 1`] = `
<div
class="prefix-Mention-wrapper"
>
<div
class="prefix-Mention-editor oneline"
>
<div
class="prefix-Mention-toolbar"
/>
<div
class="prefix-Mention-editor-wrapper"
>
<div
class="DraftEditor-root"
>
<div
class="DraftEditor-editorContainer"
>
<div
aria-describedby="placeholder-123"
class="notranslate public-DraftEditor-content"
contenteditable="true"
role="textbox"
spellcheck="false"
style="outline:none;user-select:text;-webkit-user-select:text;white-space:pre-wrap;word-wrap:break-word"
>
<div
data-contents="true"
>
<div
class=""
data-block="true"
data-editor="123"
data-offset-key="123-0-0"
>
<div
class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr"
data-offset-key="123-0-0"
>
<span
data-offset-key="123-0-0"
>
<br
data-text="true"
/>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`ConfigProvider components Menu configProvider 1`] = ` exports[`ConfigProvider components Menu configProvider 1`] = `
<ul <ul
class="config-menu config-menu-light config-menu-root config-menu-inline" class="config-menu config-menu-light config-menu-root config-menu-inline"

View File

@ -27,7 +27,6 @@ import Input from '../../input';
import InputNumber from '../../input-number'; import InputNumber from '../../input-number';
import Layout from '../../layout'; import Layout from '../../layout';
import List from '../../list'; import List from '../../list';
import Mention from '../../mention';
import Menu from '../../menu'; import Menu from '../../menu';
import Modal from '../../modal'; import Modal from '../../modal';
import Pagination from '../../pagination'; import Pagination from '../../pagination';
@ -341,9 +340,6 @@ describe('ConfigProvider', () => {
/> />
)); ));
// Mention
testPair('Mention', props => <Mention {...props} />);
// Menu // Menu
testPair('Menu', props => ( testPair('Menu', props => (
<Menu {...props} defaultOpenKeys={['bamboo']} mode="inline"> <Menu {...props} defaultOpenKeys={['bamboo']} mode="inline">

View File

@ -74,8 +74,6 @@ export { default as Layout } from './layout';
export { default as List } from './list'; export { default as List } from './list';
export { default as LocaleProvider } from './locale-provider';
export { default as message } from './message'; export { default as message } from './message';
export { default as Menu } from './menu'; export { default as Menu } from './menu';
@ -138,8 +136,6 @@ export { default as Tooltip } from './tooltip';
export { default as Typography } from './typography'; export { default as Typography } from './typography';
export { default as Mention } from './mention';
export { default as Upload } from './upload'; export { default as Upload } from './upload';
export { default as version } from './version'; export { default as version } from './version';

View File

@ -1,3 +0,0 @@
import demoTest from '../../../tests/shared/demoTest';
demoTest('locale-provider');

View File

@ -3,10 +3,8 @@ import React from 'react';
import { mount } from 'enzyme'; import { mount } from 'enzyme';
import moment from 'moment'; import moment from 'moment';
import MockDate from 'mockdate'; import MockDate from 'mockdate';
import { resetWarned } from '../../_util/warning';
import mountTest from '../../../tests/shared/mountTest'; import mountTest from '../../../tests/shared/mountTest';
import { import {
LocaleProvider,
Pagination, Pagination,
DatePicker, DatePicker,
TimePicker, TimePicker,
@ -17,6 +15,7 @@ import {
Select, Select,
Transfer, Transfer,
} from '../..'; } from '../..';
import LocaleProvider from '..';
import arEG from '../ar_EG'; import arEG from '../ar_EG';
import bgBG from '../bg_BG'; import bgBG from '../bg_BG';
import caES from '../ca_ES'; import caES from '../ca_ES';
@ -247,20 +246,4 @@ describe('Locale Provider', () => {
wrapper.setState({ locale: null }); wrapper.setState({ locale: null });
expect(wrapper.render()).toMatchSnapshot(); expect(wrapper.render()).toMatchSnapshot();
}); });
it('warning if use LocaleProvider', () => {
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
resetWarned();
mount(
<LocaleProvider locale={{}}>
<div />
</LocaleProvider>,
);
expect(errorSpy).toHaveBeenCalledWith(
'Warning: [antd: LocaleProvider] `LocaleProvider` is deprecated. Please use `locale` with `ConfigProvider` instead: http://u.ant.design/locale',
);
errorSpy.mockRestore();
});
}); });

View File

@ -1,187 +0,0 @@
---
order: 2
title:
zh-CN: 所有组件
en-US: All components
---
## zh-CN
此处列出 Ant Design 中需要国际化支持的组件,你可以在演示里切换语言。
## en-US
Components which need localization support are listed here, you can toggle the language in the demo.
```jsx
import {
LocaleProvider,
Pagination,
DatePicker,
TimePicker,
Calendar,
Popconfirm,
Table,
Modal,
Button,
Select,
Transfer,
Radio,
} from 'antd';
import zhCN from 'antd/es/locale-provider/zh_CN';
import moment from 'moment';
import 'moment/locale/zh-cn';
moment.locale('en');
const { Option } = Select;
const { RangePicker } = DatePicker;
const columns = [
{
title: 'Name',
dataIndex: 'name',
filters: [
{
text: 'filter1',
value: 'filter1',
},
],
},
{
title: 'Age',
dataIndex: 'age',
},
];
class Page extends React.Component {
state = {
visible: false,
};
showModal = () => {
this.setState({ visible: true });
};
hideModal = () => {
this.setState({ visible: false });
};
render() {
const info = () => {
Modal.info({
title: 'some info',
content: 'some info',
});
};
const confirm = () => {
Modal.confirm({
title: 'some info',
content: 'some info',
});
};
return (
<div className="locale-components">
<div className="example">
<Pagination defaultCurrent={1} total={50} showSizeChanger />
</div>
<div className="example">
<Select showSearch style={{ width: 200 }}>
<Option value="jack">jack</Option>
<Option value="lucy">lucy</Option>
</Select>
<DatePicker />
<TimePicker />
<RangePicker style={{ width: 200 }} />
</div>
<div className="example">
<Button type="primary" onClick={this.showModal}>
Show Modal
</Button>
<Button onClick={info}>Show info</Button>
<Button onClick={confirm}>Show confirm</Button>
<Popconfirm title="Question?">
<a href="#">Click to confirm</a>
</Popconfirm>
</div>
<div className="example">
<Transfer dataSource={[]} showSearch targetKeys={[]} render={item => item.title} />
</div>
<div style={{ width: 319, border: '1px solid #d9d9d9', borderRadius: 4 }}>
<Calendar fullscreen={false} value={moment()} />
</div>
<div className="example">
<Table dataSource={[]} columns={columns} />
</div>
<Modal title="Locale Modal" visible={this.state.visible} onCancel={this.hideModal}>
<p>Locale Modal</p>
</Modal>
</div>
);
}
}
class App extends React.Component {
constructor() {
super();
this.state = {
locale: null,
};
}
changeLocale = e => {
const localeValue = e.target.value;
this.setState({ locale: localeValue });
if (!localeValue) {
moment.locale('en');
} else {
moment.locale('zh-cn');
}
};
render() {
const { locale } = this.state;
return (
<div>
<div className="change-locale">
<span style={{ marginRight: 16 }}>Change locale of components: </span>
<Radio.Group defaultValue={undefined} onChange={this.changeLocale}>
<Radio.Button key="en" value={undefined}>
English
</Radio.Button>
<Radio.Button key="cn" value={zhCN}>
中文
</Radio.Button>
</Radio.Group>
</div>
<LocaleProvider locale={locale}>
<Page
key={locale ? locale.locale : 'en' /* Have to refresh for production environment */}
/>
</LocaleProvider>
</div>
);
}
}
ReactDOM.render(<App />, mountNode);
```
```css
.locale-components {
border-top: 1px solid #d9d9d9;
padding-top: 16px;
}
.example {
margin: 16px 0;
}
.example > * {
margin-right: 8px;
}
.change-locale {
margin-bottom: 16px;
}
```

View File

@ -1,32 +0,0 @@
---
order: 1
title:
zh-CN: 国际化
en-US: Localization
---
## zh-CN
`LocaleProvider` 包裹你的应用,并引用对应的语言包。
## en-US
Wrap your app with `LocaleProvider`, and apply the corresponding language package.
```jsx
import { Pagination, LocaleProvider } from 'antd';
import zhCN from 'antd/es/locale-provider/zh_CN';
const App = () => (
<div>
<Pagination defaultCurrent={1} total={50} showSizeChanger />
</div>
);
ReactDOM.render(
<LocaleProvider locale={zhCN}>
<App />
</LocaleProvider>,
mountNode,
);
```

View File

@ -1,56 +0,0 @@
---
category: Components
type: Deprecated
cols: 1
title: LocaleProvider (Deprecated)
---
`LocaleProvider` component. Deprecated, please use [ConfigProvider](/components/config-provider) instead.
## Usage
`LocaleProvider` makes use of [context](https://facebook.github.io/react/docs/context.html), a feature of React, to accomplish global effectiveness by wrapping the app only once.
```jsx
import { LocaleProvider } from 'antd';
import fr_FR from 'antd/es/locale-provider/fr_FR';
import moment from 'moment';
import 'moment/locale/fr';
moment.locale('fr');
...
return <LocaleProvider locale={fr_FR}><App /></LocaleProvider>;
```
We provide some locales like English, Chinese, Russian, German, French etc. All locale packages can be found in [here](https://github.com/ant-design/ant-design/blob/master/components/locale-provider/).
Note: if you need to use antd's UMD dist file, please use `antd/dist/antd-with-locales.js` and corresponding moment locale:
```jsx
const { LocaleProvider, locales } = window.antd;
...
return <LocaleProvider locale={locales.fr_FR}><App /></LocaleProvider>;
```
### Add a new language
If you can't find your language, you are welcome to create a locale package based on [en_US](https://github.com/ant-design/ant-design/blob/master/components/locale-provider/en_US.tsx) and send us a pull request.
### Other localization needs
This component aims to provide localization of the built-in text. If you want to support other documents, we recommend using [react-intl](https://github.com/yahoo/react-intl), refer to [Intl demo 1](http://github.com/ant-design/intl-example) and [Intl demo 2](http://yiminghe.me/learning-react/examples/react-intl.html?locale=en-US).
## API
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| locale | language package setting, you can find the packages in [antd/es/locale-provider](http://unpkg.com/antd/es/locale-provider/) | object | - | |
## FAQ
#### Locale problem is still existed even LocaleProvider is used?
Please make sure you set moment locale by `moment.locale('zh-cn')`, or you don't have two moment of different version.

View File

@ -1,57 +0,0 @@
---
category: Components
subtitle: 国际化(废弃)
cols: 1
type: 废弃
title: LocaleProvider
---
国际化组件。已废弃,请使用 [ConfigProvider](/components/config-provider) 代替。
## 使用
LocaleProvider 使用 React 的 [context](https://facebook.github.io/react/docs/context.html) 特性,只需在应用外围包裹一次即可全局生效。
```jsx
import { LocaleProvider } from 'antd';
import zh_CN from 'antd/es/locale-provider/zh_CN';
import moment from 'moment';
import 'moment/locale/zh-cn';
moment.locale('zh-cn');
...
return <LocaleProvider locale={zh_CN}><App /></LocaleProvider>;
```
我们提供了英语,中文,俄语,法语,德语等多种语言支持,所有语言包可以在 [这里](https://github.com/ant-design/ant-design/blob/master/components/locale-provider/) 找到。
注意:如果你需要使用 UMD 版的 dist 文件,应该引入 `antd/dist/antd-with-locales.js`,同时引入 moment 对应的 locale然后按以下方式使用
```jsx
const { LocaleProvider, locales } = window.antd;
...
return <LocaleProvider locale={locales.en_US}><App /></LocaleProvider>;
```
### 增加语言包
如果你找不到你需要的语言包,欢迎你在 [英文语言包](https://github.com/ant-design/ant-design/blob/master/components/locale-provider/en_US.tsx) 的基础上创建一个新的语言包,并给我们 Pull Request。
### 其他国际化需求
本模块仅用于组件的内建文案,若有业务文案的国际化需求,建议使用 [react-intl](https://github.com/yahoo/react-intl),可参考示例:[Intl demo 1](http://github.com/ant-design/intl-example) 和 [Intl demo 2](http://yiminghe.me/learning-react/examples/react-intl.html?locale=en-US)。
## API
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| locale | 语言包配置,语言包可到 [antd/es/locale-provider](http://unpkg.com/antd/es/locale-provider/) 目录下寻找 | object | - | |
## FAQ
#### 为什么我使用了 LocaleProvider 还有问题?
请检查是否设置了 `moment.locale('zh-cn')`,或者是否有两个版本的 moment 共存。

View File

@ -1,796 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders ./components/mention/demo/async.md correctly 1`] = `
<div
class="ant-mention-wrapper"
style="width:100%"
>
<div
class="ant-mention-editor oneline"
style="width:100%"
>
<div
class="ant-mention-toolbar"
/>
<div
class="ant-mention-editor-wrapper"
style="width:100%"
>
<div
class="DraftEditor-root"
>
<div
class="DraftEditor-editorContainer"
>
<div
aria-describedby="placeholder-123"
class="notranslate public-DraftEditor-content"
contenteditable="true"
role="textbox"
spellcheck="false"
style="outline:none;user-select:text;-webkit-user-select:text;white-space:pre-wrap;word-wrap:break-word"
>
<div
data-contents="true"
>
<div
class=""
data-block="true"
data-editor="123"
data-offset-key="123-0-0"
>
<div
class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr"
data-offset-key="123-0-0"
>
<span
data-offset-key="123-0-0"
>
<br
data-text="true"
/>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`renders ./components/mention/demo/avatar.md correctly 1`] = `
<div
class="ant-mention-wrapper"
style="width:100%"
>
<div
class="ant-mention-editor oneline"
style="width:100%"
>
<div
class="ant-mention-toolbar"
/>
<div
class="ant-mention-editor-wrapper"
style="width:100%"
>
<div
class="DraftEditor-root"
>
<div
class="DraftEditor-editorContainer"
>
<div
aria-describedby="placeholder-123"
class="notranslate public-DraftEditor-content"
contenteditable="true"
role="textbox"
spellcheck="false"
style="outline:none;user-select:text;-webkit-user-select:text;white-space:pre-wrap;word-wrap:break-word"
>
<div
data-contents="true"
>
<div
class=""
data-block="true"
data-editor="123"
data-offset-key="123-0-0"
>
<div
class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr"
data-offset-key="123-0-0"
>
<span
data-offset-key="123-0-0"
>
<br
data-text="true"
/>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`renders ./components/mention/demo/basic.md correctly 1`] = `
<div
class="ant-mention-wrapper"
style="width:100%"
>
<div
class="ant-mention-editor oneline"
style="width:100%"
>
<div
class="ant-mention-toolbar"
/>
<div
class="ant-mention-editor-wrapper"
style="width:100%"
>
<div
class="DraftEditor-root"
>
<div
class="DraftEditor-editorContainer"
>
<div
aria-describedby="placeholder-123"
class="notranslate public-DraftEditor-content"
contenteditable="true"
role="textbox"
spellcheck="false"
style="outline:none;user-select:text;-webkit-user-select:text;white-space:pre-wrap;word-wrap:break-word"
>
<div
data-contents="true"
>
<div
class=""
data-block="true"
data-editor="123"
data-offset-key="123-0-0"
>
<div
class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr"
data-offset-key="123-0-0"
>
<span>
<span
data-offset-key="123-0-0"
>
<span
data-text="true"
>
@afc163
</span>
</span>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`renders ./components/mention/demo/controllder-simple.md correctly 1`] = `
<div
class="ant-mention-wrapper"
>
<div
class="ant-mention-editor oneline"
>
<div
class="ant-mention-toolbar"
/>
<div
class="ant-mention-editor-wrapper"
>
<div
class="DraftEditor-root"
>
<div
class="DraftEditor-editorContainer"
>
<div
aria-describedby="placeholder-123"
class="notranslate public-DraftEditor-content"
contenteditable="true"
role="textbox"
spellcheck="false"
style="outline:none;user-select:text;-webkit-user-select:text;white-space:pre-wrap;word-wrap:break-word"
>
<div
data-contents="true"
>
<div
class=""
data-block="true"
data-editor="123"
data-offset-key="123-0-0"
>
<div
class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr"
data-offset-key="123-0-0"
>
<span>
<span
data-offset-key="123-0-0"
>
<span
data-text="true"
>
@afc163
</span>
</span>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`renders ./components/mention/demo/controlled.md correctly 1`] = `
<form
class="ant-form ant-form-horizontal"
>
<div
class="ant-row ant-form-item"
>
<div
class="ant-col ant-col-6 ant-form-item-label"
>
<label
class=""
for="mention"
title="Top coders"
>
Top coders
</label>
</div>
<div
class="ant-col ant-col-16 ant-form-item-control"
>
<div
class="ant-form-item-control-input"
>
<div
class="ant-mention-wrapper"
>
<div
class="ant-mention-editor oneline"
>
<div
class="ant-mention-toolbar"
/>
<div
class="ant-mention-editor-wrapper"
>
<div
class="DraftEditor-root"
>
<div
class="DraftEditor-editorContainer"
>
<div
aria-describedby="placeholder-123"
class="notranslate public-DraftEditor-content"
contenteditable="true"
role="textbox"
spellcheck="false"
style="outline:none;user-select:text;-webkit-user-select:text;white-space:pre-wrap;word-wrap:break-word"
>
<div
data-contents="true"
>
<div
class=""
data-block="true"
data-editor="123"
data-offset-key="123-0-0"
>
<div
class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr"
data-offset-key="123-0-0"
>
<span>
<span
data-offset-key="123-0-0"
>
<span
data-text="true"
>
@afc163
</span>
</span>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div
class="ant-row ant-form-item"
>
<div
class="ant-col ant-col-14 ant-col-offset-6 ant-form-item-control"
>
<div
class="ant-form-item-control-input"
>
<button
class="ant-btn ant-btn-primary"
type="submit"
>
<span>
Submit
</span>
</button>
   
<button
class="ant-btn"
type="button"
>
<span>
Reset
</span>
</button>
</div>
</div>
</div>
</form>
`;
exports[`renders ./components/mention/demo/custom-tag.md correctly 1`] = `
<div
class="ant-mention-wrapper"
style="width:100%"
>
<div
class="ant-mention-editor oneline"
style="width:100%"
>
<div
class="ant-mention-toolbar"
/>
<div
class="ant-mention-editor-wrapper"
style="width:100%"
>
<div
class="DraftEditor-root"
>
<div
class="public-DraftEditorPlaceholder-root"
>
<div
class="public-DraftEditorPlaceholder-inner"
id="placeholder-123"
style="white-space:pre-wrap"
>
@someone
</div>
</div>
<div
class="DraftEditor-editorContainer"
>
<div
aria-describedby="placeholder-123"
class="notranslate public-DraftEditor-content"
contenteditable="true"
role="textbox"
spellcheck="false"
style="outline:none;user-select:text;-webkit-user-select:text;white-space:pre-wrap;word-wrap:break-word"
>
<div
data-contents="true"
>
<div
class=""
data-block="true"
data-editor="123"
data-offset-key="123-0-0"
>
<div
class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr"
data-offset-key="123-0-0"
>
<span
data-offset-key="123-0-0"
>
<br
data-text="true"
/>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`renders ./components/mention/demo/multilines.md correctly 1`] = `
<div
class="ant-mention-wrapper multilines"
style="width:100%;height:100px"
>
<div
class="ant-mention-editor"
style="width:100%;height:100px"
>
<div
class="ant-mention-toolbar"
/>
<div
class="ant-mention-editor-wrapper"
style="width:100%;height:100px"
>
<div
class="DraftEditor-root"
>
<div
class="DraftEditor-editorContainer"
>
<div
aria-describedby="placeholder-123"
class="notranslate public-DraftEditor-content"
contenteditable="true"
role="textbox"
spellcheck="false"
style="outline:none;user-select:text;-webkit-user-select:text;white-space:pre-wrap;word-wrap:break-word"
>
<div
data-contents="true"
>
<div
class=""
data-block="true"
data-editor="123"
data-offset-key="123-0-0"
>
<div
class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr"
data-offset-key="123-0-0"
>
<span
data-offset-key="123-0-0"
>
<br
data-text="true"
/>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`renders ./components/mention/demo/multiple-trigger.md correctly 1`] = `
<div
class="ant-mention-wrapper"
style="width:100%"
>
<div
class="ant-mention-editor oneline"
style="width:100%"
>
<div
class="ant-mention-toolbar"
/>
<div
class="ant-mention-editor-wrapper"
style="width:100%"
>
<div
class="DraftEditor-root"
>
<div
class="public-DraftEditorPlaceholder-root"
>
<div
class="public-DraftEditorPlaceholder-inner"
id="placeholder-123"
style="white-space:pre-wrap"
>
input @ to mention people, # to mention tag
</div>
</div>
<div
class="DraftEditor-editorContainer"
>
<div
aria-describedby="placeholder-123"
class="notranslate public-DraftEditor-content"
contenteditable="true"
role="textbox"
spellcheck="false"
style="outline:none;user-select:text;-webkit-user-select:text;white-space:pre-wrap;word-wrap:break-word"
>
<div
data-contents="true"
>
<div
class=""
data-block="true"
data-editor="123"
data-offset-key="123-0-0"
>
<div
class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr"
data-offset-key="123-0-0"
>
<span
data-offset-key="123-0-0"
>
<br
data-text="true"
/>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`renders ./components/mention/demo/placement.md correctly 1`] = `
<div
class="ant-mention-placement-top ant-mention-wrapper"
style="width:100%"
>
<div
class="ant-mention-editor oneline"
style="width:100%"
>
<div
class="ant-mention-toolbar"
/>
<div
class="ant-mention-editor-wrapper"
style="width:100%"
>
<div
class="DraftEditor-root"
>
<div
class="DraftEditor-editorContainer"
>
<div
aria-describedby="placeholder-123"
class="notranslate public-DraftEditor-content"
contenteditable="true"
role="textbox"
spellcheck="false"
style="outline:none;user-select:text;-webkit-user-select:text;white-space:pre-wrap;word-wrap:break-word"
>
<div
data-contents="true"
>
<div
class=""
data-block="true"
data-editor="123"
data-offset-key="123-0-0"
>
<div
class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr"
data-offset-key="123-0-0"
>
<span
data-offset-key="123-0-0"
>
<br
data-text="true"
/>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`renders ./components/mention/demo/popupContainer.md correctly 1`] = `
<button
class="ant-btn ant-btn-primary"
type="button"
>
<span>
Click Me
</span>
</button>
`;
exports[`renders ./components/mention/demo/readonly.md correctly 1`] = `
<div>
<div
style="margin-bottom:10px"
>
<div
class="ant-mention-wrapper disabled"
style="width:100%"
>
<div
class="ant-mention-editor readonly oneline"
style="width:100%"
>
<div
class="ant-mention-toolbar"
/>
<div
class="ant-mention-editor-wrapper"
style="width:100%"
>
<div
class="DraftEditor-root"
>
<div
class="public-DraftEditorPlaceholder-root"
>
<div
class="public-DraftEditorPlaceholder-inner"
id="placeholder-123"
style="white-space:pre-wrap"
>
this is disabled Mention
</div>
</div>
<div
class="DraftEditor-editorContainer"
>
<div
aria-describedby="placeholder-123"
class="public-DraftEditor-content"
contenteditable="false"
spellcheck="false"
style="outline:none;user-select:text;-webkit-user-select:text;white-space:pre-wrap;word-wrap:break-word"
>
<div
data-contents="true"
>
<div
class=""
data-block="true"
data-editor="123"
data-offset-key="123-0-0"
>
<div
class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr"
data-offset-key="123-0-0"
>
<span
data-offset-key="123-0-0"
>
<br
data-text="true"
/>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
<input
style="width:0;opacity:0;border:0;position:absolute;left:0;top:0"
/>
</div>
</div>
</div>
</div>
<div
class="ant-mention-wrapper readonly"
style="width:100%"
>
<div
class="ant-mention-editor readonly oneline"
style="width:100%"
>
<div
class="ant-mention-toolbar"
/>
<div
class="ant-mention-editor-wrapper"
style="width:100%"
>
<div
class="DraftEditor-root"
>
<div
class="public-DraftEditorPlaceholder-root"
>
<div
class="public-DraftEditorPlaceholder-inner"
id="placeholder-123"
style="white-space:pre-wrap"
>
this is readOnly Mention
</div>
</div>
<div
class="DraftEditor-editorContainer"
>
<div
aria-describedby="placeholder-123"
class="public-DraftEditor-content"
contenteditable="false"
spellcheck="false"
style="outline:none;user-select:text;-webkit-user-select:text;white-space:pre-wrap;word-wrap:break-word"
>
<div
data-contents="true"
>
<div
class=""
data-block="true"
data-editor="123"
data-offset-key="123-0-0"
>
<div
class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr"
data-offset-key="123-0-0"
>
<span
data-offset-key="123-0-0"
>
<br
data-text="true"
/>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
<input
style="width:0;opacity:0;border:0;position:absolute;left:0;top:0"
/>
</div>
</div>
</div>
</div>
`;

View File

@ -1,5 +0,0 @@
import demoTest from '../../../tests/shared/demoTest';
jest.mock('draft-js/lib/generateRandomKey', () => () => '123');
demoTest('mention', { skip: process.env.LIB_DIR === 'dist' });

View File

@ -1,123 +0,0 @@
import React from 'react';
import { mount } from 'enzyme';
import Mention from '..';
import mountTest from '../../../tests/shared/mountTest';
const { toContentState } = Mention;
describe('Mention', () => {
mountTest(Mention);
beforeAll(() => {
jest.useFakeTimers();
});
afterAll(() => {
jest.useRealTimers();
});
it('should has focus function', () => {
const handleFocus = jest.fn();
const wrapper = mount(
<Mention
defaultValue={toContentState('@afc163')}
onFocus={handleFocus}
suggestions={['afc163', 'benjycui', 'yiminghe', 'RaoHai', '中文', 'にほんご']}
/>,
);
wrapper.instance().focus();
jest.runAllTimers();
expect(handleFocus).toHaveBeenCalled();
});
it('basic suggestion', () => {
const handleSearch = jest.fn();
const wrapper = mount(
<Mention suggestions={['afc163', 'raohai']} onSearchChange={handleSearch} />,
);
wrapper.find('DraftEditorContents').simulate('focus');
const ed = wrapper.find('.public-DraftEditor-content');
ed.simulate('beforeInput', { data: '@a' });
jest.runAllTimers();
expect(handleSearch).toHaveBeenCalledWith('a', '@');
});
it('change suggestions', () => {
const container = mount(<div id="container" />);
const wrapper = mount(
<Mention
suggestions={['afc163', 'raohai']}
getSuggestionContainer={() => container.getDOMNode()}
/>,
);
wrapper.find('DraftEditorContents').simulate('focus');
const ed = wrapper.find('.public-DraftEditor-content');
ed.simulate('beforeInput', { data: '@' });
jest.runAllTimers();
expect(container.getDOMNode().querySelectorAll('.ant-mention-dropdown-item').length).toBe(2);
expect(container.getDOMNode().querySelectorAll('.ant-mention-dropdown-item')[0].innerHTML).toBe(
'afc163',
);
wrapper.setProps({ suggestions: ['yesmeck', 'yiminghe', 'lucy'] });
jest.runAllTimers();
expect(container.getDOMNode().querySelectorAll('.ant-mention-dropdown-item').length).toBe(3);
expect(container.getDOMNode().querySelectorAll('.ant-mention-dropdown-item')[0].innerHTML).toBe(
'yesmeck',
);
});
it('select item', () => {
const onChange = jest.fn();
const onSelect = jest.fn();
const wrapper = mount(
<Mention suggestions={['afc163', 'raohai']} onChange={onChange} onSelect={onSelect} />,
);
wrapper.find('DraftEditorContents').simulate('focus');
const ed = wrapper.find('.public-DraftEditor-content');
ed.simulate('beforeInput', { data: '@' });
jest.runAllTimers();
expect(onChange).toHaveBeenCalled();
expect(onSelect).not.toHaveBeenCalled();
wrapper
.find('.ant-mention-dropdown-item')
.at(0)
.simulate('mouseDown');
wrapper
.find('.ant-mention-dropdown-item')
.at(0)
.simulate('mouseUp');
wrapper
.find('.ant-mention-dropdown-item')
.at(0)
.simulate('click');
jest.runAllTimers();
expect(onSelect).toHaveBeenCalled();
expect(wrapper.find('.public-DraftStyleDefault-block').text()).toBe('@afc163 ');
});
it('defaultSuggestion filter', () => {
const wrapper = mount(<Mention defaultSuggestions={['light', 'bamboo']} />);
wrapper.find('DraftEditorContents').simulate('focus');
const ed = wrapper.find('.public-DraftEditor-content');
ed.simulate('beforeInput', { data: '@b' });
jest.runAllTimers();
const items = wrapper.find('div.ant-mention-dropdown-item');
expect(items.length).toBe(1);
expect(items.at(0).props().children).toBe('bamboo');
});
it('check filteredSuggestions', () => {
const wrapper = mount(
<Mention defaultSuggestions={[<Mention.Nav key="light" value="light" />]} />,
);
wrapper.find('DraftEditorContents').simulate('focus');
const ed = wrapper.find('.public-DraftEditor-content');
ed.simulate('beforeInput', { data: '@l' });
jest.runAllTimers();
const items = wrapper.find('div.ant-mention-dropdown-item');
expect(items.length).toBe(1);
expect(items.at(0).props().value).toBe('light');
});
});

View File

@ -1,59 +0,0 @@
---
order: 1
title:
zh-CN: 异步加载
en-US: Asynchronous loading
---
## zh-CN
匹配内容列表为异步返回时。
## en-US
async
```jsx
import { Mention } from 'antd';
const users = ['afc163', 'benjycui', 'yiminghe', 'jljsj33', 'dqaria', 'RaoHai'];
class AsyncMention extends React.Component {
state = {
suggestions: [],
loading: false,
};
fetchSuggestions = (value, callback) => {
setTimeout(() => {
callback(users.filter(item => item.indexOf(value) !== -1));
}, 500);
};
onSearchChange = value => {
this.fetchSuggestions(value, suggestions => {
this.setState({
suggestions,
loading: false,
});
});
this.setState({
loading: true,
});
};
render() {
const { suggestions, loading } = this.state;
return (
<Mention
style={{ width: '100%' }}
loading={loading}
suggestions={suggestions}
onSearchChange={this.onSearchChange}
/>
);
}
}
ReactDOM.render(<AsyncMention />, mountNode);
```

View File

@ -1,93 +0,0 @@
---
order: 3
title:
zh-CN: 头像
en-US: Icon Image
---
## zh-CN
自定义建议(含头像)
注意自定义建议时onSearchChange 必须不能为空。
## en-US
Customize suggestions.
```jsx
import { Mention, Avatar } from 'antd';
const { Nav } = Mention;
const webFrameworks = [
{
name: 'React',
type: 'JavaScript',
icon: 'https://zos.alipayobjects.com/rmsportal/LFIeMPzdLcLnEUe.svg',
},
{
name: 'Angular',
type: 'JavaScript',
icon: 'https://zos.alipayobjects.com/rmsportal/PJTbxSvzYWjDZnJ.png',
},
{
name: 'Dva',
type: 'Javascript',
icon: 'https://zos.alipayobjects.com/rmsportal/EYPwSeEJKxDtVxI.png',
},
{
name: 'Flask',
type: 'Python',
icon: 'https://zos.alipayobjects.com/rmsportal/xaypBUijfnpAlXE.png',
},
];
class CustomNavMention extends React.Component {
state = {
suggestions: [],
};
onSearchChange = value => {
const searchValue = value.toLowerCase();
const filtered = webFrameworks.filter(
item => item.name.toLowerCase().indexOf(searchValue) !== -1,
);
const suggestions = filtered.map(suggestion => (
<Nav
value={suggestion.name}
data={suggestion}
disabled={suggestion.disabled}
key="mention-avatar"
>
<Avatar
src={suggestion.icon}
size="small"
style={{
width: 14,
height: 14,
marginRight: 8,
top: -1,
position: 'relative',
}}
/>
{suggestion.name} - {suggestion.type}
</Nav>
));
this.setState({ suggestions });
};
render() {
const { suggestions } = this.state;
return (
<Mention
style={{ width: '100%' }}
suggestions={suggestions}
onSearchChange={this.onSearchChange}
/>
);
}
}
ReactDOM.render(<CustomNavMention />, mountNode);
```

View File

@ -1,39 +0,0 @@
---
order: 0
title:
zh-CN: 基本使用
en-US: Basic
---
## zh-CN
基本使用
## en-US
Basic usage.
```jsx
import { Mention } from 'antd';
const { toString, toContentState } = Mention;
function onChange(contentState) {
console.log(toString(contentState));
}
function onSelect(suggestion) {
console.log('onSelect', suggestion);
}
ReactDOM.render(
<Mention
style={{ width: '100%' }}
onChange={onChange}
defaultValue={toContentState('@afc163')}
defaultSuggestions={['afc163', 'benjycui', 'yiminghe', 'RaoHai', '中文', 'にほんご']}
onSelect={onSelect}
/>,
mountNode,
);
```

View File

@ -1,49 +0,0 @@
---
order: 3
title:
zh-CN: 受控模式
en-US: Controlled
---
## zh-CN
受控模式.
## en-US
Controlled mode.
```jsx
import { Mention } from 'antd';
const { toContentState } = Mention;
class App extends React.Component {
state = {
value: toContentState('@afc163'),
};
componentDidMount() {
this.mention.focus();
}
handleChange = editorState => {
this.setState({
value: editorState,
});
};
render() {
return (
<Mention
ref={ele => (this.mention = ele)}
defaultSuggestions={['afc163', 'benjycui', 'yiminghe', 'RaoHai', '中文', 'にほんご']}
value={this.state.value}
onChange={this.handleChange}
/>
);
}
}
ReactDOM.render(<App />, mountNode);
```

View File

@ -1,75 +0,0 @@
---
order: 4
title:
zh-CN: 配合 Form 使用
en-US: With Form
---
## zh-CN
受控模式,例如配合 Form 使用。
## en-US
Controlled mode, for example, to work with `Form`.
```tsx
import { Mention, Form, Button } from 'antd';
const { toContentState, getMentions } = Mention;
const FormItem = Form.Item;
const App = () => {
const [form] = Form.useForm();
const checkMention = (rule, value, callback) => {
const mentions = getMentions(form.getFieldValue('mention'));
if (mentions.length < 2) {
callback(new Error('More than one must be selected!'));
} else {
callback();
}
};
const onReset = () => {
form.resetFields();
};
const onFinish = values => {
console.log('Submit:', values);
};
return (
<Form
form={form}
layout="horizontal"
initialValues={{ mention: toContentState('@afc163') }}
onFinish={onFinish}
>
<FormItem
name="mention"
id="control-mention"
label="Top coders"
labelCol={{ span: 6 }}
wrapperCol={{ span: 16 }}
rules={[{ validator: checkMention }]}
>
<Mention
defaultSuggestions={['afc163', 'benjycui', 'yiminghe', 'RaoHai', '中文', 'にほんご']}
/>
</FormItem>
<FormItem wrapperCol={{ span: 14, offset: 6 }}>
<Button htmlType="submit" type="primary">
Submit
</Button>
&nbsp;&nbsp;&nbsp;
<Button htmlType="button" onClick={onReset}>
Reset
</Button>
</FormItem>
</Form>
);
};
ReactDOM.render(<App />, mountNode);
```

View File

@ -1,70 +0,0 @@
---
order: 2
title:
zh-CN: 自定义建议
en-US: Customize Suggestion
---
## zh-CN
自定义建议
注意自定义建议时onSearchChange 必须不能为空。
## en-US
Customize suggestions.
```jsx
import { Mention } from 'antd';
const { Nav } = Mention;
const webFrameworks = [
{ name: 'React', type: 'JavaScript' },
{ name: 'Angular', type: 'JavaScript' },
{ name: 'Laravel', type: 'PHP', disabled: true },
{ name: 'Flask', type: 'Python' },
{ name: 'Django', type: 'Python' },
];
function onSelect(suggestion, data) {
console.log('onSelect', suggestion, data);
}
class CustomNavMention extends React.Component {
state = {
suggestions: [],
};
onSearchChange = value => {
const searchValue = value.toLowerCase();
const filtered = webFrameworks.filter(
item => item.name.toLowerCase().indexOf(searchValue) !== -1,
);
const suggestions = filtered.map(suggestion => (
<Nav value={suggestion.name} data={suggestion} key={suggestion.name}>
<span>
{suggestion.name} - {suggestion.type}
</span>
</Nav>
));
this.setState({ suggestions });
};
render() {
const { suggestions } = this.state;
return (
<Mention
placeholder="@someone"
style={{ width: '100%' }}
suggestions={suggestions}
onSearchChange={this.onSearchChange}
onSelect={onSelect}
/>
);
}
}
ReactDOM.render(<CustomNavMention />, mountNode);
```

View File

@ -1,34 +0,0 @@
---
order: 5
title:
zh-CN: 多行
en-US: Multi-lines Mode
---
## zh-CN
多行模式,多行模式必须指定高度。
## en-US
Multi lines mode.
```jsx
import { Mention } from 'antd';
const { toString } = Mention;
function onChange(editorState) {
console.log(toString(editorState));
}
ReactDOM.render(
<Mention
style={{ width: '100%', height: 100 }}
onChange={onChange}
defaultSuggestions={['afc163', 'benjycui', 'yiminghe', 'jljsj33', 'dqaria', 'RaoHai']}
multiLines
/>,
mountNode,
);
```

View File

@ -1,64 +0,0 @@
---
order: 8
title:
zh-CN: 自定义触发字符
en-US: Customize Trigger Token
---
## zh-CN
通过 `prefix` 属性自定义触发字符。默认为 `@`, 可以定义为数组。
## en-US
Customize Trigger Token by `prefix` props. Default to `@`, `Array<string>` also supported.
```jsx
import { Mention } from 'antd';
const { toString } = Mention;
function onChange(editorState) {
console.log(toString(editorState));
}
function onSelect(suggestion) {
console.log('onSelect', suggestion);
}
const users = ['afc163', 'benjycui', 'yiminghe', 'jljsj33', 'dqaria', 'RaoHai'];
const tags = ['1.0', '2.0', '3.0'];
class App extends React.Component {
constructor() {
super();
this.state = {
suggestions: [],
};
}
onSearchChange = (value, trigger) => {
console.log('onSearchChange', value, trigger);
const dataSource = trigger === '@' ? users : tags;
this.setState({
suggestions: dataSource.filter(item => item.indexOf(value) !== -1),
});
};
render() {
return (
<Mention
style={{ width: '100%' }}
onChange={onChange}
placeholder="input @ to mention people, # to mention tag"
prefix={['@', '#']}
onSearchChange={this.onSearchChange}
suggestions={this.state.suggestions}
onSelect={onSelect}
/>
);
}
}
ReactDOM.render(<App />, mountNode);
```

View File

@ -1,39 +0,0 @@
---
order: 0
title:
zh-CN: 向上展开
en-US: Placement
---
## zh-CN
向上展开建议。
## en-US
Change the suggestions placement.
```jsx
import { Mention } from 'antd';
const { toString } = Mention;
function onChange(contentState) {
console.log(toString(contentState));
}
function onSelect(suggestion) {
console.log('onSelect', suggestion);
}
ReactDOM.render(
<Mention
style={{ width: '100%' }}
onChange={onChange}
defaultSuggestions={['afc163', 'benjycui', 'yiminghe', 'RaoHai', '中文', 'にほんご']}
onSelect={onSelect}
placement="top"
/>,
mountNode,
);
```

View File

@ -1,65 +0,0 @@
---
order: 6
title:
zh-CN: 建议渲染父节点
en-US: SuggestionContainer
---
## zh-CN
指定提示渲染的父节点。
## en-US
To set the container of the suggestion.
```jsx
import { Mention, Popover, Button } from 'antd';
const { toString, toContentState } = Mention;
function onChange(editorState) {
console.log(toString(editorState));
}
function onSelect(suggestion) {
console.log('onSelect', suggestion);
}
class PopoverContainer extends React.Component {
getSuggestionContainer = () => this.popover.getPopupDomNode();
visibleChange = visible => {
if (visible && this.mention) {
this.mention.focus();
}
};
render() {
const mention = (
<Mention
ref={ele => (this.mention = ele)}
style={{ width: '100%' }}
onChange={onChange}
defaultValue={toContentState('@afc163')}
defaultSuggestions={['afc163', 'benjycui', 'yiminghe', 'RaoHai', '中文', 'にほんご']}
onSelect={onSelect}
getSuggestionContainer={this.getSuggestionContainer}
/>
);
return (
<Popover
trigger="click"
content={mention}
title="Title"
ref={popover => (this.popover = popover)}
onVisibleChange={this.visibleChange}
>
<Button type="primary">Click Me</Button>
</Popover>
);
}
}
ReactDOM.render(<PopoverContainer />, mountNode);
```

View File

@ -1,51 +0,0 @@
---
order: 7
title:
zh-CN: 无效或只读
en-US: disabled or readOnly
---
## zh-CN
通过 `disabled` 属性设置是否生效。通过 `readOnly` 属性设置是否只读。
## en-US
Configurate `disabled` and `readOnly`.
```jsx
import { Mention } from 'antd';
const { toString } = Mention;
function onChange(editorState) {
console.log(toString(editorState));
}
const users = ['afc163', 'benjycui', 'yiminghe', 'jljsj33', 'dqaria', 'RaoHai'];
function App() {
return (
<div>
<div style={{ marginBottom: 10 }}>
<Mention
style={{ width: '100%' }}
onChange={onChange}
placeholder="this is disabled Mention"
suggestions={users}
disabled
/>
</div>
<Mention
style={{ width: '100%' }}
onChange={onChange}
placeholder="this is readOnly Mention"
suggestions={users}
readOnly
/>
</div>
);
}
ReactDOM.render(<App />, mountNode);
```

View File

@ -1,71 +0,0 @@
---
category: Components
type: Deprecated
title: Mention (Deprecated)
---
Mention component. Deprecated, please use [Mentions](/components/mentions) instead.
## Why deprecated?
<div class="ant-alert ant-alert-error ant-alert-no-icon">
Mention use
<a href="https://www.npmjs.com/package/draft-js" target="_blank" rel="noopener noreferrer">Draft.js</a>
to measure tips position, which use nearly 11.6% package size. We hope to reduce bundle size by using lightweight solution to handle this.
</div>
## API
```jsx
<Mention
onChange={onChange}
suggestions={['afc163', 'benjycui', 'yiminghe', 'jljsj33', 'dqaria', 'RaoHai']}
/>
```
### Mention API
| API | Description | Type | Version |
| --- | --- | --- | --- |
| getMentions | get mentioned people in current contentState | Function(ContentState: contentState): string\[] | |
| toContentState | convert string to ContentState | Function(value: string): ContentState | |
| toString | convert ContentState to string | Function(contentState: ContentState): string | |
### Mention
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| autoFocus | get focus when component mounted | boolean | false | |
| defaultValue | default value | ContentState, you can use `Mention.toContentState` to convert text to `ContentState` | null | |
| defaultSuggestions | default suggestion content | Array&lt;string\|Mention.Nav> | \[] | 3.12.0 |
| disabled | Tell if the input is disabled. | boolean | false | |
| getSuggestionContainer | rendered to the root of the menu. Default rendered to the body dom. If gets any problem of the menu while scrolling. Try to make the root the dom scrolled, and make it position relative. | function | () => document.body | |
| loading | loading mode | boolean | false | |
| multiLines | multilines mode | boolean | false | |
| notFoundContent | suggestion when suggestions empty | string | 'No matches found' | |
| placeholder | placeholder of input | string | null | |
| placement | The position of the suggestion relative to the target, which can be one of `top` and `bottom` | string | 'bottom'. | |
| prefix | character which will trigger Mention to show mention list | string or Array&lt;string> | '@' | |
| readOnly | Tell if the input is readonly. | boolean | false | |
| suggestions | suggestion content | Array&lt;string\|Mention.Nav> | \[] | |
| suggestionStyle | style of suggestion container | object | {} | |
| value | core state of mention | ContentState | null | |
| onBlur | Callback function called when mention component blur | function(e) | null | |
| onChange | Callback function called when content of input changes | function(contentState: ContentState) | null | |
| onFocus | Callback function called when mention component get focus | function | null | |
| onSearchChange | Callback function called when search content changes | function(value:string, trigger: string) | \[] | |
| onSelect | Callback function called when select from suggestions | function(suggestion: string, data?: any) | null | |
### Mention methods
| Name | Description | Version |
| ------- | ------------ | ------- |
| blur() | remove focus | |
| focus() | get focus | |
### Nav
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| children | suggestion content | object | {} | |
| value | value of suggestion, the value will insert into input filed while selected | string | "" | |

View File

@ -1,172 +0,0 @@
import * as React from 'react';
import RcMention, { Nav, toString, toEditorState, getMentions } from 'rc-editor-mention';
import { polyfill } from 'react-lifecycles-compat';
import classNames from 'classnames';
import { Loading } from '@ant-design/icons';
import warning from '../_util/warning';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
export type MentionPlacement = 'top' | 'bottom';
type SuggestionItme = React.ReactElement<{ value?: string }> | string;
export interface MentionProps {
prefixCls?: string;
suggestionStyle?: React.CSSProperties;
defaultSuggestions?: Array<SuggestionItme>;
suggestions?: Array<React.ReactElement<any>>;
onSearchChange?: (value: string, trigger: string) => any;
onChange?: (contentState: any) => void;
notFoundContent?: any;
loading?: boolean;
style?: React.CSSProperties;
defaultValue?: any;
value?: any;
className?: string;
multiLines?: boolean;
prefix?: string | string[];
placeholder?: string;
getSuggestionContainer?: (triggerNode: Element) => HTMLElement;
onFocus?: React.FocusEventHandler<HTMLElement>;
onBlur?: React.FocusEventHandler<HTMLElement>;
onSelect?: (suggestion: string, data?: any) => void;
readOnly?: boolean;
disabled?: boolean;
placement?: MentionPlacement;
}
export interface MentionState {
filteredSuggestions?: Array<any>;
focus?: Boolean;
}
class Mention extends React.Component<MentionProps, MentionState> {
static getMentions = getMentions;
static defaultProps = {
notFoundContent: 'No matches found',
loading: false,
multiLines: false,
placement: 'bottom' as MentionPlacement,
};
static Nav = Nav;
static toString = toString;
static toContentState = toEditorState;
private mentionEle: any;
constructor(props: MentionProps) {
super(props);
this.state = {
filteredSuggestions: props.defaultSuggestions,
focus: false,
};
warning(
false,
'Mention',
'Mention component is deprecated. Please use Mentions component instead.',
);
}
mentionRef = (ele: any) => {
this.mentionEle = ele;
};
onSearchChange = (value: string, prefix: string) => {
if (this.props.onSearchChange) {
return this.props.onSearchChange(value, prefix);
}
return this.defaultSearchChange(value);
};
onChange = (editorState: any) => {
if (this.props.onChange) {
this.props.onChange(editorState);
}
};
onFocus = (ev: React.FocusEvent<HTMLElement>) => {
this.setState({
focus: true,
});
if (this.props.onFocus) {
this.props.onFocus(ev);
}
};
onBlur = (ev: React.FocusEvent<HTMLElement>) => {
this.setState({
focus: false,
});
if (this.props.onBlur) {
this.props.onBlur(ev);
}
};
focus = () => {
this.mentionEle._editor.focusEditor();
};
defaultSearchChange(value: string): void {
const searchValue = value.toLowerCase();
const filteredSuggestions = (this.props.defaultSuggestions || []).filter(suggestion => {
if (typeof suggestion === 'string') {
return suggestion.toLowerCase().indexOf(searchValue) !== -1;
}
if (suggestion.type && suggestion.type === Nav) {
return suggestion.props.value
? suggestion.props.value.toLowerCase().indexOf(searchValue) !== -1
: true;
}
return false;
});
this.setState({
filteredSuggestions,
});
}
renderMention = ({ getPrefixCls }: ConfigConsumerProps) => {
const {
prefixCls: customizePrefixCls,
className = '',
loading,
placement,
suggestions,
} = this.props;
const { filteredSuggestions, focus } = this.state;
const prefixCls = getPrefixCls('mention', customizePrefixCls);
const cls = classNames(className, {
[`${prefixCls}-active`]: focus,
[`${prefixCls}-placement-top`]: placement === 'top',
});
const notFoundContent = loading ? <Loading /> : this.props.notFoundContent;
return (
<RcMention
{...this.props}
prefixCls={prefixCls}
className={cls}
ref={this.mentionRef}
onSearchChange={this.onSearchChange}
onChange={this.onChange}
onFocus={this.onFocus}
onBlur={this.onBlur}
suggestions={suggestions || filteredSuggestions}
notFoundContent={notFoundContent}
/>
);
};
render() {
return <ConfigConsumer>{this.renderMention}</ConfigConsumer>;
}
}
polyfill(Mention);
export default Mention;

View File

@ -1,72 +0,0 @@
---
category: Components
type: 废弃
subtitle: 提及(废弃)
title: Mention
---
提及组件。已废弃,请使用 [Mentions](/components/mentions) 代替。
## 为何废弃?
<div class="ant-alert ant-alert-error ant-alert-no-icon">
Mention 组件使用了
<a href="https://www.npmjs.com/package/draft-js" target="_blank" rel="noopener noreferrer">Draft.js</a>
进行提示定位,占用了约 11.6% 的包大小。因而我们决定使用更轻量级的解决方案以便于在未来降低整个包的大小。
</div>
## API
```jsx
<Mention
onChange={onChange}
suggestions={['afc163', 'benjycui', 'yiminghe', 'jljsj33', 'dqaria', 'RaoHai']}
/>
```
### Mention API
| API | 说明 | 类型 | 版本 |
| --- | --- | --- | --- |
| getMentions | 获取当前 contentState 中提到的人的列表 | Function(contentState: ContentState): string\[] | |
| toContentState | 把字符串转成 ContentState | Function(value: string): ContentState | |
| toString | 把 ContentState 转成字符串 | Function(contentState: ContentState): string | |
### Mention
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| autoFocus | 自动获取焦点 | boolean | false | |
| defaultValue | 默认值 | ContentState, 可以用 `Mention.toContentState(text)` 把文字转换成 ContentState | null | |
| defaultSuggestions | 默认建议内容 | Array&lt;string\|Mention.Nav> | \[] | 3.12.0 |
| disabled | 是否禁用状态. | boolean | false | |
| getSuggestionContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位 | function() | () => document.body | |
| loading | 加载中 | boolean | false | |
| multiLines | 多行模式 | boolean | false | |
| notFoundContent | 未找到时的内容 | string | '无匹配结果,轻敲空格完成输入' | |
| placeholder | 输入框默认文字 | string | null | |
| placement | 建议框位置,可选 `top` `bottom` | string | 'bottom' | |
| prefix | 触发弹出下拉框的字符 | string or Array&lt;string> | '@' | |
| readOnly | 是否只读. | boolean | false | |
| suggestions | 建议内容 | Array&lt;string\|Mention.Nav> | \[] | |
| suggestionStyle | 弹出下拉框样式 | object | {} | |
| value | 值 | ContentState | null | |
| onBlur | 失去焦点时回调 | function(e) | null | |
| onChange | 输入框内容变化时回调 | function(contentState: ContentState) | null | |
| onFocus | 获得焦点时回调 | function(e) | null | |
| onSearchChange | 输入框中 @ 变化时回调 | function(value:string, trigger: string) | \[] | |
| onSelect | 下拉框选择建议时回调 | function(suggestion: string, data?: any) | null | |
### Mention 方法
| 名称 | 描述 | 版本 |
| ------- | -------- | ---- |
| blur() | 移除焦点 | |
| focus() | 获取焦点 | |
### Nav
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| -------- | ---------------------------------------- | ------ | ------ | ---- |
| children | 建议内容 | object | {} | |
| value | 建议值,选择建议时,用此值插入到输入框中 | string | "" | |

View File

@ -1,133 +0,0 @@
@import '../../style/themes/index';
@import '../../style/mixins/index';
@import '../../input/style/mixin';
@mention-prefix-cls: ~'@{ant-prefix}-mention';
.@{mention-prefix-cls}-wrapper {
.reset-component;
position: relative;
display: inline-block;
width: 100%;
vertical-align: middle;
.@{mention-prefix-cls}-editor {
.input;
display: block;
height: auto; // To override height in .input mixin
min-height: @input-height-base;
padding: 0;
line-height: @line-height-base;
&-wrapper {
height: auto;
overflow-y: auto;
}
}
&.@{mention-prefix-cls}-active:not(.disabled) .@{mention-prefix-cls}-editor {
.active;
}
&.disabled .@{mention-prefix-cls}-editor {
.disabled();
}
.public-DraftEditorPlaceholder-root {
position: absolute;
pointer-events: none;
.public-DraftEditorPlaceholder-inner {
height: auto;
padding: 5px @control-padding-horizontal - 1px;
color: @input-placeholder-color;
white-space: pre-wrap;
word-wrap: break-word;
outline: none;
opacity: 1;
}
}
.DraftEditor-editorContainer .public-DraftEditor-content {
height: auto;
padding: 5px @control-padding-horizontal - 1px;
}
}
.@{mention-prefix-cls}-dropdown {
.reset-component;
position: absolute;
top: -9999px;
left: -9999px;
z-index: @zindex-dropdown;
min-width: 120px;
max-height: 250px;
margin-top: 1.5em;
overflow-x: hidden;
overflow-y: auto;
background-color: @component-background;
border-radius: @border-radius-base;
outline: none;
box-shadow: @box-shadow-base;
&-placement-top {
margin-top: -0.1em;
}
&-notfound&-item {
color: @disabled-color;
.@{iconfont-css-prefix}-loading {
display: block;
color: @primary-color;
text-align: center;
}
}
&-item {
position: relative;
display: block;
padding: 5px @control-padding-horizontal;
overflow: hidden;
color: @text-color;
font-weight: normal;
line-height: 22px;
white-space: nowrap;
text-overflow: ellipsis;
cursor: pointer;
transition: background 0.3s;
&:hover {
background-color: @item-hover-bg;
}
&.focus,
&-active {
background-color: @item-active-bg;
}
&-disabled {
color: @disabled-color;
cursor: not-allowed;
&:hover {
color: @disabled-color;
background-color: @component-background;
cursor: not-allowed;
}
}
&-selected {
&,
&:hover {
color: @text-color;
font-weight: bold;
background-color: @background-color-base;
}
}
&-divider {
height: 1px;
margin: 1px 0;
overflow: hidden;
line-height: 0;
background-color: @border-color-split;
}
}
}

View File

@ -1 +0,0 @@
import './index.less';

View File

@ -6,8 +6,6 @@ title: Mentions
Mention component. Mention component.
> Mention component is deprecated. Please click [here](/components/mention) to view old document.
## When To Use ## When To Use
When need to mention someone or something. When need to mention someone or something.

View File

@ -7,8 +7,6 @@ title: Mentions
提及组件。 提及组件。
> 原 Mention 组件已废弃,原文档请点击[这里](/components/mention)。
## 何时使用 ## 何时使用
用于在输入中提及某人或某事,常用于发布、聊天或评论功能。 用于在输入中提及某人或某事,常用于发布、聊天或评论功能。

View File

@ -114,7 +114,6 @@
"rc-dialog": "~7.5.2", "rc-dialog": "~7.5.2",
"rc-drawer": "~3.0.0", "rc-drawer": "~3.0.0",
"rc-dropdown": "~3.0.0-alpha.0", "rc-dropdown": "~3.0.0-alpha.0",
"rc-editor-mention": "^1.1.13",
"rc-field-form": "^0.0.0-alpha.17", "rc-field-form": "^0.0.0-alpha.17",
"rc-input-number": "~4.5.0", "rc-input-number": "~4.5.0",
"rc-mentions": "~0.4.0", "rc-mentions": "~0.4.0",

View File

@ -31,7 +31,6 @@ Array [
"InputNumber", "InputNumber",
"Layout", "Layout",
"List", "List",
"LocaleProvider",
"message", "message",
"Menu", "Menu",
"Mentions", "Mentions",
@ -63,7 +62,6 @@ Array [
"Timeline", "Timeline",
"Tooltip", "Tooltip",
"Typography", "Typography",
"Mention",
"Upload", "Upload",
"version", "version",
] ]