import * as React from 'react' import type { IconProps } from '@planview/pv-icons' import type { DropdownTriggerProps } from '@planview/pv-uikit' import { ButtonEmpty, ButtonEmptyInverse, Tooltip } from '@planview/pv-uikit' import { useRovingTabIndex, useFocusEffect } from '../react-roving-tabindex' import type { MoreMenuChildType } from '../utils/context' import { MoreMenuContext, useMainNavigationContext } from '../utils/context' import { useMergeRefs } from '../utils/refs' export const COLLAPSE_BELOW = 'below' export const COLLAPSE_ABOVE = 'above' export type ToolbarMoreMenuProps = { /** Custom icon component for use to override the icon in the more-menu dropdown trigger (which internally uses ToolbarButtonEmpty) */ icon?: React.ReactElement /** Content to render. Accepts any valid child of a List from the ui-kit */ children: MoreMenuChildType[] | MoreMenuChildType /** Where to add items collapsed into more menu, above or below the given content */ collapse?: typeof COLLAPSE_ABOVE | typeof COLLAPSE_BELOW } /** * * `import { ToolbarMoreMenu } from '@planview/pv-toolbar'` * * In some cases you need the more menu at all times present with items already added in the \`ToolbarSectionRight\`. * Use the \`ToolbarMoreMenu\` component to handle this. * * The component let's you: * - Set your own default dropdown content (all ui-kit dropdown components are valid children) * - Set your custom icon for the dropdown-trigger * * By default, all subsequent collapsed content from the toolbar section will be moved __above__ the default content, but this can be changed using the \`collapse\` prop * * _Note: this component **only** works as a child of the \`ToolbarSectionRight\` component_ * */ export function ToolbarMoreMenu({ children, icon, collapse = COLLAPSE_ABOVE, }: ToolbarMoreMenuProps) { const { dispatch } = React.useContext(MoreMenuContext) React.useEffect(() => { dispatch({ type: 'REGISTER_MORE_MENU_CONTENT', children: React.Children.map(children, (c) => c), collapse, icon, }) return () => { dispatch({ type: 'UNREGISTER_MORE_MENU_CONTENT' }) } }, [children, collapse, icon, dispatch]) return null } type MoreMenuButtonProps = React.PropsWithoutRef & { label?: string icon: React.ReactElement activated: boolean } const MoreMenuButtonImpl: React.ForwardRefRenderFunction< HTMLButtonElement, MoreMenuButtonProps > = ({ label, icon, activated, ...otherProps }, incomingRef) => { const ref = React.useRef(null) const [tabIndex, focused, handleKeyDown, handleClick] = useRovingTabIndex( ref as React.RefObject, false ) const { wrappedInNavigation } = useMainNavigationContext() const ButtonType = wrappedInNavigation ? ButtonEmptyInverse : ButtonEmpty useFocusEffect(focused, ref as React.RefObject) const mergedRefs = useMergeRefs([ref, incomingRef]) return ( { otherProps.onKeyDown(e) handleKeyDown(e) }} onClick={handleClick} tabIndex={tabIndex} /> ) } export const MoreMenuButton = React.forwardRef(MoreMenuButtonImpl)