import React from 'react'; import { Avatar, Brand, Breadcrumb, BreadcrumbItem, Button, ButtonVariant, Card, CardBody, Divider, Dropdown, DropdownGroup, DropdownItem, DropdownList, Gallery, GalleryItem, Masthead, MastheadBrand, MastheadContent, MastheadMain, MastheadToggle, Menu, MenuContent, MenuList, MenuItem, MenuToggle, MenuToggleElement, Nav, NavItem, NavList, Page, PageSection, PageSectionVariants, PageSidebar, PageSidebarBody, PageToggleButton, Popper, SkipToContent, Text, TextContent, Toolbar, ToolbarContent, ToolbarGroup, ToolbarItem, MenuGroup, MenuSearchInput, SearchInput, Tooltip } from '@breakaway/preact-core'; import { Link } from '@reach/router'; import BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon'; import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon'; import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon'; import HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon'; import ThIcon from '@patternfly/react-icons/dist/esm/icons/th-icon'; import QuestionCircleIcon from '@patternfly/react-icons/dist/esm/icons/question-circle-icon'; import imgAvatar from '@breakaway/preact-core/src/components/assets/avatarImg.svg'; import pfIcon from '@breakaway/preact-core/src/demos/assets/pf-logo-small.svg'; import pfLogo from '@breakaway/preact-core/src/demos/assets/pf-logo.svg'; interface NavOnSelectProps { groupId: number | string; itemId: number | string; to: string; } export const MastheadWithUtilitiesAndUserDropdownMenu: React.FunctionComponent = () => { const [isDropdownOpen, setIsDropdownOpen] = React.useState(false); const [isKebabDropdownOpen, setIsKebabDropdownOpen] = React.useState(false); const [isFullKebabDropdownOpen, setIsFullKebabDropdownOpen] = React.useState(false); const [activeItem, setActiveItem] = React.useState(1); const [isOpen, setIsOpen] = React.useState(false); const [refFullOptions, setRefFullOptions] = React.useState(); const [favorites, setFavorites] = React.useState([]); const [filteredIds, setFilteredIds] = React.useState(['*']); const menuRef = React.useRef(null); const toggleRef = React.useRef(null); const onNavSelect = (_event: React.FormEvent, selectedItem: NavOnSelectProps) => { typeof selectedItem.itemId === 'number' && setActiveItem(selectedItem.itemId); }; const onDropdownToggle = () => { setIsDropdownOpen(!isDropdownOpen); }; const onDropdownSelect = () => { setIsDropdownOpen(!isDropdownOpen); }; const onKebabDropdownToggle = () => { setIsKebabDropdownOpen(!isKebabDropdownOpen); }; const onKebabDropdownSelect = () => { setIsKebabDropdownOpen(!isKebabDropdownOpen); }; const onFullKebabDropdownToggle = () => { setIsFullKebabDropdownOpen(!isFullKebabDropdownOpen); }; const onFullKebabDropdownSelect = () => { setIsFullKebabDropdownOpen(!isFullKebabDropdownOpen); }; const handleMenuKeys = (event: KeyboardEvent) => { if (!isOpen) { return; } if (menuRef.current?.contains(event.target as Node) || toggleRef.current?.contains(event.target as Node)) { if (event.key === 'Escape') { setIsOpen(!isOpen); toggleRef.current?.focus(); } } }; const handleClickOutside = (event: MouseEvent) => { if (isOpen && !menuRef.current?.contains(event.target as Node)) { setIsOpen(false); } }; const onToggleClick = (ev: React.MouseEvent) => { ev.stopPropagation(); // Stop handleClickOutside from handling setTimeout(() => { if (menuRef.current) { const firstElement = menuRef.current.querySelector( 'li > button:not(:disabled), li > a:not(:disabled), input:not(:disabled)' ); firstElement && (firstElement as HTMLElement).focus(); setRefFullOptions(Array.from(menuRef.current.querySelectorAll('li:not(li[role=separator])>*:first-child'))); } }, 0); setIsOpen(!isOpen); }; React.useEffect(() => { window.addEventListener('keydown', handleMenuKeys); window.addEventListener('click', handleClickOutside); return () => { window.removeEventListener('keydown', handleMenuKeys); window.removeEventListener('click', handleClickOutside); }; }, [isOpen, menuRef]); const toggle = ( ); const menuItems = [ Application 1 ev.preventDefault()} > Application 2 , , } > @reach/router Link } component={(props) => } > @reach/router Link with icon , , Launch Application 3} position="right"> Application 3 with tooltip Unavailable Application ]; const createFavorites = (favIds: string[]) => { const favorites: unknown[] = []; menuItems.forEach((item) => { if (item.type === MenuList) { item.props.children.filter((child) => { if (favIds.includes(child.props.itemId)) { favorites.push(child); } }); } else if (item.type === MenuGroup) { item.props.children.props.children.filter((child) => { if (favIds.includes(child.props.itemId)) { favorites.push(child); } }); } else { if (favIds.includes(item.props.itemId)) { favorites.push(item); } } }); return favorites; }; const filterItems = (items: any[], filteredIds: string[]) => { if (filteredIds.length === 1 && filteredIds[0] === '*') { return items; } let keepDivider = false; const filteredCopy = items .map((group) => { if (group.type === MenuGroup) { const filteredGroup = React.cloneElement(group, { children: React.cloneElement(group.props.children, { children: group.props.children.props.children.filter((child) => { if (filteredIds.includes(child.props.itemId)) { return child; } }) }) }); const filteredList = filteredGroup.props.children; if (filteredList.props.children.length > 0) { keepDivider = true; return filteredGroup; } else { keepDivider = false; } } else if (group.type === MenuList) { const filteredGroup = React.cloneElement(group, { children: group.props.children.filter((child) => { if (filteredIds.includes(child.props.itemId)) { return child; } }) }); if (filteredGroup.props.children.length > 0) { keepDivider = true; return filteredGroup; } else { keepDivider = false; } } else { if ((keepDivider && group.type === Divider) || filteredIds.includes(group.props.itemId)) { return group; } } }) .filter((newGroup) => newGroup); if (filteredCopy.length > 0) { const lastGroup = filteredCopy.pop(); if (lastGroup.type !== Divider) { filteredCopy.push(lastGroup); } } return filteredCopy; }; const onTextChange = (textValue: string) => { if (textValue === '') { setFilteredIds(['*']); return; } const filteredIds = refFullOptions ?.filter((item) => (item as HTMLElement).innerText.toLowerCase().includes(textValue.toString().toLowerCase())) .map((item) => item.id) || []; setFilteredIds(filteredIds); }; const onFavorite = (event: any, itemId: string, actionId: string) => { event.stopPropagation(); if (actionId === 'fav') { const isFavorite = favorites.includes(itemId); if (isFavorite) { setFavorites(favorites.filter((fav) => fav !== itemId)); } else { setFavorites([...favorites, itemId]); } } }; const filteredFavorites = filterItems(createFavorites(favorites), filteredIds); const filteredItems = filterItems(menuItems, filteredIds); if (filteredItems.length === 0) { filteredItems.push(No results found); } const menu = ( // eslint-disable-next-line no-console console.log('selected', itemId)}> onTextChange(value)} /> {filteredFavorites.length > 0 && ( {filteredFavorites} )} {filteredItems} ); const dashboardBreadcrumb = ( Section home Section title Section title Section landing ); const kebabDropdownItems = ( <> Settings Help ); const userDropdownItems = [ <> My profile User management Logout ]; const headerToolbar = (