Skip to content

Commit 1cf060c

Browse files
committed
Add renderSuggestionsContainer prop
1 parent fcbbcbb commit 1cf060c

File tree

14 files changed

+177
-83
lines changed

14 files changed

+177
-83
lines changed

.eslintrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
"react/jsx-uses-vars": 2,
8888
"react/jsx-wrap-multilines": 2,
8989

90-
"mocha/no-exclusive-tests": "error"
90+
"mocha/no-exclusive-tests": "error",
91+
"mocha/no-skipped-tests": "error"
9192
}
9293
}

FAQ.md

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,41 @@
1-
### How do I get the input field?
1+
<a name="gettingTheInputElement"></a>
2+
### How do I get the input element?
23

3-
The input field is available on the Autosuggest instance as `input`.
4+
The input element is available on the Autosuggest instance as `input`.
45

5-
For example, you could store the input field like this:
6+
You could store the input element like this:
67

78
```js
8-
<Autosuggest ref={autosuggest => this.input = autosuggest.input} ... />
9+
function storeInputReference(autosuggest) {
10+
if (autosuggest !== null) {
11+
this.input = autosuggest.input;
12+
}
13+
}
14+
15+
<Autosuggest ref={storeInputReference} ... />
916
```
1017

1118
[Codepen example](http://codepen.io/moroshko/pen/WryOMP)
1219

20+
<a name="limitSuggestionsContainerScrolling"></a>
21+
### How do I limit the scrolling of the suggestions container to the container itself?
22+
23+
When the suggestions container has a scroll bar, and you scroll beyond the start/end of the container, the page starts scrolling. To stop that, you can use [`react-isolated-scroll`](https://github.com/markdalgleish/react-isolated-scroll):
24+
25+
```js
26+
import IsolatedScroll from 'react-isolated-scroll';
27+
28+
function renderSuggestionsContainer({ ref, ...rest }) {
29+
const callRef = isolatedScroll => {
30+
if (isolatedScroll !== null) {
31+
ref(isolatedScroll.component);
32+
}
33+
};
34+
35+
return (
36+
<IsolatedScroll {...rest} ref={callRef} />
37+
);
38+
}
39+
40+
<Autosuggest renderSuggestionsContainer={renderSuggestionsContainer} ... />
41+
```

README.md

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ class Example extends React.Component {
134134
* [`onSuggestionsUpdateRequested`](#onSuggestionsUpdateRequestedProp)
135135
* [`getSuggestionValue`](#getSuggestionValueProp)
136136
* [`renderSuggestion`](#renderSuggestionProp)
137+
* [`renderSuggestionsContainer`](#renderSuggestionsContainerProp)
137138
* [`inputProps`](#inputPropsProp)
138139
* [`shouldRenderSuggestions`](#shouldRenderSuggestionsProp)
139140
* [`alwaysRenderSuggestions`](#alwaysRenderSuggestionsProp)
@@ -284,6 +285,54 @@ function renderSuggestion(suggestion) {
284285

285286
**Note:** `renderSuggestion` must be a pure function (we optimize rendering performance based on this assumption).
286287

288+
<a name="renderSuggestionsContainerProp"></a>
289+
#### renderSuggestionsContainer (optional)
290+
291+
You shouldn't use this function unless you want to customize the behaviour of the suggestions container. For example, you might want to add a custom text before/after the suggestions list, or [customize the scrolling behaviour of the suggestions container](https://github.com/moroshko/react-autosuggest/blob/master/FAQ.md#limitSuggestionsContainerScrolling).
292+
293+
`renderSuggestionsContainer` has the following signature:
294+
295+
```js
296+
function renderSuggestionsContainer(props)
297+
```
298+
299+
You should pass all the `props` to the topmost element that is returned from `renderSuggestionsContainer` with the following exceptions:
300+
301+
* `children` - these are the suggestions themselves. It's up to you where to render them.
302+
* `ref` - when `renderSuggestionsContainer` returns a composite component (e.g. `<IsolatedScroll ... />` as opposed to a DOM node like `<div ... />`), you should call `ref` with the topmost element that the composite component renders.
303+
304+
Examples:
305+
306+
```js
307+
function renderSuggestionsContainer({ children, ...rest }) {
308+
return (
309+
<div {...rest}>
310+
<p>
311+
Some text
312+
</p>
313+
{children}
314+
</div>
315+
);
316+
}
317+
```
318+
319+
320+
```js
321+
import IsolatedScroll from 'react-isolated-scroll';
322+
323+
function renderSuggestionsContainer({ ref, ...rest }) {
324+
const callRef = isolatedScroll => {
325+
if (isolatedScroll !== null) {
326+
ref(isolatedScroll.component);
327+
}
328+
};
329+
330+
return (
331+
<IsolatedScroll {...rest} ref={callRef} />
332+
);
333+
}
334+
```
335+
287336
<a name="inputPropsProp"></a>
288337
#### inputProps (required)
289338

@@ -334,7 +383,7 @@ function shouldRenderSuggestions(value) {
334383
}
335384
```
336385

337-
When `shouldRenderSuggestions` returns `true`, **suggestions will be rendered only when the input field is focused**.
386+
When `shouldRenderSuggestions` returns `true`, **suggestions will be rendered only when the input field is focused**.
338387

339388
If you would like to render suggestions regardless of whether the input field is focused or not, set `alwaysRenderSuggestions={true}` (`shouldRenderSuggestions` is ignored in this case).
340389

@@ -463,15 +512,15 @@ When not specified, `theme` defaults to:
463512

464513
```js
465514
{
466-
container: 'react-autosuggest__container',
467-
containerOpen: 'react-autosuggest__container--open',
468-
input: 'react-autosuggest__input',
469-
suggestionsContainer: 'react-autosuggest__suggestions-container',
470-
suggestion: 'react-autosuggest__suggestion',
471-
suggestionFocused: 'react-autosuggest__suggestion--focused',
472-
sectionContainer: 'react-autosuggest__section-container',
473-
sectionTitle: 'react-autosuggest__section-title',
474-
sectionSuggestionsContainer: 'react-autosuggest__section-suggestions-container'
515+
container: 'react-autosuggest__container',
516+
containerOpen: 'react-autosuggest__container--open',
517+
input: 'react-autosuggest__input',
518+
suggestionsContainer: 'react-autosuggest__suggestions-container',
519+
suggestionsList: 'react-autosuggest__suggestions-list',
520+
suggestion: 'react-autosuggest__suggestion',
521+
suggestionFocused: 'react-autosuggest__suggestion--focused',
522+
sectionContainer: 'react-autosuggest__section-container',
523+
sectionTitle: 'react-autosuggest__section-title'
475524
}
476525
```
477526

demo/src/components/App/components/Examples/components/Basic/autosuggest.css

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@
2323
}
2424

2525
.react-autosuggest__suggestions-container {
26+
display: none;
27+
}
28+
29+
.react-autosuggest__container--open .react-autosuggest__suggestions-container {
30+
display: block;
2631
position: absolute;
2732
top: 51px;
2833
width: 280px;
29-
margin: 0;
30-
padding: 0;
31-
list-style-type: none;
3234
border: 1px solid #aaa;
3335
background-color: #fff;
3436
font-family: 'Open Sans', sans-serif;
@@ -39,6 +41,12 @@
3941
z-index: 2;
4042
}
4143

44+
.react-autosuggest__suggestions-list {
45+
margin: 0;
46+
padding: 0;
47+
list-style-type: none;
48+
}
49+
4250
.react-autosuggest__suggestion {
4351
cursor: pointer;
4452
padding: 10px 20px;
@@ -58,9 +66,3 @@
5866
.react-autosuggest__section-container:first-child .react-autosuggest__section-title {
5967
border-top: 0;
6068
}
61-
62-
.react-autosuggest__section-suggestions-container {
63-
margin: 0;
64-
padding: 0;
65-
list-style-type: none;
66-
}

demo/src/components/App/components/Examples/components/CustomRender/theme.less

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,28 @@
2626
}
2727

2828
.suggestionsContainer {
29-
position: absolute;
30-
top: 51px;
31-
width: 280px;
29+
display: none;
30+
31+
.containerOpen & {
32+
display: block;
33+
position: absolute;
34+
top: 51px;
35+
width: 280px;
36+
border: 1px solid @border-color;
37+
background-color: #fff;
38+
font-family: 'Open Sans', sans-serif;
39+
font-weight: 300;
40+
font-size: 20px;
41+
border-bottom-left-radius: @border-radius;
42+
border-bottom-right-radius: @border-radius;
43+
z-index: 2;
44+
}
45+
}
46+
47+
.suggestionsList {
3248
margin: 0;
3349
padding: 0;
3450
list-style-type: none;
35-
border: 1px solid @border-color;
36-
background-color: #fff;
37-
font-family: 'Open Sans', sans-serif;
38-
font-weight: 300;
39-
font-size: 20px;
40-
border-bottom-left-radius: @border-radius;
41-
border-bottom-right-radius: @border-radius;
42-
z-index: 2;
4351
}
4452

4553
.suggestion {

demo/src/components/App/components/Examples/components/MultipleSections/theme.less

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,28 @@
2727
}
2828

2929
.suggestionsContainer {
30-
position: absolute;
31-
top: 51px;
32-
width: 280px;
30+
display: none;
31+
32+
.containerOpen & {
33+
display: block;
34+
position: absolute;
35+
top: 51px;
36+
width: 280px;
37+
border: 1px solid @border-color;
38+
background-color: #fff;
39+
font-family: 'Open Sans', sans-serif;
40+
font-weight: 300;
41+
font-size: @font-size;
42+
border-bottom-left-radius: @border-radius;
43+
border-bottom-right-radius: @border-radius;
44+
z-index: 2;
45+
}
46+
}
47+
48+
.suggestionsList {
3349
margin: 0;
3450
padding: 0;
3551
list-style-type: none;
36-
border: 1px solid @border-color;
37-
background-color: #fff;
38-
font-family: 'Open Sans', sans-serif;
39-
font-weight: 300;
40-
font-size: @font-size;
41-
border-bottom-left-radius: @border-radius;
42-
border-bottom-right-radius: @border-radius;
43-
z-index: 2;
4452
}
4553

4654
.suggestion {
@@ -62,9 +70,3 @@
6270
border-top: 0;
6371
}
6472
}
65-
66-
.sectionSuggestionsContainer {
67-
margin: 0;
68-
padding: 0;
69-
list-style-type: none;
70-
}

demo/src/components/App/components/Header/redux.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import fetch from 'isomorphic-fetch';
33
const UPDATE_STARGAZERS = 'UPDATE_STARGAZERS';
44

55
const initialState = {
6-
stargazers: '1053'
6+
stargazers: '1061'
77
};
88

99
export function loadStargazers() {

demo/standalone/app.css

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@
2323
}
2424

2525
.react-autosuggest__suggestions-container {
26+
display: none;
27+
}
28+
29+
.react-autosuggest__container--open .react-autosuggest__suggestions-container {
30+
display: block;
2631
position: relative;
2732
top: -1px;
2833
width: 280px;
29-
margin: 0;
30-
padding: 0;
31-
list-style-type: none;
3234
border: 1px solid #aaa;
3335
background-color: #fff;
3436
font-family: 'Open Sans', sans-serif;
@@ -39,6 +41,12 @@
3941
z-index: 2;
4042
}
4143

44+
.react-autosuggest__suggestions-list {
45+
margin: 0;
46+
padding: 0;
47+
list-style-type: none;
48+
}
49+
4250
.react-autosuggest__suggestion {
4351
cursor: pointer;
4452
padding: 10px 20px;

dom-structure.png

13.3 KB
Loading

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"prepublish": "npm run dist && npm run standalone"
2424
},
2525
"dependencies": {
26-
"react-autowhatever": "^4.3.0",
26+
"react-autowhatever": "^5.1.2",
2727
"react-redux": "^4.4.5",
2828
"redux": "^3.5.1"
2929
},
@@ -45,9 +45,9 @@
4545
"chai": "^3.5.0",
4646
"css-loader": "^0.23.1",
4747
"es6-promise": "^3.1.2",
48-
"eslint": "3.2.0",
48+
"eslint": "^3.2.2",
4949
"eslint-plugin-mocha": "^4.3.0",
50-
"eslint-plugin-react": "^6.0.0-rc.0",
50+
"eslint-plugin-react": "^6.0.0",
5151
"extract-text-webpack-plugin": "^1.0.1",
5252
"file-loader": "^0.8.5",
5353
"happypack": "^2.0.4",

src/Autosuggest.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ function mapStateToProps(state) {
1717
class Autosuggest extends Component {
1818
static propTypes = {
1919
suggestions: PropTypes.array.isRequired,
20+
renderSuggestionsContainer: PropTypes.func,
2021
onSuggestionsUpdateRequested: PropTypes.func.isRequired,
2122
getSuggestionValue: PropTypes.func.isRequired,
2223
renderSuggestion: PropTypes.func.isRequired,
@@ -228,9 +229,9 @@ class Autosuggest extends Component {
228229

229230
render() {
230231
const {
231-
suggestions, renderSuggestion, inputProps, shouldRenderSuggestions,
232-
onSuggestionSelected, multiSection, renderSectionTitle, id,
233-
getSectionSuggestions, theme, isFocused, isCollapsed, focusedSectionIndex,
232+
suggestions, renderSuggestionsContainer, renderSuggestion, inputProps,
233+
shouldRenderSuggestions, onSuggestionSelected, multiSection, renderSectionTitle,
234+
id, getSectionSuggestions, theme, isFocused, isCollapsed, focusedSectionIndex,
234235
focusedSuggestionIndex, valueBeforeUpDown, inputFocused, inputBlurred,
235236
inputChanged, updateFocusedSuggestion, revealSuggestions, closeSuggestions,
236237
getSuggestionValue, alwaysRenderSuggestions
@@ -359,6 +360,7 @@ class Autosuggest extends Component {
359360
<Autowhatever
360361
multiSection={multiSection}
361362
items={items}
363+
renderItemsContainer={renderSuggestionsContainer}
362364
renderItem={renderSuggestion}
363365
renderItemData={renderSuggestionData}
364366
renderSectionTitle={renderSectionTitle}

0 commit comments

Comments
 (0)