import { html, useMemo, useLayoutEffect, useRef } from '../../ui'; import PopupMenuItem from './PopupMenuItem'; /** * Component that renders a popup menu entry list. * * @param {Array} entries * @param {Object} selectedEntry * @param {function} setSelectedEntry * @param {function} onAction * @param {Object} resultsRef */ export default function PopupMenuList(props) { const { selectedEntry, setSelectedEntry, entries, ...restProps } = props; const resultsRef = useRef(); const groups = useMemo(() => groupEntries(entries), [ entries ]); // scroll to selected result useLayoutEffect(() => { const containerEl = resultsRef.current; if (!containerEl) return; const selectedEl = containerEl.querySelector('.selected'); if (selectedEl) { scrollIntoView(selectedEl); } }, [ selectedEntry ]); return html`
${ groups.map(group => html` ${ group.name && html`
${ group.name }
` } `) }
`; } // helpers function groupEntries(entries) { const groups = []; const getGroup = group => groups.find(elem => group.id === elem.id); const containsGroup = group => !!getGroup(group); // legacy support for provider built for the old popUp menu const formatGroup = group => typeof group === 'string' ? { id: group } : group; entries.forEach(entry => { // assume a default group when none is provided const group = entry.group ? formatGroup(entry.group) : { id: 'default' }; if (!containsGroup(group)) { groups.push({ ...group, entries: [ entry ] }); } else { getGroup(group).entries.push(entry); } }); return groups; } // helpers //////////////// function scrollIntoView(el) { if (typeof el.scrollIntoViewIfNeeded === 'function') { el.scrollIntoViewIfNeeded(); } else { el.scrollIntoView({ scrollMode: 'if-needed', block: 'nearest' }); } }