Skip to content

Commit 62352d9

Browse files
committed
feat: Add suffix property
1 parent 51c3ec0 commit 62352d9

File tree

7 files changed

+81
-5
lines changed

7 files changed

+81
-5
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ React.render(<Demo />, container);
7171
| notFoundContent | Set mentions content when not match | ReactNode | 'Not Found' |
7272
| placement | Set popup placement | 'top' \| 'bottom' | 'bottom' |
7373
| prefix | Set trigger prefix keyword | string \| string[] | '@' |
74+
| suffix | Set suffix string when option is selected | string | '' |
7475
| rows | Set row count | number | 1 |
7576
| split | Set split string before and after selected mention | string | ' ' |
7677
| validateSearch | Customize trigger search logic | (text: string, props: MentionsProps) => void | - |

examples/suffix.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/* eslint no-console: 0 */
2+
3+
import React from 'react';
4+
import Mentions from '../src';
5+
import '../assets/index.less';
6+
7+
const { Option } = Mentions;
8+
9+
class Demo extends React.Component {
10+
onSelect = (option, prefix) => {
11+
console.log('Select:', prefix, '-', option.value);
12+
};
13+
14+
onFocus = () => {
15+
console.log('onFocus');
16+
};
17+
18+
onBlur = () => {
19+
console.log('onBlur');
20+
};
21+
22+
render() {
23+
return (
24+
<div>
25+
<Mentions
26+
autoFocus
27+
rows={3}
28+
prefix="{"
29+
suffix="}"
30+
onSelect={this.onSelect}
31+
onFocus={this.onFocus}
32+
onBlur={this.onBlur}
33+
placeholder="输入 { 关键字进行匹配"
34+
>
35+
<Option value="light">Light</Option>
36+
<Option value="bamboo">Bamboo</Option>
37+
<Option value="cat">Cat</Option>
38+
</Mentions>
39+
</div>
40+
);
41+
}
42+
}
43+
44+
export default Demo;

src/Mentions.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export interface MentionsProps extends BaseTextareaAttrs {
3434
transitionName?: string;
3535
placement?: Placement;
3636
prefix?: string | string[];
37+
suffix?: string;
3738
prefixCls?: string;
3839
value?: string;
3940
filterOption?: false | typeof defaultFilterOption;
@@ -240,13 +241,14 @@ class Mentions extends React.Component<MentionsProps, MentionsState> {
240241

241242
public selectOption = (option: OptionProps) => {
242243
const { value, measureLocation, measurePrefix } = this.state;
243-
const { split, onSelect } = this.props;
244+
const { split, suffix = '', onSelect } = this.props;
244245

245246
const { value: mentionValue = '' } = option;
246247
const { text, selectionLocation } = replaceWithMeasure(value, {
247248
measureLocation,
248249
targetText: mentionValue,
249250
prefix: measurePrefix,
251+
suffix,
250252
selectionStart: this.textarea!.selectionStart,
251253
split: split!,
252254
});

src/util.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export function getLastMeasureIndex(text: string, prefix: string | string[] = ''
5454
interface MeasureConfig {
5555
measureLocation: number;
5656
prefix: string;
57+
suffix: string;
5758
targetText: string;
5859
selectionStart: number;
5960
split: string;
@@ -91,7 +92,7 @@ function reduceText(text: string, targetText: string, split: string) {
9192
* => little @light test
9293
*/
9394
export function replaceWithMeasure(text: string, measureConfig: MeasureConfig) {
94-
const { measureLocation, prefix, targetText, selectionStart, split } = measureConfig;
95+
const { measureLocation, prefix, suffix, targetText, selectionStart, split } = measureConfig;
9596

9697
// Before text will append one space if have other text
9798
let beforeMeasureText = text.slice(0, measureLocation);
@@ -112,8 +113,7 @@ export function replaceWithMeasure(text: string, measureConfig: MeasureConfig) {
112113
restText = restText.slice(split.length);
113114
}
114115

115-
const connectedStartText = `${beforeMeasureText}${prefix}${targetText}${split}`;
116-
116+
const connectedStartText = `${beforeMeasureText}${prefix}${targetText}${suffix}${split}`;
117117
return {
118118
text: `${connectedStartText}${restText}`,
119119
selectionLocation: connectedStartText.length,

tests/FullProcess.spec.jsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ describe('Full Process', () => {
3131
]);
3232

3333
simulateInput(wrapper, '@a');
34+
wrapper.find('textarea').instance().selectionStart = 2;
35+
wrapper.find('textarea').simulate('keyUp', {});
3436
expect(wrapper.find('DropdownMenu').props().options).toMatchObject([
3537
{ value: 'bamboo' },
3638
{ value: 'cat' },
@@ -110,4 +112,27 @@ describe('Full Process', () => {
110112

111113
expect(wrapper.state().measuring).toBe(false);
112114
});
115+
116+
it('add suffix after target if suffix exists', () => {
117+
const onChange = jest.fn();
118+
const onKeyDown = jest.fn();
119+
const wrapper = createMentions({
120+
prefix: '{',
121+
suffix: '}',
122+
split: ' ',
123+
onChange,
124+
onKeyDown,
125+
});
126+
127+
simulateInput(wrapper, '{');
128+
wrapper.find('textarea').instance().selectionStart = 1;
129+
expect(wrapper.state().measuring).toBe(true);
130+
131+
wrapper.find('textarea').simulate('keyDown', {
132+
which: KeyCode.ENTER,
133+
});
134+
135+
expect(wrapper.state().measuring).toBe(false);
136+
expect(onChange).toBeCalledWith('{bamboo} ');
137+
});
113138
});

tests/Mentions.spec.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ describe('Mentions', () => {
100100
describe('filterOption', () => {
101101
it('false', () => {
102102
const wrapper = createMentions({ filterOption: false });
103-
simulateInput(wrapper, '@notExist');
103+
simulateInput(wrapper, '@');
104104
expect(wrapper.find('DropdownMenu').props().options.length).toBe(3);
105105
});
106106

tests/shared/input.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ export function simulateInput(wrapper, text = '', keyEvent) {
55
const myKeyEvent = keyEvent || {
66
which: lastChar.charCodeAt(0),
77
key: lastChar,
8+
target: {
9+
value: text,
10+
selectionStart: text.length,
11+
},
812
};
913

1014
wrapper.find('textarea').simulate('keyDown', myKeyEvent);

0 commit comments

Comments
 (0)