downshift 1.31.12 → 1.31.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,7 +19,7 @@ autocomplete/dropdown/select/combobox components</p>
19
19
  [![downloads][downloads-badge]][npmcharts] [![version][version-badge]][package]
20
20
  [![MIT License][license-badge]][license]
21
21
 
22
- [![All Contributors](https://img.shields.io/badge/all_contributors-77-orange.svg?style=flat-square)](#contributors)
22
+ [![All Contributors](https://img.shields.io/badge/all_contributors-79-orange.svg?style=flat-square)](#contributors)
23
23
  [![PRs Welcome][prs-badge]][prs] [![Chat][chat-badge]][chat]
24
24
  [![Code of Conduct][coc-badge]][coc]
25
25
 
@@ -56,55 +56,54 @@ harder to contribute to.
56
56
  ## Table of Contents
57
57
 
58
58
  <!-- START doctoc generated TOC please keep comment here to allow auto update -->
59
-
60
59
  <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
61
60
 
62
- * [Installation](#installation)
63
- * [Usage](#usage)
64
- * [Props](#props)
65
- * [defaultSelectedItem](#defaultselecteditem)
66
- * [defaultHighlightedIndex](#defaulthighlightedindex)
67
- * [defaultInputValue](#defaultinputvalue)
68
- * [defaultIsOpen](#defaultisopen)
69
- * [itemToString](#itemtostring)
70
- * [selectedItemChanged](#selecteditemchanged)
71
- * [getA11yStatusMessage](#geta11ystatusmessage)
72
- * [onChange](#onchange)
73
- * [onSelect](#onselect)
74
- * [onStateChange](#onstatechange)
75
- * [stateReducer](#statereducer)
76
- * [onInputValueChange](#oninputvaluechange)
77
- * [itemCount](#itemcount)
78
- * [highlightedIndex](#highlightedindex)
79
- * [inputValue](#inputvalue)
80
- * [isOpen](#isopen)
81
- * [selectedItem](#selecteditem)
82
- * [render](#render)
83
- * [id](#id)
84
- * [environment](#environment)
85
- * [onOuterClick](#onouterclick)
86
- * [stateChangeTypes](#statechangetypes)
87
- * [Control Props](#control-props)
88
- * [Render Prop Function](#render-prop-function)
89
- * [prop getters](#prop-getters)
90
- * [actions](#actions)
91
- * [state](#state)
92
- * [props](#props)
93
- * [Event Handlers](#event-handlers)
94
- * [default handlers](#default-handlers)
95
- * [customizing handlers](#customizing-handlers)
96
- * [Utilities](#utilities)
97
- * [resetIdCounter](#resetidcounter)
98
- * [React Native](#react-native)
99
- * [Gotchas](#gotchas)
100
- * [Examples](#examples)
101
- * [FAQ](#faq)
102
- * [Upcoming Breaking Changes](#upcoming-breaking-changes)
103
- * [Inspiration](#inspiration)
104
- * [Other Solutions](#other-solutions)
105
- * [Bindings for ReasonML](#bindings-for-reasonml)
106
- * [Contributors](#contributors)
107
- * [LICENSE](#license)
61
+ - [Installation](#installation)
62
+ - [Usage](#usage)
63
+ - [Props](#props)
64
+ - [defaultSelectedItem](#defaultselecteditem)
65
+ - [defaultHighlightedIndex](#defaulthighlightedindex)
66
+ - [defaultInputValue](#defaultinputvalue)
67
+ - [defaultIsOpen](#defaultisopen)
68
+ - [itemToString](#itemtostring)
69
+ - [selectedItemChanged](#selecteditemchanged)
70
+ - [getA11yStatusMessage](#geta11ystatusmessage)
71
+ - [onChange](#onchange)
72
+ - [onSelect](#onselect)
73
+ - [onStateChange](#onstatechange)
74
+ - [stateReducer](#statereducer)
75
+ - [onInputValueChange](#oninputvaluechange)
76
+ - [itemCount](#itemcount)
77
+ - [highlightedIndex](#highlightedindex)
78
+ - [inputValue](#inputvalue)
79
+ - [isOpen](#isopen)
80
+ - [selectedItem](#selecteditem)
81
+ - [render](#render)
82
+ - [id](#id)
83
+ - [environment](#environment)
84
+ - [onOuterClick](#onouterclick)
85
+ - [stateChangeTypes](#statechangetypes)
86
+ - [Control Props](#control-props)
87
+ - [Render Prop Function](#render-prop-function)
88
+ - [prop getters](#prop-getters)
89
+ - [actions](#actions)
90
+ - [state](#state)
91
+ - [props](#props)
92
+ - [Event Handlers](#event-handlers)
93
+ - [default handlers](#default-handlers)
94
+ - [customizing handlers](#customizing-handlers)
95
+ - [Utilities](#utilities)
96
+ - [resetIdCounter](#resetidcounter)
97
+ - [React Native](#react-native)
98
+ - [Gotchas](#gotchas)
99
+ - [Examples](#examples)
100
+ - [FAQ](#faq)
101
+ - [Upcoming Breaking Changes](#upcoming-breaking-changes)
102
+ - [Inspiration](#inspiration)
103
+ - [Other Solutions](#other-solutions)
104
+ - [Bindings for ReasonML](#bindings-for-reasonml)
105
+ - [Contributors](#contributors)
106
+ - [LICENSE](#license)
108
107
 
109
108
  <!-- END doctoc generated TOC please keep comment here to allow auto update -->
110
109
 
@@ -126,65 +125,70 @@ npm install --save downshift
126
125
 
127
126
  ## Usage
128
127
 
128
+ > [Try it out in the browser](https://codesandbox.io/s/6z67jvklw3)
129
+
129
130
  ```jsx
131
+ import React from 'react'
132
+ import {render} from 'react-dom'
130
133
  import Downshift from 'downshift'
131
134
 
132
- function BasicAutocomplete({items, onChange}) {
133
- return (
134
- <Downshift
135
- onChange={onChange}
136
- render={({
137
- getInputProps,
138
- getItemProps,
139
- isOpen,
140
- inputValue,
141
- selectedItem,
142
- highlightedIndex,
143
- }) => (
144
- <div>
145
- <input {...getInputProps({placeholder: 'Favorite fruit ?'})} />
146
- {isOpen ? (
147
- <div style={{border: '1px solid #ccc'}}>
148
- {items
149
- .filter(
150
- i =>
151
- !inputValue ||
152
- i.toLowerCase().includes(inputValue.toLowerCase()),
153
- )
154
- .map((item, index) => (
155
- <div
156
- {...getItemProps({item})}
157
- key={item}
158
- style={{
135
+ const items = [
136
+ {value: 'apple'},
137
+ {value: 'pear'},
138
+ {value: 'orange'},
139
+ {value: 'grape'},
140
+ {value: 'banana'},
141
+ ]
142
+
143
+ render(
144
+ <Downshift
145
+ onChange={selection => alert(`You selected ${selection.value}`)}
146
+ itemToString={item => (item ? item.value : '')}
147
+ >
148
+ {({
149
+ getInputProps,
150
+ getItemProps,
151
+ getLabelProps,
152
+ isOpen,
153
+ inputValue,
154
+ highlightedIndex,
155
+ selectedItem,
156
+ }) => (
157
+ <div>
158
+ <label {...getLabelProps()}>Enter a fruit</label>
159
+ <input {...getInputProps()} />
160
+ {isOpen ? (
161
+ <div>
162
+ {items
163
+ .filter(item => !inputValue || item.value.includes(inputValue))
164
+ .map((item, index) => (
165
+ <div
166
+ {...getItemProps({
167
+ key: item.value,
168
+ index,
169
+ item,
170
+ style: {
159
171
  backgroundColor:
160
- highlightedIndex === index ? 'gray' : 'white',
172
+ highlightedIndex === index ? 'lightgray' : 'white',
161
173
  fontWeight: selectedItem === item ? 'bold' : 'normal',
162
- }}
163
- >
164
- {item}
165
- </div>
166
- ))}
167
- </div>
168
- ) : null}
169
- </div>
170
- )}
171
- />
172
- )
173
- }
174
-
175
- function App() {
176
- return (
177
- <BasicAutocomplete
178
- items={['apple', 'orange', 'carrot']}
179
- onChange={selectedItem => console.log(selectedItem)}
180
- />
181
- )
182
- }
174
+ },
175
+ })}
176
+ >
177
+ {item.value}
178
+ </div>
179
+ ))}
180
+ </div>
181
+ ) : null}
182
+ </div>
183
+ )}
184
+ </Downshift>,
185
+ document.getElementById('root'),
186
+ )
183
187
  ```
184
188
 
185
- `downshift` is the only component. It doesn't render anything itself, it just
189
+ `<Downshift />` is the only component. It doesn't render anything itself, it just
186
190
  calls the render function and renders that. ["Use a render
187
- prop!"][use-a-render-prop]! `<Downshift render={/* your JSX here! */} />`.
191
+ prop!"][use-a-render-prop]! `<Downshift>{downshift => <div>/* your JSX here! */</div>}</Downshift>`.
188
192
 
189
193
  ## Props
190
194
 
@@ -264,8 +268,8 @@ Called when the user selects an item and the selected item has changed. Called
264
268
  with the item that was selected and the new state of `downshift`. (see
265
269
  `onStateChange` for more info on `stateAndHelpers`).
266
270
 
267
- * `selectedItem`: The item that was just selected
268
- * `stateAndHelpers`: This is the same thing your `render` prop function is
271
+ - `selectedItem`: The item that was just selected
272
+ - `stateAndHelpers`: This is the same thing your `render` prop function is
269
273
  called with (see [Render Prop Function](#render-prop-function))
270
274
 
271
275
  ### onSelect
@@ -277,8 +281,8 @@ Called when the user selects an item, regardless of the previous selected item.
277
281
  Called with the item that was selected and the new state of `downshift`. (see
278
282
  `onStateChange` for more info on `stateAndHelpers`).
279
283
 
280
- * `selectedItem`: The item that was just selected
281
- * `stateAndHelpers`: This is the same thing your `render` prop function is
284
+ - `selectedItem`: The item that was just selected
285
+ - `stateAndHelpers`: This is the same thing your `render` prop function is
282
286
  called with (see [Render Prop Function](#render-prop-function))
283
287
 
284
288
  ### onStateChange
@@ -293,10 +297,10 @@ pass it as props, rather than letting downshift control all its state itself.
293
297
  The parameters both take the shape of internal state (`{highlightedIndex: number, inputValue: string, isOpen: boolean, selectedItem: any}`) but differ
294
298
  slightly.
295
299
 
296
- * `changes`: These are the properties that actually have changed since the last
300
+ - `changes`: These are the properties that actually have changed since the last
297
301
  state change. This also has a `type` property which you can learn more about
298
302
  in the [`stateChangeTypes`](#statechangetypes) section.
299
- * `stateAndHelpers`: This is the exact same thing your `render` prop function is
303
+ - `stateAndHelpers`: This is the exact same thing your `render` prop function is
300
304
  called with (see [Render Prop Function](#render-prop-function))
301
305
 
302
306
  > Tip: This function will be called any time _any_ state is changed. The best
@@ -316,8 +320,8 @@ control over how the component interacts with user updates without having to
316
320
  use [Control Props](#control-props). It gives you the current state and the
317
321
  state that will be set, and you return the state that you want to set.
318
322
 
319
- * `state`: The full current state of downshift.
320
- * `changes`: These are the properties that are about to change. This also has a
323
+ - `state`: The full current state of downshift.
324
+ - `changes`: These are the properties that are about to change. This also has a
321
325
  `type` property which you can learn more about in the
322
326
  [`stateChangeTypes`](#statechangetypes) section.
323
327
 
@@ -352,8 +356,8 @@ Called whenever the input value changes. Useful to use instead or in combination
352
356
  of `onStateChange` when `inputValue` is a controlled prop to
353
357
  [avoid issues with cursor positions](https://github.com/paypal/downshift/issues/217).
354
358
 
355
- * `inputValue`: The current value of the input
356
- * `stateAndHelpers`: This is the same thing your `render` prop function is
359
+ - `inputValue`: The current value of the input
360
+ - `stateAndHelpers`: This is the same thing your `render` prop function is
357
361
  called with (see [Render Prop Function](#render-prop-function))
358
362
 
359
363
  ### itemCount
@@ -521,7 +525,7 @@ your root element.
521
525
 
522
526
  Required properties:
523
527
 
524
- * `refKey`: if you're rendering a composite component, that component will need
528
+ - `refKey`: if you're rendering a composite component, that component will need
525
529
  to accept a prop which it forwards to the root DOM element. Commonly, folks
526
530
  call this `innerRef`. So you'd call: `getRootProps({refKey: 'innerRef'})` and
527
531
  your composite component would forward like: `<div ref={props.innerRef} />`
@@ -546,7 +550,7 @@ There are no required properties for this method.
546
550
 
547
551
  Optional properties:
548
552
 
549
- * `disabled`: If this is set to true, then no event handlers will be returned from `getInputProps` and a `disabled` prop will be returned (effectively disabling the input).
553
+ - `disabled`: If this is set to true, then no event handlers will be returned from `getInputProps` and a `disabled` prop will be returned (effectively disabling the input).
550
554
 
551
555
  #### `getLabelProps`
552
556
 
@@ -597,18 +601,18 @@ items.filter(shouldRenderItem).map(item => <div {...getItemProps({item})} />)
597
601
 
598
602
  Required properties:
599
603
 
600
- * `item`: this is the item data that will be selected when the user selects a
604
+ - `item`: this is the item data that will be selected when the user selects a
601
605
  particular item.
602
606
 
603
607
  Optional properties:
604
608
 
605
- * `index`: This is how `downshift` keeps track of your item when updating the
609
+ - `index`: This is how `downshift` keeps track of your item when updating the
606
610
  `highlightedIndex` as the user keys around. By default, `downshift` will
607
611
  assume the `index` is the order in which you're calling `getItemProps`. This
608
612
  is often good enough, but if you find odd behavior, try setting this
609
613
  explicitly. It's probably best to be explicit about `index` when using a
610
614
  windowing library like `react-virtualized`.
611
- * `disabled`: If this is set to `true`, then all of the downshift item event
615
+ - `disabled`: If this is set to `true`, then all of the downshift item event
612
616
  handlers will be omitted. Items will not be highlighted when hovered,
613
617
  and items will not be selected when clicked.
614
618
 
@@ -621,9 +625,9 @@ apply all of the proper ARIA attributes.
621
625
 
622
626
  Optional properties:
623
627
 
624
- * `disabled`: If this is set to `true`, then all of the downshift button event
628
+ - `disabled`: If this is set to `true`, then all of the downshift button event
625
629
  handlers will be omitted (it wont toggle the menu when clicked).
626
- * `aria-label`: The `aria-label` prop is in English. You should probably override
630
+ - `aria-label`: The `aria-label` prop is in English. You should probably override
627
631
  this yourself so you can provide translations:
628
632
 
629
633
  ```jsx
@@ -687,23 +691,23 @@ described below.
687
691
 
688
692
  ### default handlers
689
693
 
690
- * `ArrowDown`: moves the highlighted index down by 1. If this shift key is held
694
+ - `ArrowDown`: moves the highlighted index down by 1. If this shift key is held
691
695
  when this event fires, the highlighted index will jump down 5 indices instead of 1.
692
696
  NOTE: if the current highlighed index is within the bottom 5 indices, the top-most
693
697
  index will be highlighted.)
694
698
 
695
- * `ArrowUp`: moves the highlighted index up by 1. If this shift key is held when
699
+ - `ArrowUp`: moves the highlighted index up by 1. If this shift key is held when
696
700
  this event fires, the highlighted index will jump up 5 indices instead of 1. NOTE:
697
701
  if the current highlighed index is within the top 5 indices, the bottom-most index
698
702
  will be highlighted.)
699
703
 
700
- * `Enter`: if the menu is open, select the currently highlighted item. If the menu
704
+ - `Enter`: if the menu is open, select the currently highlighted item. If the menu
701
705
  is open, the usual 'Enter' event is prevented by Downshift's default implicit enter
702
706
  handler; so, for example, a form submission event will not work as one might expect
703
707
  (though if the menu is closed the form submission will work normally). See below
704
708
  for customizing the handlers.
705
709
 
706
- * `Escape`: will reset downshift's state. This means that `highlightedIndex` will be
710
+ - `Escape`: will reset downshift's state. This means that `highlightedIndex` will be
707
711
  set to the `defaultHighlightedIndex`, the `inputValue` will be set to the `itemToString`
708
712
  value of the `selectedItem`, and the `isOpen` state will be set to `false`.
709
713
 
@@ -788,42 +792,43 @@ Since Downshift renders it's UI using render props, Downshift supports rendering
788
792
 
789
793
  ### Gotchas
790
794
 
791
- * Your root view will need to either pass a ref to `getRootProps` or call `getRootProps` with `{ suppressRefError: true }`. This ref is used to catch a common set of errors around composite components. [Learn more in `getRootProps`](#getrootprops).
792
- * When using a `<FlatList>` or `<ScrollView>`, be sure to supply the [`keyboardShouldPersistTaps`](https://facebook.github.io/react-native/docs/scrollview.html#keyboardshouldpersisttaps) prop to ensure that your text input stays focus, while allowing for taps on the touchables rendered for your items.
795
+ - Your root view will need to either pass a ref to `getRootProps` or call `getRootProps` with `{ suppressRefError: true }`. This ref is used to catch a common set of errors around composite components. [Learn more in `getRootProps`](#getrootprops).
796
+ - When using a `<FlatList>` or `<ScrollView>`, be sure to supply the [`keyboardShouldPersistTaps`](https://facebook.github.io/react-native/docs/scrollview.html#keyboardshouldpersisttaps) prop to ensure that your text input stays focus, while allowing for taps on the touchables rendered for your items.
793
797
 
794
798
  ## Examples
795
799
 
796
800
  Examples exist on [codesandbox.io][examples]:
797
801
 
798
- * [Bare bones autocomplete](https://codesandbox.io/s/6z67jvklw3)
799
- * [Multiple selection](https://codesandbox.io/s/W6gyJ30kn) (uses controlled
802
+ - [Bare bones autocomplete](https://codesandbox.io/s/6z67jvklw3)
803
+ - [Multiple selection](https://codesandbox.io/s/W6gyJ30kn) (uses controlled
800
804
  `selectedItem` API).
801
- * [Type Ahead Example](https://codesandbox.io/s/82m2px40q9) (uses controlled
805
+ - [Type Ahead Example](https://codesandbox.io/s/82m2px40q9) (uses controlled
802
806
  `selectedItem` API).
803
- * [Integration with Apollo](https://codesandbox.io/s/m5zrvqj85p)
804
- * [Integration with Redux](https://codesandbox.io/s/3ywmnyr0zq)
805
- * [Integration with `react-instantsearch`](https://codesandbox.io/s/kvn0lpp83)
807
+ - [Integration with Apollo](https://codesandbox.io/s/m5zrvqj85p)
808
+ - [Integration with Redux](https://codesandbox.io/s/3ywmnyr0zq)
809
+ - [Integration with `react-instantsearch`](https://codesandbox.io/s/kvn0lpp83)
806
810
  from Algolia
807
- * [Material-UI (1.0.0-beta.4) Combobox Using Downshift](https://codesandbox.io/s/QMGq4kAY)
808
- * [Material-UI (1.0.0-beta.33) Multiple select with autocomplete](https://codesandbox.io/s/7k3674z09q)
809
- * [Integration with `GenieJS`](https://codesandbox.io/s/jRLKrxwgl)
811
+ - [Material-UI (1.0.0-beta.4) Combobox Using Downshift](https://codesandbox.io/s/QMGq4kAY)
812
+ - [Material-UI (1.0.0-beta.33) Multiple select with autocomplete](https://codesandbox.io/s/7k3674z09q)
813
+ - [Integration with `GenieJS`](https://codesandbox.io/s/jRLKrxwgl)
810
814
  ([learn more about `genie` here](https://github.com/kentcdodds/genie))
811
- * [Handling and displaying errors](https://codesandbox.io/s/zKE37vorr)
812
- * [Integration with React Router](https://codesandbox.io/s/ww9lwloy8w)
813
- * [Windowing with `react-tiny-virtual-list`](https://codesandbox.io/s/v670kq95l)
814
- * [Section/option group example](https://codesandbox.io/s/zx1kj58npl)
815
- * [Integration with `fuzzaldrin-plus` (Fuzzy matching)](https://codesandbox.io/s/pyq3v4o3j)
816
- * [Dropdown/select implementation with Bootstrap](https://codesandbox.io/s/53y8jvpj0k)
817
- * [Multiple editable tag selection](https://codesandbox.io/s/o4yp9vmm8z)
818
- * [Downshift implemented as compound components and a Higher Order Component](https://codesandbox.io/s/017n1jqo00)
815
+ - [Handling and displaying errors](https://codesandbox.io/s/zKE37vorr)
816
+ - [Integration with React Router](https://codesandbox.io/s/ww9lwloy8w)
817
+ - [Windowing with `react-tiny-virtual-list`](https://codesandbox.io/s/v670kq95l)
818
+ - [Section/option group example](https://codesandbox.io/s/zx1kj58npl)
819
+ - [Integration with `fuzzaldrin-plus` (Fuzzy matching)](https://codesandbox.io/s/pyq3v4o3j)
820
+ - [Dropdown/select implementation with Bootstrap](https://codesandbox.io/s/53y8jvpj0k)
821
+ - [Multiple editable tag selection](https://codesandbox.io/s/o4yp9vmm8z)
822
+ - [Downshift implemented as compound components and a Higher Order Component](https://codesandbox.io/s/017n1jqo00)
819
823
  (exposes a `withDownshift` higher order component which you can use to get at
820
824
  the state, actions, prop getters in a rendered downshift tree).
821
- * [Downshift Spectre.css example](https://codesandbox.io/s/M89KQOBRB)
822
- * [Integration with `redux-form`](https://codesandbox.io/s/k594964z13)
823
- * [Integration with `react-final-form`](https://codesandbox.io/s/qzm43nn2mj)
824
- * [Provider Pattern](https://codesandbox.io/s/mywzk3133p) - how to avoid prop-drilling if you like to break up your render method into more components
825
- * [React Native example](https://snack.expo.io/SkE0LxXqM)
826
- * [React VR example](https://github.com/infiniteluke/bassdrop)
825
+ - [Downshift Spectre.css example](https://codesandbox.io/s/M89KQOBRB)
826
+ - [Integration with `redux-form`](https://codesandbox.io/s/k594964z13)
827
+ - [Integration with `react-final-form`](https://codesandbox.io/s/qzm43nn2mj)
828
+ - [Provider Pattern](https://codesandbox.io/s/mywzk3133p) - how to avoid prop-drilling if you like to break up your render method into more components
829
+ - [React Native example](https://snack.expo.io/SkE0LxXqM)
830
+ - [React VR example](https://github.com/infiniteluke/bassdrop)
831
+ - [Multiple checkbox selection](https://codesandbox.io/s/5z711pmr3l)
827
832
 
828
833
  If you would like to add an example, follow these steps:
829
834
 
@@ -920,8 +925,8 @@ Autocomplete][jquery-complete].
920
925
 
921
926
  You can watch me build the first iteration of `downshift` on YouTube:
922
927
 
923
- * [Part 1](https://www.youtube.com/watch?v=2kzD1IjDy5s&list=PLV5CVI1eNcJh5CTgArGVwANebCrAh2OUE&index=11)
924
- * [Part 2](https://www.youtube.com/watch?v=w1Z7Jvj08_s&list=PLV5CVI1eNcJh5CTgArGVwANebCrAh2OUE&index=10)
928
+ - [Part 1](https://www.youtube.com/watch?v=2kzD1IjDy5s&list=PLV5CVI1eNcJh5CTgArGVwANebCrAh2OUE&index=11)
929
+ - [Part 2](https://www.youtube.com/watch?v=w1Z7Jvj08_s&list=PLV5CVI1eNcJh5CTgArGVwANebCrAh2OUE&index=10)
925
930
 
926
931
  You'll find more recordings of me working on `downshift` on [my livestream
927
932
  YouTube playlist][yt-playlist].
@@ -931,8 +936,8 @@ YouTube playlist][yt-playlist].
931
936
  You can implement these other solutions using `downshift`, but if you'd prefer
932
937
  to use these out of the box solutions, then that's fine too:
933
938
 
934
- * [`react-select`](https://github.com/JedWatson/react-select)
935
- * [`react-autocomplete`](https://github.com/reactjs/react-autocomplete)
939
+ - [`react-select`](https://github.com/JedWatson/react-select)
940
+ - [`react-autocomplete`](https://github.com/reactjs/react-autocomplete)
936
941
 
937
942
  ## Bindings for ReasonML
938
943
 
@@ -956,6 +961,8 @@ Thanks goes to these people ([emoji key][emojis]):
956
961
  | [<img src="https://avatars0.githubusercontent.com/u/410792?v=4" width="100px;"/><br /><sub><b>Dony Sukardi</b></sub>](http://dsds.io)<br />[💡](#example-donysukardi "Examples") [💬](#question-donysukardi "Answering Questions") [💻](https://github.com/paypal/downshift/commits?author=donysukardi "Code") [⚠️](https://github.com/paypal/downshift/commits?author=donysukardi "Tests") | [<img src="https://avatars1.githubusercontent.com/u/2755722?v=4" width="100px;"/><br /><sub><b>Dillon Mulroy</b></sub>](https://dillonmulroy.com)<br />[📖](https://github.com/paypal/downshift/commits?author=dmmulroy "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/12440573?v=4" width="100px;"/><br /><sub><b>Curtis Tate Wilkinson</b></sub>](https://twitter.com/curtytate)<br />[💻](https://github.com/paypal/downshift/commits?author=curtiswilkinson "Code") | [<img src="https://avatars3.githubusercontent.com/u/383212?v=4" width="100px;"/><br /><sub><b>Brice BERNARD</b></sub>](https://github.com/brikou)<br />[🐛](https://github.com/paypal/downshift/issues?q=author%3Abrikou "Bug reports") [💻](https://github.com/paypal/downshift/commits?author=brikou "Code") | [<img src="https://avatars3.githubusercontent.com/u/14304503?v=4" width="100px;"/><br /><sub><b>Tony Xu</b></sub>](https://github.com/xutopia)<br />[💻](https://github.com/paypal/downshift/commits?author=xutopia "Code") | [<img src="https://avatars1.githubusercontent.com/u/14035529?v=4" width="100px;"/><br /><sub><b>Anthony Ng</b></sub>](http://anthonyng.me)<br />[📖](https://github.com/paypal/downshift/commits?author=newyork-anthonyng "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/11996139?v=4" width="100px;"/><br /><sub><b>S S</b></sub>](https://github.com/notruth)<br />[💬](#question-notruth "Answering Questions") [💻](https://github.com/paypal/downshift/commits?author=notruth "Code") [📖](https://github.com/paypal/downshift/commits?author=notruth "Documentation") [🤔](#ideas-notruth "Ideas, Planning, & Feedback") [⚠️](https://github.com/paypal/downshift/commits?author=notruth "Tests") |
957
962
  | [<img src="https://avatars0.githubusercontent.com/u/29493001?v=4" width="100px;"/><br /><sub><b>Austin Tackaberry</b></sub>](http://austintackaberry.co)<br />[💬](#question-austintackaberry "Answering Questions") [💻](https://github.com/paypal/downshift/commits?author=austintackaberry "Code") [📖](https://github.com/paypal/downshift/commits?author=austintackaberry "Documentation") [🐛](https://github.com/paypal/downshift/issues?q=author%3Aaustintackaberry "Bug reports") [💡](#example-austintackaberry "Examples") [🤔](#ideas-austintackaberry "Ideas, Planning, & Feedback") [👀](#review-austintackaberry "Reviewed Pull Requests") [⚠️](https://github.com/paypal/downshift/commits?author=austintackaberry "Tests") | [<img src="https://avatars3.githubusercontent.com/u/4168055?v=4" width="100px;"/><br /><sub><b>Jean Duthon</b></sub>](https://github.com/jduthon)<br />[🐛](https://github.com/paypal/downshift/issues?q=author%3Ajduthon "Bug reports") [💻](https://github.com/paypal/downshift/commits?author=jduthon "Code") | [<img src="https://avatars3.githubusercontent.com/u/3889580?v=4" width="100px;"/><br /><sub><b>Anton Telesh</b></sub>](http://antontelesh.github.io)<br />[🐛](https://github.com/paypal/downshift/issues?q=author%3AAntontelesh "Bug reports") [💻](https://github.com/paypal/downshift/commits?author=Antontelesh "Code") | [<img src="https://avatars3.githubusercontent.com/u/1060669?v=4" width="100px;"/><br /><sub><b>Eric Edem</b></sub>](https://github.com/ericedem)<br />[💻](https://github.com/paypal/downshift/commits?author=ericedem "Code") [📖](https://github.com/paypal/downshift/commits?author=ericedem "Documentation") [🤔](#ideas-ericedem "Ideas, Planning, & Feedback") [⚠️](https://github.com/paypal/downshift/commits?author=ericedem "Tests") | [<img src="https://avatars3.githubusercontent.com/u/3409645?v=4" width="100px;"/><br /><sub><b>Austin Wood</b></sub>](https://github.com/indiesquidge)<br />[💬](#question-indiesquidge "Answering Questions") [📖](https://github.com/paypal/downshift/commits?author=indiesquidge "Documentation") [👀](#review-indiesquidge "Reviewed Pull Requests") | [<img src="https://avatars3.githubusercontent.com/u/14275790?v=4" width="100px;"/><br /><sub><b>Mark Murray</b></sub>](https://github.com/mmmurray)<br />[🚇](#infra-mmmurray "Infrastructure (Hosting, Build-Tools, etc)") | [<img src="https://avatars0.githubusercontent.com/u/1862172?v=4" width="100px;"/><br /><sub><b>Gianmarco</b></sub>](https://github.com/gsimone)<br />[🐛](https://github.com/paypal/downshift/issues?q=author%3Agsimone "Bug reports") [💻](https://github.com/paypal/downshift/commits?author=gsimone "Code") |
958
963
  | [<img src="https://avatars2.githubusercontent.com/u/6838136?v=4" width="100px;"/><br /><sub><b>Emmanuel Pastor</b></sub>](https://github.com/pastr)<br />[💡](#example-pastr "Examples") | [<img src="https://avatars2.githubusercontent.com/u/10345034?v=4" width="100px;"/><br /><sub><b>dalehurwitz</b></sub>](https://github.com/dalehurwitz)<br />[💻](https://github.com/paypal/downshift/commits?author=dalehurwitz "Code") | [<img src="https://avatars1.githubusercontent.com/u/4813007?v=4" width="100px;"/><br /><sub><b>Bogdan Lobor</b></sub>](https://github.com/blobor)<br />[🐛](https://github.com/paypal/downshift/issues?q=author%3Ablobor "Bug reports") [💻](https://github.com/paypal/downshift/commits?author=blobor "Code") | [<img src="https://avatars0.githubusercontent.com/u/1127238?v=4" width="100px;"/><br /><sub><b>Luke Herrington</b></sub>](https://github.com/infiniteluke)<br />[💡](#example-infiniteluke "Examples") | [<img src="https://avatars2.githubusercontent.com/u/6361167?v=4" width="100px;"/><br /><sub><b>Brandon Clemons</b></sub>](https://github.com/drobannx)<br />[💻](https://github.com/paypal/downshift/commits?author=drobannx "Code") | [<img src="https://avatars0.githubusercontent.com/u/10591587?v=4" width="100px;"/><br /><sub><b>Kieran</b></sub>](https://github.com/aMollusk)<br />[💻](https://github.com/paypal/downshift/commits?author=aMollusk "Code") | [<img src="https://avatars3.githubusercontent.com/u/11570627?v=4" width="100px;"/><br /><sub><b>Brushedoctopus</b></sub>](https://github.com/Brushedoctopus)<br />[🐛](https://github.com/paypal/downshift/issues?q=author%3ABrushedoctopus "Bug reports") [💻](https://github.com/paypal/downshift/commits?author=Brushedoctopus "Code") |
964
+ | [<img src="https://avatars3.githubusercontent.com/u/5456216?v=4" width="100px;"/><br /><sub><b>Cameron Edwards</b></sub>](http://cameronpedwards.com)<br />[💻](https://github.com/paypal/downshift/commits?author=cameronprattedwards "Code") | [<img src="https://avatars0.githubusercontent.com/u/7252803?v=4" width="100px;"/><br /><sub><b>Alfred Ringstad</b></sub>](https://hyperlab.se)<br />[💻](https://github.com/paypal/downshift/commits?author=alfredringstad "Code") |
965
+
959
966
  <!-- ALL-CONTRIBUTORS-LIST:END -->
960
967
 
961
968
  This project follows the [all-contributors][all-contributors] specification.
@@ -1012,6 +1012,12 @@ var _initialiseProps = function () {
1012
1012
  Enter: function Enter(event) {
1013
1013
  if (this.getState().isOpen) {
1014
1014
  event.preventDefault();
1015
+ var itemIndex = this.getState().highlightedIndex;
1016
+ var item = this.items[itemIndex];
1017
+ var itemNode = this.getItemNodeFromIndex(itemIndex);
1018
+ if (item == null || itemNode && itemNode.hasAttribute('disabled')) {
1019
+ return;
1020
+ }
1015
1021
  this.selectHighlightedItem({
1016
1022
  type: Downshift.stateChangeTypes.keyDownEnter
1017
1023
  });
@@ -1073,18 +1079,27 @@ var _initialiseProps = function () {
1073
1079
  if (_this4.props.environment.document.activeElement === _this4.props.environment.document.body) {
1074
1080
  event.target.focus();
1075
1081
  }
1076
- // Ensure that toggle of menu occurs after the potential blur event in iOS
1077
- setTimeout(function () {
1078
- return _this4.toggleMenu({ type: Downshift.stateChangeTypes.clickButton });
1079
- });
1082
+ // to simplify testing components that use downshift, we'll not wrap this in a setTimeout
1083
+ // if the NODE_ENV is test. With the proper build system, this should be dead code eliminated
1084
+ // when building for production and should therefore have no impact on production code.
1085
+ if (process.env.NODE_ENV === 'test') {
1086
+ _this4.toggleMenu({ type: Downshift.stateChangeTypes.clickButton });
1087
+ } else {
1088
+ // Ensure that toggle of menu occurs after the potential blur event in iOS
1089
+ setTimeout(function () {
1090
+ return _this4.toggleMenu({ type: Downshift.stateChangeTypes.clickButton });
1091
+ });
1092
+ }
1080
1093
  };
1081
1094
 
1082
- this.button_handleBlur = function () {
1095
+ this.button_handleBlur = function (event) {
1096
+ var blurTarget = event.target; // Save blur target for comparison with activeElement later
1083
1097
  // Need setTimeout, so that when the user presses Tab, the activeElement is the next focused element, not body element
1084
1098
  setTimeout(function () {
1085
- if (!_this4.isMouseDown && (_this4.props.environment.document.activeElement == null || _this4.props.environment.document.activeElement.id !== _this4.inputId)) {
1086
- _this4.reset({ type: Downshift.stateChangeTypes.blurButton });
1087
- }
1099
+ if (!_this4.isMouseDown && (_this4.props.environment.document.activeElement == null || _this4.props.environment.document.activeElement.id !== _this4.inputId) && _this4.props.environment.document.activeElement !== blurTarget // Do nothing if we refocus the same element again (to solve issue in Safari on iOS)
1100
+ ) {
1101
+ _this4.reset({ type: Downshift.stateChangeTypes.blurButton });
1102
+ }
1088
1103
  });
1089
1104
  };
1090
1105
 
@@ -1007,6 +1007,12 @@ var _initialiseProps = function () {
1007
1007
  Enter: function Enter(event) {
1008
1008
  if (this.getState().isOpen) {
1009
1009
  event.preventDefault();
1010
+ var itemIndex = this.getState().highlightedIndex;
1011
+ var item = this.items[itemIndex];
1012
+ var itemNode = this.getItemNodeFromIndex(itemIndex);
1013
+ if (item == null || itemNode && itemNode.hasAttribute('disabled')) {
1014
+ return;
1015
+ }
1010
1016
  this.selectHighlightedItem({
1011
1017
  type: Downshift.stateChangeTypes.keyDownEnter
1012
1018
  });
@@ -1068,18 +1074,27 @@ var _initialiseProps = function () {
1068
1074
  if (_this4.props.environment.document.activeElement === _this4.props.environment.document.body) {
1069
1075
  event.target.focus();
1070
1076
  }
1071
- // Ensure that toggle of menu occurs after the potential blur event in iOS
1072
- setTimeout(function () {
1073
- return _this4.toggleMenu({ type: Downshift.stateChangeTypes.clickButton });
1074
- });
1077
+ // to simplify testing components that use downshift, we'll not wrap this in a setTimeout
1078
+ // if the NODE_ENV is test. With the proper build system, this should be dead code eliminated
1079
+ // when building for production and should therefore have no impact on production code.
1080
+ if (process.env.NODE_ENV === 'test') {
1081
+ _this4.toggleMenu({ type: Downshift.stateChangeTypes.clickButton });
1082
+ } else {
1083
+ // Ensure that toggle of menu occurs after the potential blur event in iOS
1084
+ setTimeout(function () {
1085
+ return _this4.toggleMenu({ type: Downshift.stateChangeTypes.clickButton });
1086
+ });
1087
+ }
1075
1088
  };
1076
1089
 
1077
- this.button_handleBlur = function () {
1090
+ this.button_handleBlur = function (event) {
1091
+ var blurTarget = event.target; // Save blur target for comparison with activeElement later
1078
1092
  // Need setTimeout, so that when the user presses Tab, the activeElement is the next focused element, not body element
1079
1093
  setTimeout(function () {
1080
- if (!_this4.isMouseDown && (_this4.props.environment.document.activeElement == null || _this4.props.environment.document.activeElement.id !== _this4.inputId)) {
1081
- _this4.reset({ type: Downshift.stateChangeTypes.blurButton });
1082
- }
1094
+ if (!_this4.isMouseDown && (_this4.props.environment.document.activeElement == null || _this4.props.environment.document.activeElement.id !== _this4.inputId) && _this4.props.environment.document.activeElement !== blurTarget // Do nothing if we refocus the same element again (to solve issue in Safari on iOS)
1095
+ ) {
1096
+ _this4.reset({ type: Downshift.stateChangeTypes.blurButton });
1097
+ }
1083
1098
  });
1084
1099
  };
1085
1100
 
@@ -850,6 +850,12 @@ var _initialiseProps = function () {
850
850
  Enter: function Enter(event) {
851
851
  if (this.getState().isOpen) {
852
852
  event.preventDefault();
853
+ var itemIndex = this.getState().highlightedIndex;
854
+ var item = this.items[itemIndex];
855
+ var itemNode = this.getItemNodeFromIndex(itemIndex);
856
+ if (item == null || itemNode && itemNode.hasAttribute('disabled')) {
857
+ return;
858
+ }
853
859
  this.selectHighlightedItem({
854
860
  type: Downshift.stateChangeTypes.keyDownEnter
855
861
  });
@@ -910,18 +916,27 @@ var _initialiseProps = function () {
910
916
  if (_this4.props.environment.document.activeElement === _this4.props.environment.document.body) {
911
917
  event.target.focus();
912
918
  }
913
- // Ensure that toggle of menu occurs after the potential blur event in iOS
914
- setTimeout(function () {
915
- return _this4.toggleMenu({ type: Downshift.stateChangeTypes.clickButton });
916
- });
919
+ // to simplify testing components that use downshift, we'll not wrap this in a setTimeout
920
+ // if the NODE_ENV is test. With the proper build system, this should be dead code eliminated
921
+ // when building for production and should therefore have no impact on production code.
922
+ if (process.env.NODE_ENV === 'test') {
923
+ _this4.toggleMenu({ type: Downshift.stateChangeTypes.clickButton });
924
+ } else {
925
+ // Ensure that toggle of menu occurs after the potential blur event in iOS
926
+ setTimeout(function () {
927
+ return _this4.toggleMenu({ type: Downshift.stateChangeTypes.clickButton });
928
+ });
929
+ }
917
930
  };
918
931
 
919
- this.button_handleBlur = function () {
932
+ this.button_handleBlur = function (event) {
933
+ var blurTarget = event.target; // Save blur target for comparison with activeElement later
920
934
  // Need setTimeout, so that when the user presses Tab, the activeElement is the next focused element, not body element
921
935
  setTimeout(function () {
922
- if (!_this4.isMouseDown && (_this4.props.environment.document.activeElement == null || _this4.props.environment.document.activeElement.id !== _this4.inputId)) {
923
- _this4.reset({ type: Downshift.stateChangeTypes.blurButton });
924
- }
936
+ if (!_this4.isMouseDown && (_this4.props.environment.document.activeElement == null || _this4.props.environment.document.activeElement.id !== _this4.inputId) && _this4.props.environment.document.activeElement !== blurTarget // Do nothing if we refocus the same element again (to solve issue in Safari on iOS)
937
+ ) {
938
+ _this4.reset({ type: Downshift.stateChangeTypes.blurButton });
939
+ }
925
940
  });
926
941
  };
927
942