UNPKG

@wordpress/components

Version:
120 lines (105 loc) 3.92 kB
import { createElement } from "@wordpress/element"; /** * External dependencies */ import { map } from 'lodash'; import scrollIntoView from 'dom-scroll-into-view'; import classnames from 'classnames'; /** * WordPress dependencies */ import { Component } from '@wordpress/element'; import { withSafeTimeout } from '@wordpress/compose'; class SuggestionsList extends Component { constructor() { super(...arguments); this.handleMouseDown = this.handleMouseDown.bind(this); this.bindList = this.bindList.bind(this); } componentDidUpdate() { // only have to worry about scrolling selected suggestion into view // when already expanded if (this.props.selectedIndex > -1 && this.props.scrollIntoView) { this.scrollingIntoView = true; scrollIntoView(this.list.children[this.props.selectedIndex], this.list, { onlyScrollIfNeeded: true }); this.props.setTimeout(() => { this.scrollingIntoView = false; }, 100); } } bindList(ref) { this.list = ref; } handleHover(suggestion) { return () => { if (!this.scrollingIntoView) { this.props.onHover(suggestion); } }; } handleClick(suggestion) { return () => { this.props.onSelect(suggestion); }; } handleMouseDown(e) { // By preventing default here, we will not lose focus of <input> when clicking a suggestion e.preventDefault(); } computeSuggestionMatch(suggestion) { const match = this.props.displayTransform(this.props.match || '').toLocaleLowerCase(); if (match.length === 0) { return null; } suggestion = this.props.displayTransform(suggestion); const indexOfMatch = suggestion.toLocaleLowerCase().indexOf(match); return { suggestionBeforeMatch: suggestion.substring(0, indexOfMatch), suggestionMatch: suggestion.substring(indexOfMatch, indexOfMatch + match.length), suggestionAfterMatch: suggestion.substring(indexOfMatch + match.length) }; } render() { // We set `tabIndex` here because otherwise Firefox sets focus on this // div when tabbing off of the input in `TokenField` -- not really sure // why, since usually a div isn't focusable by default // TODO does this still apply now that it's a <ul> and not a <div>? return createElement("ul", { ref: this.bindList, className: "components-form-token-field__suggestions-list", id: `components-form-token-suggestions-${this.props.instanceId}`, role: "listbox" }, map(this.props.suggestions, (suggestion, index) => { const match = this.computeSuggestionMatch(suggestion); const classeName = classnames('components-form-token-field__suggestion', { 'is-selected': index === this.props.selectedIndex }); /* eslint-disable jsx-a11y/click-events-have-key-events */ return createElement("li", { id: `components-form-token-suggestions-${this.props.instanceId}-${index}`, role: "option", className: classeName, key: this.props.displayTransform(suggestion), onMouseDown: this.handleMouseDown, onClick: this.handleClick(suggestion), onMouseEnter: this.handleHover(suggestion), "aria-selected": index === this.props.selectedIndex }, match ? createElement("span", { "aria-label": this.props.displayTransform(suggestion) }, match.suggestionBeforeMatch, createElement("strong", { className: "components-form-token-field__suggestion-match" }, match.suggestionMatch), match.suggestionAfterMatch) : this.props.displayTransform(suggestion)); /* eslint-enable jsx-a11y/click-events-have-key-events */ })); } } SuggestionsList.defaultProps = { match: '', onHover: () => {}, onSelect: () => {}, suggestions: Object.freeze([]) }; export default withSafeTimeout(SuggestionsList); //# sourceMappingURL=suggestions-list.js.map