UNPKG

@wordpress/components

Version:
167 lines (162 loc) 6.2 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.getAutoCompleterUI = getAutoCompleterUI; var _clsx = _interopRequireDefault(require("clsx")); var _element = require("@wordpress/element"); var _richText = require("@wordpress/rich-text"); var _compose = require("@wordpress/compose"); var _a11y = require("@wordpress/a11y"); var _i18n = require("@wordpress/i18n"); var _getDefaultUseItems = _interopRequireDefault(require("./get-default-use-items")); var _button = _interopRequireDefault(require("../button")); var _popover = _interopRequireDefault(require("../popover")); var _visuallyHidden = require("../visually-hidden"); var _reactDom = require("react-dom"); var _jsxRuntime = require("react/jsx-runtime"); /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ function ListBox({ items, onSelect, selectedIndex, instanceId, listBoxId, className, Component = 'div' }) { return /*#__PURE__*/(0, _jsxRuntime.jsx)(Component, { id: listBoxId, role: "listbox", className: "components-autocomplete__results", children: items.map((option, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_button.default, { id: `components-autocomplete-item-${instanceId}-${option.key}`, role: "option", __next40pxDefaultSize: true, "aria-selected": index === selectedIndex, accessibleWhenDisabled: true, disabled: option.isDisabled, className: (0, _clsx.default)('components-autocomplete__result', className, { // Unused, for backwards compatibility. 'is-selected': index === selectedIndex }), variant: index === selectedIndex ? 'primary' : undefined, onClick: () => onSelect(option), children: option.label }, option.key)) }); } function getAutoCompleterUI(autocompleter) { var _autocompleter$useIte; const useItems = (_autocompleter$useIte = autocompleter.useItems) !== null && _autocompleter$useIte !== void 0 ? _autocompleter$useIte : (0, _getDefaultUseItems.default)(autocompleter); function AutocompleterUI({ filterValue, instanceId, listBoxId, className, selectedIndex, onChangeOptions, onSelect, onReset, reset, contentRef }) { const [items] = useItems(filterValue); const popoverAnchor = (0, _richText.useAnchor)({ editableContentElement: contentRef.current }); const [needsA11yCompat, setNeedsA11yCompat] = (0, _element.useState)(false); const popoverRef = (0, _element.useRef)(null); const popoverRefs = (0, _compose.useMergeRefs)([popoverRef, (0, _compose.useRefEffect)(node => { if (!contentRef.current) { return; } // If the popover is rendered in a different document than // the content, we need to duplicate the options list in the // content document so that it's available to the screen // readers, which check the DOM ID based aria-* attributes. setNeedsA11yCompat(node.ownerDocument !== contentRef.current.ownerDocument); }, [contentRef])]); useOnClickOutside(popoverRef, reset); const debouncedSpeak = (0, _compose.useDebounce)(_a11y.speak, 500); function announce(options) { if (!debouncedSpeak) { return; } if (!!options.length) { if (filterValue) { debouncedSpeak((0, _i18n.sprintf)(/* translators: %d: number of results. */ (0, _i18n._n)('%d result found, use up and down arrow keys to navigate.', '%d results found, use up and down arrow keys to navigate.', options.length), options.length), 'assertive'); } else { debouncedSpeak((0, _i18n.sprintf)(/* translators: %d: number of results. */ (0, _i18n._n)('Initial %d result loaded. Type to filter all available results. Use up and down arrow keys to navigate.', 'Initial %d results loaded. Type to filter all available results. Use up and down arrow keys to navigate.', options.length), options.length), 'assertive'); } } else { debouncedSpeak((0, _i18n.__)('No results.'), 'assertive'); } } (0, _element.useLayoutEffect)(() => { onChangeOptions(items); announce(items); // We want to avoid introducing unexpected side effects. // See https://github.com/WordPress/gutenberg/pull/41820 }, [items]); if (items.length === 0) { return null; } return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, { children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_popover.default, { focusOnMount: false, onClose: onReset, placement: "top-start", className: "components-autocomplete__popover", anchor: popoverAnchor, ref: popoverRefs, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(ListBox, { items: items, onSelect: onSelect, selectedIndex: selectedIndex, instanceId: instanceId, listBoxId: listBoxId, className: className }) }), contentRef.current && needsA11yCompat && (0, _reactDom.createPortal)(/*#__PURE__*/(0, _jsxRuntime.jsx)(ListBox, { items: items, onSelect: onSelect, selectedIndex: selectedIndex, instanceId: instanceId, listBoxId: listBoxId, className: className, Component: _visuallyHidden.VisuallyHidden }), contentRef.current.ownerDocument.body)] }); } return AutocompleterUI; } function useOnClickOutside(ref, handler) { (0, _element.useEffect)(() => { const listener = event => { // Do nothing if clicking ref's element or descendent elements, or if the ref is not referencing an element if (!ref.current || ref.current.contains(event.target)) { return; } handler(event); }; document.addEventListener('mousedown', listener); document.addEventListener('touchstart', listener); return () => { document.removeEventListener('mousedown', listener); document.removeEventListener('touchstart', listener); }; }, [handler, ref]); } //# sourceMappingURL=autocompleter-ui.js.map