UNPKG

@grafana/ui

Version:
127 lines (122 loc) 4.37 kB
'use strict'; 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'); "use strict"; 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