var _excluded = ["props", "refresh", "store"], _excluded2 = ["inputElement", "formElement", "panelElement"], _excluded3 = ["inputElement"], _excluded4 = ["inputElement", "maxLength"], _excluded5 = ["item", "source"]; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(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; } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } import { onInput } from './onInput'; import { onKeyDown as _onKeyDown } from './onKeyDown'; import { getActiveItem, isOrContainsNode } from './utils'; export function getPropGetters(_ref) { var props = _ref.props, refresh = _ref.refresh, store = _ref.store, setters = _objectWithoutProperties(_ref, _excluded); var getEnvironmentProps = function getEnvironmentProps(providedProps) { var inputElement = providedProps.inputElement, formElement = providedProps.formElement, panelElement = providedProps.panelElement, rest = _objectWithoutProperties(providedProps, _excluded2); return _objectSpread({ // On touch devices, we do not rely on the native `blur` event of the // input to close the panel, but rather on a custom `touchstart` event // outside of the autocomplete elements. // This ensures a working experience on mobile because we blur the input // on touch devices when the user starts scrolling (`touchmove`). // @TODO: support cases where there are multiple Autocomplete instances. // Right now, a second instance makes this computation return false. onTouchStart: function onTouchStart(event) { // The `onTouchStart` event shouldn't trigger the `blur` handler when // it's not an interaction with Autocomplete. We detect it with the // following heuristics: // - the panel is closed AND there are no pending requests // (no interaction with the autocomplete, no future state updates) // - OR the touched target is the input element (should open the panel) var isAutocompleteInteraction = store.getState().isOpen || !store.pendingRequests.isEmpty(); if (!isAutocompleteInteraction || event.target === inputElement) { return; } var isTargetWithinAutocomplete = [formElement, panelElement].some(function (contextNode) { return isOrContainsNode(contextNode, event.target); }); if (isTargetWithinAutocomplete === false) { store.dispatch('blur', null); // If requests are still pending when the user closes the panel, they // could reopen the panel once they resolve. // We want to prevent any subsequent query from reopening the panel // because it would result in an unsolicited UI behavior. if (!props.debug) { store.pendingRequests.cancelAll(); } } }, // When scrolling on touch devices (mobiles, tablets, etc.), we want to // mimic the native platform behavior where the input is blurred to // hide the virtual keyboard. This gives more vertical space to // discover all the suggestions showing up in the panel. onTouchMove: function onTouchMove(event) { if (store.getState().isOpen === false || inputElement !== props.environment.document.activeElement || event.target === inputElement) { return; } inputElement.blur(); } }, rest); }; var getRootProps = function getRootProps(rest) { return _objectSpread({ role: 'combobox', 'aria-expanded': store.getState().isOpen, 'aria-haspopup': 'listbox', 'aria-owns': store.getState().isOpen ? "".concat(props.id, "-list") : undefined, 'aria-labelledby': "".concat(props.id, "-label") }, rest); }; var getFormProps = function getFormProps(providedProps) { var inputElement = providedProps.inputElement, rest = _objectWithoutProperties(providedProps, _excluded3); return _objectSpread({ action: '', noValidate: true, role: 'search', onSubmit: function onSubmit(event) { var _providedProps$inputE; event.preventDefault(); props.onSubmit(_objectSpread({ event: event, refresh: refresh, state: store.getState() }, setters)); store.dispatch('submit', null); (_providedProps$inputE = providedProps.inputElement) === null || _providedProps$inputE === void 0 ? void 0 : _providedProps$inputE.blur(); }, onReset: function onReset(event) { var _providedProps$inputE2; event.preventDefault(); props.onReset(_objectSpread({ event: event, refresh: refresh, state: store.getState() }, setters)); store.dispatch('reset', null); (_providedProps$inputE2 = providedProps.inputElement) === null || _providedProps$inputE2 === void 0 ? void 0 : _providedProps$inputE2.focus(); } }, rest); }; var getInputProps = function getInputProps(providedProps) { function onFocus(event) { // We want to trigger a query when `openOnFocus` is true // because the panel should open with the current query. if (props.openOnFocus || Boolean(store.getState().query)) { onInput(_objectSpread({ event: event, props: props, query: store.getState().completion || store.getState().query, refresh: refresh, store: store }, setters)); } store.dispatch('focus', null); } var isTouchDevice = ('ontouchstart' in props.environment); var _ref2 = providedProps || {}, inputElement = _ref2.inputElement, _ref2$maxLength = _ref2.maxLength, maxLength = _ref2$maxLength === void 0 ? 512 : _ref2$maxLength, rest = _objectWithoutProperties(_ref2, _excluded4); var activeItem = getActiveItem(store.getState()); return _objectSpread({ 'aria-autocomplete': 'both', 'aria-activedescendant': store.getState().isOpen && store.getState().activeItemId !== null ? "".concat(props.id, "-item-").concat(store.getState().activeItemId) : undefined, 'aria-controls': store.getState().isOpen ? "".concat(props.id, "-list") : undefined, 'aria-labelledby': "".concat(props.id, "-label"), value: store.getState().completion || store.getState().query, id: "".concat(props.id, "-input"), autoComplete: 'off', autoCorrect: 'off', autoCapitalize: 'off', enterKeyHint: activeItem !== null && activeItem !== void 0 && activeItem.itemUrl ? 'go' : 'search', spellCheck: 'false', autoFocus: props.autoFocus, placeholder: props.placeholder, maxLength: maxLength, type: 'search', onChange: function onChange(event) { onInput(_objectSpread({ event: event, props: props, query: event.currentTarget.value.slice(0, maxLength), refresh: refresh, store: store }, setters)); }, onKeyDown: function onKeyDown(event) { _onKeyDown(_objectSpread({ event: event, props: props, refresh: refresh, store: store }, setters)); }, onFocus: onFocus, onBlur: function onBlur() { // We do rely on the `blur` event on touch devices. // See explanation in `onTouchStart`. if (!isTouchDevice) { store.dispatch('blur', null); // If requests are still pending when the user closes the panel, they // could reopen the panel once they resolve. // We want to prevent any subsequent query from reopening the panel // because it would result in an unsolicited UI behavior. if (!props.debug) { store.pendingRequests.cancelAll(); } } }, onClick: function onClick(event) { // When the panel is closed and you click on the input while // the input is focused, the `onFocus` event is not triggered // (default browser behavior). // In an autocomplete context, it makes sense to open the panel in this // case. // We mimic this event by catching the `onClick` event which // triggers the `onFocus` for the panel to open. if (providedProps.inputElement === props.environment.document.activeElement && !store.getState().isOpen) { onFocus(event); } } }, rest); }; var getLabelProps = function getLabelProps(rest) { return _objectSpread({ htmlFor: "".concat(props.id, "-input"), id: "".concat(props.id, "-label") }, rest); }; var getListProps = function getListProps(rest) { return _objectSpread({ role: 'listbox', 'aria-labelledby': "".concat(props.id, "-label"), id: "".concat(props.id, "-list") }, rest); }; var getPanelProps = function getPanelProps(rest) { return _objectSpread({ onMouseDown: function onMouseDown(event) { // Prevents the `activeElement` from being changed to the panel so // that the blur event is not triggered, otherwise it closes the // panel. event.preventDefault(); }, onMouseLeave: function onMouseLeave() { store.dispatch('mouseleave', null); } }, rest); }; var getItemProps = function getItemProps(providedProps) { var item = providedProps.item, source = providedProps.source, rest = _objectWithoutProperties(providedProps, _excluded5); return _objectSpread({ id: "".concat(props.id, "-item-").concat(item.__autocomplete_id), role: 'option', 'aria-selected': store.getState().activeItemId === item.__autocomplete_id, onMouseMove: function onMouseMove(event) { if (item.__autocomplete_id === store.getState().activeItemId) { return; } store.dispatch('mousemove', item.__autocomplete_id); var activeItem = getActiveItem(store.getState()); if (store.getState().activeItemId !== null && activeItem) { var _item = activeItem.item, itemInputValue = activeItem.itemInputValue, itemUrl = activeItem.itemUrl, _source = activeItem.source; _source.onActive(_objectSpread({ event: event, item: _item, itemInputValue: itemInputValue, itemUrl: itemUrl, refresh: refresh, source: _source, state: store.getState() }, setters)); } }, onMouseDown: function onMouseDown(event) { // Prevents the `activeElement` from being changed to the item so it // can remain with the current `activeElement`. event.preventDefault(); }, onClick: function onClick(event) { var itemInputValue = source.getItemInputValue({ item: item, state: store.getState() }); var itemUrl = source.getItemUrl({ item: item, state: store.getState() }); // If `getItemUrl` is provided, it means that the suggestion // is a link, not plain text that aims at updating the query. // We can therefore skip the state change because it will update // the `activeItemId`, resulting in a UI flash, especially // noticeable on mobile. var runPreCommand = itemUrl ? Promise.resolve() : onInput(_objectSpread({ event: event, nextState: { isOpen: false }, props: props, query: itemInputValue, refresh: refresh, store: store }, setters)); runPreCommand.then(function () { source.onSelect(_objectSpread({ event: event, item: item, itemInputValue: itemInputValue, itemUrl: itemUrl, refresh: refresh, source: source, state: store.getState() }, setters)); }); } }, rest); }; return { getEnvironmentProps: getEnvironmentProps, getRootProps: getRootProps, getFormProps: getFormProps, getLabelProps: getLabelProps, getInputProps: getInputProps, getPanelProps: getPanelProps, getListProps: getListProps, getItemProps: getItemProps }; }