Skip to content

Commit bb28cae

Browse files
Christopher Tempeljukben
Christopher Tempel
authored andcommitted
append suggestions dropdown in body (#149)
* append suggestions dropdown in body see #128 #128 * add property renderToBody * fix lint and flow errors * fix positioning += instead of =+ * new prop renderToBody adding documentation for the new prop "renderToBody"
1 parent 38d3930 commit bb28cae

File tree

5 files changed

+49
-12
lines changed

5 files changed

+49
-12
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ or there is UMD build available. [Check out this pen as example](https://codepen
5353
| movePopupAsYouType | boolean | When it's true the textarea will move along with a caret as a user continues to type. Defaults to false. |
5454
| boundariesElement | string \| HTMLElement | Element which should prevent autocomplete to overflow. Defaults to _body_. |
5555
| textAreaComponent | React.Component \| {component: React.Component, ref: string} | What component use for as textarea. Default is `textarea`. (You can combine this with [react-autosize-textarea](https://github.com/buildo/react-autosize-textarea) for instance) |
56+
| renderToBody | boolean | When set to `true` the autocomplete will be rendered at the end of the `<body>`. Default is `false`. |
5657
| style | Style Object | Style's of textarea |
5758
| listStyle | Style Object | Styles of list's wrapper |
5859
| itemStyle | Style Object | Styles of item's wrapper |

example/App.jsx

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ class App extends React.Component {
3131
minChar: 0,
3232
optionsCaret: "start",
3333
actualTokenInProvider: "",
34-
showSecondTextarea: false
34+
showSecondTextarea: false,
35+
renderToBody: false
3536
};
3637

3738
_handleOptionsCaretEnd = () => {
@@ -64,6 +65,12 @@ class App extends React.Component {
6465
}));
6566
};
6667

68+
_handleRenderToBody = () => {
69+
this.setState(({ renderToBody }) => ({
70+
renderToBody: !renderToBody
71+
}));
72+
};
73+
6774
_onChangeHandle = ({ target: { value } }) => {
6875
this.setState({
6976
text: value
@@ -130,7 +137,8 @@ class App extends React.Component {
130137
actualTokenInProvider,
131138
showSecondTextarea,
132139
text,
133-
minChar
140+
minChar,
141+
renderToBody
134142
} = this.state;
135143

136144
return (
@@ -188,6 +196,17 @@ class App extends React.Component {
188196
Move popup as you type
189197
</label>
190198
</div>
199+
<div>
200+
<label>
201+
<input
202+
data-test="renderToBody"
203+
type="checkbox"
204+
defaultChecked={renderToBody}
205+
onChange={this._handleRenderToBody}
206+
/>
207+
Render autocomplete to body
208+
</label>
209+
</div>
191210
<div>
192211
<label>
193212
<input
@@ -255,6 +274,7 @@ class App extends React.Component {
255274
minChar={minChar}
256275
value={text}
257276
onChange={this._onChangeHandle}
277+
renderToBody={renderToBody}
258278
trigger={{
259279
":": {
260280
dataProvider: token =>

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@
8282
},
8383
"peerDependencies": {
8484
"prop-types": "^15.0.0",
85-
"react": "^16.0.0"
85+
"react": "^16.0.0",
86+
"react-dom": "16.6.0"
8687
},
8788
"dependencies": {
8889
"custom-event": "^1.0.1",

src/Textarea.jsx

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
/* eslint react/no-multi-comp: 0 */
33

44
import React from "react";
5+
import ReactDOM from 'react-dom'
56
import PropTypes from "prop-types";
67
import getCaretCoordinates from "textarea-caret";
78
import CustomEvent from "custom-event";
@@ -49,7 +50,8 @@ type AutocompleteProps = {
4950
top: ?number,
5051
left: ?number,
5152
children: *,
52-
textareaRef: HTMLElement
53+
textareaRef: HTMLElement,
54+
renderToBody: ?boolean
5355
};
5456

5557
class Autocomplete extends React.Component<AutocompleteProps> {
@@ -149,6 +151,11 @@ class Autocomplete extends React.Component<AutocompleteProps> {
149151
unusedClasses.push(POSITION_CONFIGURATION.Y.TOP);
150152
}
151153

154+
if(this.props.renderToBody) {
155+
topPosition += textareaBounds.top;
156+
leftPosition += textareaBounds.left;
157+
}
158+
152159
this.ref.style.top = `${topPosition}px`;
153160
this.ref.style.left = `${leftPosition}px`;
154161

@@ -157,9 +164,9 @@ class Autocomplete extends React.Component<AutocompleteProps> {
157164
}
158165

159166
render() {
160-
const { style, className, innerRef, children } = this.props;
161-
162-
return (
167+
const { style, className, innerRef, children, renderToBody } = this.props;
168+
const body = document.body;
169+
const autocompleteContainer = (
163170
<div
164171
ref={ref => {
165172
// $FlowFixMe
@@ -173,6 +180,8 @@ class Autocomplete extends React.Component<AutocompleteProps> {
173180
{children}
174181
</div>
175182
);
183+
184+
return renderToBody && body !== null ? ReactDOM.createPortal(autocompleteContainer, body) : autocompleteContainer;
176185
}
177186
}
178187

@@ -186,7 +195,8 @@ class ReactTextareaAutocomplete extends React.Component<
186195
minChar: 1,
187196
boundariesElement: "body",
188197
scrollToItem: true,
189-
textAreaComponent: "textarea"
198+
textAreaComponent: "textarea",
199+
renderToBody: false
190200
};
191201

192202
constructor(props: TextareaProps) {
@@ -645,7 +655,8 @@ class ReactTextareaAutocomplete extends React.Component<
645655
"dropdownStyle",
646656
"dropdownClassName",
647657
"movePopupAsYouType",
648-
"textAreaComponent"
658+
"textAreaComponent",
659+
"renderToBody"
649660
];
650661

651662
// eslint-disable-next-line
@@ -937,7 +948,8 @@ class ReactTextareaAutocomplete extends React.Component<
937948
containerClassName,
938949
loaderStyle,
939950
loaderClassName,
940-
textAreaComponent
951+
textAreaComponent,
952+
renderToBody
941953
} = this.props;
942954
const {
943955
left,
@@ -995,6 +1007,7 @@ class ReactTextareaAutocomplete extends React.Component<
9951007
movePopupAsYouType={movePopupAsYouType}
9961008
boundariesElement={boundariesElement}
9971009
textareaRef={this.textareaRef}
1010+
renderToBody={renderToBody}
9981011
>
9991012
{suggestionData && component && textToReplace && (
10001013
<List
@@ -1113,7 +1126,8 @@ ReactTextareaAutocomplete.propTypes = {
11131126
loaderClassName: PropTypes.string,
11141127
dropdownClassName: PropTypes.string,
11151128
boundariesElement: containerPropCheck, //eslint-disable-line
1116-
trigger: triggerPropsCheck //eslint-disable-line
1129+
trigger: triggerPropsCheck, //eslint-disable-line
1130+
renderToBody: PropTypes.bool
11171131
};
11181132

11191133
export default ReactTextareaAutocomplete;

src/types.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ export type TextareaProps = {
9393
listClassName: ?string,
9494
itemClassName: ?string,
9595
loaderClassName: ?string,
96-
dropdownClassName: ?string
96+
dropdownClassName: ?string,
97+
renderToBody: ?boolean
9798
};
9899

99100
export type TextareaState = {

0 commit comments

Comments
 (0)