UNPKG

116 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
6
7var _objectWithoutPropertiesLoose = _interopDefault(require('@babel/runtime/helpers/objectWithoutPropertiesLoose'));
8var _extends = _interopDefault(require('@babel/runtime/helpers/extends'));
9var _assertThisInitialized = _interopDefault(require('@babel/runtime/helpers/assertThisInitialized'));
10var _inheritsLoose = _interopDefault(require('@babel/runtime/helpers/inheritsLoose'));
11var PropTypes = _interopDefault(require('prop-types'));
12var react = require('react');
13var reactIs = require('react-is');
14var computeScrollIntoView = _interopDefault(require('compute-scroll-into-view'));
15
16var idCounter = 0;
17/**
18 * Accepts a parameter and returns it if it's a function
19 * or a noop function if it's not. This allows us to
20 * accept a callback, but not worry about it if it's not
21 * passed.
22 * @param {Function} cb the callback
23 * @return {Function} a function
24 */
25
26function cbToCb(cb) {
27 return typeof cb === 'function' ? cb : noop;
28}
29
30function noop() {}
31/**
32 * Scroll node into view if necessary
33 * @param {HTMLElement} node the element that should scroll into view
34 * @param {HTMLElement} menuNode the menu element of the component
35 */
36
37
38function scrollIntoView(node, menuNode) {
39 if (node === null) {
40 return;
41 }
42
43 var actions = computeScrollIntoView(node, {
44 boundary: menuNode,
45 block: 'nearest',
46 scrollMode: 'if-needed'
47 });
48 actions.forEach(function (_ref) {
49 var el = _ref.el,
50 top = _ref.top,
51 left = _ref.left;
52 el.scrollTop = top;
53 el.scrollLeft = left;
54 });
55}
56/**
57 * @param {HTMLElement} parent the parent node
58 * @param {HTMLElement} child the child node
59 * @return {Boolean} whether the parent is the child or the child is in the parent
60 */
61
62
63function isOrContainsNode(parent, child) {
64 return parent === child || parent.contains && parent.contains(child);
65}
66/**
67 * Simple debounce implementation. Will call the given
68 * function once after the time given has passed since
69 * it was last called.
70 * @param {Function} fn the function to call after the time
71 * @param {Number} time the time to wait
72 * @return {Function} the debounced function
73 */
74
75
76function debounce(fn, time) {
77 var timeoutId;
78
79 function cancel() {
80 if (timeoutId) {
81 clearTimeout(timeoutId);
82 }
83 }
84
85 function wrapper() {
86 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
87 args[_key] = arguments[_key];
88 }
89
90 cancel();
91 timeoutId = setTimeout(function () {
92 timeoutId = null;
93 fn.apply(void 0, args);
94 }, time);
95 }
96
97 wrapper.cancel = cancel;
98 return wrapper;
99}
100/**
101 * This is intended to be used to compose event handlers.
102 * They are executed in order until one of them sets
103 * `event.preventDownshiftDefault = true`.
104 * @param {...Function} fns the event handler functions
105 * @return {Function} the event handler to add to an element
106 */
107
108
109function callAllEventHandlers() {
110 for (var _len2 = arguments.length, fns = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
111 fns[_key2] = arguments[_key2];
112 }
113
114 return function (event) {
115 for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
116 args[_key3 - 1] = arguments[_key3];
117 }
118
119 return fns.some(function (fn) {
120 if (fn) {
121 fn.apply(void 0, [event].concat(args));
122 }
123
124 return event.preventDownshiftDefault || event.hasOwnProperty('nativeEvent') && event.nativeEvent.preventDownshiftDefault;
125 });
126 };
127}
128
129function handleRefs() {
130 for (var _len4 = arguments.length, refs = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
131 refs[_key4] = arguments[_key4];
132 }
133
134 return function (node) {
135 refs.forEach(function (ref) {
136 if (typeof ref === 'function') {
137 ref(node);
138 } else if (ref) {
139 ref.current = node;
140 }
141 });
142 };
143}
144/**
145 * This generates a unique ID for an instance of Downshift
146 * @return {String} the unique ID
147 */
148
149
150function generateId() {
151 return String(idCounter++);
152}
153/**
154 * Resets idCounter to 0. Used for SSR.
155 */
156
157
158function resetIdCounter() {
159 idCounter = 0;
160}
161/**
162 * Default implementation for status message. Only added when menu is open.
163 * Will specift if there are results in the list, and if so, how many,
164 * and what keys are relevant.
165 *
166 * @param {Object} param the downshift state and other relevant properties
167 * @return {String} the a11y status message
168 */
169
170
171function getA11yStatusMessage(_ref2) {
172 var isOpen = _ref2.isOpen,
173 resultCount = _ref2.resultCount;
174
175 if (!isOpen) {
176 return '';
177 }
178
179 if (!resultCount) {
180 return 'No results are available.';
181 }
182
183 return resultCount + " result" + (resultCount === 1 ? ' is' : 's are') + " available, use up and down arrow keys to navigate. Press Enter key to select.";
184}
185/**
186 * Takes an argument and if it's an array, returns the first item in the array
187 * otherwise returns the argument
188 * @param {*} arg the maybe-array
189 * @param {*} defaultValue the value if arg is falsey not defined
190 * @return {*} the arg or it's first item
191 */
192
193
194function unwrapArray(arg, defaultValue) {
195 arg = Array.isArray(arg) ?
196 /* istanbul ignore next (preact) */
197 arg[0] : arg;
198
199 if (!arg && defaultValue) {
200 return defaultValue;
201 } else {
202 return arg;
203 }
204}
205/**
206 * @param {Object} element (P)react element
207 * @return {Boolean} whether it's a DOM element
208 */
209
210
211function isDOMElement(element) {
212 // then we assume this is react
213 return typeof element.type === 'string';
214}
215/**
216 * @param {Object} element (P)react element
217 * @return {Object} the props
218 */
219
220
221function getElementProps(element) {
222 return element.props;
223}
224/**
225 * Throws a helpful error message for required properties. Useful
226 * to be used as a default in destructuring or object params.
227 * @param {String} fnName the function name
228 * @param {String} propName the prop name
229 */
230
231
232function requiredProp(fnName, propName) {
233 // eslint-disable-next-line no-console
234 console.error("The property \"" + propName + "\" is required in \"" + fnName + "\"");
235}
236
237var stateKeys = ['highlightedIndex', 'inputValue', 'isOpen', 'selectedItem', 'type'];
238/**
239 * @param {Object} state the state object
240 * @return {Object} state that is relevant to downshift
241 */
242
243function pickState(state) {
244 if (state === void 0) {
245 state = {};
246 }
247
248 var result = {};
249 stateKeys.forEach(function (k) {
250 if (state.hasOwnProperty(k)) {
251 result[k] = state[k];
252 }
253 });
254 return result;
255}
256/**
257 * This will perform a shallow merge of the given state object
258 * with the state coming from props
259 * (for the controlled component scenario)
260 * This is used in state updater functions so they're referencing
261 * the right state regardless of where it comes from.
262 *
263 * @param {Object} state The state of the component/hook.
264 * @param {Object} props The props that may contain controlled values.
265 * @returns {Object} The merged controlled state.
266 */
267
268
269function getState(state, props) {
270 return Object.keys(state).reduce(function (prevState, key) {
271 prevState[key] = isControlledProp(props, key) ? props[key] : state[key];
272 return prevState;
273 }, {});
274}
275/**
276 * This determines whether a prop is a "controlled prop" meaning it is
277 * state which is controlled by the outside of this component rather
278 * than within this component.
279 *
280 * @param {Object} props The props that may contain controlled values.
281 * @param {String} key the key to check
282 * @return {Boolean} whether it is a controlled controlled prop
283 */
284
285
286function isControlledProp(props, key) {
287 return props[key] !== undefined;
288}
289/**
290 * Normalizes the 'key' property of a KeyboardEvent in IE/Edge
291 * @param {Object} event a keyboardEvent object
292 * @return {String} keyboard key
293 */
294
295
296function normalizeArrowKey(event) {
297 var key = event.key,
298 keyCode = event.keyCode;
299 /* istanbul ignore next (ie) */
300
301 if (keyCode >= 37 && keyCode <= 40 && key.indexOf('Arrow') !== 0) {
302 return "Arrow" + key;
303 }
304
305 return key;
306}
307/**
308 * Simple check if the value passed is object literal
309 * @param {*} obj any things
310 * @return {Boolean} whether it's object literal
311 */
312
313
314function isPlainObject(obj) {
315 return Object.prototype.toString.call(obj) === '[object Object]';
316}
317/**
318 * Returns the new index in the list, in a circular way. If next value is out of bonds from the total,
319 * it will wrap to either 0 or itemCount - 1.
320 *
321 * @param {number} moveAmount Number of positions to move. Negative to move backwards, positive forwards.
322 * @param {number} baseIndex The initial position to move from.
323 * @param {number} itemCount The total number of items.
324 * @param {Function} getItemNodeFromIndex Used to check if item is disabled.
325 * @param {boolean} circular Specify if navigation is circular. Default is true.
326 * @returns {number} The new index after the move.
327 */
328
329
330function getNextWrappingIndex(moveAmount, baseIndex, itemCount, getItemNodeFromIndex, circular) {
331 if (circular === void 0) {
332 circular = true;
333 }
334
335 var itemsLastIndex = itemCount - 1;
336
337 if (typeof baseIndex !== 'number' || baseIndex < 0 || baseIndex >= itemCount) {
338 baseIndex = moveAmount > 0 ? -1 : itemsLastIndex + 1;
339 }
340
341 var newIndex = baseIndex + moveAmount;
342
343 if (newIndex < 0) {
344 newIndex = circular ? itemsLastIndex : 0;
345 } else if (newIndex > itemsLastIndex) {
346 newIndex = circular ? 0 : itemsLastIndex;
347 }
348
349 var nonDisabledNewIndex = getNextNonDisabledIndex(moveAmount, newIndex, itemCount, getItemNodeFromIndex, circular);
350 return nonDisabledNewIndex === -1 ? baseIndex : nonDisabledNewIndex;
351}
352/**
353 * Returns the next index in the list of an item that is not disabled.
354 *
355 * @param {number} moveAmount Number of positions to move. Negative to move backwards, positive forwards.
356 * @param {number} baseIndex The initial position to move from.
357 * @param {number} itemCount The total number of items.
358 * @param {Function} getItemNodeFromIndex Used to check if item is disabled.
359 * @param {boolean} circular Specify if navigation is circular. Default is true.
360 * @returns {number} The new index. Returns baseIndex if item is not disabled. Returns next non-disabled item otherwise. If no non-disabled found it will return -1.
361 */
362
363
364function getNextNonDisabledIndex(moveAmount, baseIndex, itemCount, getItemNodeFromIndex, circular) {
365 var currentElementNode = getItemNodeFromIndex(baseIndex);
366
367 if (!currentElementNode || !currentElementNode.hasAttribute('disabled')) {
368 return baseIndex;
369 }
370
371 if (moveAmount > 0) {
372 for (var index = baseIndex + 1; index < itemCount; index++) {
373 if (!getItemNodeFromIndex(index).hasAttribute('disabled')) {
374 return index;
375 }
376 }
377 } else {
378 for (var _index = baseIndex - 1; _index >= 0; _index--) {
379 if (!getItemNodeFromIndex(_index).hasAttribute('disabled')) {
380 return _index;
381 }
382 }
383 }
384
385 if (circular) {
386 return moveAmount > 0 ? getNextNonDisabledIndex(1, 0, itemCount, getItemNodeFromIndex, false) : getNextNonDisabledIndex(-1, itemCount - 1, itemCount, getItemNodeFromIndex, false);
387 }
388
389 return -1;
390}
391/**
392 * Checks if event target is within the downshift elements.
393 *
394 * @param {EventTarget} target Target to check.
395 * @param {HTMLElement[]} downshiftElements The elements that form downshift (list, toggle button etc).
396 * @param {Document} document The document.
397 * @param {boolean} checkActiveElement Whether to also check activeElement.
398 *
399 * @returns {boolean} Whether or not the target is within downshift elements.
400 */
401
402
403function targetWithinDownshift(target, downshiftElements, document, checkActiveElement) {
404 if (checkActiveElement === void 0) {
405 checkActiveElement = true;
406 }
407
408 return downshiftElements.some(function (contextNode) {
409 return contextNode && (isOrContainsNode(contextNode, target) || checkActiveElement && isOrContainsNode(contextNode, document.activeElement));
410 });
411}
412
413var cleanupStatus = debounce(function () {
414 getStatusDiv().textContent = '';
415}, 500);
416/**
417 * @param {String} status the status message
418 * @param {Object} documentProp document passed by the user.
419 */
420
421function setStatus(status, documentProp) {
422 var div = getStatusDiv(documentProp);
423
424 if (!status) {
425 return;
426 }
427
428 div.textContent = status;
429 cleanupStatus();
430}
431/**
432 * Get the status node or create it if it does not already exist.
433 * @param {Object} documentProp document passed by the user.
434 * @return {HTMLElement} the status node.
435 */
436
437
438function getStatusDiv(documentProp) {
439 if (documentProp === void 0) {
440 documentProp = document;
441 }
442
443 var statusDiv = documentProp.getElementById('a11y-status-message');
444
445 if (statusDiv) {
446 return statusDiv;
447 }
448
449 statusDiv = documentProp.createElement('div');
450 statusDiv.setAttribute('id', 'a11y-status-message');
451 statusDiv.setAttribute('role', 'status');
452 statusDiv.setAttribute('aria-live', 'polite');
453 statusDiv.setAttribute('aria-relevant', 'additions text');
454 Object.assign(statusDiv.style, {
455 border: '0',
456 clip: 'rect(0 0 0 0)',
457 height: '1px',
458 margin: '-1px',
459 overflow: 'hidden',
460 padding: '0',
461 position: 'absolute',
462 width: '1px'
463 });
464 documentProp.body.appendChild(statusDiv);
465 return statusDiv;
466}
467
468var unknown = process.env.NODE_ENV !== "production" ? '__autocomplete_unknown__' : 0;
469var mouseUp = process.env.NODE_ENV !== "production" ? '__autocomplete_mouseup__' : 1;
470var itemMouseEnter = process.env.NODE_ENV !== "production" ? '__autocomplete_item_mouseenter__' : 2;
471var keyDownArrowUp = process.env.NODE_ENV !== "production" ? '__autocomplete_keydown_arrow_up__' : 3;
472var keyDownArrowDown = process.env.NODE_ENV !== "production" ? '__autocomplete_keydown_arrow_down__' : 4;
473var keyDownEscape = process.env.NODE_ENV !== "production" ? '__autocomplete_keydown_escape__' : 5;
474var keyDownEnter = process.env.NODE_ENV !== "production" ? '__autocomplete_keydown_enter__' : 6;
475var keyDownHome = process.env.NODE_ENV !== "production" ? '__autocomplete_keydown_home__' : 7;
476var keyDownEnd = process.env.NODE_ENV !== "production" ? '__autocomplete_keydown_end__' : 8;
477var clickItem = process.env.NODE_ENV !== "production" ? '__autocomplete_click_item__' : 9;
478var blurInput = process.env.NODE_ENV !== "production" ? '__autocomplete_blur_input__' : 10;
479var changeInput = process.env.NODE_ENV !== "production" ? '__autocomplete_change_input__' : 11;
480var keyDownSpaceButton = process.env.NODE_ENV !== "production" ? '__autocomplete_keydown_space_button__' : 12;
481var clickButton = process.env.NODE_ENV !== "production" ? '__autocomplete_click_button__' : 13;
482var blurButton = process.env.NODE_ENV !== "production" ? '__autocomplete_blur_button__' : 14;
483var controlledPropUpdatedSelectedItem = process.env.NODE_ENV !== "production" ? '__autocomplete_controlled_prop_updated_selected_item__' : 15;
484var touchEnd = process.env.NODE_ENV !== "production" ? '__autocomplete_touchend__' : 16;
485
486var stateChangeTypes = /*#__PURE__*/Object.freeze({
487 __proto__: null,
488 unknown: unknown,
489 mouseUp: mouseUp,
490 itemMouseEnter: itemMouseEnter,
491 keyDownArrowUp: keyDownArrowUp,
492 keyDownArrowDown: keyDownArrowDown,
493 keyDownEscape: keyDownEscape,
494 keyDownEnter: keyDownEnter,
495 keyDownHome: keyDownHome,
496 keyDownEnd: keyDownEnd,
497 clickItem: clickItem,
498 blurInput: blurInput,
499 changeInput: changeInput,
500 keyDownSpaceButton: keyDownSpaceButton,
501 clickButton: clickButton,
502 blurButton: blurButton,
503 controlledPropUpdatedSelectedItem: controlledPropUpdatedSelectedItem,
504 touchEnd: touchEnd
505});
506
507var Downshift =
508/*#__PURE__*/
509function () {
510 var Downshift =
511 /*#__PURE__*/
512 function (_Component) {
513 _inheritsLoose(Downshift, _Component);
514
515 function Downshift(_props) {
516 var _this = _Component.call(this, _props) || this;
517
518 _this.id = _this.props.id || "downshift-" + generateId();
519 _this.menuId = _this.props.menuId || _this.id + "-menu";
520 _this.labelId = _this.props.labelId || _this.id + "-label";
521 _this.inputId = _this.props.inputId || _this.id + "-input";
522
523 _this.getItemId = _this.props.getItemId || function (index) {
524 return _this.id + "-item-" + index;
525 };
526
527 _this.input = null;
528 _this.items = [];
529 _this.itemCount = null;
530 _this.previousResultCount = 0;
531 _this.timeoutIds = [];
532
533 _this.internalSetTimeout = function (fn, time) {
534 var id = setTimeout(function () {
535 _this.timeoutIds = _this.timeoutIds.filter(function (i) {
536 return i !== id;
537 });
538 fn();
539 }, time);
540
541 _this.timeoutIds.push(id);
542 };
543
544 _this.setItemCount = function (count) {
545 _this.itemCount = count;
546 };
547
548 _this.unsetItemCount = function () {
549 _this.itemCount = null;
550 };
551
552 _this.setHighlightedIndex = function (highlightedIndex, otherStateToSet) {
553 if (highlightedIndex === void 0) {
554 highlightedIndex = _this.props.defaultHighlightedIndex;
555 }
556
557 if (otherStateToSet === void 0) {
558 otherStateToSet = {};
559 }
560
561 otherStateToSet = pickState(otherStateToSet);
562
563 _this.internalSetState(_extends({
564 highlightedIndex: highlightedIndex
565 }, otherStateToSet));
566 };
567
568 _this.clearSelection = function (cb) {
569 _this.internalSetState({
570 selectedItem: null,
571 inputValue: '',
572 highlightedIndex: _this.props.defaultHighlightedIndex,
573 isOpen: _this.props.defaultIsOpen
574 }, cb);
575 };
576
577 _this.selectItem = function (item, otherStateToSet, cb) {
578 otherStateToSet = pickState(otherStateToSet);
579
580 _this.internalSetState(_extends({
581 isOpen: _this.props.defaultIsOpen,
582 highlightedIndex: _this.props.defaultHighlightedIndex,
583 selectedItem: item,
584 inputValue: _this.props.itemToString(item)
585 }, otherStateToSet), cb);
586 };
587
588 _this.selectItemAtIndex = function (itemIndex, otherStateToSet, cb) {
589 var item = _this.items[itemIndex];
590
591 if (item == null) {
592 return;
593 }
594
595 _this.selectItem(item, otherStateToSet, cb);
596 };
597
598 _this.selectHighlightedItem = function (otherStateToSet, cb) {
599 return _this.selectItemAtIndex(_this.getState().highlightedIndex, otherStateToSet, cb);
600 };
601
602 _this.internalSetState = function (stateToSet, cb) {
603 var isItemSelected, onChangeArg;
604 var onStateChangeArg = {};
605 var isStateToSetFunction = typeof stateToSet === 'function'; // we want to call `onInputValueChange` before the `setState` call
606 // so someone controlling the `inputValue` state gets notified of
607 // the input change as soon as possible. This avoids issues with
608 // preserving the cursor position.
609 // See https://github.com/downshift-js/downshift/issues/217 for more info.
610
611 if (!isStateToSetFunction && stateToSet.hasOwnProperty('inputValue')) {
612 _this.props.onInputValueChange(stateToSet.inputValue, _extends({}, _this.getStateAndHelpers(), {}, stateToSet));
613 }
614
615 return _this.setState(function (state) {
616 state = _this.getState(state);
617 var newStateToSet = isStateToSetFunction ? stateToSet(state) : stateToSet; // Your own function that could modify the state that will be set.
618
619 newStateToSet = _this.props.stateReducer(state, newStateToSet); // checks if an item is selected, regardless of if it's different from
620 // what was selected before
621 // used to determine if onSelect and onChange callbacks should be called
622
623 isItemSelected = newStateToSet.hasOwnProperty('selectedItem'); // this keeps track of the object we want to call with setState
624
625 var nextState = {}; // this is just used to tell whether the state changed
626
627 var nextFullState = {}; // we need to call on change if the outside world is controlling any of our state
628 // and we're trying to update that state. OR if the selection has changed and we're
629 // trying to update the selection
630
631 if (isItemSelected && newStateToSet.selectedItem !== state.selectedItem) {
632 onChangeArg = newStateToSet.selectedItem;
633 }
634
635 newStateToSet.type = newStateToSet.type || unknown;
636 Object.keys(newStateToSet).forEach(function (key) {
637 // onStateChangeArg should only have the state that is
638 // actually changing
639 if (state[key] !== newStateToSet[key]) {
640 onStateChangeArg[key] = newStateToSet[key];
641 } // the type is useful for the onStateChangeArg
642 // but we don't actually want to set it in internal state.
643 // this is an undocumented feature for now... Not all internalSetState
644 // calls support it and I'm not certain we want them to yet.
645 // But it enables users controlling the isOpen state to know when
646 // the isOpen state changes due to mouseup events which is quite handy.
647
648
649 if (key === 'type') {
650 return;
651 }
652
653 nextFullState[key] = newStateToSet[key]; // if it's coming from props, then we don't care to set it internally
654
655 if (!isControlledProp(_this.props, key)) {
656 nextState[key] = newStateToSet[key];
657 }
658 }); // if stateToSet is a function, then we weren't able to call onInputValueChange
659 // earlier, so we'll call it now that we know what the inputValue state will be.
660
661 if (isStateToSetFunction && newStateToSet.hasOwnProperty('inputValue')) {
662 _this.props.onInputValueChange(newStateToSet.inputValue, _extends({}, _this.getStateAndHelpers(), {}, newStateToSet));
663 }
664
665 return nextState;
666 }, function () {
667 // call the provided callback if it's a function
668 cbToCb(cb)(); // only call the onStateChange and onChange callbacks if
669 // we have relevant information to pass them.
670
671 var hasMoreStateThanType = Object.keys(onStateChangeArg).length > 1;
672
673 if (hasMoreStateThanType) {
674 _this.props.onStateChange(onStateChangeArg, _this.getStateAndHelpers());
675 }
676
677 if (isItemSelected) {
678 _this.props.onSelect(stateToSet.selectedItem, _this.getStateAndHelpers());
679 }
680
681 if (onChangeArg !== undefined) {
682 _this.props.onChange(onChangeArg, _this.getStateAndHelpers());
683 } // this is currently undocumented and therefore subject to change
684 // We'll try to not break it, but just be warned.
685
686
687 _this.props.onUserAction(onStateChangeArg, _this.getStateAndHelpers());
688 });
689 };
690
691 _this.rootRef = function (node) {
692 return _this._rootNode = node;
693 };
694
695 _this.getRootProps = function (_ref, _temp) {
696 var _extends2;
697
698 if (_ref === void 0) {
699 _ref = {};
700 }
701
702 var _ref2 = _temp === void 0 ? {} : _temp,
703 _ref2$suppressRefErro = _ref2.suppressRefError,
704 suppressRefError = _ref2$suppressRefErro === void 0 ? false : _ref2$suppressRefErro;
705
706 var _ref3 = _ref,
707 _ref3$refKey = _ref3.refKey,
708 refKey = _ref3$refKey === void 0 ? 'ref' : _ref3$refKey,
709 ref = _ref3.ref,
710 rest = _objectWithoutPropertiesLoose(_ref3, ["refKey", "ref"]);
711
712 // this is used in the render to know whether the user has called getRootProps.
713 // It uses that to know whether to apply the props automatically
714 _this.getRootProps.called = true;
715 _this.getRootProps.refKey = refKey;
716 _this.getRootProps.suppressRefError = suppressRefError;
717
718 var _this$getState = _this.getState(),
719 isOpen = _this$getState.isOpen;
720
721 return _extends((_extends2 = {}, _extends2[refKey] = handleRefs(ref, _this.rootRef), _extends2.role = 'combobox', _extends2['aria-expanded'] = isOpen, _extends2['aria-haspopup'] = 'listbox', _extends2['aria-owns'] = isOpen ? _this.menuId : null, _extends2['aria-labelledby'] = _this.labelId, _extends2), rest);
722 };
723
724 _this.keyDownHandlers = {
725 ArrowDown: function ArrowDown(event) {
726 var _this2 = this;
727
728 event.preventDefault();
729
730 if (this.getState().isOpen) {
731 var amount = event.shiftKey ? 5 : 1;
732 this.moveHighlightedIndex(amount, {
733 type: keyDownArrowDown
734 });
735 } else {
736 this.internalSetState({
737 isOpen: true,
738 type: keyDownArrowDown
739 }, function () {
740 var itemCount = _this2.getItemCount();
741
742 if (itemCount > 0) {
743 var _this2$getState = _this2.getState(),
744 highlightedIndex = _this2$getState.highlightedIndex;
745
746 var nextHighlightedIndex = getNextWrappingIndex(1, highlightedIndex, itemCount, function (index) {
747 return _this2.getItemNodeFromIndex(index);
748 });
749
750 _this2.setHighlightedIndex(nextHighlightedIndex, {
751 type: keyDownArrowDown
752 });
753 }
754 });
755 }
756 },
757 ArrowUp: function ArrowUp(event) {
758 var _this3 = this;
759
760 event.preventDefault();
761
762 if (this.getState().isOpen) {
763 var amount = event.shiftKey ? -5 : -1;
764 this.moveHighlightedIndex(amount, {
765 type: keyDownArrowUp
766 });
767 } else {
768 this.internalSetState({
769 isOpen: true,
770 type: keyDownArrowUp
771 }, function () {
772 var itemCount = _this3.getItemCount();
773
774 if (itemCount > 0) {
775 var _this3$getState = _this3.getState(),
776 highlightedIndex = _this3$getState.highlightedIndex;
777
778 var nextHighlightedIndex = getNextWrappingIndex(-1, highlightedIndex, itemCount, function (index) {
779 return _this3.getItemNodeFromIndex(index);
780 });
781
782 _this3.setHighlightedIndex(nextHighlightedIndex, {
783 type: keyDownArrowUp
784 });
785 }
786 });
787 }
788 },
789 Enter: function Enter(event) {
790 var _this$getState2 = this.getState(),
791 isOpen = _this$getState2.isOpen,
792 highlightedIndex = _this$getState2.highlightedIndex;
793
794 if (isOpen && highlightedIndex != null) {
795 event.preventDefault();
796 var item = this.items[highlightedIndex];
797 var itemNode = this.getItemNodeFromIndex(highlightedIndex);
798
799 if (item == null || itemNode && itemNode.hasAttribute('disabled')) {
800 return;
801 }
802
803 this.selectHighlightedItem({
804 type: keyDownEnter
805 });
806 }
807 },
808 Escape: function Escape(event) {
809 event.preventDefault();
810 this.reset({
811 type: keyDownEscape,
812 selectedItem: null,
813 inputValue: ''
814 });
815 }
816 };
817 _this.buttonKeyDownHandlers = _extends({}, _this.keyDownHandlers, {
818 ' ': function _(event) {
819 event.preventDefault();
820 this.toggleMenu({
821 type: keyDownSpaceButton
822 });
823 }
824 });
825 _this.inputKeyDownHandlers = _extends({}, _this.keyDownHandlers, {
826 Home: function Home(event) {
827 var _this4 = this;
828
829 event.preventDefault();
830 var itemCount = this.getItemCount();
831
832 var _this$getState3 = this.getState(),
833 isOpen = _this$getState3.isOpen;
834
835 if (itemCount <= 0 || !isOpen) {
836 return;
837 } // get next non-disabled starting downwards from 0 if that's disabled.
838
839
840 var newHighlightedIndex = getNextNonDisabledIndex(1, 0, itemCount, function (index) {
841 return _this4.getItemNodeFromIndex(index);
842 }, false);
843 this.setHighlightedIndex(newHighlightedIndex, {
844 type: keyDownHome
845 });
846 },
847 End: function End(event) {
848 var _this5 = this;
849
850 event.preventDefault();
851 var itemCount = this.getItemCount();
852
853 var _this$getState4 = this.getState(),
854 isOpen = _this$getState4.isOpen;
855
856 if (itemCount <= 0 || !isOpen) {
857 return;
858 } // get next non-disabled starting upwards from last index if that's disabled.
859
860
861 var newHighlightedIndex = getNextNonDisabledIndex(-1, itemCount - 1, itemCount, function (index) {
862 return _this5.getItemNodeFromIndex(index);
863 }, false);
864 this.setHighlightedIndex(newHighlightedIndex, {
865 type: keyDownEnd
866 });
867 }
868 });
869
870 _this.getToggleButtonProps = function (_ref4) {
871 if (_ref4 === void 0) {
872 _ref4 = {};
873 }
874
875 var _ref5 = _ref4,
876 onClick = _ref5.onClick,
877 onPress = _ref5.onPress,
878 onKeyDown = _ref5.onKeyDown,
879 onKeyUp = _ref5.onKeyUp,
880 onBlur = _ref5.onBlur,
881 rest = _objectWithoutPropertiesLoose(_ref5, ["onClick", "onPress", "onKeyDown", "onKeyUp", "onBlur"]);
882
883 var _this$getState5 = _this.getState(),
884 isOpen = _this$getState5.isOpen;
885
886 var enabledEventHandlers = {
887 onClick: callAllEventHandlers(onClick, _this.buttonHandleClick),
888 onKeyDown: callAllEventHandlers(onKeyDown, _this.buttonHandleKeyDown),
889 onKeyUp: callAllEventHandlers(onKeyUp, _this.buttonHandleKeyUp),
890 onBlur: callAllEventHandlers(onBlur, _this.buttonHandleBlur)
891 };
892 var eventHandlers = rest.disabled ? {} : enabledEventHandlers;
893 return _extends({
894 type: 'button',
895 role: 'button',
896 'aria-label': isOpen ? 'close menu' : 'open menu',
897 'aria-haspopup': true,
898 'data-toggle': true
899 }, eventHandlers, {}, rest);
900 };
901
902 _this.buttonHandleKeyUp = function (event) {
903 // Prevent click event from emitting in Firefox
904 event.preventDefault();
905 };
906
907 _this.buttonHandleKeyDown = function (event) {
908 var key = normalizeArrowKey(event);
909
910 if (_this.buttonKeyDownHandlers[key]) {
911 _this.buttonKeyDownHandlers[key].call(_assertThisInitialized(_this), event);
912 }
913 };
914
915 _this.buttonHandleClick = function (event) {
916 event.preventDefault(); // handle odd case for Safari and Firefox which
917 // don't give the button the focus properly.
918
919 /* istanbul ignore if (can't reasonably test this) */
920
921 if ( _this.props.environment.document.activeElement === _this.props.environment.document.body) {
922 event.target.focus();
923 } // to simplify testing components that use downshift, we'll not wrap this in a setTimeout
924 // if the NODE_ENV is test. With the proper build system, this should be dead code eliminated
925 // when building for production and should therefore have no impact on production code.
926
927
928 if (process.env.NODE_ENV === 'test') {
929 _this.toggleMenu({
930 type: clickButton
931 });
932 } else {
933 // Ensure that toggle of menu occurs after the potential blur event in iOS
934 _this.internalSetTimeout(function () {
935 return _this.toggleMenu({
936 type: clickButton
937 });
938 });
939 }
940 };
941
942 _this.buttonHandleBlur = function (event) {
943 var blurTarget = event.target; // Save blur target for comparison with activeElement later
944 // Need setTimeout, so that when the user presses Tab, the activeElement is the next focused element, not body element
945
946 _this.internalSetTimeout(function () {
947 if (!_this.isMouseDown && (_this.props.environment.document.activeElement == null || _this.props.environment.document.activeElement.id !== _this.inputId) && _this.props.environment.document.activeElement !== blurTarget // Do nothing if we refocus the same element again (to solve issue in Safari on iOS)
948 ) {
949 _this.reset({
950 type: blurButton
951 });
952 }
953 });
954 };
955
956 _this.getLabelProps = function (props) {
957 return _extends({
958 htmlFor: _this.inputId,
959 id: _this.labelId
960 }, props);
961 };
962
963 _this.getInputProps = function (_ref6) {
964 if (_ref6 === void 0) {
965 _ref6 = {};
966 }
967
968 var _ref7 = _ref6,
969 onKeyDown = _ref7.onKeyDown,
970 onBlur = _ref7.onBlur,
971 onChange = _ref7.onChange,
972 onInput = _ref7.onInput,
973 onChangeText = _ref7.onChangeText,
974 rest = _objectWithoutPropertiesLoose(_ref7, ["onKeyDown", "onBlur", "onChange", "onInput", "onChangeText"]);
975
976 var onChangeKey;
977 var eventHandlers = {};
978 /* istanbul ignore next (preact) */
979
980 onChangeKey = 'onChange';
981
982 var _this$getState6 = _this.getState(),
983 inputValue = _this$getState6.inputValue,
984 isOpen = _this$getState6.isOpen,
985 highlightedIndex = _this$getState6.highlightedIndex;
986
987 if (!rest.disabled) {
988 var _eventHandlers;
989
990 eventHandlers = (_eventHandlers = {}, _eventHandlers[onChangeKey] = callAllEventHandlers(onChange, onInput, _this.inputHandleChange), _eventHandlers.onKeyDown = callAllEventHandlers(onKeyDown, _this.inputHandleKeyDown), _eventHandlers.onBlur = callAllEventHandlers(onBlur, _this.inputHandleBlur), _eventHandlers);
991 }
992 /* istanbul ignore if (react-native) */
993
994
995 return _extends({
996 'aria-autocomplete': 'list',
997 'aria-activedescendant': isOpen && typeof highlightedIndex === 'number' && highlightedIndex >= 0 ? _this.getItemId(highlightedIndex) : null,
998 'aria-controls': isOpen ? _this.menuId : null,
999 'aria-labelledby': _this.labelId,
1000 // https://developer.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion
1001 // revert back since autocomplete="nope" is ignored on latest Chrome and Opera
1002 autoComplete: 'off',
1003 value: inputValue,
1004 id: _this.inputId
1005 }, eventHandlers, {}, rest);
1006 };
1007
1008 _this.inputHandleKeyDown = function (event) {
1009 var key = normalizeArrowKey(event);
1010
1011 if (key && _this.inputKeyDownHandlers[key]) {
1012 _this.inputKeyDownHandlers[key].call(_assertThisInitialized(_this), event);
1013 }
1014 };
1015
1016 _this.inputHandleChange = function (event) {
1017 _this.internalSetState({
1018 type: changeInput,
1019 isOpen: true,
1020 inputValue: event.target.value,
1021 highlightedIndex: _this.props.defaultHighlightedIndex
1022 });
1023 };
1024
1025 _this.inputHandleBlur = function () {
1026 // Need setTimeout, so that when the user presses Tab, the activeElement is the next focused element, not the body element
1027 _this.internalSetTimeout(function () {
1028 var downshiftButtonIsActive = _this.props.environment.document && !!_this.props.environment.document.activeElement && !!_this.props.environment.document.activeElement.dataset && _this.props.environment.document.activeElement.dataset.toggle && _this._rootNode && _this._rootNode.contains(_this.props.environment.document.activeElement);
1029
1030 if (!_this.isMouseDown && !downshiftButtonIsActive) {
1031 _this.reset({
1032 type: blurInput
1033 });
1034 }
1035 });
1036 };
1037
1038 _this.menuRef = function (node) {
1039 _this._menuNode = node;
1040 };
1041
1042 _this.getMenuProps = function (_ref8, _temp2) {
1043 var _extends3;
1044
1045 if (_ref8 === void 0) {
1046 _ref8 = {};
1047 }
1048
1049 var _ref9 = _temp2 === void 0 ? {} : _temp2,
1050 _ref9$suppressRefErro = _ref9.suppressRefError,
1051 suppressRefError = _ref9$suppressRefErro === void 0 ? false : _ref9$suppressRefErro;
1052
1053 var _ref10 = _ref8,
1054 _ref10$refKey = _ref10.refKey,
1055 refKey = _ref10$refKey === void 0 ? 'ref' : _ref10$refKey,
1056 ref = _ref10.ref,
1057 props = _objectWithoutPropertiesLoose(_ref10, ["refKey", "ref"]);
1058
1059 _this.getMenuProps.called = true;
1060 _this.getMenuProps.refKey = refKey;
1061 _this.getMenuProps.suppressRefError = suppressRefError;
1062 return _extends((_extends3 = {}, _extends3[refKey] = handleRefs(ref, _this.menuRef), _extends3.role = 'listbox', _extends3['aria-labelledby'] = props && props['aria-label'] ? null : _this.labelId, _extends3.id = _this.menuId, _extends3), props);
1063 };
1064
1065 _this.getItemProps = function (_ref11) {
1066 var _enabledEventHandlers;
1067
1068 if (_ref11 === void 0) {
1069 _ref11 = {};
1070 }
1071
1072 var _ref12 = _ref11,
1073 onMouseMove = _ref12.onMouseMove,
1074 onMouseDown = _ref12.onMouseDown,
1075 onClick = _ref12.onClick,
1076 onPress = _ref12.onPress,
1077 index = _ref12.index,
1078 _ref12$item = _ref12.item,
1079 item = _ref12$item === void 0 ? process.env.NODE_ENV === 'production' ?
1080 /* istanbul ignore next */
1081 undefined : requiredProp('getItemProps', 'item') : _ref12$item,
1082 rest = _objectWithoutPropertiesLoose(_ref12, ["onMouseMove", "onMouseDown", "onClick", "onPress", "index", "item"]);
1083
1084 if (index === undefined) {
1085 _this.items.push(item);
1086
1087 index = _this.items.indexOf(item);
1088 } else {
1089 _this.items[index] = item;
1090 }
1091
1092 var onSelectKey = 'onClick';
1093 var customClickHandler = onClick;
1094 var enabledEventHandlers = (_enabledEventHandlers = {
1095 // onMouseMove is used over onMouseEnter here. onMouseMove
1096 // is only triggered on actual mouse movement while onMouseEnter
1097 // can fire on DOM changes, interrupting keyboard navigation
1098 onMouseMove: callAllEventHandlers(onMouseMove, function () {
1099 if (index === _this.getState().highlightedIndex) {
1100 return;
1101 }
1102
1103 _this.setHighlightedIndex(index, {
1104 type: itemMouseEnter
1105 }); // We never want to manually scroll when changing state based
1106 // on `onMouseMove` because we will be moving the element out
1107 // from under the user which is currently scrolling/moving the
1108 // cursor
1109
1110
1111 _this.avoidScrolling = true;
1112
1113 _this.internalSetTimeout(function () {
1114 return _this.avoidScrolling = false;
1115 }, 250);
1116 }),
1117 onMouseDown: callAllEventHandlers(onMouseDown, function (event) {
1118 // This prevents the activeElement from being changed
1119 // to the item so it can remain with the current activeElement
1120 // which is a more common use case.
1121 event.preventDefault();
1122 })
1123 }, _enabledEventHandlers[onSelectKey] = callAllEventHandlers(customClickHandler, function () {
1124 _this.selectItemAtIndex(index, {
1125 type: clickItem
1126 });
1127 }), _enabledEventHandlers); // Passing down the onMouseDown handler to prevent redirect
1128 // of the activeElement if clicking on disabled items
1129
1130 var eventHandlers = rest.disabled ? {
1131 onMouseDown: enabledEventHandlers.onMouseDown
1132 } : enabledEventHandlers;
1133 return _extends({
1134 id: _this.getItemId(index),
1135 role: 'option',
1136 'aria-selected': _this.getState().highlightedIndex === index
1137 }, eventHandlers, {}, rest);
1138 };
1139
1140 _this.clearItems = function () {
1141 _this.items = [];
1142 };
1143
1144 _this.reset = function (otherStateToSet, cb) {
1145 if (otherStateToSet === void 0) {
1146 otherStateToSet = {};
1147 }
1148
1149 otherStateToSet = pickState(otherStateToSet);
1150
1151 _this.internalSetState(function (_ref13) {
1152 var selectedItem = _ref13.selectedItem;
1153 return _extends({
1154 isOpen: _this.props.defaultIsOpen,
1155 highlightedIndex: _this.props.defaultHighlightedIndex,
1156 inputValue: _this.props.itemToString(selectedItem)
1157 }, otherStateToSet);
1158 }, cb);
1159 };
1160
1161 _this.toggleMenu = function (otherStateToSet, cb) {
1162 if (otherStateToSet === void 0) {
1163 otherStateToSet = {};
1164 }
1165
1166 otherStateToSet = pickState(otherStateToSet);
1167
1168 _this.internalSetState(function (_ref14) {
1169 var isOpen = _ref14.isOpen;
1170 return _extends({
1171 isOpen: !isOpen
1172 }, isOpen && {
1173 highlightedIndex: _this.props.defaultHighlightedIndex
1174 }, {}, otherStateToSet);
1175 }, function () {
1176 var _this$getState7 = _this.getState(),
1177 isOpen = _this$getState7.isOpen,
1178 highlightedIndex = _this$getState7.highlightedIndex;
1179
1180 if (isOpen) {
1181 if (_this.getItemCount() > 0 && typeof highlightedIndex === 'number') {
1182 _this.setHighlightedIndex(highlightedIndex, otherStateToSet);
1183 }
1184 }
1185
1186 cbToCb(cb)();
1187 });
1188 };
1189
1190 _this.openMenu = function (cb) {
1191 _this.internalSetState({
1192 isOpen: true
1193 }, cb);
1194 };
1195
1196 _this.closeMenu = function (cb) {
1197 _this.internalSetState({
1198 isOpen: false
1199 }, cb);
1200 };
1201
1202 _this.updateStatus = debounce(function () {
1203 var state = _this.getState();
1204
1205 var item = _this.items[state.highlightedIndex];
1206
1207 var resultCount = _this.getItemCount();
1208
1209 var status = _this.props.getA11yStatusMessage(_extends({
1210 itemToString: _this.props.itemToString,
1211 previousResultCount: _this.previousResultCount,
1212 resultCount: resultCount,
1213 highlightedItem: item
1214 }, state));
1215
1216 _this.previousResultCount = resultCount;
1217 setStatus(status, _this.props.environment.document);
1218 }, 200);
1219
1220 // fancy destructuring + defaults + aliases
1221 // this basically says each value of state should either be set to
1222 // the initial value or the default value if the initial value is not provided
1223 var _this$props = _this.props,
1224 defaultHighlightedIndex = _this$props.defaultHighlightedIndex,
1225 _this$props$initialHi = _this$props.initialHighlightedIndex,
1226 _highlightedIndex = _this$props$initialHi === void 0 ? defaultHighlightedIndex : _this$props$initialHi,
1227 defaultIsOpen = _this$props.defaultIsOpen,
1228 _this$props$initialIs = _this$props.initialIsOpen,
1229 _isOpen = _this$props$initialIs === void 0 ? defaultIsOpen : _this$props$initialIs,
1230 _this$props$initialIn = _this$props.initialInputValue,
1231 _inputValue = _this$props$initialIn === void 0 ? '' : _this$props$initialIn,
1232 _this$props$initialSe = _this$props.initialSelectedItem,
1233 _selectedItem = _this$props$initialSe === void 0 ? null : _this$props$initialSe;
1234
1235 var _state = _this.getState({
1236 highlightedIndex: _highlightedIndex,
1237 isOpen: _isOpen,
1238 inputValue: _inputValue,
1239 selectedItem: _selectedItem
1240 });
1241
1242 if (_state.selectedItem != null && _this.props.initialInputValue === undefined) {
1243 _state.inputValue = _this.props.itemToString(_state.selectedItem);
1244 }
1245
1246 _this.state = _state;
1247 return _this;
1248 }
1249
1250 var _proto = Downshift.prototype;
1251
1252 /**
1253 * Clear all running timeouts
1254 */
1255 _proto.internalClearTimeouts = function internalClearTimeouts() {
1256 this.timeoutIds.forEach(function (id) {
1257 clearTimeout(id);
1258 });
1259 this.timeoutIds = [];
1260 }
1261 /**
1262 * Gets the state based on internal state or props
1263 * If a state value is passed via props, then that
1264 * is the value given, otherwise it's retrieved from
1265 * stateToMerge
1266 *
1267 * @param {Object} stateToMerge defaults to this.state
1268 * @return {Object} the state
1269 */
1270 ;
1271
1272 _proto.getState = function getState$1(stateToMerge) {
1273 if (stateToMerge === void 0) {
1274 stateToMerge = this.state;
1275 }
1276
1277 return getState(stateToMerge, this.props);
1278 };
1279
1280 _proto.getItemCount = function getItemCount() {
1281 // things read better this way. They're in priority order:
1282 // 1. `this.itemCount`
1283 // 2. `this.props.itemCount`
1284 // 3. `this.items.length`
1285 var itemCount = this.items.length;
1286
1287 if (this.itemCount != null) {
1288 itemCount = this.itemCount;
1289 } else if (this.props.itemCount !== undefined) {
1290 itemCount = this.props.itemCount;
1291 }
1292
1293 return itemCount;
1294 };
1295
1296 _proto.getItemNodeFromIndex = function getItemNodeFromIndex(index) {
1297 return this.props.environment.document.getElementById(this.getItemId(index));
1298 };
1299
1300 _proto.scrollHighlightedItemIntoView = function scrollHighlightedItemIntoView() {
1301 /* istanbul ignore else (react-native) */
1302 {
1303 var node = this.getItemNodeFromIndex(this.getState().highlightedIndex);
1304 this.props.scrollIntoView(node, this._menuNode);
1305 }
1306 };
1307
1308 _proto.moveHighlightedIndex = function moveHighlightedIndex(amount, otherStateToSet) {
1309 var _this6 = this;
1310
1311 var itemCount = this.getItemCount();
1312
1313 var _this$getState8 = this.getState(),
1314 highlightedIndex = _this$getState8.highlightedIndex;
1315
1316 if (itemCount > 0) {
1317 var nextHighlightedIndex = getNextWrappingIndex(amount, highlightedIndex, itemCount, function (index) {
1318 return _this6.getItemNodeFromIndex(index);
1319 });
1320 this.setHighlightedIndex(nextHighlightedIndex, otherStateToSet);
1321 }
1322 };
1323
1324 _proto.getStateAndHelpers = function getStateAndHelpers() {
1325 var _this$getState9 = this.getState(),
1326 highlightedIndex = _this$getState9.highlightedIndex,
1327 inputValue = _this$getState9.inputValue,
1328 selectedItem = _this$getState9.selectedItem,
1329 isOpen = _this$getState9.isOpen;
1330
1331 var itemToString = this.props.itemToString;
1332 var id = this.id;
1333 var getRootProps = this.getRootProps,
1334 getToggleButtonProps = this.getToggleButtonProps,
1335 getLabelProps = this.getLabelProps,
1336 getMenuProps = this.getMenuProps,
1337 getInputProps = this.getInputProps,
1338 getItemProps = this.getItemProps,
1339 openMenu = this.openMenu,
1340 closeMenu = this.closeMenu,
1341 toggleMenu = this.toggleMenu,
1342 selectItem = this.selectItem,
1343 selectItemAtIndex = this.selectItemAtIndex,
1344 selectHighlightedItem = this.selectHighlightedItem,
1345 setHighlightedIndex = this.setHighlightedIndex,
1346 clearSelection = this.clearSelection,
1347 clearItems = this.clearItems,
1348 reset = this.reset,
1349 setItemCount = this.setItemCount,
1350 unsetItemCount = this.unsetItemCount,
1351 setState = this.internalSetState;
1352 return {
1353 // prop getters
1354 getRootProps: getRootProps,
1355 getToggleButtonProps: getToggleButtonProps,
1356 getLabelProps: getLabelProps,
1357 getMenuProps: getMenuProps,
1358 getInputProps: getInputProps,
1359 getItemProps: getItemProps,
1360 // actions
1361 reset: reset,
1362 openMenu: openMenu,
1363 closeMenu: closeMenu,
1364 toggleMenu: toggleMenu,
1365 selectItem: selectItem,
1366 selectItemAtIndex: selectItemAtIndex,
1367 selectHighlightedItem: selectHighlightedItem,
1368 setHighlightedIndex: setHighlightedIndex,
1369 clearSelection: clearSelection,
1370 clearItems: clearItems,
1371 setItemCount: setItemCount,
1372 unsetItemCount: unsetItemCount,
1373 setState: setState,
1374 // props
1375 itemToString: itemToString,
1376 // derived
1377 id: id,
1378 // state
1379 highlightedIndex: highlightedIndex,
1380 inputValue: inputValue,
1381 isOpen: isOpen,
1382 selectedItem: selectedItem
1383 };
1384 } //////////////////////////// ROOT
1385 ;
1386
1387 _proto.componentDidMount = function componentDidMount() {
1388 var _this7 = this;
1389
1390 /* istanbul ignore if (react-native) */
1391 if (process.env.NODE_ENV !== 'production' && !false && this.getMenuProps.called && !this.getMenuProps.suppressRefError) {
1392 validateGetMenuPropsCalledCorrectly(this._menuNode, this.getMenuProps);
1393 }
1394 /* istanbul ignore if (react-native) */
1395
1396
1397 {
1398 // this.isMouseDown helps us track whether the mouse is currently held down.
1399 // This is useful when the user clicks on an item in the list, but holds the mouse
1400 // down long enough for the list to disappear (because the blur event fires on the input)
1401 // this.isMouseDown is used in the blur handler on the input to determine whether the blur event should
1402 // trigger hiding the menu.
1403 var onMouseDown = function () {
1404 _this7.isMouseDown = true;
1405 };
1406
1407 var onMouseUp = function (event) {
1408 _this7.isMouseDown = false; // if the target element or the activeElement is within a downshift node
1409 // then we don't want to reset downshift
1410
1411 var contextWithinDownshift = targetWithinDownshift(event.target, [_this7._rootNode, _this7._menuNode], _this7.props.environment.document);
1412
1413 if (!contextWithinDownshift && _this7.getState().isOpen) {
1414 _this7.reset({
1415 type: mouseUp
1416 }, function () {
1417 return _this7.props.onOuterClick(_this7.getStateAndHelpers());
1418 });
1419 }
1420 }; // Touching an element in iOS gives focus and hover states, but touching out of
1421 // the element will remove hover, and persist the focus state, resulting in the
1422 // blur event not being triggered.
1423 // this.isTouchMove helps us track whether the user is tapping or swiping on a touch screen.
1424 // If the user taps outside of Downshift, the component should be reset,
1425 // but not if the user is swiping
1426
1427
1428 var onTouchStart = function () {
1429 _this7.isTouchMove = false;
1430 };
1431
1432 var onTouchMove = function () {
1433 _this7.isTouchMove = true;
1434 };
1435
1436 var onTouchEnd = function (event) {
1437 var contextWithinDownshift = targetWithinDownshift(event.target, [_this7._rootNode, _this7._menuNode], _this7.props.environment.document, false);
1438
1439 if (!_this7.isTouchMove && !contextWithinDownshift && _this7.getState().isOpen) {
1440 _this7.reset({
1441 type: touchEnd
1442 }, function () {
1443 return _this7.props.onOuterClick(_this7.getStateAndHelpers());
1444 });
1445 }
1446 };
1447
1448 var environment = this.props.environment;
1449 environment.addEventListener('mousedown', onMouseDown);
1450 environment.addEventListener('mouseup', onMouseUp);
1451 environment.addEventListener('touchstart', onTouchStart);
1452 environment.addEventListener('touchmove', onTouchMove);
1453 environment.addEventListener('touchend', onTouchEnd);
1454
1455 this.cleanup = function () {
1456 _this7.internalClearTimeouts();
1457
1458 _this7.updateStatus.cancel();
1459
1460 environment.removeEventListener('mousedown', onMouseDown);
1461 environment.removeEventListener('mouseup', onMouseUp);
1462 environment.removeEventListener('touchstart', onTouchStart);
1463 environment.removeEventListener('touchmove', onTouchMove);
1464 environment.removeEventListener('touchend', onTouchEnd);
1465 };
1466 }
1467 };
1468
1469 _proto.shouldScroll = function shouldScroll(prevState, prevProps) {
1470 var _ref15 = this.props.highlightedIndex === undefined ? this.getState() : this.props,
1471 currentHighlightedIndex = _ref15.highlightedIndex;
1472
1473 var _ref16 = prevProps.highlightedIndex === undefined ? prevState : prevProps,
1474 prevHighlightedIndex = _ref16.highlightedIndex;
1475
1476 var scrollWhenOpen = currentHighlightedIndex && this.getState().isOpen && !prevState.isOpen;
1477 return scrollWhenOpen || currentHighlightedIndex !== prevHighlightedIndex;
1478 };
1479
1480 _proto.componentDidUpdate = function componentDidUpdate(prevProps, prevState) {
1481 if (process.env.NODE_ENV !== 'production') {
1482 validateControlledUnchanged(prevProps, this.props);
1483 /* istanbul ignore if (react-native) */
1484
1485 if ( this.getMenuProps.called && !this.getMenuProps.suppressRefError) {
1486 validateGetMenuPropsCalledCorrectly(this._menuNode, this.getMenuProps);
1487 }
1488 }
1489
1490 if (isControlledProp(this.props, 'selectedItem') && this.props.selectedItemChanged(prevProps.selectedItem, this.props.selectedItem)) {
1491 this.internalSetState({
1492 type: controlledPropUpdatedSelectedItem,
1493 inputValue: this.props.itemToString(this.props.selectedItem)
1494 });
1495 }
1496
1497 if (!this.avoidScrolling && this.shouldScroll(prevState, prevProps)) {
1498 this.scrollHighlightedItemIntoView();
1499 }
1500 /* istanbul ignore else (react-native) */
1501
1502
1503 this.updateStatus();
1504 };
1505
1506 _proto.componentWillUnmount = function componentWillUnmount() {
1507 this.cleanup(); // avoids memory leak
1508 };
1509
1510 _proto.render = function render() {
1511 var children = unwrapArray(this.props.children, noop); // because the items are rerendered every time we call the children
1512 // we clear this out each render and it will be populated again as
1513 // getItemProps is called.
1514
1515 this.clearItems(); // we reset this so we know whether the user calls getRootProps during
1516 // this render. If they do then we don't need to do anything,
1517 // if they don't then we need to clone the element they return and
1518 // apply the props for them.
1519
1520 this.getRootProps.called = false;
1521 this.getRootProps.refKey = undefined;
1522 this.getRootProps.suppressRefError = undefined; // we do something similar for getMenuProps
1523
1524 this.getMenuProps.called = false;
1525 this.getMenuProps.refKey = undefined;
1526 this.getMenuProps.suppressRefError = undefined; // we do something similar for getLabelProps
1527
1528 this.getLabelProps.called = false; // and something similar for getInputProps
1529
1530 this.getInputProps.called = false;
1531 var element = unwrapArray(children(this.getStateAndHelpers()));
1532
1533 if (!element) {
1534 return null;
1535 }
1536
1537 if (this.getRootProps.called || this.props.suppressRefError) {
1538 if (process.env.NODE_ENV !== 'production' && !this.getRootProps.suppressRefError && !this.props.suppressRefError) {
1539 validateGetRootPropsCalledCorrectly(element, this.getRootProps);
1540 }
1541
1542 return element;
1543 } else if (isDOMElement(element)) {
1544 // they didn't apply the root props, but we can clone
1545 // this and apply the props ourselves
1546 return react.cloneElement(element, this.getRootProps(getElementProps(element)));
1547 }
1548 /* istanbul ignore else */
1549
1550
1551 if (process.env.NODE_ENV !== 'production') {
1552 // they didn't apply the root props, but they need to
1553 // otherwise we can't query around the autocomplete
1554 throw new Error('downshift: If you return a non-DOM element, you must apply the getRootProps function');
1555 }
1556 /* istanbul ignore next */
1557
1558
1559 return undefined;
1560 };
1561
1562 return Downshift;
1563 }(react.Component);
1564
1565 Downshift.defaultProps = {
1566 defaultHighlightedIndex: null,
1567 defaultIsOpen: false,
1568 getA11yStatusMessage: getA11yStatusMessage,
1569 itemToString: function itemToString(i) {
1570 if (i == null) {
1571 return '';
1572 }
1573
1574 if (process.env.NODE_ENV !== 'production' && isPlainObject(i) && !i.hasOwnProperty('toString')) {
1575 // eslint-disable-next-line no-console
1576 console.warn('downshift: An object was passed to the default implementation of `itemToString`. You should probably provide your own `itemToString` implementation. Please refer to the `itemToString` API documentation.', 'The object that was passed:', i);
1577 }
1578
1579 return String(i);
1580 },
1581 onStateChange: noop,
1582 onInputValueChange: noop,
1583 onUserAction: noop,
1584 onChange: noop,
1585 onSelect: noop,
1586 onOuterClick: noop,
1587 selectedItemChanged: function selectedItemChanged(prevItem, item) {
1588 return prevItem !== item;
1589 },
1590 environment: typeof window === 'undefined'
1591 /* istanbul ignore next (ssr) */
1592 ? {} : window,
1593 stateReducer: function stateReducer(state, stateToSet) {
1594 return stateToSet;
1595 },
1596 suppressRefError: false,
1597 scrollIntoView: scrollIntoView
1598 };
1599 Downshift.stateChangeTypes = stateChangeTypes;
1600 return Downshift;
1601}();
1602
1603process.env.NODE_ENV !== "production" ? Downshift.propTypes = {
1604 children: PropTypes.func,
1605 defaultHighlightedIndex: PropTypes.number,
1606 defaultIsOpen: PropTypes.bool,
1607 initialHighlightedIndex: PropTypes.number,
1608 initialSelectedItem: PropTypes.any,
1609 initialInputValue: PropTypes.string,
1610 initialIsOpen: PropTypes.bool,
1611 getA11yStatusMessage: PropTypes.func,
1612 itemToString: PropTypes.func,
1613 onChange: PropTypes.func,
1614 onSelect: PropTypes.func,
1615 onStateChange: PropTypes.func,
1616 onInputValueChange: PropTypes.func,
1617 onUserAction: PropTypes.func,
1618 onOuterClick: PropTypes.func,
1619 selectedItemChanged: PropTypes.func,
1620 stateReducer: PropTypes.func,
1621 itemCount: PropTypes.number,
1622 id: PropTypes.string,
1623 environment: PropTypes.shape({
1624 addEventListener: PropTypes.func,
1625 removeEventListener: PropTypes.func,
1626 document: PropTypes.shape({
1627 getElementById: PropTypes.func,
1628 activeElement: PropTypes.any,
1629 body: PropTypes.any
1630 })
1631 }),
1632 suppressRefError: PropTypes.bool,
1633 scrollIntoView: PropTypes.func,
1634 // things we keep in state for uncontrolled components
1635 // but can accept as props for controlled components
1636
1637 /* eslint-disable react/no-unused-prop-types */
1638 selectedItem: PropTypes.any,
1639 isOpen: PropTypes.bool,
1640 inputValue: PropTypes.string,
1641 highlightedIndex: PropTypes.number,
1642 labelId: PropTypes.string,
1643 inputId: PropTypes.string,
1644 menuId: PropTypes.string,
1645 getItemId: PropTypes.func
1646 /* eslint-enable react/no-unused-prop-types */
1647
1648} : void 0;
1649
1650function validateGetMenuPropsCalledCorrectly(node, _ref17) {
1651 var refKey = _ref17.refKey;
1652
1653 if (!node) {
1654 // eslint-disable-next-line no-console
1655 console.error("downshift: The ref prop \"" + refKey + "\" from getMenuProps was not applied correctly on your menu element.");
1656 }
1657}
1658
1659function validateGetRootPropsCalledCorrectly(element, _ref18) {
1660 var refKey = _ref18.refKey;
1661 var refKeySpecified = refKey !== 'ref';
1662 var isComposite = !isDOMElement(element);
1663
1664 if (isComposite && !refKeySpecified && !reactIs.isForwardRef(element)) {
1665 // eslint-disable-next-line no-console
1666 console.error('downshift: You returned a non-DOM element. You must specify a refKey in getRootProps');
1667 } else if (!isComposite && refKeySpecified) {
1668 // eslint-disable-next-line no-console
1669 console.error("downshift: You returned a DOM element. You should not specify a refKey in getRootProps. You specified \"" + refKey + "\"");
1670 }
1671
1672 if (!reactIs.isForwardRef(element) && !getElementProps(element)[refKey]) {
1673 // eslint-disable-next-line no-console
1674 console.error("downshift: You must apply the ref prop \"" + refKey + "\" from getRootProps onto your root element.");
1675 }
1676}
1677
1678function validateControlledUnchanged(prevProps, nextProps) {
1679 var warningDescription = "This prop should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled Downshift element for the lifetime of the component. More info: https://github.com/downshift-js/downshift#control-props";
1680 ['selectedItem', 'isOpen', 'inputValue', 'highlightedIndex'].forEach(function (propKey) {
1681 if (prevProps[propKey] !== undefined && nextProps[propKey] === undefined) {
1682 // eslint-disable-next-line no-console
1683 console.error("downshift: A component has changed the controlled prop \"" + propKey + "\" to be uncontrolled. " + warningDescription);
1684 } else if (prevProps[propKey] === undefined && nextProps[propKey] !== undefined) {
1685 // eslint-disable-next-line no-console
1686 console.error("downshift: A component has changed the uncontrolled prop \"" + propKey + "\" to be controlled. " + warningDescription);
1687 }
1688 });
1689}
1690
1691var defaultStateValues = {
1692 highlightedIndex: -1,
1693 isOpen: false,
1694 selectedItem: null,
1695 inputValue: ''
1696};
1697
1698function getElementIds(_ref) {
1699 var id = _ref.id,
1700 labelId = _ref.labelId,
1701 menuId = _ref.menuId,
1702 getItemId = _ref.getItemId,
1703 toggleButtonId = _ref.toggleButtonId;
1704 var uniqueId = id === undefined ? "downshift-" + generateId() : id;
1705 return {
1706 labelId: labelId || uniqueId + "-label",
1707 menuId: menuId || uniqueId + "-menu",
1708 getItemId: getItemId || function (index) {
1709 return uniqueId + "-item-" + index;
1710 },
1711 toggleButtonId: toggleButtonId || uniqueId + "-toggle-button"
1712 };
1713}
1714
1715function getItemIndex(index, item, items) {
1716 if (index !== undefined) {
1717 return index;
1718 }
1719
1720 if (items.length === 0) {
1721 return -1;
1722 }
1723
1724 return items.indexOf(item);
1725}
1726
1727function itemToString(item) {
1728 return item ? String(item) : '';
1729}
1730
1731function getPropTypesValidator(caller, propTypes) {
1732 // istanbul ignore next
1733 return function (options) {
1734 if (options === void 0) {
1735 options = {};
1736 }
1737
1738 Object.keys(propTypes).forEach(function (key) {
1739 PropTypes.checkPropTypes(propTypes, options, key, caller.name);
1740 });
1741 };
1742}
1743
1744function isAcceptedCharacterKey(key) {
1745 return /^\S{1}$/.test(key);
1746}
1747
1748function capitalizeString(string) {
1749 return "" + string.slice(0, 1).toUpperCase() + string.slice(1);
1750}
1751
1752function invokeOnChangeHandler(key, props, state, newState) {
1753 var handler = "on" + capitalizeString(key) + "Change";
1754
1755 if (props[handler] && newState[key] !== undefined && newState[key] !== state[key]) {
1756 props[handler](newState);
1757 }
1758}
1759
1760function callOnChangeProps(action, state, newState) {
1761 var props = action.props,
1762 type = action.type;
1763 var changes = {};
1764 Object.keys(state).forEach(function (key) {
1765 invokeOnChangeHandler(key, props, state, newState);
1766
1767 if (newState[key] !== state[key]) {
1768 changes[key] = newState[key];
1769 }
1770 });
1771
1772 if (props.onStateChange && Object.keys(changes).length) {
1773 props.onStateChange(_extends({
1774 type: type
1775 }, changes));
1776 }
1777}
1778
1779function useEnhancedReducer(reducer, initialState, props) {
1780 var enhancedReducer = react.useCallback(function (state, action) {
1781 state = getState(state, action.props);
1782 var stateReduceLocal = action.props.stateReducer;
1783 var changes = reducer(state, action);
1784 var newState = stateReduceLocal(state, _extends({}, action, {
1785 changes: changes
1786 }));
1787 callOnChangeProps(action, state, newState);
1788 return newState;
1789 }, [reducer]);
1790
1791 var _useReducer = react.useReducer(enhancedReducer, initialState),
1792 state = _useReducer[0],
1793 dispatch = _useReducer[1];
1794
1795 return [getState(state, props), function dispatchWithProps(action) {
1796 return dispatch(_extends({
1797 props: props
1798 }, action));
1799 }];
1800}
1801/**
1802 * Default state reducer that returns the changes.
1803 *
1804 * @param {Object} s state.
1805 * @param {Object} a action with changes.
1806 * @returns {Object} changes.
1807 */
1808
1809
1810function stateReducer(s, a) {
1811 return a.changes;
1812}
1813/**
1814 * Returns a message to be added to aria-live region when item is selected.
1815 *
1816 * @param {Object} selectionParameters Parameters required to build the message.
1817 * @returns {string} The a11y message.
1818 */
1819
1820
1821function getA11ySelectionMessage(selectionParameters) {
1822 var selectedItem = selectionParameters.selectedItem,
1823 itemToStringLocal = selectionParameters.itemToString;
1824 return itemToStringLocal(selectedItem) + " has been selected.";
1825}
1826
1827var defaultProps = {
1828 itemToString: itemToString,
1829 stateReducer: stateReducer,
1830 getA11ySelectionMessage: getA11ySelectionMessage,
1831 scrollIntoView: scrollIntoView,
1832 circularNavigation: false,
1833 environment: typeof window === 'undefined'
1834 /* istanbul ignore next (ssr) */
1835 ? {} : window
1836};
1837
1838function getDefaultValue(props, propKey) {
1839 var defaultPropKey = "default" + capitalizeString(propKey);
1840
1841 if (defaultPropKey in props) {
1842 return props[defaultPropKey];
1843 }
1844
1845 return defaultStateValues[propKey];
1846}
1847
1848function getInitialValue(props, propKey) {
1849 if (propKey in props) {
1850 return props[propKey];
1851 }
1852
1853 var initialPropKey = "initial" + capitalizeString(propKey);
1854
1855 if (initialPropKey in props) {
1856 return props[initialPropKey];
1857 }
1858
1859 return getDefaultValue(props, propKey);
1860}
1861
1862function getInitialState(props) {
1863 var selectedItem = getInitialValue(props, 'selectedItem');
1864 var isOpen = getInitialValue(props, 'isOpen');
1865 var highlightedIndex = getInitialValue(props, 'highlightedIndex');
1866 var inputValue = getInitialValue(props, 'inputValue');
1867 return {
1868 highlightedIndex: highlightedIndex < 0 && selectedItem ? props.items.indexOf(selectedItem) : highlightedIndex,
1869 isOpen: isOpen,
1870 selectedItem: selectedItem,
1871 inputValue: inputValue
1872 };
1873}
1874
1875function getHighlightedIndexOnOpen(props, state, offset, getItemNodeFromIndex) {
1876 var items = props.items,
1877 initialHighlightedIndex = props.initialHighlightedIndex,
1878 defaultHighlightedIndex = props.defaultHighlightedIndex;
1879 var selectedItem = state.selectedItem,
1880 highlightedIndex = state.highlightedIndex; // initialHighlightedIndex will give value to highlightedIndex on initial state only.
1881
1882 if (initialHighlightedIndex !== undefined && highlightedIndex === initialHighlightedIndex) {
1883 return initialHighlightedIndex;
1884 }
1885
1886 if (defaultHighlightedIndex !== undefined) {
1887 return defaultHighlightedIndex;
1888 }
1889
1890 if (selectedItem) {
1891 if (offset === 0) {
1892 return items.indexOf(selectedItem);
1893 }
1894
1895 return getNextWrappingIndex(offset, items.indexOf(selectedItem), items.length, getItemNodeFromIndex, false);
1896 }
1897
1898 if (offset === 0) {
1899 return -1;
1900 }
1901
1902 return offset < 0 ? items.length - 1 : 0;
1903}
1904
1905function getItemIndexByCharacterKey(keysSoFar, highlightedIndex, items, itemToStringParam, getItemNodeFromIndex) {
1906 var lowerCasedItemStrings = items.map(function (item) {
1907 return itemToStringParam(item).toLowerCase();
1908 });
1909 var lowerCasedKeysSoFar = keysSoFar.toLowerCase();
1910
1911 var isValid = function (itemString, index) {
1912 var element = getItemNodeFromIndex(index);
1913 return itemString.startsWith(lowerCasedKeysSoFar) && !(element && element.hasAttribute('disabled'));
1914 };
1915
1916 for (var index = highlightedIndex + 1; index < lowerCasedItemStrings.length; index++) {
1917 var itemString = lowerCasedItemStrings[index];
1918
1919 if (isValid(itemString, index)) {
1920 return index;
1921 }
1922 }
1923
1924 for (var _index = 0; _index < highlightedIndex; _index++) {
1925 var _itemString = lowerCasedItemStrings[_index];
1926
1927 if (isValid(_itemString, _index)) {
1928 return _index;
1929 }
1930 }
1931
1932 return highlightedIndex;
1933}
1934
1935var propTypes = {
1936 items: PropTypes.array.isRequired,
1937 itemToString: PropTypes.func,
1938 getA11yStatusMessage: PropTypes.func,
1939 getA11ySelectionMessage: PropTypes.func,
1940 circularNavigation: PropTypes.bool,
1941 highlightedIndex: PropTypes.number,
1942 defaultHighlightedIndex: PropTypes.number,
1943 initialHighlightedIndex: PropTypes.number,
1944 isOpen: PropTypes.bool,
1945 defaultIsOpen: PropTypes.bool,
1946 initialIsOpen: PropTypes.bool,
1947 selectedItem: PropTypes.any,
1948 initialSelectedItem: PropTypes.any,
1949 defaultSelectedItem: PropTypes.any,
1950 id: PropTypes.string,
1951 labelId: PropTypes.string,
1952 menuId: PropTypes.string,
1953 getItemId: PropTypes.func,
1954 toggleButtonId: PropTypes.string,
1955 stateReducer: PropTypes.func,
1956 onSelectedItemChange: PropTypes.func,
1957 onHighlightedIndexChange: PropTypes.func,
1958 onStateChange: PropTypes.func,
1959 onIsOpenChange: PropTypes.func,
1960 environment: PropTypes.shape({
1961 addEventListener: PropTypes.func,
1962 removeEventListener: PropTypes.func,
1963 document: PropTypes.shape({
1964 getElementById: PropTypes.func,
1965 activeElement: PropTypes.any,
1966 body: PropTypes.any
1967 })
1968 })
1969};
1970/**
1971 * Default implementation for status message. Only added when menu is open.
1972 * Will specift if there are results in the list, and if so, how many,
1973 * and what keys are relevant.
1974 *
1975 * @param {Object} param the downshift state and other relevant properties
1976 * @return {String} the a11y status message
1977 */
1978
1979function getA11yStatusMessage$1(_ref) {
1980 var isOpen = _ref.isOpen,
1981 resultCount = _ref.resultCount;
1982
1983 if (!isOpen) {
1984 return '';
1985 }
1986
1987 if (!resultCount) {
1988 return 'No results are available.';
1989 }
1990
1991 return resultCount + " result" + (resultCount === 1 ? ' is' : 's are') + " available, use up and down arrow keys to navigate. Press Enter or Space Bar keys to select.";
1992}
1993
1994var defaultProps$1 = _extends({}, defaultProps, {
1995 getA11yStatusMessage: getA11yStatusMessage$1
1996});
1997
1998var MenuKeyDownArrowDown = process.env.NODE_ENV !== "production" ? '__menu_keydown_arrow_down__' : 0;
1999var MenuKeyDownArrowUp = process.env.NODE_ENV !== "production" ? '__menu_keydown_arrow_up__' : 1;
2000var MenuKeyDownEscape = process.env.NODE_ENV !== "production" ? '__menu_keydown_escape__' : 2;
2001var MenuKeyDownHome = process.env.NODE_ENV !== "production" ? '__menu_keydown_home__' : 3;
2002var MenuKeyDownEnd = process.env.NODE_ENV !== "production" ? '__menu_keydown_end__' : 4;
2003var MenuKeyDownEnter = process.env.NODE_ENV !== "production" ? '__menu_keydown_enter__' : 5;
2004var MenuKeyDownSpaceButton = process.env.NODE_ENV !== "production" ? '__menu_keydown_space_button__' : 6;
2005var MenuKeyDownCharacter = process.env.NODE_ENV !== "production" ? '__menu_keydown_character__' : 7;
2006var MenuBlur = process.env.NODE_ENV !== "production" ? '__menu_blur__' : 8;
2007var MenuMouseLeave = process.env.NODE_ENV !== "production" ? '__menu_mouse_leave__' : 9;
2008var ItemMouseMove = process.env.NODE_ENV !== "production" ? '__item_mouse_move__' : 10;
2009var ItemClick = process.env.NODE_ENV !== "production" ? '__item_click__' : 11;
2010var ToggleButtonClick = process.env.NODE_ENV !== "production" ? '__togglebutton_click__' : 12;
2011var ToggleButtonKeyDownArrowDown = process.env.NODE_ENV !== "production" ? '__togglebutton_keydown_arrow_down__' : 13;
2012var ToggleButtonKeyDownArrowUp = process.env.NODE_ENV !== "production" ? '__togglebutton_keydown_arrow_up__' : 14;
2013var ToggleButtonKeyDownCharacter = process.env.NODE_ENV !== "production" ? '__togglebutton_keydown_character__' : 15;
2014var FunctionToggleMenu = process.env.NODE_ENV !== "production" ? '__function_toggle_menu__' : 16;
2015var FunctionOpenMenu = process.env.NODE_ENV !== "production" ? '__function_open_menu__' : 17;
2016var FunctionCloseMenu = process.env.NODE_ENV !== "production" ? '__function_close_menu__' : 18;
2017var FunctionSetHighlightedIndex = process.env.NODE_ENV !== "production" ? '__function_set_highlighted_index__' : 19;
2018var FunctionSelectItem = process.env.NODE_ENV !== "production" ? '__function_select_item__' : 20;
2019var FunctionSetInputValue = process.env.NODE_ENV !== "production" ? '__function_set_input_value__' : 21;
2020var FunctionReset = process.env.NODE_ENV !== "production" ? '__function_reset__' : 22;
2021
2022var stateChangeTypes$1 = /*#__PURE__*/Object.freeze({
2023 __proto__: null,
2024 MenuKeyDownArrowDown: MenuKeyDownArrowDown,
2025 MenuKeyDownArrowUp: MenuKeyDownArrowUp,
2026 MenuKeyDownEscape: MenuKeyDownEscape,
2027 MenuKeyDownHome: MenuKeyDownHome,
2028 MenuKeyDownEnd: MenuKeyDownEnd,
2029 MenuKeyDownEnter: MenuKeyDownEnter,
2030 MenuKeyDownSpaceButton: MenuKeyDownSpaceButton,
2031 MenuKeyDownCharacter: MenuKeyDownCharacter,
2032 MenuBlur: MenuBlur,
2033 MenuMouseLeave: MenuMouseLeave,
2034 ItemMouseMove: ItemMouseMove,
2035 ItemClick: ItemClick,
2036 ToggleButtonClick: ToggleButtonClick,
2037 ToggleButtonKeyDownArrowDown: ToggleButtonKeyDownArrowDown,
2038 ToggleButtonKeyDownArrowUp: ToggleButtonKeyDownArrowUp,
2039 ToggleButtonKeyDownCharacter: ToggleButtonKeyDownCharacter,
2040 FunctionToggleMenu: FunctionToggleMenu,
2041 FunctionOpenMenu: FunctionOpenMenu,
2042 FunctionCloseMenu: FunctionCloseMenu,
2043 FunctionSetHighlightedIndex: FunctionSetHighlightedIndex,
2044 FunctionSelectItem: FunctionSelectItem,
2045 FunctionSetInputValue: FunctionSetInputValue,
2046 FunctionReset: FunctionReset
2047});
2048
2049/* eslint-disable complexity */
2050
2051function downshiftSelectReducer(state, action) {
2052 var type = action.type,
2053 props = action.props,
2054 shiftKey = action.shiftKey;
2055 var changes;
2056
2057 switch (type) {
2058 case ItemMouseMove:
2059 changes = {
2060 highlightedIndex: action.index
2061 };
2062 break;
2063
2064 case ItemClick:
2065 changes = {
2066 isOpen: getDefaultValue(props, 'isOpen'),
2067 highlightedIndex: getDefaultValue(props, 'highlightedIndex'),
2068 selectedItem: props.items[action.index]
2069 };
2070 break;
2071
2072 case ToggleButtonKeyDownCharacter:
2073 {
2074 var lowercasedKey = action.key;
2075 var inputValue = "" + state.inputValue + lowercasedKey;
2076 var itemIndex = getItemIndexByCharacterKey(inputValue, state.selectedItem ? props.items.indexOf(state.selectedItem) : -1, props.items, props.itemToString, action.getItemNodeFromIndex);
2077 changes = _extends({
2078 inputValue: inputValue
2079 }, itemIndex >= 0 && {
2080 selectedItem: props.items[itemIndex]
2081 });
2082 }
2083 break;
2084
2085 case ToggleButtonKeyDownArrowDown:
2086 changes = {
2087 highlightedIndex: getHighlightedIndexOnOpen(props, state, 1, action.getItemNodeFromIndex),
2088 isOpen: true
2089 };
2090 break;
2091
2092 case ToggleButtonKeyDownArrowUp:
2093 changes = {
2094 highlightedIndex: getHighlightedIndexOnOpen(props, state, -1, action.getItemNodeFromIndex),
2095 isOpen: true
2096 };
2097 break;
2098
2099 case MenuKeyDownEnter:
2100 case MenuKeyDownSpaceButton:
2101 changes = _extends({
2102 isOpen: getDefaultValue(props, 'isOpen'),
2103 highlightedIndex: getDefaultValue(props, 'highlightedIndex')
2104 }, state.highlightedIndex >= 0 && {
2105 selectedItem: props.items[state.highlightedIndex]
2106 });
2107 break;
2108
2109 case MenuKeyDownHome:
2110 changes = {
2111 highlightedIndex: getNextNonDisabledIndex(1, 0, props.items.length, action.getItemNodeFromIndex, false)
2112 };
2113 break;
2114
2115 case MenuKeyDownEnd:
2116 changes = {
2117 highlightedIndex: getNextNonDisabledIndex(-1, props.items.length - 1, props.items.length, action.getItemNodeFromIndex, false)
2118 };
2119 break;
2120
2121 case MenuKeyDownEscape:
2122 changes = {
2123 isOpen: false,
2124 highlightedIndex: -1
2125 };
2126 break;
2127
2128 case MenuBlur:
2129 changes = {
2130 isOpen: false,
2131 highlightedIndex: -1
2132 };
2133 break;
2134
2135 case MenuKeyDownCharacter:
2136 {
2137 var _lowercasedKey = action.key;
2138
2139 var _inputValue = "" + state.inputValue + _lowercasedKey;
2140
2141 var highlightedIndex = getItemIndexByCharacterKey(_inputValue, state.highlightedIndex, props.items, props.itemToString, action.getItemNodeFromIndex);
2142 changes = _extends({
2143 inputValue: _inputValue
2144 }, highlightedIndex >= 0 && {
2145 highlightedIndex: highlightedIndex
2146 });
2147 }
2148 break;
2149
2150 case MenuKeyDownArrowDown:
2151 changes = {
2152 highlightedIndex: getNextWrappingIndex(shiftKey ? 5 : 1, state.highlightedIndex, props.items.length, action.getItemNodeFromIndex, props.circularNavigation)
2153 };
2154 break;
2155
2156 case MenuKeyDownArrowUp:
2157 changes = {
2158 highlightedIndex: getNextWrappingIndex(shiftKey ? -5 : -1, state.highlightedIndex, props.items.length, action.getItemNodeFromIndex, props.circularNavigation)
2159 };
2160 break;
2161
2162 case MenuMouseLeave:
2163 changes = {
2164 highlightedIndex: -1
2165 };
2166 break;
2167
2168 case ToggleButtonClick:
2169 case FunctionToggleMenu:
2170 changes = {
2171 isOpen: !state.isOpen,
2172 highlightedIndex: state.isOpen ? -1 : getHighlightedIndexOnOpen(props, state, 0)
2173 };
2174 break;
2175
2176 case FunctionOpenMenu:
2177 changes = {
2178 isOpen: true,
2179 highlightedIndex: getHighlightedIndexOnOpen(props, state, 0)
2180 };
2181 break;
2182
2183 case FunctionCloseMenu:
2184 changes = {
2185 isOpen: false
2186 };
2187 break;
2188
2189 case FunctionSetHighlightedIndex:
2190 changes = {
2191 highlightedIndex: action.highlightedIndex
2192 };
2193 break;
2194
2195 case FunctionSelectItem:
2196 changes = {
2197 selectedItem: action.selectedItem
2198 };
2199 break;
2200
2201 case FunctionSetInputValue:
2202 changes = {
2203 inputValue: action.inputValue
2204 };
2205 break;
2206
2207 case FunctionReset:
2208 changes = {
2209 highlightedIndex: getDefaultValue(props, 'highlightedIndex'),
2210 isOpen: getDefaultValue(props, 'isOpen'),
2211 selectedItem: getDefaultValue(props, 'selectedItem'),
2212 inputValue: getDefaultValue(props, 'inputValue')
2213 };
2214 break;
2215
2216 default:
2217 throw new Error('Reducer called without proper action type.');
2218 }
2219
2220 return _extends({}, state, {}, changes);
2221}
2222/* eslint-enable complexity */
2223
2224var validatePropTypes = process.env.NODE_ENV === 'production' ?
2225/* istanbul ignore next */
2226null : getPropTypesValidator(useSelect, propTypes);
2227useSelect.stateChangeTypes = stateChangeTypes$1;
2228
2229function useSelect(userProps) {
2230 if (userProps === void 0) {
2231 userProps = {};
2232 }
2233
2234 /* istanbul ignore else */
2235 if (process.env.NODE_ENV !== 'production') {
2236 validatePropTypes(userProps);
2237 } // Props defaults and destructuring.
2238
2239
2240 var props = _extends({}, defaultProps$1, {}, userProps);
2241
2242 var items = props.items,
2243 itemToString = props.itemToString,
2244 getA11yStatusMessage = props.getA11yStatusMessage,
2245 getA11ySelectionMessage = props.getA11ySelectionMessage,
2246 scrollIntoView = props.scrollIntoView,
2247 environment = props.environment,
2248 initialIsOpen = props.initialIsOpen,
2249 defaultIsOpen = props.defaultIsOpen; // Initial state depending on controlled props.
2250
2251 var initialState = getInitialState(props); // Reducer init.
2252
2253 var _useEnhancedReducer = useEnhancedReducer(downshiftSelectReducer, initialState, props),
2254 _useEnhancedReducer$ = _useEnhancedReducer[0],
2255 isOpen = _useEnhancedReducer$.isOpen,
2256 highlightedIndex = _useEnhancedReducer$.highlightedIndex,
2257 selectedItem = _useEnhancedReducer$.selectedItem,
2258 inputValue = _useEnhancedReducer$.inputValue,
2259 dispatch = _useEnhancedReducer[1];
2260 /* Refs */
2261
2262
2263 var toggleButtonRef = react.useRef(null);
2264 var menuRef = react.useRef(null);
2265 var isInitialMount = react.useRef(true);
2266 var shouldScroll = react.useRef(true);
2267 var clearTimeout = react.useRef(null);
2268 var mouseAndTouchTrackers = react.useRef({
2269 isMouseDown: false,
2270 isTouchMove: false
2271 });
2272 var elementIds = react.useRef(getElementIds(props)); // Some utils.
2273
2274 var getItemNodeFromIndex = function (index) {
2275 return environment.document.getElementById(elementIds.current.getItemId(index));
2276 };
2277 /* Effects */
2278
2279 /* Sets a11y status message on changes in isOpen. */
2280
2281
2282 react.useEffect(function () {
2283 if (isInitialMount.current) {
2284 return;
2285 }
2286
2287 setStatus(getA11yStatusMessage({
2288 highlightedIndex: highlightedIndex,
2289 inputValue: inputValue,
2290 isOpen: isOpen,
2291 itemToString: itemToString,
2292 resultCount: items.length,
2293 highlightedItem: items[highlightedIndex],
2294 selectedItem: selectedItem
2295 }), environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2296 }, [isOpen]);
2297 /* Sets a11y status message on changes in selectedItem. */
2298
2299 react.useEffect(function () {
2300 if (isInitialMount.current) {
2301 return;
2302 }
2303
2304 setStatus(getA11ySelectionMessage({
2305 highlightedIndex: highlightedIndex,
2306 inputValue: inputValue,
2307 isOpen: isOpen,
2308 itemToString: itemToString,
2309 resultCount: items.length,
2310 highlightedItem: items[highlightedIndex],
2311 selectedItem: selectedItem
2312 }), environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2313 }, [selectedItem]);
2314 /* Sets cleanup for the keysSoFar after 500ms. */
2315
2316 react.useEffect(function () {
2317 // init the clean function here as we need access to dispatch.
2318 if (isInitialMount.current) {
2319 clearTimeout.current = debounce(function (outerDispatch) {
2320 outerDispatch({
2321 type: FunctionSetInputValue,
2322 inputValue: ''
2323 });
2324 }, 500);
2325 }
2326
2327 if (!inputValue) {
2328 return;
2329 }
2330
2331 clearTimeout.current(dispatch); // eslint-disable-next-line react-hooks/exhaustive-deps
2332 }, [inputValue]);
2333 /* Controls the focus on the menu or the toggle button. */
2334
2335 react.useEffect(function () {
2336 // Don't focus menu on first render.
2337 if (isInitialMount.current) {
2338 // Unless it was initialised as open.
2339 if ((initialIsOpen || defaultIsOpen || isOpen) && menuRef.current) {
2340 menuRef.current.focus();
2341 }
2342
2343 return;
2344 } // Focus menu on open.
2345 // istanbul ignore next
2346
2347
2348 if (isOpen && menuRef.current) {
2349 menuRef.current.focus(); // Focus toggleButton on close.
2350 } else if (environment.document.activeElement === menuRef.current && toggleButtonRef.current) {
2351 toggleButtonRef.current.focus();
2352 } // eslint-disable-next-line react-hooks/exhaustive-deps
2353
2354 }, [isOpen]);
2355 /* Scroll on highlighted item if change comes from keyboard. */
2356
2357 react.useEffect(function () {
2358 if (highlightedIndex < 0 || !isOpen || !items.length) {
2359 return;
2360 }
2361
2362 if (shouldScroll.current === false) {
2363 shouldScroll.current = true;
2364 } else {
2365 scrollIntoView(getItemNodeFromIndex(highlightedIndex), menuRef.current);
2366 } // eslint-disable-next-line react-hooks/exhaustive-deps
2367
2368 }, [highlightedIndex]);
2369 /* Make initial ref false. */
2370
2371 react.useEffect(function () {
2372 isInitialMount.current = false;
2373 }, []);
2374 /* Add mouse/touch events to document. */
2375
2376 react.useEffect(function () {
2377 // The same strategy for checking if a click occurred inside or outside downsift
2378 // as in downshift.js.
2379 var onMouseDown = function () {
2380 mouseAndTouchTrackers.current.isMouseDown = true;
2381 };
2382
2383 var onMouseUp = function (event) {
2384 mouseAndTouchTrackers.current.isMouseDown = false;
2385
2386 if (isOpen && !targetWithinDownshift(event.target, [toggleButtonRef.current, menuRef.current], environment.document)) {
2387 dispatch({
2388 type: MenuBlur
2389 });
2390 }
2391 };
2392
2393 var onTouchStart = function () {
2394 mouseAndTouchTrackers.current.isTouchMove = false;
2395 };
2396
2397 var onTouchMove = function () {
2398 mouseAndTouchTrackers.current.isTouchMove = true;
2399 };
2400
2401 var onTouchEnd = function (event) {
2402 if (isOpen && !mouseAndTouchTrackers.current.isTouchMove && !targetWithinDownshift(event.target, [toggleButtonRef.current, menuRef.current], environment.document, false)) {
2403 dispatch({
2404 type: MenuBlur
2405 });
2406 }
2407 };
2408
2409 environment.addEventListener('mousedown', onMouseDown);
2410 environment.addEventListener('mouseup', onMouseUp);
2411 environment.addEventListener('touchstart', onTouchStart);
2412 environment.addEventListener('touchmove', onTouchMove);
2413 environment.addEventListener('touchend', onTouchEnd);
2414 return function () {
2415 environment.removeEventListener('mousedown', onMouseDown);
2416 environment.removeEventListener('mouseup', onMouseUp);
2417 environment.removeEventListener('touchstart', onTouchStart);
2418 environment.removeEventListener('touchmove', onTouchMove);
2419 environment.removeEventListener('touchend', onTouchEnd);
2420 };
2421 }); // Event handler functions.
2422
2423 var toggleButtonKeyDownHandlers = {
2424 ArrowDown: function ArrowDown(event) {
2425 event.preventDefault();
2426 dispatch({
2427 type: ToggleButtonKeyDownArrowDown,
2428 getItemNodeFromIndex: getItemNodeFromIndex,
2429 shiftKey: event.shiftKey
2430 });
2431 },
2432 ArrowUp: function ArrowUp(event) {
2433 event.preventDefault();
2434 dispatch({
2435 type: ToggleButtonKeyDownArrowUp,
2436 getItemNodeFromIndex: getItemNodeFromIndex,
2437 shiftKey: event.shiftKey
2438 });
2439 }
2440 };
2441 var menuKeyDownHandlers = {
2442 ArrowDown: function ArrowDown(event) {
2443 event.preventDefault();
2444 dispatch({
2445 type: MenuKeyDownArrowDown,
2446 getItemNodeFromIndex: getItemNodeFromIndex,
2447 shiftKey: event.shiftKey
2448 });
2449 },
2450 ArrowUp: function ArrowUp(event) {
2451 event.preventDefault();
2452 dispatch({
2453 type: MenuKeyDownArrowUp,
2454 getItemNodeFromIndex: getItemNodeFromIndex,
2455 shiftKey: event.shiftKey
2456 });
2457 },
2458 Home: function Home(event) {
2459 event.preventDefault();
2460 dispatch({
2461 type: MenuKeyDownHome,
2462 getItemNodeFromIndex: getItemNodeFromIndex
2463 });
2464 },
2465 End: function End(event) {
2466 event.preventDefault();
2467 dispatch({
2468 type: MenuKeyDownEnd,
2469 getItemNodeFromIndex: getItemNodeFromIndex
2470 });
2471 },
2472 Escape: function Escape() {
2473 dispatch({
2474 type: MenuKeyDownEscape
2475 });
2476 },
2477 Enter: function Enter(event) {
2478 event.preventDefault();
2479 dispatch({
2480 type: MenuKeyDownEnter
2481 });
2482 },
2483 ' ': function _(event) {
2484 event.preventDefault();
2485 dispatch({
2486 type: MenuKeyDownSpaceButton
2487 });
2488 }
2489 }; // Event handlers.
2490
2491 var menuHandleKeyDown = function (event) {
2492 var key = normalizeArrowKey(event);
2493
2494 if (key && menuKeyDownHandlers[key]) {
2495 menuKeyDownHandlers[key](event);
2496 } else if (isAcceptedCharacterKey(key)) {
2497 dispatch({
2498 type: MenuKeyDownCharacter,
2499 key: key,
2500 getItemNodeFromIndex: getItemNodeFromIndex
2501 });
2502 }
2503 };
2504
2505 var menuHandleBlur = function () {
2506 var shouldBlur = !mouseAndTouchTrackers.current.isMouseDown;
2507 /* istanbul ignore else */
2508
2509 if (shouldBlur) {
2510 dispatch({
2511 type: MenuBlur
2512 });
2513 }
2514 };
2515
2516 var menuHandleMouseLeave = function () {
2517 dispatch({
2518 type: MenuMouseLeave
2519 });
2520 };
2521
2522 var toggleButtonHandleClick = function () {
2523 dispatch({
2524 type: ToggleButtonClick
2525 });
2526 };
2527
2528 var toggleButtonHandleKeyDown = function (event) {
2529 var key = normalizeArrowKey(event);
2530
2531 if (key && toggleButtonKeyDownHandlers[key]) {
2532 toggleButtonKeyDownHandlers[key](event);
2533 } else if (isAcceptedCharacterKey(key)) {
2534 dispatch({
2535 type: ToggleButtonKeyDownCharacter,
2536 key: key,
2537 getItemNodeFromIndex: getItemNodeFromIndex
2538 });
2539 }
2540 };
2541
2542 var itemHandleMouseMove = function (index) {
2543 if (index === highlightedIndex) {
2544 return;
2545 }
2546
2547 shouldScroll.current = false;
2548 dispatch({
2549 type: ItemMouseMove,
2550 index: index
2551 });
2552 };
2553
2554 var itemHandleClick = function (index) {
2555 dispatch({
2556 type: ItemClick,
2557 index: index
2558 });
2559 }; // Action functions.
2560
2561
2562 return {
2563 // prop getters.
2564 getToggleButtonProps: function getToggleButtonProps(_ref3) {
2565 var _extends3;
2566
2567 if (_ref3 === void 0) {
2568 _ref3 = {};
2569 }
2570
2571 var _ref4 = _ref3,
2572 onClick = _ref4.onClick,
2573 onKeyDown = _ref4.onKeyDown,
2574 _ref4$refKey = _ref4.refKey,
2575 refKey = _ref4$refKey === void 0 ? 'ref' : _ref4$refKey,
2576 ref = _ref4.ref,
2577 rest = _objectWithoutPropertiesLoose(_ref4, ["onClick", "onKeyDown", "refKey", "ref"]);
2578
2579 var toggleProps = _extends((_extends3 = {}, _extends3[refKey] = handleRefs(ref, function (toggleButtonNode) {
2580 toggleButtonRef.current = toggleButtonNode;
2581 }), _extends3.id = elementIds.current.toggleButtonId, _extends3['aria-haspopup'] = 'listbox', _extends3['aria-expanded'] = isOpen, _extends3['aria-labelledby'] = elementIds.current.labelId + " " + elementIds.current.toggleButtonId, _extends3), rest);
2582
2583 if (!rest.disabled) {
2584 toggleProps.onClick = callAllEventHandlers(onClick, toggleButtonHandleClick);
2585 toggleProps.onKeyDown = callAllEventHandlers(onKeyDown, toggleButtonHandleKeyDown);
2586 }
2587
2588 return toggleProps;
2589 },
2590 getLabelProps: function getLabelProps(labelProps) {
2591 return _extends({
2592 id: elementIds.current.labelId,
2593 htmlFor: elementIds.current.toggleButtonId
2594 }, labelProps);
2595 },
2596 getMenuProps: function getMenuProps(_ref) {
2597 var _extends2;
2598
2599 if (_ref === void 0) {
2600 _ref = {};
2601 }
2602
2603 var _ref2 = _ref,
2604 onMouseLeave = _ref2.onMouseLeave,
2605 _ref2$refKey = _ref2.refKey,
2606 refKey = _ref2$refKey === void 0 ? 'ref' : _ref2$refKey,
2607 onKeyDown = _ref2.onKeyDown,
2608 onBlur = _ref2.onBlur,
2609 ref = _ref2.ref,
2610 rest = _objectWithoutPropertiesLoose(_ref2, ["onMouseLeave", "refKey", "onKeyDown", "onBlur", "ref"]);
2611
2612 return _extends((_extends2 = {}, _extends2[refKey] = handleRefs(ref, function (menuNode) {
2613 menuRef.current = menuNode;
2614 }), _extends2.id = elementIds.current.menuId, _extends2.role = 'listbox', _extends2['aria-labelledby'] = elementIds.current.labelId, _extends2.tabIndex = -1, _extends2), isOpen && highlightedIndex > -1 && {
2615 'aria-activedescendant': elementIds.current.getItemId(highlightedIndex)
2616 }, {
2617 onMouseLeave: callAllEventHandlers(onMouseLeave, menuHandleMouseLeave),
2618 onKeyDown: callAllEventHandlers(onKeyDown, menuHandleKeyDown),
2619 onBlur: callAllEventHandlers(onBlur, menuHandleBlur)
2620 }, rest);
2621 },
2622 getItemProps: function getItemProps(_ref5) {
2623 if (_ref5 === void 0) {
2624 _ref5 = {};
2625 }
2626
2627 var _ref6 = _ref5,
2628 item = _ref6.item,
2629 index = _ref6.index,
2630 onMouseMove = _ref6.onMouseMove,
2631 onClick = _ref6.onClick,
2632 rest = _objectWithoutPropertiesLoose(_ref6, ["item", "index", "onMouseMove", "onClick"]);
2633
2634 var itemIndex = getItemIndex(index, item, items);
2635
2636 if (itemIndex < 0) {
2637 throw new Error('Pass either item or item index in getItemProps!');
2638 }
2639
2640 var itemProps = _extends({
2641 role: 'option',
2642 'aria-selected': "" + (itemIndex === highlightedIndex),
2643 id: elementIds.current.getItemId(itemIndex)
2644 }, rest);
2645
2646 if (!rest.disabled) {
2647 itemProps.onMouseMove = callAllEventHandlers(onMouseMove, function () {
2648 return itemHandleMouseMove(itemIndex);
2649 });
2650 itemProps.onClick = callAllEventHandlers(onClick, function () {
2651 return itemHandleClick(itemIndex);
2652 });
2653 }
2654
2655 return itemProps;
2656 },
2657 // actions.
2658 toggleMenu: function toggleMenu() {
2659 dispatch({
2660 type: FunctionToggleMenu
2661 });
2662 },
2663 openMenu: function openMenu() {
2664 dispatch({
2665 type: FunctionOpenMenu
2666 });
2667 },
2668 closeMenu: function closeMenu() {
2669 dispatch({
2670 type: FunctionCloseMenu
2671 });
2672 },
2673 setHighlightedIndex: function setHighlightedIndex(newHighlightedIndex) {
2674 dispatch({
2675 type: FunctionSetHighlightedIndex,
2676 highlightedIndex: newHighlightedIndex
2677 });
2678 },
2679 selectItem: function selectItem(newSelectedItem) {
2680 dispatch({
2681 type: FunctionSelectItem,
2682 selectedItem: newSelectedItem
2683 });
2684 },
2685 reset: function reset() {
2686 dispatch({
2687 type: FunctionReset
2688 });
2689 },
2690 setInputValue: function setInputValue(newInputValue) {
2691 dispatch({
2692 type: FunctionSetInputValue,
2693 inputValue: newInputValue
2694 });
2695 },
2696 // state.
2697 highlightedIndex: highlightedIndex,
2698 isOpen: isOpen,
2699 selectedItem: selectedItem,
2700 inputValue: inputValue
2701 };
2702}
2703
2704function getElementIds$1(_ref) {
2705 var id = _ref.id,
2706 inputId = _ref.inputId,
2707 rest = _objectWithoutPropertiesLoose(_ref, ["id", "inputId"]);
2708
2709 var uniqueId = id === undefined ? "downshift-" + generateId() : id;
2710 return _extends({
2711 inputId: inputId || uniqueId + "-input"
2712 }, getElementIds(_extends({
2713 id: id
2714 }, rest)));
2715}
2716
2717function getInitialState$1(props) {
2718 var initialState = getInitialState(props);
2719 var selectedItem = initialState.selectedItem;
2720 var inputValue = initialState.inputValue;
2721
2722 if (inputValue === '' && selectedItem && props.defaultInputValue === undefined && props.initialInputValue === undefined && props.inputValue === undefined) {
2723 inputValue = props.itemToString(selectedItem);
2724 }
2725
2726 return _extends({}, initialState, {
2727 inputValue: inputValue
2728 });
2729}
2730
2731var propTypes$1 = {
2732 items: PropTypes.array.isRequired,
2733 itemToString: PropTypes.func,
2734 getA11yStatusMessage: PropTypes.func,
2735 getA11ySelectionMessage: PropTypes.func,
2736 circularNavigation: PropTypes.bool,
2737 highlightedIndex: PropTypes.number,
2738 defaultHighlightedIndex: PropTypes.number,
2739 initialHighlightedIndex: PropTypes.number,
2740 isOpen: PropTypes.bool,
2741 defaultIsOpen: PropTypes.bool,
2742 initialIsOpen: PropTypes.bool,
2743 selectedItem: PropTypes.any,
2744 initialSelectedItem: PropTypes.any,
2745 defaultSelectedItem: PropTypes.any,
2746 inputValue: PropTypes.string,
2747 defaultInputValue: PropTypes.string,
2748 initialInputValue: PropTypes.string,
2749 id: PropTypes.string,
2750 labelId: PropTypes.string,
2751 menuId: PropTypes.string,
2752 getItemId: PropTypes.func,
2753 inputId: PropTypes.string,
2754 toggleButtonId: PropTypes.string,
2755 stateReducer: PropTypes.func,
2756 onSelectedItemChange: PropTypes.func,
2757 onHighlightedIndexChange: PropTypes.func,
2758 onStateChange: PropTypes.func,
2759 onIsOpenChange: PropTypes.func,
2760 onInputValueChange: PropTypes.func,
2761 environment: PropTypes.shape({
2762 addEventListener: PropTypes.func,
2763 removeEventListener: PropTypes.func,
2764 document: PropTypes.shape({
2765 getElementById: PropTypes.func,
2766 activeElement: PropTypes.any,
2767 body: PropTypes.any
2768 })
2769 })
2770};
2771
2772var defaultProps$2 = _extends({}, defaultProps, {
2773 getA11yStatusMessage: getA11yStatusMessage,
2774 circularNavigation: true
2775});
2776
2777var InputKeyDownArrowDown = process.env.NODE_ENV !== "production" ? '__input_keydown_arrow_down__' : 0;
2778var InputKeyDownArrowUp = process.env.NODE_ENV !== "production" ? '__input_keydown_arrow_up__' : 1;
2779var InputKeyDownEscape = process.env.NODE_ENV !== "production" ? '__input_keydown_escape__' : 2;
2780var InputKeyDownHome = process.env.NODE_ENV !== "production" ? '__input_keydown_home__' : 3;
2781var InputKeyDownEnd = process.env.NODE_ENV !== "production" ? '__input_keydown_end__' : 4;
2782var InputKeyDownEnter = process.env.NODE_ENV !== "production" ? '__input_keydown_enter__' : 5;
2783var InputChange = process.env.NODE_ENV !== "production" ? '__input_change__' : 6;
2784var InputBlur = process.env.NODE_ENV !== "production" ? '__input_blur__' : 7;
2785var MenuMouseLeave$1 = process.env.NODE_ENV !== "production" ? '__menu_mouse_leave__' : 8;
2786var ItemMouseMove$1 = process.env.NODE_ENV !== "production" ? '__item_mouse_move__' : 9;
2787var ItemClick$1 = process.env.NODE_ENV !== "production" ? '__item_click__' : 10;
2788var ToggleButtonClick$1 = process.env.NODE_ENV !== "production" ? '__togglebutton_click__' : 11;
2789var FunctionToggleMenu$1 = process.env.NODE_ENV !== "production" ? '__function_toggle_menu__' : 12;
2790var FunctionOpenMenu$1 = process.env.NODE_ENV !== "production" ? '__function_open_menu__' : 13;
2791var FunctionCloseMenu$1 = process.env.NODE_ENV !== "production" ? '__function_close_menu__' : 14;
2792var FunctionSetHighlightedIndex$1 = process.env.NODE_ENV !== "production" ? '__function_set_highlighted_index__' : 15;
2793var FunctionSelectItem$1 = process.env.NODE_ENV !== "production" ? '__function_select_item__' : 16;
2794var FunctionSetInputValue$1 = process.env.NODE_ENV !== "production" ? '__function_set_input_value__' : 17;
2795var FunctionReset$1 = process.env.NODE_ENV !== "production" ? '__function_reset__' : 18;
2796
2797var stateChangeTypes$2 = /*#__PURE__*/Object.freeze({
2798 __proto__: null,
2799 InputKeyDownArrowDown: InputKeyDownArrowDown,
2800 InputKeyDownArrowUp: InputKeyDownArrowUp,
2801 InputKeyDownEscape: InputKeyDownEscape,
2802 InputKeyDownHome: InputKeyDownHome,
2803 InputKeyDownEnd: InputKeyDownEnd,
2804 InputKeyDownEnter: InputKeyDownEnter,
2805 InputChange: InputChange,
2806 InputBlur: InputBlur,
2807 MenuMouseLeave: MenuMouseLeave$1,
2808 ItemMouseMove: ItemMouseMove$1,
2809 ItemClick: ItemClick$1,
2810 ToggleButtonClick: ToggleButtonClick$1,
2811 FunctionToggleMenu: FunctionToggleMenu$1,
2812 FunctionOpenMenu: FunctionOpenMenu$1,
2813 FunctionCloseMenu: FunctionCloseMenu$1,
2814 FunctionSetHighlightedIndex: FunctionSetHighlightedIndex$1,
2815 FunctionSelectItem: FunctionSelectItem$1,
2816 FunctionSetInputValue: FunctionSetInputValue$1,
2817 FunctionReset: FunctionReset$1
2818});
2819
2820/* eslint-disable complexity */
2821
2822function downshiftUseComboboxReducer(state, action) {
2823 var type = action.type,
2824 props = action.props,
2825 shiftKey = action.shiftKey;
2826 var changes;
2827
2828 switch (type) {
2829 case ItemMouseMove$1:
2830 changes = {
2831 highlightedIndex: action.index
2832 };
2833 break;
2834
2835 case ItemClick$1:
2836 changes = {
2837 isOpen: getDefaultValue(props, 'isOpen'),
2838 highlightedIndex: getDefaultValue(props, 'highlightedIndex'),
2839 selectedItem: props.items[action.index],
2840 inputValue: props.itemToString(props.items[action.index])
2841 };
2842 break;
2843
2844 case InputKeyDownArrowDown:
2845 if (state.isOpen) {
2846 changes = {
2847 highlightedIndex: getNextWrappingIndex(shiftKey ? 5 : 1, state.highlightedIndex, props.items.length, action.getItemNodeFromIndex, props.circularNavigation)
2848 };
2849 } else {
2850 changes = {
2851 highlightedIndex: getHighlightedIndexOnOpen(props, state, 1, action.getItemNodeFromIndex),
2852 isOpen: true
2853 };
2854 }
2855
2856 break;
2857
2858 case InputKeyDownArrowUp:
2859 if (state.isOpen) {
2860 changes = {
2861 highlightedIndex: getNextWrappingIndex(shiftKey ? -5 : -1, state.highlightedIndex, props.items.length, action.getItemNodeFromIndex, props.circularNavigation)
2862 };
2863 } else {
2864 changes = {
2865 highlightedIndex: getHighlightedIndexOnOpen(props, state, -1, action.getItemNodeFromIndex),
2866 isOpen: true
2867 };
2868 }
2869
2870 break;
2871
2872 case InputKeyDownEnter:
2873 changes = _extends({}, state.highlightedIndex >= 0 && {
2874 selectedItem: props.items[state.highlightedIndex],
2875 isOpen: getDefaultValue(props, 'isOpen'),
2876 highlightedIndex: getDefaultValue(props, 'highlightedIndex'),
2877 inputValue: props.itemToString(props.items[state.highlightedIndex])
2878 });
2879 break;
2880
2881 case InputKeyDownEscape:
2882 changes = {
2883 isOpen: false,
2884 selectedItem: null,
2885 highlightedIndex: -1,
2886 inputValue: ''
2887 };
2888 break;
2889
2890 case InputKeyDownHome:
2891 changes = {
2892 highlightedIndex: getNextNonDisabledIndex(1, 0, props.items.length, action.getItemNodeFromIndex, false)
2893 };
2894 break;
2895
2896 case InputKeyDownEnd:
2897 changes = {
2898 highlightedIndex: getNextNonDisabledIndex(-1, props.items.length - 1, props.items.length, action.getItemNodeFromIndex, false)
2899 };
2900 break;
2901
2902 case InputBlur:
2903 changes = _extends({
2904 isOpen: false
2905 }, state.highlightedIndex >= 0 && {
2906 selectedItem: props.items[state.highlightedIndex],
2907 inputValue: props.itemToString(props.items[state.highlightedIndex]),
2908 highlightedIndex: -1
2909 });
2910 break;
2911
2912 case InputChange:
2913 changes = {
2914 isOpen: true,
2915 highlightedIndex: getDefaultValue(props, 'highlightedIndex'),
2916 inputValue: action.inputValue
2917 };
2918 break;
2919
2920 case MenuMouseLeave$1:
2921 changes = {
2922 highlightedIndex: -1
2923 };
2924 break;
2925
2926 case ToggleButtonClick$1:
2927 case FunctionToggleMenu$1:
2928 changes = {
2929 isOpen: !state.isOpen,
2930 highlightedIndex: state.isOpen ? -1 : getHighlightedIndexOnOpen(props, state, 0)
2931 };
2932 break;
2933
2934 case FunctionOpenMenu$1:
2935 changes = {
2936 isOpen: true,
2937 highlightedIndex: getHighlightedIndexOnOpen(props, state, 0)
2938 };
2939 break;
2940
2941 case FunctionCloseMenu$1:
2942 changes = {
2943 isOpen: false
2944 };
2945 break;
2946
2947 case FunctionSetHighlightedIndex$1:
2948 changes = {
2949 highlightedIndex: action.highlightedIndex
2950 };
2951 break;
2952
2953 case FunctionSelectItem$1:
2954 changes = {
2955 selectedItem: action.selectedItem
2956 };
2957 break;
2958
2959 case FunctionSetInputValue$1:
2960 changes = {
2961 inputValue: action.inputValue
2962 };
2963 break;
2964
2965 case FunctionReset$1:
2966 changes = {
2967 highlightedIndex: getDefaultValue(props, 'highlightedIndex'),
2968 isOpen: getDefaultValue(props, 'isOpen'),
2969 selectedItem: getDefaultValue(props, 'selectedItem'),
2970 inputValue: getDefaultValue(props, 'inputValue')
2971 };
2972 break;
2973
2974 default:
2975 throw new Error('Reducer called without proper action type.');
2976 }
2977
2978 return _extends({}, state, {}, changes);
2979}
2980/* eslint-enable complexity */
2981
2982var validatePropTypes$1 = process.env.NODE_ENV === 'production' ?
2983/* istanbul ignore next */
2984null : getPropTypesValidator(useCombobox, propTypes$1);
2985useCombobox.stateChangeTypes = stateChangeTypes$2;
2986
2987function useCombobox(userProps) {
2988 if (userProps === void 0) {
2989 userProps = {};
2990 }
2991
2992 /* istanbul ignore else */
2993 if (process.env.NODE_ENV !== 'production') {
2994 validatePropTypes$1(userProps);
2995 } // Props defaults and destructuring.
2996
2997
2998 var props = _extends({}, defaultProps$2, {}, userProps);
2999
3000 var initialIsOpen = props.initialIsOpen,
3001 defaultIsOpen = props.defaultIsOpen,
3002 items = props.items,
3003 scrollIntoView = props.scrollIntoView,
3004 getA11ySelectionMessage = props.getA11ySelectionMessage,
3005 getA11yStatusMessage = props.getA11yStatusMessage,
3006 itemToString = props.itemToString,
3007 environment = props.environment; // Initial state depending on controlled props.
3008
3009 var initialState = getInitialState$1(props); // Reducer init.
3010
3011 var _useEnhancedReducer = useEnhancedReducer(downshiftUseComboboxReducer, initialState, props),
3012 _useEnhancedReducer$ = _useEnhancedReducer[0],
3013 isOpen = _useEnhancedReducer$.isOpen,
3014 highlightedIndex = _useEnhancedReducer$.highlightedIndex,
3015 selectedItem = _useEnhancedReducer$.selectedItem,
3016 inputValue = _useEnhancedReducer$.inputValue,
3017 dispatch = _useEnhancedReducer[1];
3018 /* Refs */
3019
3020
3021 var menuRef = react.useRef(null);
3022 var itemRefs = react.useRef();
3023 var inputRef = react.useRef(null);
3024 var toggleButtonRef = react.useRef(null);
3025 var comboboxRef = react.useRef(null);
3026 itemRefs.current = [];
3027 var shouldScroll = react.useRef(true);
3028 var isInitialMount = react.useRef(true);
3029 var mouseAndTouchTrackers = react.useRef({
3030 isMouseDown: false,
3031 isTouchMove: false
3032 });
3033 var elementIds = react.useRef(getElementIds$1(props));
3034 /* Effects */
3035
3036 /* Sets a11y status message on changes in isOpen. */
3037
3038 react.useEffect(function () {
3039 if (isInitialMount.current) {
3040 return;
3041 }
3042
3043 setStatus(getA11yStatusMessage({
3044 highlightedIndex: highlightedIndex,
3045 inputValue: inputValue,
3046 isOpen: isOpen,
3047 itemToString: itemToString,
3048 resultCount: items.length,
3049 highlightedItem: items[highlightedIndex],
3050 selectedItem: selectedItem
3051 }), environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
3052 }, [isOpen]);
3053 /* Sets a11y status message on changes in selectedItem. */
3054
3055 react.useEffect(function () {
3056 if (isInitialMount.current) {
3057 return;
3058 }
3059
3060 setStatus(getA11ySelectionMessage({
3061 highlightedIndex: highlightedIndex,
3062 inputValue: inputValue,
3063 isOpen: isOpen,
3064 itemToString: itemToString,
3065 resultCount: items.length,
3066 highlightedItem: items[highlightedIndex],
3067 selectedItem: selectedItem
3068 }), environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
3069 }, [selectedItem]);
3070 /* Scroll on highlighted item if change comes from keyboard. */
3071
3072 react.useEffect(function () {
3073 if (highlightedIndex < 0 || !isOpen || !itemRefs.current.length) {
3074 return;
3075 }
3076
3077 if (shouldScroll.current === false) {
3078 shouldScroll.current = true;
3079 } else {
3080 scrollIntoView(itemRefs.current[highlightedIndex], menuRef.current);
3081 } // eslint-disable-next-line react-hooks/exhaustive-deps
3082
3083 }, [highlightedIndex]);
3084 /* Controls the focus on the menu or the toggle button. */
3085
3086 react.useEffect(function () {
3087 // Don't focus menu on first render.
3088 if (isInitialMount.current) {
3089 // Unless it was initialised as open.
3090 if (initialIsOpen || defaultIsOpen || isOpen) {
3091 if (inputRef.current) {
3092 inputRef.current.focus();
3093 }
3094 }
3095 } // eslint-disable-next-line react-hooks/exhaustive-deps
3096
3097 }, [isOpen]);
3098 /* Make initial ref false. */
3099
3100 react.useEffect(function () {
3101 isInitialMount.current = false;
3102 }, []);
3103 /* Add mouse/touch events to document. */
3104
3105 react.useEffect(function () {
3106 // The same strategy for checking if a click occurred inside or outside downsift
3107 // as in downshift.js.
3108 var onMouseDown = function () {
3109 mouseAndTouchTrackers.current.isMouseDown = true;
3110 };
3111
3112 var onMouseUp = function (event) {
3113 mouseAndTouchTrackers.current.isMouseDown = false;
3114
3115 if (isOpen && !targetWithinDownshift(event.target, [comboboxRef.current, menuRef.current, toggleButtonRef.current], environment.document)) {
3116 dispatch({
3117 type: InputBlur
3118 });
3119 }
3120 };
3121
3122 var onTouchStart = function () {
3123 mouseAndTouchTrackers.current.isTouchMove = false;
3124 };
3125
3126 var onTouchMove = function () {
3127 mouseAndTouchTrackers.current.isTouchMove = true;
3128 };
3129
3130 var onTouchEnd = function (event) {
3131 if (isOpen && !mouseAndTouchTrackers.current.isTouchMove && !targetWithinDownshift(event.target, [comboboxRef.current, menuRef.current, toggleButtonRef.current], environment.document, false)) {
3132 dispatch({
3133 type: InputBlur
3134 });
3135 }
3136 };
3137
3138 environment.addEventListener('mousedown', onMouseDown);
3139 environment.addEventListener('mouseup', onMouseUp);
3140 environment.addEventListener('touchstart', onTouchStart);
3141 environment.addEventListener('touchmove', onTouchMove);
3142 environment.addEventListener('touchend', onTouchEnd);
3143 return function () {
3144 environment.removeEventListener('mousedown', onMouseDown);
3145 environment.removeEventListener('mouseup', onMouseUp);
3146 environment.removeEventListener('touchstart', onTouchStart);
3147 environment.removeEventListener('touchmove', onTouchMove);
3148 environment.removeEventListener('touchend', onTouchEnd);
3149 };
3150 });
3151
3152 var getItemNodeFromIndex = function (index) {
3153 return itemRefs.current[index];
3154 };
3155 /* Event handler functions */
3156
3157
3158 var inputKeyDownHandlers = {
3159 ArrowDown: function ArrowDown(event) {
3160 event.preventDefault();
3161 dispatch({
3162 type: InputKeyDownArrowDown,
3163 shiftKey: event.shiftKey,
3164 getItemNodeFromIndex: getItemNodeFromIndex
3165 });
3166 },
3167 ArrowUp: function ArrowUp(event) {
3168 event.preventDefault();
3169 dispatch({
3170 type: InputKeyDownArrowUp,
3171 shiftKey: event.shiftKey,
3172 getItemNodeFromIndex: getItemNodeFromIndex
3173 });
3174 },
3175 Home: function Home(event) {
3176 event.preventDefault();
3177 dispatch({
3178 type: InputKeyDownHome,
3179 getItemNodeFromIndex: getItemNodeFromIndex
3180 });
3181 },
3182 End: function End(event) {
3183 event.preventDefault();
3184 dispatch({
3185 type: InputKeyDownEnd,
3186 getItemNodeFromIndex: getItemNodeFromIndex
3187 });
3188 },
3189 Escape: function Escape() {
3190 dispatch({
3191 type: InputKeyDownEscape
3192 });
3193 },
3194 Enter: function Enter(event) {
3195 event.preventDefault();
3196 dispatch({
3197 type: InputKeyDownEnter,
3198 getItemNodeFromIndex: getItemNodeFromIndex
3199 });
3200 }
3201 }; // Event handlers.
3202
3203 var inputHandleKeyDown = function (event) {
3204 var key = normalizeArrowKey(event);
3205
3206 if (key && inputKeyDownHandlers[key]) {
3207 inputKeyDownHandlers[key](event);
3208 }
3209 };
3210
3211 var inputHandleChange = function (event) {
3212 dispatch({
3213 type: InputChange,
3214 inputValue: event.target.value
3215 });
3216 };
3217
3218 var inputHandleBlur = function () {
3219 /* istanbul ignore else */
3220 if (!mouseAndTouchTrackers.current.isMouseDown) {
3221 dispatch({
3222 type: InputBlur
3223 });
3224 }
3225 };
3226
3227 var menuHandleMouseLeave = function () {
3228 dispatch({
3229 type: MenuMouseLeave$1
3230 });
3231 };
3232
3233 var itemHandleMouseMove = function (index) {
3234 if (index === highlightedIndex) {
3235 return;
3236 }
3237
3238 shouldScroll.current = false;
3239 dispatch({
3240 type: ItemMouseMove$1,
3241 index: index
3242 });
3243 };
3244
3245 var itemHandleClick = function (index) {
3246 dispatch({
3247 type: ItemClick$1,
3248 index: index
3249 });
3250 };
3251
3252 var toggleButtonHandleClick = function () {
3253 dispatch({
3254 type: ToggleButtonClick$1
3255 });
3256
3257 if (!isOpen && inputRef.current) {
3258 inputRef.current.focus();
3259 }
3260 }; // returns
3261
3262
3263 return {
3264 // prop getters.
3265 getItemProps: function getItemProps(_ref3) {
3266 var _extends3, _ref5;
3267
3268 if (_ref3 === void 0) {
3269 _ref3 = {};
3270 }
3271
3272 var _ref4 = _ref3,
3273 item = _ref4.item,
3274 index = _ref4.index,
3275 _ref4$refKey = _ref4.refKey,
3276 refKey = _ref4$refKey === void 0 ? 'ref' : _ref4$refKey,
3277 ref = _ref4.ref,
3278 onMouseMove = _ref4.onMouseMove,
3279 onClick = _ref4.onClick,
3280 onPress = _ref4.onPress,
3281 rest = _objectWithoutPropertiesLoose(_ref4, ["item", "index", "refKey", "ref", "onMouseMove", "onClick", "onPress"]);
3282
3283 var itemIndex = getItemIndex(index, item, items);
3284
3285 if (itemIndex < 0) {
3286 throw new Error('Pass either item or item index in getItemProps!');
3287 }
3288
3289 var onSelectKey = 'onClick';
3290 var customClickHandler = onClick;
3291 return _extends((_extends3 = {}, _extends3[refKey] = handleRefs(ref, function (itemNode) {
3292 if (itemNode) {
3293 itemRefs.current.push(itemNode);
3294 }
3295 }), _extends3.role = 'option', _extends3['aria-selected'] = "" + (itemIndex === highlightedIndex), _extends3.id = elementIds.current.getItemId(itemIndex), _extends3), !rest.disabled && (_ref5 = {
3296 onMouseMove: callAllEventHandlers(onMouseMove, function () {
3297 itemHandleMouseMove(itemIndex);
3298 })
3299 }, _ref5[onSelectKey] = callAllEventHandlers(customClickHandler, function () {
3300 itemHandleClick(itemIndex);
3301 }), _ref5), {}, rest);
3302 },
3303 getLabelProps: function getLabelProps(labelProps) {
3304 return _extends({
3305 id: elementIds.current.labelId,
3306 htmlFor: elementIds.current.inputId
3307 }, labelProps);
3308 },
3309 getMenuProps: function getMenuProps(_ref) {
3310 var _extends2;
3311
3312 if (_ref === void 0) {
3313 _ref = {};
3314 }
3315
3316 var _ref2 = _ref,
3317 onMouseLeave = _ref2.onMouseLeave,
3318 _ref2$refKey = _ref2.refKey,
3319 refKey = _ref2$refKey === void 0 ? 'ref' : _ref2$refKey,
3320 ref = _ref2.ref,
3321 rest = _objectWithoutPropertiesLoose(_ref2, ["onMouseLeave", "refKey", "ref"]);
3322
3323 return _extends((_extends2 = {}, _extends2[refKey] = handleRefs(ref, function (menuNode) {
3324 menuRef.current = menuNode;
3325 }), _extends2.id = elementIds.current.menuId, _extends2.role = 'listbox', _extends2['aria-labelledby'] = elementIds.current.labelId, _extends2.onMouseLeave = callAllEventHandlers(onMouseLeave, menuHandleMouseLeave), _extends2), rest);
3326 },
3327 getInputProps: function getInputProps(_ref8) {
3328 var _extends5;
3329
3330 if (_ref8 === void 0) {
3331 _ref8 = {};
3332 }
3333
3334 var _ref9 = _ref8,
3335 onKeyDown = _ref9.onKeyDown,
3336 onChange = _ref9.onChange,
3337 onInput = _ref9.onInput,
3338 onBlur = _ref9.onBlur,
3339 onChangeText = _ref9.onChangeText,
3340 _ref9$refKey = _ref9.refKey,
3341 refKey = _ref9$refKey === void 0 ? 'ref' : _ref9$refKey,
3342 ref = _ref9.ref,
3343 rest = _objectWithoutPropertiesLoose(_ref9, ["onKeyDown", "onChange", "onInput", "onBlur", "onChangeText", "refKey", "ref"]);
3344
3345 /* istanbul ignore next (preact) */
3346 var onChangeKey = 'onChange';
3347 var eventHandlers = {};
3348
3349 if (!rest.disabled) {
3350 var _eventHandlers;
3351
3352 eventHandlers = (_eventHandlers = {}, _eventHandlers[onChangeKey] = callAllEventHandlers(onChange, onInput, inputHandleChange), _eventHandlers.onKeyDown = callAllEventHandlers(onKeyDown, inputHandleKeyDown), _eventHandlers.onBlur = callAllEventHandlers(onBlur, inputHandleBlur), _eventHandlers);
3353 }
3354 /* istanbul ignore if (react-native) */
3355
3356
3357 return _extends((_extends5 = {}, _extends5[refKey] = handleRefs(ref, function (inputNode) {
3358 inputRef.current = inputNode;
3359 }), _extends5.id = elementIds.current.inputId, _extends5['aria-autocomplete'] = 'list', _extends5['aria-controls'] = elementIds.current.menuId, _extends5), isOpen && highlightedIndex > -1 && {
3360 'aria-activedescendant': elementIds.current.getItemId(highlightedIndex)
3361 }, {
3362 'aria-labelledby': elementIds.current.labelId,
3363 // https://developer.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion
3364 // revert back since autocomplete="nope" is ignored on latest Chrome and Opera
3365 autoComplete: 'off',
3366 value: inputValue
3367 }, eventHandlers, {}, rest);
3368 },
3369 getComboboxProps: function getComboboxProps(_ref10) {
3370 var _extends6;
3371
3372 if (_ref10 === void 0) {
3373 _ref10 = {};
3374 }
3375
3376 var _ref11 = _ref10,
3377 _ref11$refKey = _ref11.refKey,
3378 refKey = _ref11$refKey === void 0 ? 'ref' : _ref11$refKey,
3379 ref = _ref11.ref,
3380 rest = _objectWithoutPropertiesLoose(_ref11, ["refKey", "ref"]);
3381
3382 return _extends((_extends6 = {}, _extends6[refKey] = handleRefs(ref, function (comboboxNode) {
3383 comboboxRef.current = comboboxNode;
3384 }), _extends6.role = 'combobox', _extends6['aria-haspopup'] = 'listbox', _extends6['aria-owns'] = elementIds.current.menuId, _extends6['aria-expanded'] = isOpen, _extends6), rest);
3385 },
3386 getToggleButtonProps: function getToggleButtonProps(_ref6) {
3387 var _extends4;
3388
3389 if (_ref6 === void 0) {
3390 _ref6 = {};
3391 }
3392
3393 var _ref7 = _ref6,
3394 onClick = _ref7.onClick,
3395 onPress = _ref7.onPress,
3396 _ref7$refKey = _ref7.refKey,
3397 refKey = _ref7$refKey === void 0 ? 'ref' : _ref7$refKey,
3398 ref = _ref7.ref,
3399 rest = _objectWithoutPropertiesLoose(_ref7, ["onClick", "onPress", "refKey", "ref"]);
3400
3401 return _extends((_extends4 = {}, _extends4[refKey] = handleRefs(ref, function (toggleButtonNode) {
3402 toggleButtonRef.current = toggleButtonNode;
3403 }), _extends4.id = elementIds.current.toggleButtonId, _extends4.tabIndex = -1, _extends4), !rest.disabled && _extends({}, {
3404 onClick: callAllEventHandlers(onClick, toggleButtonHandleClick)
3405 }), {}, rest);
3406 },
3407 // actions.
3408 toggleMenu: function toggleMenu() {
3409 dispatch({
3410 type: FunctionToggleMenu$1
3411 });
3412 },
3413 openMenu: function openMenu() {
3414 dispatch({
3415 type: FunctionOpenMenu$1
3416 });
3417 },
3418 closeMenu: function closeMenu() {
3419 dispatch({
3420 type: FunctionCloseMenu$1
3421 });
3422 },
3423 setHighlightedIndex: function setHighlightedIndex(newHighlightedIndex) {
3424 dispatch({
3425 type: FunctionSetHighlightedIndex$1,
3426 highlightedIndex: newHighlightedIndex
3427 });
3428 },
3429 setInputValue: function setInputValue(newInputValue) {
3430 dispatch({
3431 type: FunctionSetInputValue$1,
3432 inputValue: newInputValue
3433 });
3434 },
3435 selectItem: function selectItem(newSelectedItem) {
3436 dispatch({
3437 type: FunctionSelectItem$1,
3438 selectedItem: newSelectedItem
3439 });
3440 },
3441 reset: function reset() {
3442 dispatch({
3443 type: FunctionReset$1
3444 });
3445 },
3446 // state.
3447 highlightedIndex: highlightedIndex,
3448 isOpen: isOpen,
3449 selectedItem: selectedItem,
3450 inputValue: inputValue
3451 };
3452}
3453
3454exports.default = Downshift;
3455exports.resetIdCounter = resetIdCounter;
3456exports.useCombobox = useCombobox;
3457exports.useSelect = useSelect;