@react-awesome-query-builder/antd
Version:
User-friendly query builder for React. AntDesign widgets
359 lines (353 loc) • 16.8 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _react = _interopRequireWildcard(require("react"));
var _antd = require("antd");
var _domUtils = require("../../utils/domUtils");
var _ui = require("@react-awesome-query-builder/ui");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
var fixListValuesGroupOrder = _ui.Utils.Autocomplete.fixListValuesGroupOrder;
var makeCustomListValue = _ui.Utils.ListUtils.makeCustomListValue;
var useListValuesAutocomplete = _ui.Hooks.useListValuesAutocomplete;
// see type ListItem
var mapListItemToOptionKeys = {
value: "value",
title: "label",
groupTitle: "grouplabel"
};
var _default = exports["default"] = function _default(props) {
var _config$settings$load, _config$settings$notF;
var config = props.config,
placeholder = props.placeholder,
allowCustomValues = props.allowCustomValues,
customProps = props.customProps,
value = props.value,
readonly = props.readonly,
multiple = props.multiple,
useAsyncSearch = props.useAsyncSearch;
// hook
var _useListValuesAutocom = useListValuesAutocomplete(props, {
debounceTimeout: 100,
multiple: multiple,
uif: "antd"
}),
open = _useListValuesAutocom.open,
onDropdownVisibleChange = _useListValuesAutocom.onDropdownVisibleChange,
onChange = _useListValuesAutocom.onChange,
isSpecialValue = _useListValuesAutocom.isSpecialValue,
onSearch = _useListValuesAutocom.onSearch,
inputValue = _useListValuesAutocom.inputValue,
options = _useListValuesAutocom.options,
isInitialLoading = _useListValuesAutocom.isInitialLoading,
isLoading = _useListValuesAutocom.isLoading,
aPlaceholder = _useListValuesAutocom.aPlaceholder,
extendOptions = _useListValuesAutocom.extendOptions,
getOptionDisabled = _useListValuesAutocom.getOptionDisabled,
getOptionIsCustom = _useListValuesAutocom.getOptionIsCustom,
getOptionLabel = _useListValuesAutocom.getOptionLabel,
onInputChange = _useListValuesAutocom.onInputChange;
var filteredOptions = extendOptions(options);
// To colorize custom options
if (multiple && allowCustomValues && value !== null && value !== void 0 && value.length) {
var _iterator = _createForOfIteratorHelper(value),
_step;
try {
var _loop = function _loop() {
var v = _step.value;
if (getOptionIsCustom(v) && !options.find(function (_ref) {
var value = _ref.value;
return value === v;
})) {
filteredOptions.push(makeCustomListValue(v));
}
};
for (_iterator.s(); !(_step = _iterator.n()).done;) {
_loop();
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
}
var optionsMaxWidth = (0, _react.useMemo)(function () {
return filteredOptions.reduce(function (max, option) {
return Math.max(max, (0, _domUtils.calcTextWidth)(option.title, null));
}, 0);
}, [options]);
var _config$settings = config.settings,
defaultSelectWidth = _config$settings.defaultSelectWidth,
defaultSearchWidth = _config$settings.defaultSearchWidth,
renderSize = _config$settings.renderSize;
var placeholderWidth = (0, _domUtils.calcTextWidth)(placeholder);
var isEmptyValue = multiple ? !(value !== null && value !== void 0 && value.length) : !value;
var aValue = !isEmptyValue ? value : multiple ? [] : undefined;
var width = aValue || !placeholderWidth ? null : placeholderWidth + _domUtils.SELECT_WIDTH_OFFSET_RIGHT;
var dropdownWidth = optionsMaxWidth && !isNaN(optionsMaxWidth) ? optionsMaxWidth + _domUtils.SELECT_WIDTH_OFFSET_RIGHT : null;
var minWidth = width || defaultSelectWidth;
var isClearAllClicked = _react["default"].useRef(false);
var style = {
width: multiple ? undefined : minWidth,
minWidth: minWidth
};
var dropdownStyle = {
width: dropdownWidth
};
var mode = !multiple ? undefined : (customProps === null || customProps === void 0 ? void 0 : customProps.mode) || (allowCustomValues && customProps !== null && customProps !== void 0 && customProps.tokenSeparators ? "tags" : "multiple");
var dynamicPlaceholder = !readonly ? aPlaceholder : "";
var nestByGroup = function nestByGroup(opts) {
var fix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var newOpts = opts;
if (fix) {
newOpts = fixListValuesGroupOrder(newOpts);
}
var nestedOpts = [];
var _iterator2 = _createForOfIteratorHelper(newOpts),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var o = _step2.value;
var groupTitle = o.groupTitle;
delete o.groupTitle;
if (groupTitle) {
o.grouplabel = groupTitle;
var targetGroup = void 0;
var lastO = nestedOpts[nestedOpts.length - 1];
if (lastO !== null && lastO !== void 0 && lastO.options && lastO.label === groupTitle) {
targetGroup = lastO;
} else {
targetGroup = {
label: groupTitle,
options: []
};
nestedOpts.push(targetGroup);
}
targetGroup.options.push(o);
} else {
nestedOpts.push(o);
}
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
return nestedOpts;
};
var renderOptionLabel = function renderOptionLabel(option) {
var tooltip = option.tooltip;
var label = getOptionLabel(option);
if (tooltip) {
label = /*#__PURE__*/_react["default"].createElement(_antd.Tooltip, {
title: tooltip
}, label);
}
return label;
};
// rendering special 'Load more' option has side effect: on change rc-select will save its title as internal value in own state
var optionsToRender = nestByGroup(filteredOptions === null || filteredOptions === void 0 ? void 0 : filteredOptions.filter(function (option) {
return !option.specialValue;
}).map(function (option) {
return {
label: getOptionIsCustom(option) ? /*#__PURE__*/_react["default"].createElement("span", {
className: "customSelectOption"
}, getOptionLabel(option)) : renderOptionLabel(option),
value: option.value,
groupTitle: option.groupTitle,
disabled: getOptionDisabled(option)
};
}));
var onSpecialClick = function onSpecialClick(specialValue) {
return function () {
var option = filteredOptions.find(function (opt) {
return opt.specialValue == specialValue;
});
onChange(null, specialValue, option);
};
};
var specialOptions = filteredOptions === null || filteredOptions === void 0 ? void 0 : filteredOptions.filter(function (option) {
return !!option.specialValue;
}).map(function (option) {
return /*#__PURE__*/_react["default"].createElement("a", {
style: {
padding: "5px 10px",
display: "block",
cursor: "pointer"
},
key: option.specialValue,
disabled: getOptionDisabled(option),
onClick: onSpecialClick(option.specialValue)
}, getOptionLabel(option));
});
var aOnSelect = /*#__PURE__*/function () {
var _ref2 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee(newValue, option) {
var isAutoTokenization;
return _regenerator["default"].wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
// For both multiple/single `newValue` is string, `option` is {value, children}
// ! Custom option is always `{}`
isAutoTokenization = multiple && !!option.props && !(option.value !== undefined || option.label !== undefined);
if (!isAutoTokenization) {
_context.next = 3;
break;
}
return _context.abrupt("return");
case 3:
if (!isSpecialValue(option)) {
_context.next = 8;
break;
}
_context.next = 6;
return onChange(null, newValue, option);
case 6:
_context.next = 11;
break;
case 8:
if (!multiple) {
_context.next = 11;
break;
}
_context.next = 11;
return onChange(null, newValue, option);
case 11:
case "end":
return _context.stop();
}
}, _callee);
}));
return function aOnSelect(_x, _x2) {
return _ref2.apply(this, arguments);
};
}();
var aOnClear = function aOnClear() {
if (open) {
// tip: if closed, search is hidden, so let's clear tags AND search value
isClearAllClicked.current = true;
}
};
var aOnChange = /*#__PURE__*/function () {
var _ref3 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee2(newValue, option) {
var isAddFromSearch, shouldIgnore;
return _regenerator["default"].wrap(function _callee2$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
// For multiple `newValue` is array of strings, `option` is array of {value, children}
// For single `newValue` is string/undefined, `option` is {value, children}/undefined
// ! Custom option is always `{}`
//
// For multiple called on:
// - click (x) at right (clear all)
// - tag removal
// - option selection (`aOnSelect` is also called after)
// - trying to add new tag from search input (for mode "tags" - unwanted!)
// - automatic tokenization (like pasting "1,2,3") - issue #1115
//
// For single called on:
// - click (x) at right (clear all)
// - option selection (`aOnSelect` is also called after)
// ! NOT when trying to add new tag
isAddFromSearch = multiple && newValue.length && newValue.length > aValue.length && newValue[newValue.length - 1] == inputValue;
shouldIgnore = isSpecialValue(option) // use onSelect instead
|| mode === "tags" && isAddFromSearch // obsolete, we don't use tags mode
|| isClearAllClicked.current && inputValue;
isClearAllClicked.current = false;
if (shouldIgnore) {
_context2.next = 6;
break;
}
_context2.next = 6;
return onChange(null, newValue, option);
case 6:
case "end":
return _context2.stop();
}
}, _callee2);
}));
return function aOnChange(_x3, _x4) {
return _ref3.apply(this, arguments);
};
}();
// to keep compatibility with antD
var aOnSearch = /*#__PURE__*/function () {
var _ref4 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee3(newInputValue) {
return _regenerator["default"].wrap(function _callee3$(_context3) {
while (1) switch (_context3.prev = _context3.next) {
case 0:
if (isClearAllClicked.current) {
isClearAllClicked.current = false;
}
// if (newInputValue === "" && !open) {
// return; // ?
// }
_context3.next = 3;
return onInputChange(null, newInputValue);
case 3:
case "end":
return _context3.stop();
}
}, _callee3);
}));
return function aOnSearch(_x5) {
return _ref4.apply(this, arguments);
};
}();
var dropdownRender = (0, _react.useCallback)(function (menu) {
return /*#__PURE__*/_react["default"].createElement("div", null, menu, specialOptions.length > 0 && /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement(_antd.Divider, {
style: {
margin: "0px"
}
}), /*#__PURE__*/_react["default"].createElement("div", {
style: {
display: "flex",
flexDirection: "column"
}
}, specialOptions)));
}, [filteredOptions]);
var filterOption = (0, _react.useCallback)(function (input, option) {
var keysForFilter = config.settings.listKeysForSearch.map(function (k) {
return mapListItemToOptionKeys[k];
});
var valueForFilter = keysForFilter.map(function (k) {
return typeof option[k] == "string" ? option[k] : "";
}).join("\0");
var matches = valueForFilter.toLowerCase().indexOf(input.toLowerCase()) >= 0;
return matches;
}, [config]);
return /*#__PURE__*/_react["default"].createElement(_antd.Select, (0, _extends2["default"])({
filterOption: useAsyncSearch ? false : filterOption,
dropdownRender: dropdownRender,
allowClear: true,
notFoundContent: isLoading ? (_config$settings$load = config.settings.loadingLabel) !== null && _config$settings$load !== void 0 ? _config$settings$load : "Loading..." : (_config$settings$notF = config.settings.notFoundLabel) !== null && _config$settings$notF !== void 0 ? _config$settings$notF : "Not found",
disabled: readonly,
mode: mode,
style: (customProps === null || customProps === void 0 ? void 0 : customProps.style) || style,
dropdownStyle: (customProps === null || customProps === void 0 ? void 0 : customProps.dropdownStyle) || dropdownStyle,
key: "widget-autocomplete",
popupMatchSelectWidth: (customProps === null || customProps === void 0 ? void 0 : customProps.popupMatchSelectWidth) || (customProps === null || customProps === void 0 ? void 0 : customProps.dropdownMatchSelectWidth) || false,
placeholder: (customProps === null || customProps === void 0 ? void 0 : customProps.placeholder) || dynamicPlaceholder,
onDropdownVisibleChange: onDropdownVisibleChange,
onChange: aOnChange,
onClear: aOnClear,
onSelect: aOnSelect,
onSearch: aOnSearch,
showSearch: true,
size: renderSize,
loading: isLoading,
value: aValue,
searchValue: inputValue,
open: open,
options: optionsToRender
}, customProps));
};