UNPKG

react-awesome-query-builder

Version:

User-friendly query builder for React. Please migrate to new @react-awesome-query-builder/* See https://github.com/ukrbublik/react-awesome-query-builder#migration-to-600

456 lines (445 loc) 18.7 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _react = _interopRequireDefault(require("react")); var _debounce = _interopRequireDefault(require("lodash/debounce")); var _stuff = require("../utils/stuff"); var _autocomplete = require("../utils/autocomplete"); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); 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 = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } var useListValuesAutocomplete = function useListValuesAutocomplete(_ref, _ref2) { var asyncFetch = _ref.asyncFetch, useLoadMore = _ref.useLoadMore, useAsyncSearch = _ref.useAsyncSearch, forceAsyncSearch = _ref.forceAsyncSearch, selectedAsyncListValues = _ref.asyncListValues, staticListValues = _ref.listValues, allowCustomValues = _ref.allowCustomValues, selectedValue = _ref.value, setValue = _ref.setValue, placeholder = _ref.placeholder; var debounceTimeout = _ref2.debounceTimeout, multiple = _ref2.multiple; var knownSpecialValues = ["LOAD_MORE", "LOADING_MORE"]; var loadMoreTitle = "Load more..."; var loadingMoreTitle = "Loading more..."; var aPlaceholder = forceAsyncSearch ? "Type to search" : placeholder; // state var _React$useState = _react["default"].useState(false), _React$useState2 = (0, _slicedToArray2["default"])(_React$useState, 2), open = _React$useState2[0], setOpen = _React$useState2[1]; var _React$useState3 = _react["default"].useState(undefined), _React$useState4 = (0, _slicedToArray2["default"])(_React$useState3, 2), asyncFetchMeta = _React$useState4[0], setAsyncFetchMeta = _React$useState4[1]; var _React$useState5 = _react["default"].useState(0), _React$useState6 = (0, _slicedToArray2["default"])(_React$useState5, 2), loadingCnt = _React$useState6[0], setLoadingCnt = _React$useState6[1]; var _React$useState7 = _react["default"].useState(false), _React$useState8 = (0, _slicedToArray2["default"])(_React$useState7, 2), isLoadingMore = _React$useState8[0], setIsLoadingMore = _React$useState8[1]; var _React$useState9 = _react["default"].useState(""), _React$useState10 = (0, _slicedToArray2["default"])(_React$useState9, 2), inputValue = _React$useState10[0], setInputValue = _React$useState10[1]; var _React$useState11 = _react["default"].useState(undefined), _React$useState12 = (0, _slicedToArray2["default"])(_React$useState11, 2), asyncListValues = _React$useState12[0], setAsyncListValues = _React$useState12[1]; // ref var asyncFectchCnt = _react["default"].useRef(0); var componentIsMounted = _react["default"].useRef(true); var isSelectedLoadMore = _react["default"].useRef(false); // compute var nSelectedAsyncListValues = (0, _stuff.listValuesToArray)(selectedAsyncListValues); var listValues = asyncFetch ? !allowCustomValues ? (0, _autocomplete.mergeListValues)(asyncListValues, nSelectedAsyncListValues, true) : asyncListValues : staticListValues; //const isDirtyInitialListValues = asyncListValues == undefined && selectedAsyncListValues && selectedAsyncListValues.length && typeof selectedAsyncListValues[0] != "object"; var isLoading = loadingCnt > 0; var canInitialLoad = open && asyncFetch && asyncListValues === undefined && (forceAsyncSearch ? inputValue : true); var isInitialLoading = canInitialLoad && isLoading; var canLoadMore = !isInitialLoading && listValues && listValues.length > 0 && asyncFetchMeta && asyncFetchMeta.hasMore && (asyncFetchMeta.filter || "") === inputValue; var canShowLoadMore = !isLoading && canLoadMore; var options = (0, _stuff.mapListValues)(listValues, _autocomplete.listValueToOption); var hasValue = selectedValue != null; // const selectedListValue = hasValue ? getListValue(selectedValue, listValues) : null; // const selectedOption = listValueToOption(selectedListValue); // fetch var fetchListValues = /*#__PURE__*/function () { var _ref3 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee() { var filter, isLoadMore, offset, meta, newAsyncFetchCnt, res, isFetchCancelled, _ref4, values, hasMore, newMeta, nValues, assumeHasMore, newValues, realNewMeta, _args = arguments; return _regenerator["default"].wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: filter = _args.length > 0 && _args[0] !== undefined ? _args[0] : null; isLoadMore = _args.length > 1 && _args[1] !== undefined ? _args[1] : false; // clear obsolete meta if (!isLoadMore && asyncFetchMeta) { setAsyncFetchMeta(undefined); } offset = isLoadMore && asyncListValues ? asyncListValues.length : 0; meta = isLoadMore && asyncFetchMeta || !useLoadMore && { pageSize: 0 }; newAsyncFetchCnt = ++asyncFectchCnt.current; _context.next = 8; return asyncFetch(filter, offset, meta); case 8: res = _context.sent; isFetchCancelled = asyncFectchCnt.current != newAsyncFetchCnt; if (!(isFetchCancelled || !componentIsMounted.current)) { _context.next = 12; break; } return _context.abrupt("return", null); case 12: _ref4 = res && res.values ? res : { values: res }, values = _ref4.values, hasMore = _ref4.hasMore, newMeta = _ref4.meta; nValues = (0, _stuff.listValuesToArray)(values); if (isLoadMore) { newValues = (0, _autocomplete.mergeListValues)(asyncListValues, nValues, false); assumeHasMore = newValues.length > asyncListValues.length; } else { newValues = nValues; if (useLoadMore) { assumeHasMore = newValues.length > 0; } } // save new meta realNewMeta = hasMore != null || newMeta != null || assumeHasMore != null ? _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, assumeHasMore != null ? { hasMore: assumeHasMore } : {}), hasMore != null ? { hasMore: hasMore } : {}), newMeta != null ? newMeta : {}), {}, { filter: filter }) : undefined; if (realNewMeta) { setAsyncFetchMeta(realNewMeta); } return _context.abrupt("return", newValues); case 18: case "end": return _context.stop(); } }, _callee); })); return function fetchListValues() { return _ref3.apply(this, arguments); }; }(); var loadListValues = /*#__PURE__*/function () { var _ref5 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2() { var filter, isLoadMore, list, _args2 = arguments; return _regenerator["default"].wrap(function _callee2$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: filter = _args2.length > 0 && _args2[0] !== undefined ? _args2[0] : null; isLoadMore = _args2.length > 1 && _args2[1] !== undefined ? _args2[1] : false; setLoadingCnt(function (x) { return x + 1; }); setIsLoadingMore(isLoadMore); _context2.next = 6; return fetchListValues(filter, isLoadMore); case 6: list = _context2.sent; if (componentIsMounted.current) { _context2.next = 9; break; } return _context2.abrupt("return"); case 9: if (list != null) { // tip: null can be used for reject (eg, if user don't want to filter by input) setAsyncListValues(list); } setLoadingCnt(function (x) { return x - 1; }); setIsLoadingMore(false); case 12: case "end": return _context2.stop(); } }, _callee2); })); return function loadListValues() { return _ref5.apply(this, arguments); }; }(); var loadListValuesDebounced = _react["default"].useCallback((0, _debounce["default"])(loadListValues, debounceTimeout), []); // Unmount _react["default"].useEffect(function () { return function () { componentIsMounted.current = false; }; }, []); // Initial loading _react["default"].useEffect(function () { if (canInitialLoad && loadingCnt == 0 && asyncFectchCnt.current == 0) { (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3() { return _regenerator["default"].wrap(function _callee3$(_context3) { while (1) switch (_context3.prev = _context3.next) { case 0: _context3.next = 2; return loadListValues(); case 2: case "end": return _context3.stop(); } }, _callee3); }))(); } }, [canInitialLoad]); // Event handlers var onOpen = function onOpen() { setOpen(true); }; var onClose = function onClose(_e) { if (isSelectedLoadMore.current) { isSelectedLoadMore.current = false; if (multiple) { setOpen(false); } } else { setOpen(false); } }; var onDropdownVisibleChange = function onDropdownVisibleChange(open) { if (open) { onOpen(); } else { onClose(); } }; var isSpecialValue = function isSpecialValue(option) { var specialValue = (option === null || option === void 0 ? void 0 : option.specialValue) || (option === null || option === void 0 ? void 0 : option.value); return knownSpecialValues.includes(specialValue); }; var onChange = /*#__PURE__*/function () { var _ref7 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee4(_e, option) { var specialValue, _options, newSelectedListValues, newSelectedValues, v; return _regenerator["default"].wrap(function _callee4$(_context4) { while (1) switch (_context4.prev = _context4.next) { case 0: specialValue = (option === null || option === void 0 ? void 0 : option.specialValue) || (option === null || option === void 0 ? void 0 : option.value) || multiple && option.map(function (opt) { return (opt === null || opt === void 0 ? void 0 : opt.specialValue) || (opt === null || opt === void 0 ? void 0 : opt.value); }).find(function (v) { return !!v; }); if (!(specialValue == "LOAD_MORE")) { _context4.next = 7; break; } isSelectedLoadMore.current = true; _context4.next = 5; return loadListValues(inputValue, true); case 5: _context4.next = 8; break; case 7: if (specialValue == "LOADING_MORE") { isSelectedLoadMore.current = true; } else { if (multiple) { _options = option; newSelectedListValues = _options.map(function (o, i) { var item = o.value != null ? o : (0, _autocomplete.getListValue)(o, listValues); // AntDesign puts array of labels in `_e` (`option` is array of objects, but custom option is always `{}`) // MUI puts array of labels in `option` var customItem = allowCustomValues && !item ? Array.isArray(_e) ? _e[i] : o : null; return item || customItem; }); newSelectedValues = newSelectedListValues.filter(function (o) { return o !== undefined; }).map(function (o) { return o.value !== undefined ? o.value : o; }); if (!newSelectedValues.length) newSelectedValues = undefined; //not allow [] setValue(newSelectedValues, newSelectedListValues); } else { v = option == null ? undefined : option.value; setValue(v, [option]); } } case 8: case "end": return _context4.stop(); } }, _callee4); })); return function onChange(_x, _x2) { return _ref7.apply(this, arguments); }; }(); var onInputChange = /*#__PURE__*/function () { var _ref8 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee5(_e, newInputValue) { var val, canSearchAsync; return _regenerator["default"].wrap(function _callee5$(_context5) { while (1) switch (_context5.prev = _context5.next) { case 0: val = newInputValue; //const isTypeToSearch = e.type == 'change'; if (!(val === loadMoreTitle || val === loadingMoreTitle)) { _context5.next = 3; break; } return _context5.abrupt("return"); case 3: setInputValue(val); if (allowCustomValues) { if (multiple) { //todo } else { setValue(val, [val]); } } canSearchAsync = useAsyncSearch && (forceAsyncSearch ? !!val : true); if (!canSearchAsync) { _context5.next = 11; break; } _context5.next = 9; return loadListValuesDebounced(val); case 9: _context5.next = 12; break; case 11: if (useAsyncSearch && forceAsyncSearch) { setAsyncListValues([]); } case 12: case "end": return _context5.stop(); } }, _callee5); })); return function onInputChange(_x3, _x4) { return _ref8.apply(this, arguments); }; }(); // to keep compatibility with antD var onSearch = /*#__PURE__*/function () { var _ref9 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee6(newInputValue) { return _regenerator["default"].wrap(function _callee6$(_context6) { while (1) switch (_context6.prev = _context6.next) { case 0: if (!(newInputValue === "" && !open)) { _context6.next = 2; break; } return _context6.abrupt("return"); case 2: _context6.next = 4; return onInputChange(null, newInputValue); case 4: case "end": return _context6.stop(); } }, _callee6); })); return function onSearch(_x5) { return _ref9.apply(this, arguments); }; }(); // Options var extendOptions = function extendOptions(options) { var filtered = (0, _toConsumableArray2["default"])(options); if (useLoadMore) { if (canShowLoadMore) { filtered.push({ specialValue: "LOAD_MORE", title: loadMoreTitle }); } else if (isLoadingMore) { filtered.push({ specialValue: "LOADING_MORE", title: loadingMoreTitle, disabled: true }); } } return filtered; }; var getOptionSelected = function getOptionSelected(option, valueOrOption) { if (valueOrOption == null) return null; var selectedValue = valueOrOption.value != undefined ? valueOrOption.value : valueOrOption; return option.value === selectedValue; }; var getOptionDisabled = function getOptionDisabled(valueOrOption) { return valueOrOption && valueOrOption.disabled; }; var getOptionLabel = function getOptionLabel(valueOrOption) { if (valueOrOption == null) return null; var option = valueOrOption.value != undefined ? valueOrOption : (0, _autocomplete.listValueToOption)((0, _autocomplete.getListValue)(valueOrOption, listValues)); if (!option && valueOrOption.specialValue) { // special last 'Load more...' item return valueOrOption.title; } if (!option && allowCustomValues) { // there is just string value, it's not item from list return valueOrOption; } if (!option) { // weird return valueOrOption; } return option.title; }; return { options: options, listValues: listValues, hasValue: hasValue, open: open, onOpen: onOpen, onClose: onClose, onDropdownVisibleChange: onDropdownVisibleChange, onChange: onChange, inputValue: inputValue, onInputChange: onInputChange, onSearch: onSearch, canShowLoadMore: canShowLoadMore, isInitialLoading: isInitialLoading, isLoading: isLoading, isLoadingMore: isLoadingMore, isSpecialValue: isSpecialValue, extendOptions: extendOptions, getOptionSelected: getOptionSelected, getOptionDisabled: getOptionDisabled, getOptionLabel: getOptionLabel, // unused //selectedListValue, //selectedOption, aPlaceholder: aPlaceholder }; }; var _default = useListValuesAutocomplete; exports["default"] = _default;