import * as React from 'react'; import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/AppLauncher/app-launcher'; import ThIcon from '@patternfly/react-icons/dist/esm/icons/th-icon'; import { DropdownDirection, DropdownPosition, DropdownToggle, DropdownContext } from '../Dropdown'; import { DropdownWithContext } from '../Dropdown/DropdownWithContext'; import { ApplicationLauncherGroup } from './ApplicationLauncherGroup'; import { ApplicationLauncherSeparator } from './ApplicationLauncherSeparator'; import { ApplicationLauncherItem } from './ApplicationLauncherItem'; import { ApplicationLauncherContext } from './ApplicationLauncherContext'; import { createRenderableFavorites, extendItemsWithFavorite } from '../../../helpers/favorites'; import { SearchInput } from '../../../components/SearchInput'; export interface ApplicationLauncherProps extends React.HTMLProps { /** Additional element css classes */ className?: string; /** Display menu above or below dropdown toggle */ direction?: DropdownDirection | 'up' | 'down'; /** Array of application launcher items */ items?: React.ReactNode[]; /** Render Application launcher toggle as disabled icon */ isDisabled?: boolean; /** open bool */ isOpen?: boolean; /** Indicates where menu will be alligned horizontally */ position?: DropdownPosition | 'right' | 'left'; /** Function callback called when user selects item */ onSelect?: (event: any) => void; /** Callback called when application launcher toggle is clicked */ onToggle?: ( event: MouseEvent | TouchEvent | KeyboardEvent | React.KeyboardEvent | React.MouseEvent, isOpen: boolean ) => void; /** Adds accessible text to the button. Required for plain buttons */ 'aria-label'?: string; /** Flag to indicate if application launcher has groups */ isGrouped?: boolean; /** Toggle Icon, optional to override the icon used for the toggle */ toggleIcon?: React.ReactNode; /** The container to append the menu to. Defaults to 'inline'. * If your menu is being cut off you can append it to an element higher up the DOM tree. * Some examples: * menuAppendTo="parent" * menuAppendTo={() => document.body} * menuAppendTo={document.getElementById('target')} */ menuAppendTo?: HTMLElement | (() => HTMLElement) | 'inline' | 'parent'; /** ID list of favorited ApplicationLauncherItems */ favorites?: string[]; /** Enables favorites. Callback called when an ApplicationLauncherItem's favorite button is clicked */ onFavorite?: (event: React.MouseEvent, itemId: string, isFavorite: boolean) => void; /** Enables search. Callback called when text input is entered into search box */ onSearch?: (event: React.FormEvent, textInput: string) => void; /** Placeholder text for search input */ searchPlaceholderText?: string; /** Text for search input when no results are found */ searchNoResultsText?: string; /** Additional properties for search input */ searchProps?: any; /** Label for the favorites group */ favoritesLabel?: string; /** ID of toggle */ toggleId?: string; /** z-index of the application launcher when menuAppendTo is not inline. */ zIndex?: number; } class ApplicationLauncher extends React.Component { static displayName = 'ApplicationLauncher'; static defaultProps: ApplicationLauncherProps = { className: '', isDisabled: false, direction: DropdownDirection.down, favorites: [] as string[], items: [] as React.ReactNode[], isOpen: false, position: DropdownPosition.left, /* eslint-disable @typescript-eslint/no-unused-vars */ onSelect: (_event: any): any => undefined, onToggle: (_event: any, _value: boolean): any => undefined, /* eslint-enable @typescript-eslint/no-unused-vars */ 'aria-label': 'Application launcher', isGrouped: false, toggleIcon: , searchPlaceholderText: 'Filter by name...', searchNoResultsText: 'No results found', favoritesLabel: 'Favorites', menuAppendTo: 'inline' }; createSearchBox = () => { const { onSearch, searchPlaceholderText, searchProps } = this.props; return (
} >
); }; render() { const { 'aria-label': ariaLabel, isOpen, onToggle, toggleIcon, toggleId, onSelect, isDisabled, className, isGrouped, favorites, onFavorite, onSearch, items, /* eslint-disable @typescript-eslint/no-unused-vars */ searchPlaceholderText, searchProps, ref, /* eslint-enable @typescript-eslint/no-unused-vars */ favoritesLabel, searchNoResultsText, menuAppendTo, zIndex = 9999, ...props } = this.props; let renderableItems: React.ReactNode[] = []; if (onFavorite) { let favoritesGroup: React.ReactNode[] = []; let renderableFavorites: React.ReactNode[] = []; if (favorites.length > 0) { renderableFavorites = createRenderableFavorites(items, isGrouped, favorites, true); favoritesGroup = [ {renderableFavorites} ]; } if (renderableFavorites.length > 0) { renderableItems = favoritesGroup.concat(extendItemsWithFavorite(items, isGrouped, favorites)); } else { renderableItems = extendItemsWithFavorite(items, isGrouped, favorites); } } else { renderableItems = items; } if (items.length === 0) { renderableItems = [ {searchNoResultsText} ]; } if (onSearch) { renderableItems = [this.createSearchBox(), ...renderableItems]; } return ( {toggleIcon} } isGrouped={isGrouped} /> ); } } export { ApplicationLauncher };