UNPKG

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