rui-react
Version:
React UI library
135 lines (134 loc) • 5.68 kB
JavaScript
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import Input from "../Input/input";
import React, { useEffect, useRef, useState, } from "react";
import { scopedClass } from "../../helpers/utils";
import classNames from "classnames";
import useDebounce from "../../hooks/useDebounce";
import useClickOutside from "../../hooks/useClickOutside";
import { OptionList } from "./optionList";
var AutoComplete = function (props) {
var _a;
var fetchSuggestion = props.fetchSuggestion, onSelect = props.onSelect, delay = props.delay, size = props.size, restProps = __rest(props, ["fetchSuggestion", "onSelect", "delay", "size"]);
var _b = useState([]), suggestions = _b[0], setSuggestions = _b[1];
var _c = useState(false), optionListVisible = _c[0], setOptionListVisible = _c[1];
var _d = useState(""), value = _d[0], setValue = _d[1];
var debouncedValue = useDebounce(value, delay);
var triggerSuggestions = useRef(false);
var _e = useState(false), isLoading = _e[0], setIsLoading = _e[1];
var _f = useState(-1), candidateIndex = _f[0], setCandidateIndex = _f[1];
var optionListRef = useRef(null);
var inputWrapperRef = useRef(null);
var componentRef = useRef(null);
var clearSuggestions = function () { return setSuggestions([]); };
useEffect(function () {
if (!triggerSuggestions.current)
return;
var results = fetchSuggestion(debouncedValue);
if (results instanceof Promise) {
setIsLoading(true);
results
.then(function (data) {
if (data.length) {
setSuggestions(data);
}
else {
setOptionListVisible(false);
}
setIsLoading(false);
})
.catch(function (error) {
setIsLoading(false);
setOptionListVisible(false);
});
}
else {
if (results.length) {
setSuggestions(results);
}
else {
setOptionListVisible(false);
}
}
}, [debouncedValue, fetchSuggestion]);
useClickOutside(componentRef, function () { return setOptionListVisible(false); });
var handleChange = function (e) {
setValue(e.target.value);
setOptionListVisible(true);
triggerSuggestions.current = true;
};
var handleSelect = function (selectedValue) {
setValue(selectedValue);
if (onSelect)
onSelect(selectedValue);
setOptionListVisible(false);
triggerSuggestions.current = false;
};
var handleKeyDown = function (e) {
if (optionListRef.current === null || inputWrapperRef.current === null)
return;
var listHeight = optionListRef.current.clientHeight;
var itemHeight = inputWrapperRef.current.clientHeight;
switch (e.key) {
case "ArrowUp":
e.preventDefault();
if (candidateIndex < 0)
return;
if ((candidateIndex + 1) * itemHeight > listHeight)
optionListRef.current.scrollTop -= itemHeight;
setCandidateIndex(function (index) { return index - 1; });
break;
case "ArrowDown":
e.preventDefault();
if (candidateIndex >= suggestions.length - 1)
return;
if ((candidateIndex + 2) * itemHeight > listHeight)
optionListRef.current.scrollTop += itemHeight;
setCandidateIndex(function (index) { return index + 1; });
break;
case "Enter":
if (candidateIndex < 0)
return;
handleSelect(suggestions[candidateIndex]);
setCandidateIndex(-1);
break;
case "Escape":
setOptionListVisible(false);
setCandidateIndex(-1);
break;
default:
break;
}
};
var sc = scopedClass("autoComplete");
var classes_list = classNames(sc("list"), (_a = {},
_a[sc("list", size)] = size,
_a));
return (React.createElement("div", { ref: componentRef, className: sc("wrapper") },
React.createElement(Input, __assign({}, restProps, { size: size, value: value, onChange: handleChange, onKeyDown: handleKeyDown, ref: inputWrapperRef })),
React.createElement(OptionList, { visible: optionListVisible, clearSuggestions: clearSuggestions, isLoading: isLoading, className: classes_list, suggestions: suggestions, candidateIndex: candidateIndex, handleSelect: handleSelect, ref: optionListRef })));
};
AutoComplete.defaultProps = {
delay: 300,
};
export default AutoComplete;