import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/Nav/nav'; import { css } from '@patternfly/react-styles'; import { getOUIAProps, OUIAProps, getDefaultOUIAId } from '../../helpers'; export type NavSelectClickHandler = ( event: React.FormEvent, itemId: number | string, groupId: number | string, to: string ) => void; export interface NavProps extends Omit, HTMLElement>, 'onSelect'>, OUIAProps { /** Anything that can be rendered inside of the nav */ children?: React.ReactNode; /** Additional classes added to the container */ className?: string; /** Callback for updating when item selection changes */ onSelect?: ( event: React.FormEvent, selectedItem: { groupId: number | string; itemId: number | string; to: string; } ) => void; /** Callback for when a list is expanded or collapsed */ onToggle?: ( event: React.MouseEvent, toggledItem: { groupId: number | string; isExpanded: boolean; } ) => void; /** Accessible label for the nav when there are multiple navs on the page */ 'aria-label'?: string; /** Indicates which theme color to use */ theme?: 'dark' | 'light'; /** For horizontal navs */ variant?: 'default' | 'horizontal' | 'tertiary' | 'horizontal-subnav'; /** Value to overwrite the randomly generated data-ouia-component-id.*/ ouiaId?: number | string; /** Set the value of data-ouia-safe. Only set to true when the component is in a static state, i.e. no animations are occurring. At all other times, this value must be false. */ ouiaSafe?: boolean; } export interface NavContextProps { onSelect?: ( event: React.FormEvent, groupId: number | string, itemId: number | string, to: string, preventDefault: boolean, onClick: NavSelectClickHandler ) => void; onToggle?: (event: React.MouseEvent, groupId: number | string, expanded: boolean) => void; updateIsScrollable?: (isScrollable: boolean) => void; isHorizontal?: boolean; flyoutRef?: React.Ref; setFlyoutRef?: (ref: React.Ref) => void; navRef?: React.RefObject; } export const navContextDefaults = {}; export const NavContext = React.createContext(navContextDefaults); class Nav extends React.Component< NavProps, { isScrollable: boolean; ouiaStateId: string; flyoutRef: React.Ref | null } > { static displayName = 'Nav'; static defaultProps: NavProps = { onSelect: () => undefined, onToggle: () => undefined, theme: 'dark', ouiaSafe: true }; state = { isScrollable: false, ouiaStateId: getDefaultOUIAId(Nav.displayName, this.props.variant), flyoutRef: null as React.Ref }; navRef = React.createRef(); // Callback from NavItem onSelect( event: React.FormEvent, groupId: number | string, itemId: number | string, to: string, preventDefault: boolean, onClick: NavSelectClickHandler ) { if (preventDefault) { event.preventDefault(); } this.props.onSelect(event, { groupId, itemId, to }); if (onClick) { onClick(event, itemId, groupId, to); } } // Callback from NavExpandable onToggle(event: React.MouseEvent, groupId: number | string, toggleValue: boolean) { this.props.onToggle(event, { groupId, isExpanded: toggleValue }); } render() { const { 'aria-label': ariaLabel, children, className, // eslint-disable-next-line @typescript-eslint/no-unused-vars onSelect, // eslint-disable-next-line @typescript-eslint/no-unused-vars onToggle, theme, ouiaId, ouiaSafe, variant, ...props } = this.props; const isHorizontal = ['horizontal', 'tertiary'].includes(variant); return (