UNPKG

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