UNPKG

diagram-js

Version:

A toolbox for displaying and modifying diagrams on the web

107 lines (92 loc) 3.17 kB
import classNames from 'clsx'; import { html, useMemo } from '../../ui'; /** * @typedef {import('./PopupMenuProvider').PopupMenuHeaderEntry} PopupMenuHeaderEntry */ /** * Component that renders a popup menu header. * * @param {Object} props * @param {PopupMenuHeaderEntry[]} props.headerEntries * @param {PopupMenuHeaderEntry} props.selectedEntry * @param {(event: MouseEvent, entry: PopupMenuHeaderEntry) => void} props.onSelect * @param {(entry: PopupMenuHeaderEntry | null) => void} props.setSelectedEntry * @param {string} props.title */ export default function PopupMenuHeader(props) { const { headerEntries, onSelect, selectedEntry, setSelectedEntry, title } = props; const groups = useMemo(() => groupEntries(headerEntries), [ headerEntries ]); const isActionable = (entry) => { return entry.action && !entry.disabled; }; const handleClick = (event, entry) => { if (!isActionable(entry)) { return; } return onSelect(event, entry); }; return html` <div class="djs-popup-header"> <h3 class="djs-popup-title" title=${ title }>${ title }</h3> ${ groups.map((group) => html` <ul key=${ group.id } class="djs-popup-header-group" data-header-group=${ group.id }> ${ group.entries.map(entry => html` <li key=${ entry.id }> <${ isActionable(entry) ? 'button' : 'span' } class=${ getHeaderClasses(entry, entry === selectedEntry) } onClick=${ event => handleClick(event, entry) } title=${ entry.title || entry.label } data-id=${ entry.id } aria-disabled=${ entry.disabled || undefined } onMouseEnter=${ () => isActionable(entry) && setSelectedEntry(entry) } onMouseLeave=${ () => isActionable(entry) && setSelectedEntry(null) } onFocus=${ () => isActionable(entry) && setSelectedEntry(entry) } onBlur=${ () => isActionable(entry) && setSelectedEntry(null) } > ${(entry.imageUrl && html`<img class="djs-popup-entry-icon" src=${ entry.imageUrl } alt="" />`) || (entry.imageHtml && html`<div class="djs-popup-entry-icon" dangerouslySetInnerHTML=${ { __html: entry.imageHtml } } />`)} ${ entry.label ? html` <span class="djs-popup-label">${ entry.label }</span> ` : null } </${ entry.action ? 'button' : 'span' }> </li> `) } </ul> `) } </div> `; } // helpers function groupEntries(entries) { return entries.reduce((groups, entry) => { const groupId = entry.group || 'default'; const group = groups.find(group => group.id === groupId); if (group) { group.entries.push(entry); } else { groups.push({ id: groupId, entries: [ entry ] }); } return groups; }, []); } function getHeaderClasses(entry, selected) { return classNames( 'entry', entry.className, entry.active ? 'active' : '', entry.disabled ? 'disabled' : '', selected ? 'selected' : '' ); }