Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ React.render(<Demo />, container);
| notFoundContent | Set mentions content when not match | ReactNode | 'Not Found' |
| placement | Set popup placement | 'top' \| 'bottom' | 'bottom' |
| prefix | Set trigger prefix keyword | string \| string[] | '@' |
| suffix | Set suffix string when option is selected | string | '' |
| rows | Set row count | number | 1 |
| split | Set split string before and after selected mention | string | ' ' |
| validateSearch | Customize trigger search logic | (text: string, props: MentionsProps) => void | - |
Expand Down
44 changes: 44 additions & 0 deletions examples/suffix.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/* eslint no-console: 0 */

import React from 'react';
import Mentions from '../src';
import '../assets/index.less';

const { Option } = Mentions;

class Demo extends React.Component {
onSelect = (option, prefix) => {
console.log('Select:', prefix, '-', option.value);
};

onFocus = () => {
console.log('onFocus');
};

onBlur = () => {
console.log('onBlur');
};

render() {
return (
<div>
<Mentions
autoFocus
rows={3}
prefix="{"
suffix="}"
onSelect={this.onSelect}
onFocus={this.onFocus}
onBlur={this.onBlur}
placeholder="输入 { 关键字进行匹配"
>
<Option value="light">Light</Option>
<Option value="bamboo">Bamboo</Option>
<Option value="cat">Cat</Option>
</Mentions>
</div>
);
}
}

export default Demo;
4 changes: 3 additions & 1 deletion src/Mentions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export interface MentionsProps extends BaseTextareaAttrs {
transitionName?: string;
placement?: Placement;
prefix?: string | string[];
suffix?: string;
prefixCls?: string;
value?: string;
filterOption?: false | typeof defaultFilterOption;
Expand Down Expand Up @@ -240,13 +241,14 @@ class Mentions extends React.Component<MentionsProps, MentionsState> {

public selectOption = (option: OptionProps) => {
const { value, measureLocation, measurePrefix } = this.state;
const { split, onSelect } = this.props;
const { split, suffix = '', onSelect } = this.props;

const { value: mentionValue = '' } = option;
const { text, selectionLocation } = replaceWithMeasure(value, {
measureLocation,
targetText: mentionValue,
prefix: measurePrefix,
suffix,
selectionStart: this.textarea!.selectionStart,
split: split!,
});
Expand Down
6 changes: 3 additions & 3 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export function getLastMeasureIndex(text: string, prefix: string | string[] = ''
interface MeasureConfig {
measureLocation: number;
prefix: string;
suffix: string;
targetText: string;
selectionStart: number;
split: string;
Expand Down Expand Up @@ -91,7 +92,7 @@ function reduceText(text: string, targetText: string, split: string) {
* => little @light test
*/
export function replaceWithMeasure(text: string, measureConfig: MeasureConfig) {
const { measureLocation, prefix, targetText, selectionStart, split } = measureConfig;
const { measureLocation, prefix, suffix, targetText, selectionStart, split } = measureConfig;

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

const connectedStartText = `${beforeMeasureText}${prefix}${targetText}${split}`;

const connectedStartText = `${beforeMeasureText}${prefix}${targetText}${suffix}${split}`;
return {
text: `${connectedStartText}${restText}`,
selectionLocation: connectedStartText.length,
Expand Down
25 changes: 25 additions & 0 deletions tests/FullProcess.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ describe('Full Process', () => {
]);

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

expect(wrapper.state().measuring).toBe(false);
});

it('add suffix after target if suffix exists', () => {
const onChange = jest.fn();
const onKeyDown = jest.fn();
const wrapper = createMentions({
prefix: '{',
suffix: '}',
split: ' ',
onChange,
onKeyDown,
});

simulateInput(wrapper, '{');
wrapper.find('textarea').instance().selectionStart = 1;
expect(wrapper.state().measuring).toBe(true);

wrapper.find('textarea').simulate('keyDown', {
which: KeyCode.ENTER,
});

expect(wrapper.state().measuring).toBe(false);
expect(onChange).toBeCalledWith('{bamboo} ');
});
});
4 changes: 4 additions & 0 deletions tests/shared/input.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ export function simulateInput(wrapper, text = '', keyEvent) {
const myKeyEvent = keyEvent || {
which: lastChar.charCodeAt(0),
key: lastChar,
target: {
value: text,
selectionStart: text.length,
},
};

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