'use strict';
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var React = require('preact');
var React__default = _interopDefault(React);
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var defineProperty = function (obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
};
var _extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
var inherits = function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};
var objectWithoutProperties = function (obj, keys) {
var target = {};
for (var i in obj) {
if (keys.indexOf(i) >= 0) continue;
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
target[i] = obj[i];
}
return target;
};
var possibleConstructorReturn = function (self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};
var toConsumableArray = function (arr) {
if (Array.isArray(arr)) {
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
return arr2;
} else {
return Array.from(arr);
}
};
// istanbul ignore next
var statusDiv = typeof document === 'undefined' ? null : document.getElementById('a11y-status-message');
var statuses = [];
function setStatus(status) {
var isSameAsLast = statuses[statuses.length - 1] === status;
if (isSameAsLast) {
statuses = [].concat(toConsumableArray(statuses), [status]);
} else {
statuses = [status];
}
var div = getStatusDiv();
div.innerHTML = '' + statuses.filter(Boolean).map(getStatusHtml).join('');
}
function getStatusHtml(status, index) {
var display = index === statuses.length - 1 ? 'block' : 'none';
return '
' + status + '
';
}
function getStatusDiv() {
if (statusDiv) {
return statusDiv;
}
statusDiv = document.createElement('div');
statusDiv.setAttribute('id', 'a11y-status-message');
statusDiv.setAttribute('role', 'status');
statusDiv.setAttribute('aria-live', 'assertive');
statusDiv.setAttribute('aria-relevant', 'additions text');
Object.assign(statusDiv.style, {
border: '0',
clip: 'rect(0 0 0 0)',
height: '1px',
margin: '-1px',
overflow: 'hidden',
padding: '0',
position: 'absolute',
width: '1px'
});
document.body.appendChild(statusDiv);
return statusDiv;
}
var idCounter = 1;
/**
* Accepts a parameter and returns it if it's a function
* or a noop function if it's not. This allows us to
* accept a callback, but not worry about it if it's not
* passed.
* @param {Function} cb the callback
* @return {Function} a function
*/
function cbToCb(cb) {
return typeof cb === 'function' ? cb : noop;
}
function noop() {}
function findParent(finder, node, rootNode) {
if (node !== null && node !== rootNode.parentNode) {
if (finder(node)) {
return node;
} else {
return findParent(finder, node.parentNode, rootNode);
}
} else {
return null;
}
}
/**
* Get the closest element that scrolls
* @param {HTMLElement} node - the child element to start searching for scroll parent at
* @param {HTMLElement} rootNode - the root element of the component
* @return {HTMLElement} the closest parentNode that scrolls
*/
var getClosestScrollParent = findParent.bind(null, function (node) {
return node.scrollHeight > node.clientHeight;
});
/**
* Scroll node into view if necessary
* @param {HTMLElement} node - the element that should scroll into view
* @param {HTMLElement} rootNode - the root element of the component
* @param {Boolean} alignToTop - align element to the top of the visible area of the scrollable ancestor
*/
function scrollIntoView(node, rootNode) {
var scrollParent = getClosestScrollParent(node, rootNode);
if (scrollParent === null) {
return;
}
var scrollParentStyles = getComputedStyle(scrollParent);
var scrollParentRect = scrollParent.getBoundingClientRect();
var scrollParentBorderTopWidth = parseInt(scrollParentStyles.borderTopWidth, 10);
var scrollParentBorderBottomWidth = parseInt(scrollParentStyles.borderBottomWidth, 10);
var scrollParentTop = scrollParentRect.top + scrollParentBorderTopWidth;
var nodeRect = node.getBoundingClientRect();
var nodeOffsetTop = nodeRect.top + scrollParent.scrollTop;
var nodeTop = nodeOffsetTop - scrollParentTop;
if (nodeTop < scrollParent.scrollTop) {
// the item is above the scrollable area
scrollParent.scrollTop = nodeTop;
} else if (nodeTop + nodeRect.height + scrollParentBorderTopWidth + scrollParentBorderBottomWidth > scrollParent.scrollTop + scrollParentRect.height) {
// the item is below the scrollable area
scrollParent.scrollTop = nodeTop + nodeRect.height - scrollParentRect.height + scrollParentBorderTopWidth + scrollParentBorderBottomWidth;
}
// the item is within the scrollable area (do nothing)
}
/**
* Simple debounce implementation. Will call the given
* function once after the time given has passed since
* it was last called.
* @param {Function} fn the function to call after the time
* @param {Number} time the time to wait
* @return {Function} the debounced function
*/
function debounce(fn, time) {
var timeoutId = void 0;
return wrapper;
function wrapper() {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
if (timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(function () {
timeoutId = null;
fn.apply(undefined, args);
}, time);
}
}
/**
* This is intended to be used to compose event handlers
* They are executed in order until one of them calls
* `event.preventDefault()`. Not sure this is the best
* way to do this, but it seems legit...
* @param {Function} fns the event hanlder functions
* @return {Function} the event handler to add to an element
*/
function composeEventHandlers() {
for (var _len2 = arguments.length, fns = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
fns[_key2] = arguments[_key2];
}
return function (event) {
for (var _len3 = arguments.length, args = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
args[_key3 - 1] = arguments[_key3];
}
return fns.some(function (fn) {
fn && fn.apply(undefined, [event].concat(args));
return event.defaultPrevented;
});
};
}
/**
* This generates a unique ID for all autocomplete inputs
* @param {String} prefix the prefix for the id
* @return {String} the unique ID
*/
function generateId(prefix) {
return prefix + '-' + idCounter++;
}
/**
* Returns the first argument that is not undefined
* @param {...*} args the arguments
* @return {*} the defined value
*/
function firstDefined() {
for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
args[_key4] = arguments[_key4];
}
return args.find(function (a) {
return typeof a !== 'undefined';
});
}
function isNumber(thing) {
// not NaN and is a number type
// eslint-disable-next-line no-self-compare
return thing === thing && typeof thing === 'number';
}
// eslint-disable-next-line complexity
function getA11yStatusMessage(_ref) {
var isOpen = _ref.isOpen,
highlightedItem = _ref.highlightedItem,
selectedItem = _ref.selectedItem,
resultCount = _ref.resultCount,
previousResultCount = _ref.previousResultCount,
itemToString = _ref.itemToString;
if (!isOpen) {
if (selectedItem) {
return itemToString(selectedItem);
} else {
return '';
}
}
var resultCountChanged = resultCount !== previousResultCount;
if (!resultCount) {
return 'No results.';
} else if (!highlightedItem || resultCountChanged) {
return resultCount + ' ' + (resultCount === 1 ? 'result is' : 'results are') + ' available, use up and down arrow keys to navigate.';
}
return itemToString(highlightedItem);
}
/**
* Takes an argument and if it's an array, returns the first item in the array
* otherwise returns the argument
* @param {*} arg the maybe-array
* @param {*} defaultValue the value if arg is falsey not defined
* @return {*} the arg or it's first item
*/
function unwrapArray(arg, defaultValue) {
arg = Array.isArray(arg) ? /* istanbul ignore next (preact) */arg[0] : arg;
if (!arg && defaultValue) {
return defaultValue;
} else {
return arg;
}
}
/**
* @param {Object} element (P)react element
* @return {Boolean} whether it's a DOM element
*/
function isDOMElement(element) {
/* istanbul ignore if */
if (element.nodeName) {
// then this is preact
return typeof element.nodeName === 'string';
} else {
// then we assume this is react
return typeof element.type === 'string';
}
}
/**
* @param {Object} element (P)react element
* @return {Object} the props
*/
function getElementProps(element) {
// props for react, attributes for preact
return element.props || /* istanbul ignore next (preact) */element.attributes;
}
/**
* Throws a helpful error message for required properties. Useful
* to be used as a default in destructuring or object params.
* @param {String} fnName the function name
* @param {String} propName the prop name
*/
function requiredProp(fnName, propName) {
throw new Error('The property "' + propName + '" is required in "' + fnName + '"');
}
/* eslint camelcase:0 */
var Downshift$1 = function (_Component) {
inherits(Downshift, _Component);
function Downshift() {
var _ref;
classCallCheck(this, Downshift);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
var _this = possibleConstructorReturn(this, (_ref = Downshift.__proto__ || Object.getPrototypeOf(Downshift)).call.apply(_ref, [this].concat(args)));
_initialiseProps.call(_this);
_this.id = generateId('downshift');
var state = _this.getState({
highlightedIndex: _this.props.defaultHighlightedIndex,
isOpen: _this.props.defaultIsOpen,
inputValue: _this.props.defaultInputValue,
selectedItem: _this.props.defaultSelectedItem
});
if (state.selectedItem) {
state.inputValue = _this.props.itemToString(state.selectedItem);
}
_this.state = state;
_this.root_handleClick = composeEventHandlers(_this.props.onClick, _this.root_handleClick);
return _this;
}
// this is an experimental feature
// so we're not going to document this yet
createClass(Downshift, [{
key: 'getState',
/**
* Gets the state based on internal state or props
* If a state value is passed via props, then that
* is the value given, otherwise it's retrieved from
* stateToMerge
*
* This will perform a shallow merge of the given state object
* with the state coming from props
* (for the controlled component scenario)
* This is used in state updater functions so they're referencing
* the right state regardless of where it comes from.
*
* @param {Object} stateToMerge defaults to this.state
* @return {Object} the state
*/
value: function getState() {
var _this2 = this;
var stateToMerge = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.state;
return Object.keys(stateToMerge).reduce(function (state, key) {
state[key] = _this2.isStateProp(key) ? _this2.props[key] : stateToMerge[key];
return state;
}, {});
}
/**
* This determines whether a prop is a "controlled prop" meaning it is
* state which is controlled by the outside of this component rather
* than within this component.
* @param {String} key the key to check
* @return {Boolean} whether it is a controlled controlled prop
*/
}, {
key: 'isStateProp',
value: function isStateProp(key) {
return this.props[key] !== undefined;
}
}, {
key: 'getItemCount',
value: function getItemCount() {
if (this.props.itemCount === undefined) {
return this.items.length;
} else {
return this.props.itemCount;
}
}
// eslint-disable-next-line complexity
}, {
key: 'internalSetState',
// any piece of our state can live in two places:
// 1. Uncontrolled: it's internal (this.state)
// We will call this.setState to update that state
// 2. Controlled: it's external (this.props)
// We will call this.props.onStateChange to update that state
//
// In addition, we'll call this.props.onChange if the
// selectedItem is changed.
value: function internalSetState(stateToSet, cb) {
var _this3 = this;
var onChangeArg = void 0;
var onStateChangeArg = {};
return this.setState(function (state) {
state = _this3.getState(state);
stateToSet = typeof stateToSet === 'function' ? stateToSet(state) : stateToSet;
// this keeps track of the object we want to call with setState
var nextState = {};
// this is just used to tell whether the state changed
var nextFullState = {};
// we need to call on change if the outside world is controlling any of our state
// and we're trying to update that state. OR if the selection has changed and we're
// trying to update the selection
if (stateToSet.hasOwnProperty('selectedItem') && stateToSet.selectedItem !== state.selectedItem) {
onChangeArg = stateToSet.selectedItem;
}
Object.keys(stateToSet).forEach(function (key) {
// the type is useful for the onStateChangeArg
// but we don't actually want to set it in internal state.
// this is an undocumented feature for now... Not all internalSetState
// calls support it and I'm not certain we want them to yet.
// But it enables users controlling the isOpen state to know when
// the isOpen state changes due to mouseup events which is quite handy.
if (key === 'type') {
return;
}
// onStateChangeArg should only have the state that is
// actually changing
if (state[key] !== stateToSet[key]) {
onStateChangeArg[key] = stateToSet[key];
}
nextFullState[key] = stateToSet[key];
// if it's coming from props, then we don't care to set it internally
if (!_this3.isStateProp(key)) {
nextState[key] = stateToSet[key];
}
});
return nextState;
}, function () {
// call the provided callback if it's a callback
cbToCb(cb)();
// only call the onStateChange and onChange callbacks if
// we have relevant information to pass them.
if (Object.keys(onStateChangeArg).length) {
_this3.props.onStateChange(onStateChangeArg, _this3.getState());
}
if (onChangeArg !== undefined) {
_this3.props.onChange(onChangeArg, _this3.getState());
}
});
}
}, {
key: 'getControllerStateAndHelpers',
value: function getControllerStateAndHelpers() {
var _getState = this.getState(),
highlightedIndex = _getState.highlightedIndex,
inputValue = _getState.inputValue,
selectedItem = _getState.selectedItem,
isOpen = _getState.isOpen;
var itemToString = this.props.itemToString;
var getRootProps = this.getRootProps,
getButtonProps = this.getButtonProps,
getLabelProps = this.getLabelProps,
getInputProps = this.getInputProps,
getItemProps = this.getItemProps,
openMenu = this.openMenu,
closeMenu = this.closeMenu,
toggleMenu = this.toggleMenu,
selectItem = this.selectItem,
selectItemAtIndex = this.selectItemAtIndex,
selectHighlightedItem = this.selectHighlightedItem,
setHighlightedIndex = this.setHighlightedIndex,
clearSelection = this.clearSelection;
return {
// prop getters
getRootProps: getRootProps,
getButtonProps: getButtonProps,
getLabelProps: getLabelProps,
getInputProps: getInputProps,
getItemProps: getItemProps,
// actions
openMenu: openMenu,
closeMenu: closeMenu,
toggleMenu: toggleMenu,
selectItem: selectItem,
selectItemAtIndex: selectItemAtIndex,
selectHighlightedItem: selectHighlightedItem,
setHighlightedIndex: setHighlightedIndex,
clearSelection: clearSelection,
itemToString: itemToString,
// state
highlightedIndex: highlightedIndex,
inputValue: inputValue,
isOpen: isOpen,
selectedItem: selectedItem
};
}
//////////////////////////// ROOT
//\\\\\\\\\\\\\\\\\\\\\\\\\\ ROOT
//////////////////////////// BUTTON
//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ BUTTON
/////////////////////////////// LABEL
//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ LABEL
/////////////////////////////// INPUT
}, {
key: 'getItemId',
//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ INPUT
/////////////////////////////// ITEM
value: function getItemId(index) {
return this.id + '-item-' + index;
}
}, {
key: 'getItemIndexFromId',
value: function getItemIndexFromId(id) {
if (id) {
return Number(id.split(this.id + '-item-')[1]);
} else {
return null;
}
}
//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ ITEM
}, {
key: 'componentDidMount',
value: function componentDidMount() {
var _this4 = this;
// the _isMounted property is because we have `updateStatus` in a `debounce`
// and we don't want to update the status if the component has been umounted
this._isMounted = true;
// this.isMouseDown helps us track whether the mouse is currently held down.
// This is useful when the user clicks on an item in the list, but holds the mouse
// down long enough for the list to disappear (because the blur event fires on the input)
// this.isMouseDown is used in the blur handler on the input to determine whether the blur event should
// trigger hiding the menu.
var onMouseDown = function onMouseDown() {
_this4.isMouseDown = true;
};
var onMouseUp = function onMouseUp(event) {
_this4.isMouseDown = false;
if ((event.target === _this4._rootNode || !_this4._rootNode.contains(event.target)) && _this4.getState().isOpen) {
_this4.reset(Downshift.stateChangeTypes.mouseUp);
}
};
window.addEventListener('mousedown', onMouseDown);
window.addEventListener('mouseup', onMouseUp);
this.cleanup = function () {
_this4._isMounted = false;
window.removeEventListener('mousedown', onMouseDown);
window.removeEventListener('mouseup', onMouseUp);
};
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate(prevProps) {
if (this.isStateProp('selectedItem') && this.props.selectedItem !== prevProps.selectedItem) {
this.internalSetState({
inputValue: this.props.itemToString(this.props.selectedItem)
});
}
this.updateStatus();
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
this.cleanup(); // avoids memory leak
}
}, {
key: 'render',
value: function render() {
var children = unwrapArray(this.props.children, noop);
// because the items are rerendered every time we call the children
// we clear this out each render and
this.items = [];
// we reset this so we know whether the user calls getRootProps during
// this render. If they do then we don't need to do anything,
// if they don't then we need to clone the element they return and
// apply the props for them.
this.getRootProps.called = false;
this.getRootProps.refKey = undefined;
// we do something similar for getLabelProps
this.getLabelProps.called = false;
// and something similar for getInputProps
this.getInputProps.called = false;
var element = unwrapArray(children(this.getControllerStateAndHelpers()));
if (!element) {
return null;
}
if (this.getRootProps.called) {
validateGetRootPropsCalledCorrectly(element, this.getRootProps);
return element;
} else if (isDOMElement(element)) {
// they didn't apply the root props, but we can clone
// this and apply the props ourselves
return React__default.cloneElement(element, this.getRootProps(getElementProps(element)));
} else {
// they didn't apply the root props, but they need to
// otherwise we can't query around the autocomplete
throw new Error('downshift: If you return a non-DOM element, you must use apply the getRootProps function');
}
}
}]);
return Downshift;
}(React.Component);
Downshift$1.defaultProps = {
defaultHighlightedIndex: null,
defaultSelectedItem: null,
defaultInputValue: '',
defaultIsOpen: false,
getA11yStatusMessage: getA11yStatusMessage,
itemToString: function itemToString(i) {
return i == null ? '' : String(i);
},
onStateChange: function onStateChange() {},
onChange: function onChange() {} };
Downshift$1.stateChangeTypes = {
mouseUp: '__autocomplete_mouseup__'
};
var _initialiseProps = function _initialiseProps() {
var _this5 = this;
this.input = null;
this.items = [];
this.previousResultCount = 0;
this.getItemNodeFromIndex = function (index) {
return document.getElementById(_this5.getItemId(index));
};
this.setHighlightedIndex = function () {
var highlightedIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _this5.props.defaultHighlightedIndex;
_this5.internalSetState({ highlightedIndex: highlightedIndex }, function () {
var node = _this5.getItemNodeFromIndex(_this5.getState().highlightedIndex);
var rootNode = _this5._rootNode;
scrollIntoView(node, rootNode);
});
};
this.highlightIndex = function (index) {
_this5.openMenu(function () {
_this5.setHighlightedIndex(index);
});
};
this.moveHighlightedIndex = function (amount) {
if (_this5.getState().isOpen) {
_this5.changeHighlightedIndex(amount);
} else {
_this5.highlightIndex();
}
};
this.changeHighlightedIndex = function (moveAmount) {
var itemsLastIndex = _this5.getItemCount() - 1;
if (itemsLastIndex < 0) {
return;
}
var _getState2 = _this5.getState(),
highlightedIndex = _getState2.highlightedIndex;
var baseIndex = highlightedIndex;
if (baseIndex === null) {
baseIndex = moveAmount > 0 ? -1 : itemsLastIndex + 1;
}
var newIndex = baseIndex + moveAmount;
if (newIndex < 0) {
newIndex = itemsLastIndex;
} else if (newIndex > itemsLastIndex) {
newIndex = 0;
}
_this5.setHighlightedIndex(newIndex);
};
this.clearSelection = function () {
_this5.internalSetState({
selectedItem: null,
inputValue: '',
isOpen: false
}, function () {
var inputNode = _this5._rootNode.querySelector('#' + _this5.inputId);
inputNode && inputNode.focus && inputNode.focus();
});
};
this.selectItem = function (item) {
_this5.internalSetState({
isOpen: false,
highlightedIndex: null,
selectedItem: item,
inputValue: _this5.props.itemToString(item)
});
};
this.selectItemAtIndex = function (itemIndex) {
var item = _this5.items[itemIndex];
if (!item) {
return;
}
_this5.selectItem(item);
};
this.selectHighlightedItem = function () {
return _this5.selectItemAtIndex(_this5.getState().highlightedIndex);
};
this.rootRef = function (node) {
return _this5._rootNode = node;
};
this.getRootProps = function () {
var _babelHelpers$extends;
var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var _ref3$refKey = _ref3.refKey,
refKey = _ref3$refKey === undefined ? 'ref' : _ref3$refKey,
onClick = _ref3.onClick,
rest = objectWithoutProperties(_ref3, ['refKey', 'onClick']);
// this is used in the render to know whether the user has called getRootProps.
// It uses that to know whether to apply the props automatically
_this5.getRootProps.called = true;
_this5.getRootProps.refKey = refKey;
return _extends((_babelHelpers$extends = {}, defineProperty(_babelHelpers$extends, refKey, _this5.rootRef), defineProperty(_babelHelpers$extends, 'onClick', composeEventHandlers(onClick, _this5.root_handleClick)), _babelHelpers$extends), rest);
};
this.root_handleClick = function (event) {
event.preventDefault();
var itemParent = findParent(function (node) {
var index = _this5.getItemIndexFromId(node.getAttribute('id'));
return isNumber(index);
}, event.target, _this5._rootNode);
if (itemParent) {
_this5.selectItemAtIndex(_this5.getItemIndexFromId(itemParent.getAttribute('id')));
}
};
this.keyDownHandlers = {
ArrowDown: function ArrowDown(event) {
event.preventDefault();
var amount = event.shiftKey ? 5 : 1;
this.moveHighlightedIndex(amount);
},
ArrowUp: function ArrowUp(event) {
event.preventDefault();
var amount = event.shiftKey ? -5 : -1;
this.moveHighlightedIndex(amount);
},
Enter: function Enter(event) {
event.preventDefault();
if (this.getState().isOpen) {
this.selectHighlightedItem();
}
},
Escape: function Escape(event) {
event.preventDefault();
this.reset();
}
};
this.buttonKeyDownHandlers = _extends({}, this.keyDownHandlers, {
' ': function _(event) {
event.preventDefault();
this.toggleMenu();
}
});
this.getButtonProps = function () {
var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var onClick = _ref4.onClick,
onKeyDown = _ref4.onKeyDown,
rest = objectWithoutProperties(_ref4, ['onClick', 'onKeyDown']);
var _getState3 = _this5.getState(),
isOpen = _getState3.isOpen;
return _extends({
role: 'button',
'aria-label': isOpen ? 'close menu' : 'open menu',
'aria-expanded': isOpen,
'aria-haspopup': true,
onClick: composeEventHandlers(onClick, _this5.button_handleClick),
onKeyDown: composeEventHandlers(onKeyDown, _this5.button_handleKeyDown)
}, rest);
};
this.button_handleKeyDown = function (event) {
if (_this5.buttonKeyDownHandlers[event.key]) {
_this5.buttonKeyDownHandlers[event.key].call(_this5, event);
}
};
this.button_handleClick = function (event) {
event.preventDefault();
_this5.toggleMenu();
};
this.getLabelProps = function () {
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_this5.getLabelProps.called = true;
if (_this5.getInputProps.called && props.htmlFor && props.htmlFor !== _this5.inputId) {
throw new Error('downshift: You provided the htmlFor of "' + props.htmlFor + '" for your label, but the id of your input is "' + _this5.inputId + '". You must either remove the id from your input or set the htmlFor of the label equal to the input id.');
}
_this5.inputId = firstDefined(_this5.inputId, props.htmlFor, generateId('downshift-input'));
return _extends({}, props, {
htmlFor: _this5.inputId
});
};
this.getInputProps = function () {
var _babelHelpers$extends2;
var _ref5 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var onKeyDown = _ref5.onKeyDown,
onBlur = _ref5.onBlur,
onChange = _ref5.onChange,
onInput = _ref5.onInput,
rest = objectWithoutProperties(_ref5, ['onKeyDown', 'onBlur', 'onChange', 'onInput']);
_this5.getInputProps.called = true;
if (_this5.getLabelProps.called && rest.id && rest.id !== _this5.inputId) {
throw new Error('downshift: You provided the id of "' + rest.id + '" for your input, but the htmlFor of your label is "' + _this5.inputId + '". You must either remove the id from your input or set the htmlFor of the label equal to the input id.');
}
_this5.inputId = firstDefined(_this5.inputId, rest.id, generateId('downshift-input'));
var onChangeKey = 'onInput';
var _getState4 = _this5.getState(),
inputValue = _getState4.inputValue,
isOpen = _getState4.isOpen,
highlightedIndex = _getState4.highlightedIndex;
return _extends((_babelHelpers$extends2 = {
role: 'combobox',
'aria-autocomplete': 'list',
'aria-expanded': isOpen,
'aria-activedescendant': typeof highlightedIndex === 'number' && highlightedIndex >= 0 ? _this5.getItemId(highlightedIndex) : null,
autoComplete: 'off',
value: inputValue
}, defineProperty(_babelHelpers$extends2, onChangeKey, composeEventHandlers(onChange, onInput, _this5.input_handleChange)), defineProperty(_babelHelpers$extends2, 'onKeyDown', composeEventHandlers(onKeyDown, _this5.input_handleKeyDown)), defineProperty(_babelHelpers$extends2, 'onBlur', composeEventHandlers(onBlur, _this5.input_handleBlur)), _babelHelpers$extends2), rest, {
id: _this5.inputId
});
};
this.input_handleKeyDown = function (event) {
if (event.key && _this5.keyDownHandlers[event.key]) {
_this5.keyDownHandlers[event.key].call(_this5, event);
}
};
this.input_handleChange = function (event) {
_this5.internalSetState({ isOpen: true, inputValue: event.target.value });
};
this.input_handleBlur = function () {
if (!_this5.isMouseDown) {
_this5.reset();
}
};
this.getItemProps = function () {
var _ref6 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var onMouseEnter = _ref6.onMouseEnter,
_ref6$item = _ref6.item,
item = _ref6$item === undefined ? requiredProp('getItemProps', 'item') : _ref6$item,
_ref6$index = _ref6.index,
index = _ref6$index === undefined ? requiredProp('getItemProps', 'index') : _ref6$index,
rest = objectWithoutProperties(_ref6, ['onMouseEnter', 'item', 'index']);
_this5.items[index] = item;
return _extends({
id: _this5.getItemId(index),
onMouseEnter: composeEventHandlers(onMouseEnter, function () {
_this5.setHighlightedIndex(index);
})
}, rest);
};
this.reset = function (type) {
_this5.internalSetState(function (_ref7) {
var selectedItem = _ref7.selectedItem;
return {
type: type,
isOpen: false,
highlightedIndex: null,
inputValue: _this5.props.itemToString(selectedItem)
};
});
};
this.toggleMenu = function (newState, cb) {
_this5.internalSetState(function (_ref8) {
var isOpen = _ref8.isOpen;
var nextIsOpen = !isOpen;
if (typeof newState === 'boolean') {
nextIsOpen = newState;
}
return { isOpen: nextIsOpen };
}, function () {
var _getState5 = _this5.getState(),
isOpen = _getState5.isOpen;
if (isOpen) {
_this5.setHighlightedIndex();
}
cbToCb(cb)();
});
};
this.openMenu = function (cb) {
_this5.toggleMenu(true, cb);
};
this.closeMenu = function (cb) {
_this5.toggleMenu(false, cb);
};
this.updateStatus = debounce(function () {
if (!_this5._isMounted) {
return;
}
var state = _this5.getState();
var item = _this5.items[state.highlightedIndex] || {};
var resultCount = _this5.getItemCount();
var status = _this5.props.getA11yStatusMessage(_extends({
itemToString: _this5.props.itemToString,
previousResultCount: _this5.previousResultCount,
resultCount: resultCount,
highlightedItem: item
}, state));
_this5.previousResultCount = resultCount;
setStatus(status);
}, 200);
};
function validateGetRootPropsCalledCorrectly(element, _ref2) {
var refKey = _ref2.refKey;
var refKeySpecified = refKey !== 'ref';
var isComposite = !isDOMElement(element);
if (isComposite && !refKeySpecified) {
throw new Error('downshift: You returned a non-DOM element. You must specify a refKey in getRootProps');
} else if (!isComposite && refKeySpecified) {
throw new Error('downshift: You returned a DOM element. You should not specify a refKey in getRootProps. You specified "' + refKey + '"');
}
if (!getElementProps(element).hasOwnProperty(refKey)) {
throw new Error('downshift: You must apply the ref prop "' + refKey + '" from getRootProps onto your root element.');
}
if (!getElementProps(element).hasOwnProperty('onClick')) {
throw new Error('downshift: You must apply the "onClick" prop from getRootProps onto your root element.');
}
}
/*
* Fix importing in typescript after rollup compilation
* https://github.com/rollup/rollup/issues/1156
* https://github.com/Microsoft/TypeScript/issues/13017#issuecomment-268657860
*/
Downshift$1.default = Downshift$1;
module.exports = Downshift$1;