UNPKG

@wordpress/components

Version:
98 lines (91 loc) 3.36 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getDefaultUseItems; var _removeAccents = _interopRequireDefault(require("remove-accents")); var _compose = require("@wordpress/compose"); var _element = require("@wordpress/element"); var _strings = require("../utils/strings"); /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ function filterOptions(search, options = [], maxResults = 10) { const filtered = []; for (let i = 0; i < options.length; i++) { const option = options[i]; // Merge label into keywords. let { keywords = [] } = option; if ('string' === typeof option.label) { keywords = [...keywords, option.label]; } const isMatch = keywords.some(keyword => search.test((0, _removeAccents.default)(keyword))); if (!isMatch) { continue; } filtered.push(option); // Abort early if max reached. if (filtered.length === maxResults) { break; } } return filtered; } function getDefaultUseItems(autocompleter) { return filterValue => { const [items, setItems] = (0, _element.useState)([]); /* * We support both synchronous and asynchronous retrieval of completer options * but internally treat all as async so we maintain a single, consistent code path. * * Because networks can be slow, and the internet is wonderfully unpredictable, * we don't want two promises updating the state at once. This ensures that only * the most recent promise will act on `optionsData`. This doesn't use the state * because `setState` is batched, and so there's no guarantee that setting * `activePromise` in the state would result in it actually being in `this.state` * before the promise resolves and we check to see if this is the active promise or not. */ (0, _element.useLayoutEffect)(() => { const { options, isDebounced } = autocompleter; const loadOptions = (0, _compose.debounce)(() => { const promise = Promise.resolve(typeof options === 'function' ? options(filterValue) : options).then(optionsData => { if (promise.canceled) { return; } const keyedOptions = optionsData.map((optionData, optionIndex) => ({ key: `${autocompleter.name}-${optionIndex}`, value: optionData, label: autocompleter.getOptionLabel(optionData), keywords: autocompleter.getOptionKeywords ? autocompleter.getOptionKeywords(optionData) : [], isDisabled: autocompleter.isOptionDisabled ? autocompleter.isOptionDisabled(optionData) : false })); // Create a regular expression to filter the options. const search = new RegExp('(?:\\b|\\s|^)' + (0, _strings.escapeRegExp)(filterValue), 'i'); setItems(filterOptions(search, keyedOptions)); }); return promise; }, isDebounced ? 250 : 0); const promise = loadOptions(); return () => { loadOptions.cancel(); if (promise) { promise.canceled = true; } }; }, [filterValue]); return [items]; }; } //# sourceMappingURL=get-default-use-items.js.map