Skip to content
Merged
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
10 changes: 10 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@
"bug",
"code"
]
},
{
"login": "jvorcak",
"name": "Ján Vorčák",
"avatar_url": "https://avatars2.githubusercontent.com/u/1083817?v=4",
"profile": "https://twitter.com/janvorcak",
"contributions": [
"bug",
"code"
]
}
]
}
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Enhanced textarea to achieve autocomplete functionality.

[![MIT License][license-badge]][License]
[![PRs Welcome][prs-badge]][prs]
[![All Contributors](https://img.shields.io/badge/all_contributors-5-orange.svg?style=flat-square)](#contributors)
[![All Contributors](https://img.shields.io/badge/all_contributors-6-orange.svg?style=flat-square)](#contributors)
<hr>

</div>
Expand Down Expand Up @@ -128,7 +128,7 @@ export default App;
- **component** is the component for render the item in suggestion list. It has `selected` and `entity` props provided by React Textarea Autocomplete
- **output** (Optional for string based item. If the item is an object this method is *required*) This function defines text which will be placed into textarea after the user makes a selection.

You can also specify the behavior of caret if you return object `{text: "item", caretPosition: "start"}` the caret will be before the word once the user confirms his selection. Other possible value is "end" and number, which is absolute number in contex of textarea. (0 is equal position before the first char);
You can also specify the behavior of caret if you return object `{text: "item", caretPosition: "start"}` the caret will be before the word once the user confirms his selection. Other possible value is "next", "end" and number, which is absolute number in contex of textarea. (0 is equal position before the first char);

Default behavior for string based item is string: `<TRIGGER><ITEM><TRIGGER>`). This method should **always** return a unique string.

Expand Down Expand Up @@ -222,8 +222,8 @@ Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore -->
| [<img src="https://avatars3.githubusercontent.com/u/8135252?v=4" width="100px;"/><br /><sub><b>Jakub Beneš</b></sub>](https://jukben.cz)<br />[💻](https://github.com/webscopeio/react-textarea-autocomplete/commits?author=jukben "Code") [📖](https://github.com/webscopeio/react-textarea-autocomplete/commits?author=jukben "Documentation") [🎨](#design-jukben "Design") [🤔](#ideas-jukben "Ideas, Planning, & Feedback") | [<img src="https://avatars3.githubusercontent.com/u/3114719?v=4" width="100px;"/><br /><sub><b>Andrey Taktaev</b></sub>](https://github.com/JokerNN)<br />[💻](https://github.com/webscopeio/react-textarea-autocomplete/commits?author=JokerNN "Code") | [<img src="https://avatars0.githubusercontent.com/u/10706203?v=4" width="100px;"/><br /><sub><b>Marcin Lichwała</b></sub>](https://github.com/marcinlichwala)<br />[💻](https://github.com/webscopeio/react-textarea-autocomplete/commits?author=marcinlichwala "Code") [📖](https://github.com/webscopeio/react-textarea-autocomplete/commits?author=marcinlichwala "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/9276511?v=4" width="100px;"/><br /><sub><b>Davidson Nascimento</b></sub>](https://github.com/davidsonsns)<br />[💻](https://github.com/webscopeio/react-textarea-autocomplete/commits?author=davidsonsns "Code") | [<img src="https://avatars1.githubusercontent.com/u/7477359?v=4" width="100px;"/><br /><sub><b>KajMagnus</b></sub>](http://www.effectivediscussions.org/)<br />[🐛](https://github.com/webscopeio/react-textarea-autocomplete/issues?q=author%3Akajmagnus "Bug reports") [💻](https://github.com/webscopeio/react-textarea-autocomplete/commits?author=kajmagnus "Code") |
| :---: | :---: | :---: | :---: | :---: |
| [<img src="https://avatars3.githubusercontent.com/u/8135252?v=4" width="100px;"/><br /><sub><b>Jakub Beneš</b></sub>](https://jukben.cz)<br />[💻](https://github.com/webscopeio/react-textarea-autocomplete/commits?author=jukben "Code") [📖](https://github.com/webscopeio/react-textarea-autocomplete/commits?author=jukben "Documentation") [🎨](#design-jukben "Design") [🤔](#ideas-jukben "Ideas, Planning, & Feedback") | [<img src="https://avatars3.githubusercontent.com/u/3114719?v=4" width="100px;"/><br /><sub><b>Andrey Taktaev</b></sub>](https://github.com/JokerNN)<br />[💻](https://github.com/webscopeio/react-textarea-autocomplete/commits?author=JokerNN "Code") | [<img src="https://avatars0.githubusercontent.com/u/10706203?v=4" width="100px;"/><br /><sub><b>Marcin Lichwała</b></sub>](https://github.com/marcinlichwala)<br />[💻](https://github.com/webscopeio/react-textarea-autocomplete/commits?author=marcinlichwala "Code") [📖](https://github.com/webscopeio/react-textarea-autocomplete/commits?author=marcinlichwala "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/9276511?v=4" width="100px;"/><br /><sub><b>Davidson Nascimento</b></sub>](https://github.com/davidsonsns)<br />[💻](https://github.com/webscopeio/react-textarea-autocomplete/commits?author=davidsonsns "Code") | [<img src="https://avatars1.githubusercontent.com/u/7477359?v=4" width="100px;"/><br /><sub><b>KajMagnus</b></sub>](http://www.effectivediscussions.org/)<br />[🐛](https://github.com/webscopeio/react-textarea-autocomplete/issues?q=author%3Akajmagnus "Bug reports") [💻](https://github.com/webscopeio/react-textarea-autocomplete/commits?author=kajmagnus "Code") | [<img src="https://avatars2.githubusercontent.com/u/1083817?v=4" width="100px;"/><br /><sub><b>Ján Vorčák</b></sub>](https://twitter.com/janvorcak)<br />[🐛](https://github.com/webscopeio/react-textarea-autocomplete/issues?q=author%3Ajvorcak "Bug reports") [💻](https://github.com/webscopeio/react-textarea-autocomplete/commits?author=jvorcak "Code") |
| :---: | :---: | :---: | :---: | :---: | :---: |
<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
Expand Down
20 changes: 18 additions & 2 deletions cypress/integration/textarea.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ describe('React Textarea Autocomplete', () => {
* This is probably Cypress bug (1.0.2)
* This test needs to be runned in headed mode, otherwise fails
*/
cy.get('[data-test="changeCaretOption"]').click();
cy.get('[id="caretStart"]').click();

cy.get('.rta__textarea').type('This is test :ro{downarrow}{downarrow}');

Expand All @@ -54,7 +54,7 @@ describe('React Textarea Autocomplete', () => {
* This is probably Cypress bug (1.0.2)
* This test needs to be runned in headed mode, otherwise fails
*/
cy.get('[data-test="changeCaretOption"]').click();
cy.get('[id="caretEnd"]').click();

cy.get('.rta__textarea').type('This is test :ro{downarrow}{downarrow}');

Expand All @@ -63,13 +63,29 @@ describe('React Textarea Autocomplete', () => {
cy.get('[data-test="actualCaretPosition"]').contains('15'); // emoji is 2 bytes
});

it('should have place caret after word with a space', () => {
/**
* This is probably Cypress bug (1.0.2)
* This test needs to be runned in headed mode, otherwise fails
*/
cy.get('[id="caretNext"]').click();

cy.get('.rta__textarea').type('This is test :ro{downarrow}{downarrow}');

cy.get('.rta__item:nth-child(3)').click();

cy.get('[data-test="actualCaretPosition"]').contains('16'); // emoji is 2 bytes
});

it('set caret position', () => {
cy.get('[id="caretEnd"]').click();
cy.get('.rta__textarea').type('This is test :ro{uparrow}{enter}');
cy.get('[data-test="setCaretPosition"]').click();
cy.get('[data-test="actualCaretPosition"]').contains('1');
});

it('get caret position', () => {
cy.get('[id="caretEnd"]').click();
const stub = cy.stub();

cy.on('window:alert', stub);
Expand Down
83 changes: 64 additions & 19 deletions example/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,26 @@ class App extends React.Component {
clickoutsideOption: false,
caretPosition: 0,
text: '',
};
optionsCaret: 'start',
}

_handleOptionsCaretEnd = () => {
this.setState(() => ({
optionsCaret: 'end',
}))
}

_handleOptionsCaretNext = () => {
this.setState(() => ({
optionsCaret: 'next',
}))
}

_handleOptionsCaretStart = () => {
this.setState(({ optionsCaretStart }) => ({
optionsCaretStart: !optionsCaretStart,
}));
};
this.setState(() => ({
optionsCaret: 'start',
}))
}

_handleClickoutsideOption = () => {
this.setState(({ clickoutsideOption }) => ({
Expand Down Expand Up @@ -68,9 +81,11 @@ class App extends React.Component {

_outputCaretStart = item => ({ text: item.char, caretPosition: 'start' });

_outputCaretNext = item => ({ text: item.char, caretPosition: 'next' });

render() {
const {
optionsCaretStart,
optionsCaret,
caretPosition,
clickoutsideOption,
text,
Expand All @@ -79,15 +94,41 @@ class App extends React.Component {
return (
<div>
<div>
<label>
<input
data-test="changeCaretOption"
type="checkbox"
defaultChecked={optionsCaretStart}
onChange={this._handleOptionsCaretStart}
/>
<input
id="caretStart"
name="caret"
value="start"
type="radio"
checked={this.state.optionsCaret === 'start'}
onChange={this._handleOptionsCaretStart}
/>
<label htmlFor="caretStart">
Place caret before word
</label>

<input
id="caretEnd"
name="caret"
value="end"
type="radio"
checked={this.state.optionsCaret === 'end'}
onChange={this._handleOptionsCaretEnd}
/>
<label htmlFor="caretEnd">
Place caret after word
</label>

<input
id="caretNext"
name="caret"
value="next"
type="radio"
checked={this.state.optionsCaret === 'next'}
onChange={this._handleOptionsCaretNext}
/>
<label htmlFor="caretNext">
Place caret after word with a space
</label>
</div>
<div>
<label>
Expand Down Expand Up @@ -140,9 +181,11 @@ class App extends React.Component {
.slice(0, 10)
.map(({ name, char }) => ({ name, char })),
component: Item,
output: optionsCaretStart
? this._outputCaretStart
: this._outputCaretEnd,
output: {
start: this._outputCaretStart,
end: this._outputCaretEnd,
next: this._outputCaretNext,
}[optionsCaret]
},
'@': {
dataProvider: token =>
Expand All @@ -152,9 +195,11 @@ class App extends React.Component {
}, 1000)
),
component: Item,
output: optionsCaretStart
? this._outputCaretStart
: this._outputCaretEnd,
output: {
start: this._outputCaretStart,
end: this._outputCaretEnd,
next: this._outputCaretNext,
}[optionsCaret]
},
}}
/>
Expand Down
5 changes: 4 additions & 1 deletion src/Textarea.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class ReactTextareaAutocomplete extends React.Component<
switch (position) {
case 'start':
return startToken;
case 'next':
case 'end':
return startToken + token.length;
default:
Expand Down Expand Up @@ -132,7 +133,9 @@ class ReactTextareaAutocomplete extends React.Component<
);

const startOfTokenPosition = textToModify.search(/\S*$/);
const newTokenString = newToken.text;
// we add space after emoji is selected if a caret position is next
const newTokenString =
newToken.caretPosition === 'next' ? `${newToken.text} ` : newToken.text;
const newCaretPosition = computeCaretPosition(
newToken.caretPosition,
newTokenString,
Expand Down
2 changes: 1 addition & 1 deletion src/types.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// @flow

export type caretPositionType = 'start' | 'end' | number;
export type caretPositionType = 'start' | 'end' | 'next' | number;

export type textToReplaceType = {|
text: string,
Expand Down