ra-core
Version:
Core components of react-admin, a frontend Framework for building admin applications on top of REST services, using ES6, React
225 lines • 10.1 kB
JavaScript
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSuggestionsFactory = exports.useSuggestions = void 0;
var react_1 = require("react");
var set_1 = __importDefault(require("lodash/set"));
var useChoices_1 = require("./choices/useChoices");
var i18n_1 = require("../i18n");
/*
* Returns helper functions for suggestions handling.
*
* @param allowDuplicates A boolean indicating whether a suggestion can be added several times
* @param choices An array of available choices
* @param limitChoicesToValue A boolean indicating whether the initial suggestions should be limited to the currently selected one(s)
* @param matchSuggestion Optional unless `optionText` is a React element. Function which check whether a choice matches a filter. Must return a boolean.
* @param optionText Either a string defining the property to use to get the choice text, a function or a React element
* @param optionValue The property to use to get the choice value
* @param selectedItem The currently selected item. Maybe an array of selected items
* @param suggestionLimit The maximum number of suggestions returned
* @param translateChoice A boolean indicating whether to option text should be translated
*
* @returns An object with helper functions:
* - getChoiceText: Returns the choice text or a React element
* - getChoiceValue: Returns the choice value
* - getSuggestions: A function taking a filter value (string) and returning the matching suggestions
*/
var useSuggestions = function (_a) {
var allowCreate = _a.allowCreate, choices = _a.choices, _b = _a.createText, createText = _b === void 0 ? 'ra.action.create' : _b, _c = _a.createValue, createValue = _c === void 0 ? '@@create' : _c, _d = _a.createHintValue, createHintValue = _d === void 0 ? '@@ra-create-hint' : _d, limitChoicesToValue = _a.limitChoicesToValue, matchSuggestion = _a.matchSuggestion, optionText = _a.optionText, optionValue = _a.optionValue, selectedItem = _a.selectedItem, _e = _a.suggestionLimit, suggestionLimit = _e === void 0 ? 0 : _e, translateChoice = _a.translateChoice;
var translate = (0, i18n_1.useTranslate)();
var _f = (0, useChoices_1.useChoices)({
optionText: optionText,
optionValue: optionValue,
translateChoice: translateChoice,
createValue: createValue,
createHintValue: createHintValue,
}), getChoiceText = _f.getChoiceText, getChoiceValue = _f.getChoiceValue;
// eslint-disable-next-line react-hooks/exhaustive-deps
var getSuggestions = (0, react_1.useCallback)((0, exports.getSuggestionsFactory)({
allowCreate: allowCreate,
choices: choices,
createText: createText,
createValue: createValue,
getChoiceText: getChoiceText,
getChoiceValue: getChoiceValue,
limitChoicesToValue: limitChoicesToValue,
matchSuggestion: matchSuggestion,
optionText: optionText,
optionValue: optionValue,
selectedItem: selectedItem,
suggestionLimit: suggestionLimit,
}), [
allowCreate,
choices,
createText,
createValue,
getChoiceText,
getChoiceValue,
limitChoicesToValue,
matchSuggestion,
optionText,
optionValue,
selectedItem,
suggestionLimit,
translate,
]);
return {
getChoiceText: getChoiceText,
getChoiceValue: getChoiceValue,
getSuggestions: getSuggestions,
};
};
exports.useSuggestions = useSuggestions;
var escapeRegExp = function (value) {
return value ? value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') : '';
}; // $& means the whole matched string
/**
* Default matcher implementation which check whether the suggestion text matches the filter.
*/
var defaultMatchSuggestion = function (getChoiceText) {
return function (filter, suggestion, exact) {
if (exact === void 0) { exact = false; }
var suggestionText = getChoiceText(suggestion);
var isReactElement = (0, react_1.isValidElement)(suggestionText);
var regex = escapeRegExp(filter);
return isReactElement
? false
: suggestionText &&
!!suggestionText.match(
// We must escape any RegExp reserved characters to avoid errors
// For example, the filter might contain * which must be escaped as \*
new RegExp(exact ? "^".concat(regex, "$") : regex, 'i'));
};
};
/**
* Get the suggestions to display after applying a fuzzy search on the available choices
*
* @example
*
* getSuggestions({
* choices: [{ id: 1, name: 'admin' }, { id: 2, name: 'publisher' }],
* optionText: 'name',
* optionValue: 'id',
* getSuggestionText: choice => choice[optionText],
* })('pub')
*
* // Will return [{ id: 2, name: 'publisher' }]
* getSuggestions({
* choices: [{ id: 1, name: 'admin' }, { id: 2, name: 'publisher' }],
* optionText: 'name',
* optionValue: 'id',
* getSuggestionText: choice => choice[optionText],
* })('pub')
*
* // Will return [{ id: 2, name: 'publisher' }]
*/
var getSuggestionsFactory = function (_a) {
var _b = _a.allowCreate, allowCreate = _b === void 0 ? false : _b, _c = _a.choices, choices = _c === void 0 ? [] : _c, _d = _a.createText, createText = _d === void 0 ? 'ra.action.create' : _d, _e = _a.createValue, createValue = _e === void 0 ? '@@create' : _e, _f = _a.optionText, optionText = _f === void 0 ? 'name' : _f, _g = _a.optionValue, optionValue = _g === void 0 ? 'id' : _g, getChoiceText = _a.getChoiceText, getChoiceValue = _a.getChoiceValue, _h = _a.limitChoicesToValue, limitChoicesToValue = _h === void 0 ? false : _h, _j = _a.matchSuggestion, matchSuggestion = _j === void 0 ? defaultMatchSuggestion(getChoiceText) : _j, selectedItem = _a.selectedItem, _k = _a.suggestionLimit, suggestionLimit = _k === void 0 ? 0 : _k;
return function (filter) {
var suggestions = [];
// if an item is selected and matches the filter
if (selectedItem &&
!Array.isArray(selectedItem) &&
matchSuggestion(filter, selectedItem)) {
if (limitChoicesToValue) {
// display only the selected item
suggestions = choices.filter(function (choice) {
return getChoiceValue(choice) === getChoiceValue(selectedItem);
});
}
else {
suggestions = __spreadArray([], choices, true);
}
}
else {
suggestions = choices.filter(function (choice) {
return matchSuggestion(filter, choice) ||
(selectedItem != null &&
(!Array.isArray(selectedItem)
? getChoiceValue(choice) ===
getChoiceValue(selectedItem)
: selectedItem.some(function (selected) {
return getChoiceValue(choice) ===
getChoiceValue(selected);
})));
});
}
suggestions = limitSuggestions(suggestions, suggestionLimit);
var hasExactMatch = suggestions.some(function (suggestion) {
return matchSuggestion(filter, suggestion, true);
});
if (allowCreate) {
var filterIsSelectedItem =
// If the selectedItem is an array (for example AutocompleteArrayInput)
// we shouldn't try to match
!!selectedItem && !Array.isArray(selectedItem)
? matchSuggestion(filter, selectedItem, true)
: false;
if (!hasExactMatch && !filterIsSelectedItem) {
suggestions.push(getSuggestion({
optionText: optionText,
optionValue: optionValue,
text: createText,
value: createValue,
}));
}
}
// Only keep unique items. Necessary because we might have fetched
// the currently selected choice in addition of the possible choices
// that may also contain it
var result = suggestions.filter(function (suggestion, index) { return suggestions.indexOf(suggestion) === index; });
return result;
};
};
exports.getSuggestionsFactory = getSuggestionsFactory;
/**
* @example
*
* limitSuggestions(
* [{ id: 1, name: 'foo'}, { id: 2, name: 'bar' }],
* 1
* );
*
* // Will return [{ id: 1, name: 'foo' }]
*
* @param suggestions List of suggestions
* @param limit
*/
var limitSuggestions = function (suggestions, limit) {
if (limit === void 0) { limit = 0; }
return Number.isInteger(limit) && limit > 0
? suggestions.slice(0, limit)
: suggestions;
};
/**
* addSuggestion(
* [{ id: 1, name: 'foo'}, { id: 2, name: 'bar' }],
* );
*
* // Will return [{ id: null, name: '' }, { id: 1, name: 'foo' }, { id: 2, name: 'bar' }]
*
* @param suggestions List of suggestions
* @param options
* @param options.optionText
*/
var getSuggestion = function (_a) {
var _b = _a.optionText, optionText = _b === void 0 ? 'name' : _b, _c = _a.optionValue, optionValue = _c === void 0 ? 'id' : _c, _d = _a.text, text = _d === void 0 ? '' : _d, _e = _a.value, value = _e === void 0 ? null : _e;
var suggestion = {};
(0, set_1.default)(suggestion, optionValue, value);
if (typeof optionText === 'string') {
(0, set_1.default)(suggestion, optionText, text);
}
return suggestion;
};
//# sourceMappingURL=useSuggestions.js.map
;