instantsearch-ui-components
Version:
Common UI components for InstantSearch.
248 lines (247 loc) • 8.67 kB
JavaScript
import _typeof from "@babel/runtime/helpers/typeof";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
export function createAutocompletePropGetters(_ref) {
var useEffect = _ref.useEffect,
useId = _ref.useId,
useMemo = _ref.useMemo,
useRef = _ref.useRef,
useState = _ref.useState;
return function usePropGetters(_ref2) {
var indices = _ref2.indices,
indicesConfig = _ref2.indicesConfig,
onRefine = _ref2.onRefine,
globalOnSelect = _ref2.onSelect,
_onApply = _ref2.onApply,
placeholder = _ref2.placeholder;
var getElementId = createGetElementId(useId());
var inputRef = useRef(null);
var rootRef = useRef(null);
var _useState = useState(false),
_useState2 = _slicedToArray(_useState, 2),
isOpen = _useState2[0],
setIsOpen = _useState2[1];
var _useState3 = useState(undefined),
_useState4 = _slicedToArray(_useState3, 2),
activeDescendant = _useState4[0],
setActiveDescendant = _useState4[1];
var _useMemo = useMemo(function () {
return buildItems({
indices: indices,
indicesConfig: indicesConfig,
getElementId: getElementId
});
}, [indices, indicesConfig, getElementId]),
items = _useMemo.items,
itemsIds = _useMemo.itemsIds;
useEffect(function () {
var onBodyClick = function onBodyClick(event) {
var _unwrapRef;
if ((_unwrapRef = unwrapRef(rootRef)) !== null && _unwrapRef !== void 0 && _unwrapRef.contains(event.target)) {
return;
}
setIsOpen(false);
};
document.body.addEventListener('click', onBodyClick);
return function () {
document.body.removeEventListener('click', onBodyClick);
};
}, [rootRef]);
var getNextActiveDescendant = function getNextActiveDescendant(key) {
switch (key) {
case 'ArrowLeft':
case 'ArrowUp':
{
var prevIndex = itemsIds.indexOf(activeDescendant || '') - 1;
return itemsIds[prevIndex] || itemsIds[itemsIds.length - 1];
}
case 'ArrowRight':
case 'ArrowDown':
{
var nextIndex = itemsIds.indexOf(activeDescendant || '') + 1;
return itemsIds[nextIndex] || itemsIds[0];
}
default:
return undefined;
}
};
var submit = function submit() {
var _override$activeDesce;
var override = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
if (isOpen) {
setIsOpen(false);
} else {
var _inputRef$current;
(_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.blur();
}
var actualDescendant = (_override$activeDesce = override.activeDescendant) !== null && _override$activeDesce !== void 0 ? _override$activeDesce : activeDescendant;
if (!actualDescendant && override.query) {
onRefine(override.query);
}
if (actualDescendant && items.has(actualDescendant)) {
var _getQuery;
var _ref3 = items.get(actualDescendant),
_item = _ref3.item,
_ref3$config = _ref3.config,
indexOnSelect = _ref3$config.onSelect,
getQuery = _ref3$config.getQuery,
getURL = _ref3$config.getURL;
var actualOnSelect = indexOnSelect !== null && indexOnSelect !== void 0 ? indexOnSelect : globalOnSelect;
actualOnSelect({
item: _item,
query: (_getQuery = getQuery === null || getQuery === void 0 ? void 0 : getQuery(_item)) !== null && _getQuery !== void 0 ? _getQuery : '',
url: getURL === null || getURL === void 0 ? void 0 : getURL(_item),
setQuery: function setQuery(query) {
return onRefine(query);
}
});
setActiveDescendant(undefined);
}
};
return {
getInputProps: function getInputProps() {
return {
id: getElementId('input'),
ref: inputRef,
role: 'combobox',
'aria-autocomplete': 'list',
'aria-expanded': isOpen,
'aria-haspopup': 'grid',
'aria-controls': getElementId('panel'),
'aria-activedescendant': activeDescendant,
placeholder: placeholder,
onFocus: function onFocus() {
return setIsOpen(true);
},
onKeyDown: function onKeyDown(event) {
switch (event.key) {
case 'Escape':
{
if (isOpen) {
setIsOpen(false);
event.preventDefault();
} else {
setActiveDescendant(undefined);
}
break;
}
case 'ArrowLeft':
case 'ArrowUp':
case 'ArrowRight':
case 'ArrowDown':
{
var _document$getElementB;
setIsOpen(true);
var nextActiveDescendant = getNextActiveDescendant(event.key);
setActiveDescendant(nextActiveDescendant);
(_document$getElementB = document.getElementById(nextActiveDescendant)) === null || _document$getElementB === void 0 ? void 0 : _document$getElementB.scrollIntoView(false);
event.preventDefault();
break;
}
case 'Enter':
{
submit({
query: event.target.value
});
break;
}
case 'Tab':
setIsOpen(false);
break;
default:
setIsOpen(true);
return;
}
},
onKeyUp: function onKeyUp(event) {
switch (event.key) {
case 'ArrowLeft':
case 'ArrowUp':
case 'ArrowRight':
case 'ArrowDown':
case 'Escape':
case 'Return':
event.preventDefault();
return;
default:
setActiveDescendant(undefined);
break;
}
}
};
},
getItemProps: function getItemProps(item, index) {
var id = getElementId('item', item.__indexName, index);
return {
id: id,
role: 'row',
'aria-selected': id === activeDescendant,
onSelect: function onSelect() {
return submit({
activeDescendant: id
});
},
onApply: function onApply() {
var _getQuery2;
var _ref4 = items.get(id),
currentItem = _ref4.item,
getQuery = _ref4.config.getQuery;
_onApply((_getQuery2 = getQuery === null || getQuery === void 0 ? void 0 : getQuery(currentItem)) !== null && _getQuery2 !== void 0 ? _getQuery2 : '');
}
};
},
getPanelProps: function getPanelProps() {
return {
hidden: !isOpen,
id: getElementId('panel'),
role: 'grid',
'aria-labelledby': getElementId('input')
};
},
getRootProps: function getRootProps() {
return {
ref: rootRef
};
}
};
};
}
function buildItems(_ref5) {
var indices = _ref5.indices,
indicesConfig = _ref5.indicesConfig,
getElementId = _ref5.getElementId;
var itemsIds = [];
var items = new Map();
for (var i = 0; i < indicesConfig.length; i++) {
var _indices$i;
var config = indicesConfig[i];
var hits = ((_indices$i = indices[i]) === null || _indices$i === void 0 ? void 0 : _indices$i.hits) || [];
for (var position = 0; position < hits.length; position++) {
var itemId = getElementId('item', config.indexName, position);
items.set(itemId, {
item: hits[position],
config: config
});
itemsIds.push(itemId);
}
}
return {
items: items,
itemsIds: itemsIds
};
}
function createGetElementId(autocompleteId) {
return function getElementId() {
var prefix = 'autocomplete';
for (var _len = arguments.length, suffixes = new Array(_len), _key = 0; _key < _len; _key++) {
suffixes[_key] = arguments[_key];
}
return "".concat(prefix).concat(autocompleteId).concat(suffixes.join(':'));
};
}
/**
* Returns the framework-agnostic value of a ref.
*/
function unwrapRef(ref) {
return ref.current && _typeof(ref.current) === 'object' && 'base' in ref.current ? ref.current.base // Preact
: ref.current; // React
}