UNPKG

@wordpress/components

Version:
130 lines (115 loc) 4.07 kB
import { createElement } from "@wordpress/element"; /** * External dependencies */ import scrollView from 'dom-scroll-into-view'; import classnames from 'classnames'; /** * WordPress dependencies */ import { useState } from '@wordpress/element'; import { useRefEffect } from '@wordpress/compose'; /** * Internal dependencies */ const handleMouseDown = e => { // By preventing default here, we will not lose focus of <input> when clicking a suggestion. e.preventDefault(); }; export function SuggestionsList(_ref) { let { selectedIndex, scrollIntoView, match, onHover, onSelect, suggestions = [], displayTransform, instanceId, __experimentalRenderItem } = _ref; const [scrollingIntoView, setScrollingIntoView] = useState(false); const listRef = useRefEffect(listNode => { // only have to worry about scrolling selected suggestion into view // when already expanded. let rafId; if (selectedIndex > -1 && scrollIntoView && listNode.children[selectedIndex]) { setScrollingIntoView(true); scrollView(listNode.children[selectedIndex], listNode, { onlyScrollIfNeeded: true }); rafId = requestAnimationFrame(() => { setScrollingIntoView(false); }); } return () => { if (rafId !== undefined) { cancelAnimationFrame(rafId); } }; }, [selectedIndex, scrollIntoView]); const handleHover = suggestion => { return () => { if (!scrollingIntoView) { onHover === null || onHover === void 0 ? void 0 : onHover(suggestion); } }; }; const handleClick = suggestion => { return () => { onSelect === null || onSelect === void 0 ? void 0 : onSelect(suggestion); }; }; const computeSuggestionMatch = suggestion => { const matchText = displayTransform(match).toLocaleLowerCase(); if (matchText.length === 0) { return null; } const transformedSuggestion = displayTransform(suggestion); const indexOfMatch = transformedSuggestion.toLocaleLowerCase().indexOf(matchText); return { suggestionBeforeMatch: transformedSuggestion.substring(0, indexOfMatch), suggestionMatch: transformedSuggestion.substring(indexOfMatch, indexOfMatch + matchText.length), suggestionAfterMatch: transformedSuggestion.substring(indexOfMatch + matchText.length) }; }; return createElement("ul", { ref: listRef, className: "components-form-token-field__suggestions-list", id: `components-form-token-suggestions-${instanceId}`, role: "listbox" }, suggestions.map((suggestion, index) => { const matchText = computeSuggestionMatch(suggestion); const className = classnames('components-form-token-field__suggestion', { 'is-selected': index === selectedIndex }); let output; if (typeof __experimentalRenderItem === 'function') { output = __experimentalRenderItem({ item: suggestion }); } else if (matchText) { output = createElement("span", { "aria-label": displayTransform(suggestion) }, matchText.suggestionBeforeMatch, createElement("strong", { className: "components-form-token-field__suggestion-match" }, matchText.suggestionMatch), matchText.suggestionAfterMatch); } else { output = displayTransform(suggestion); } /* eslint-disable jsx-a11y/click-events-have-key-events */ return createElement("li", { id: `components-form-token-suggestions-${instanceId}-${index}`, role: "option", className: className, key: typeof suggestion === 'object' && 'value' in suggestion ? suggestion === null || suggestion === void 0 ? void 0 : suggestion.value : displayTransform(suggestion), onMouseDown: handleMouseDown, onClick: handleClick(suggestion), onMouseEnter: handleHover(suggestion), "aria-selected": index === selectedIndex }, output); /* eslint-enable jsx-a11y/click-events-have-key-events */ })); } export default SuggestionsList; //# sourceMappingURL=suggestions-list.js.map