@grafana/ui
Version:
Grafana Components Library
127 lines (122 loc) • 4.37 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var lodash = require('lodash');
var React = require('react');
var i18n = require('@grafana/i18n');
var filter = require('./filter.cjs');
var useLatestAsyncCall = require('./useLatestAsyncCall.cjs');
;
const asyncNoop = () => Promise.resolve([]);
const DEBOUNCE_TIME_MS = 200;
function useOptions(rawOptions, createCustomValue, customValueDescription) {
const isAsync = typeof rawOptions === "function";
const loadOptions = useLatestAsyncCall.useLatestAsyncCall(isAsync ? rawOptions : asyncNoop);
const debouncedLoadOptions = React.useMemo(
() => lodash.debounce((searchTerm) => {
return loadOptions(searchTerm).then((options) => {
setAsyncOptions(options);
setAsyncLoading(false);
setAsyncError(false);
}).catch((error) => {
if (!(error instanceof useLatestAsyncCall.StaleResultError)) {
setAsyncError(true);
setAsyncLoading(false);
if (error) {
console.error("Error loading async options for Combobox", error);
}
}
});
}, DEBOUNCE_TIME_MS),
[loadOptions]
);
const [asyncOptions, setAsyncOptions] = React.useState([]);
const [asyncLoading, setAsyncLoading] = React.useState(false);
const [asyncError, setAsyncError] = React.useState(false);
const [userTypedSearch, setUserTypedSearch] = React.useState("");
const addCustomValue = React.useCallback(
(opts) => {
let currentOptions = opts;
if (createCustomValue && userTypedSearch) {
const customValueExists = opts.some((opt) => opt.value === userTypedSearch);
if (!customValueExists) {
currentOptions = currentOptions.slice();
currentOptions.unshift({
label: userTypedSearch,
value: userTypedSearch,
description: customValueDescription != null ? customValueDescription : i18n.t("combobox.custom-value.description", "Use custom value")
});
}
}
return currentOptions;
},
[createCustomValue, customValueDescription, userTypedSearch]
);
const updateOptions = React.useCallback(
(inputValue) => {
setUserTypedSearch(inputValue);
if (isAsync) {
setAsyncLoading(true);
debouncedLoadOptions(inputValue);
}
},
[debouncedLoadOptions, isAsync]
);
const stringifiedOptions = React.useMemo(() => {
return isAsync ? [] : rawOptions.map(filter.itemToString);
}, [isAsync, rawOptions]);
const filteredOptions = React.useMemo(() => {
if (isAsync) {
return asyncOptions;
}
return filter.fuzzyFind(rawOptions, stringifiedOptions, userTypedSearch);
}, [asyncOptions, isAsync, rawOptions, stringifiedOptions, userTypedSearch]);
const [finalOptions, groupStartIndices] = React.useMemo(() => {
const { options, groupStartIndices: groupStartIndices2 } = sortByGroup(filteredOptions);
return [addCustomValue(options), groupStartIndices2];
}, [filteredOptions, addCustomValue]);
const resetSearch = React.useCallback(() => {
setUserTypedSearch("");
}, []);
return { options: finalOptions, groupStartIndices, updateOptions, asyncLoading, asyncError, resetSearch };
}
function sortByGroup(options) {
var _a, _b;
const groupedOptions = /* @__PURE__ */ new Map();
const groupStartIndices = /* @__PURE__ */ new Map();
for (const option of options) {
const group = option.group;
const existing = groupedOptions.get(group);
if (existing) {
existing.push(option);
} else {
groupedOptions.set(group, [option]);
}
}
if (groupedOptions.size <= 1) {
if ((_a = options[0]) == null ? void 0 : _a.group) {
groupStartIndices.set((_b = options[0]) == null ? void 0 : _b.group, 0);
}
return {
options,
groupStartIndices
};
}
const result = new Array(options.length);
let currentIndex = 0;
for (const [group, groupOptions] of groupedOptions) {
if (group) {
groupStartIndices.set(group, currentIndex);
}
for (const option of groupOptions) {
result[currentIndex++] = option;
}
}
return {
options: result,
groupStartIndices
};
}
exports.DEBOUNCE_TIME_MS = DEBOUNCE_TIME_MS;
exports.sortByGroup = sortByGroup;
exports.useOptions = useOptions;
//# sourceMappingURL=useOptions.cjs.map