1 import React
from 'react';
2 import AutosuggestAccountContainer
from '../features/compose/containers/autosuggest_account_container';
3 import ImmutablePropTypes
from 'react-immutable-proptypes';
4 import PropTypes
from 'prop-types';
5 import { isRtl
} from '../rtl';
6 import ImmutablePureComponent
from 'react-immutable-pure-component';
7 import Textarea
from 'react-textarea-autosize';
9 const textAtCursorMatchesToken
= (str
, caretPosition
) => {
12 let left
= str
.slice(0, caretPosition
).search(/\S+$/);
13 let right
= str
.slice(caretPosition
).search(/\s/);
16 word
= str
.slice(left
);
18 word
= str
.slice(left
, right
+ caretPosition
);
21 if (!word
|| word
.trim().length
< 2 || word
[0] !== '@') {
25 word
= word
.trim().toLowerCase().slice(1);
27 if (word
.length
> 0) {
28 return [left
+ 1, word
];
34 class AutosuggestTextarea
extends ImmutablePureComponent
{
37 value: PropTypes
.string
,
38 suggestions: ImmutablePropTypes
.list
,
39 disabled: PropTypes
.bool
,
40 placeholder: PropTypes
.string
,
41 onSuggestionSelected: PropTypes
.func
.isRequired
,
42 onSuggestionsClearRequested: PropTypes
.func
.isRequired
,
43 onSuggestionsFetchRequested: PropTypes
.func
.isRequired
,
44 onChange: PropTypes
.func
.isRequired
,
45 onKeyUp: PropTypes
.func
,
46 onKeyDown: PropTypes
.func
,
47 onPaste: PropTypes
.func
.isRequired
,
48 autoFocus: PropTypes
.bool
,
51 static defaultProps
= {
56 suggestionsHidden: false,
57 selectedSuggestion: 0,
63 const [ tokenStart
, token
] = textAtCursorMatchesToken(e
.target
.value
, e
.target
.selectionStart
);
65 if (token
!== null && this.state
.lastToken
!== token
) {
66 this.setState({ lastToken: token
, selectedSuggestion: 0, tokenStart
});
67 this.props
.onSuggestionsFetchRequested(token
);
68 } else if (token
=== null) {
69 this.setState({ lastToken: null });
70 this.props
.onSuggestionsClearRequested();
73 this.props
.onChange(e
);
77 const { suggestions
, disabled
} = this.props
;
78 const { selectedSuggestion
, suggestionsHidden
} = this.state
;
87 if (!suggestionsHidden
) {
89 this.setState({ suggestionsHidden: true });
94 if (suggestions
.size
> 0 && !suggestionsHidden
) {
96 this.setState({ selectedSuggestion: Math
.min(selectedSuggestion
+ 1, suggestions
.size
- 1) });
101 if (suggestions
.size
> 0 && !suggestionsHidden
) {
103 this.setState({ selectedSuggestion: Math
.max(selectedSuggestion
- 1, 0) });
110 if (this.state
.lastToken
!== null && suggestions
.size
> 0 && !suggestionsHidden
) {
113 this.props
.onSuggestionSelected(this.state
.tokenStart
, this.state
.lastToken
, suggestions
.get(selectedSuggestion
));
119 if (e
.defaultPrevented
|| !this.props
.onKeyDown
) {
123 this.props
.onKeyDown(e
);
127 this.setState({ suggestionsHidden: true });
130 onSuggestionClick
= (e
) => {
131 const suggestion
= Number(e
.currentTarget
.getAttribute('data-index'));
133 this.props
.onSuggestionSelected(this.state
.tokenStart
, this.state
.lastToken
, suggestion
);
134 this.textarea
.focus();
137 componentWillReceiveProps (nextProps
) {
138 if (nextProps
.suggestions
!== this.props
.suggestions
&& nextProps
.suggestions
.size
> 0 && this.state
.suggestionsHidden
) {
139 this.setState({ suggestionsHidden: false });
143 setTextarea
= (c
) => {
148 if (e
.clipboardData
&& e
.clipboardData
.files
.length
=== 1) {
149 this.props
.onPaste(e
.clipboardData
.files
);
155 const { value
, suggestions
, disabled
, placeholder
, onKeyUp
, autoFocus
} = this.props
;
156 const { suggestionsHidden
, selectedSuggestion
} = this.state
;
157 const style
= { direction: 'ltr' };
160 style
.direction
= 'rtl';
164 <div className
='autosuggest-textarea'>
166 inputRef
={this.setTextarea
}
167 className
='autosuggest-textarea__textarea'
169 placeholder
={placeholder
}
170 autoFocus
={autoFocus
}
172 onChange
={this.onChange
}
173 onKeyDown
={this.onKeyDown
}
176 onPaste
={this.onPaste
}
180 <div className
={`autosuggest-textarea__suggestions ${suggestionsHidden || suggestions.isEmpty() ? '' : 'autosuggest-textarea__suggestions--visible'}`}>
181 {suggestions
.map((suggestion
, i
) => (
186 data
-index
={suggestion
}
187 className
={`autosuggest-textarea__suggestions__item ${i === selectedSuggestion ? 'selected' : ''}`}
188 onMouseDown
={this.onSuggestionClick
}
190 <AutosuggestAccountContainer id
={suggestion
} />
200 export default AutosuggestTextarea
;