import * as React from 'react' import ResizeContext, { WrappingParentContext, GenericContext, MoreMenuContext, } from '../utils/context' import type { DisplayOnType } from '../utils' import { uniqueId, DISPLAY_ON_TABLET_PORTRAIT } from '../utils' import { useFocusEffect, useRovingTabIndex } from '../react-roving-tabindex' export type ToolbarItemProps = { /** * Target display of this item. Choose 'phone' to prevent collapsing. */ displayOn?: DisplayOnType /** * Expects one \`ToolbarItemView\` element and one \`MoreMenuView\` element */ children: | [ React.ReactElement>, React.ReactElement, ] | React.ReactElement> } export const ToolbarItem = React.memo( ({ children, displayOn = DISPLAY_ON_TABLET_PORTRAIT, }: ToolbarItemProps) => { const { shouldDisplay } = React.useContext(ResizeContext) const showMoreMenuItem = shouldDisplay(displayOn) const state = React.useMemo( () => ({ displayOn, showMoreMenuItem }), [displayOn, showMoreMenuItem] ) return ( {children} ) }, (prev, next) => prev.children === next.children && prev.displayOn === next.displayOn ) ToolbarItem.displayName = 'ToolbarItem' type ToolbarItemViewProps = { /** * @deprecated This had been introduced as a temporary fix. We plan to * fix more fully in a future release which will result in this prop being removed. */ refOverride?: React.MutableRefObject /** * @deprecated Pass disabled state directly to the child */ disabled?: boolean /** * Render-prop function to return children */ children: ( ref: React.MutableRefObject, props: { /** @deprecated Pass disabled state directly to the child */ disabled?: boolean showLabels: boolean toolbarItemProps: { onKeyDown: React.KeyboardEventHandler onClick: React.MouseEventHandler tabIndex: number focused: boolean } } ) => React.JSX.Element } function ChildWrap({ refOverride, children, disabled, }: ToolbarItemViewProps) { const { showLabels } = React.useContext(ResizeContext) const innerRef: React.MutableRefObject = React.useRef(null) const ref = refOverride ?? innerRef const [tabIndex, focused, handleKeyDown, handleClick] = useRovingTabIndex( ref as React.RefObject, false ) useFocusEffect(focused, ref as React.RefObject) return children(ref, { showLabels, disabled, toolbarItemProps: { tabIndex, focused, onKeyDown: handleKeyDown, onClick: handleClick, }, }) } export function ToolbarItemView( props: ToolbarItemViewProps ) { const { inMoreMenuSection } = React.useContext(MoreMenuContext) const { showMoreMenuItem } = React.useContext(GenericContext) const { wrappedInToolbarParent } = React.useContext(WrappingParentContext) return inMoreMenuSection && showMoreMenuItem && !wrappedInToolbarParent ? null : ( {props.children} ) } export type ToolbarItemCollapsedViewProps = { /** * Needs to be a compatible child to the pv-uikit Dropdown component */ children: React.ReactElement } export const ToolbarItemCollapsedView = React.memo( ({ children }: ToolbarItemCollapsedViewProps) => { const { displayOn } = React.useContext(GenericContext) const { wrappedInToolbarParent } = React.useContext( WrappingParentContext ) const { dispatch } = React.useContext(MoreMenuContext) const idRef = React.useRef(null) const getId = () => { if (!idRef.current) { idRef.current = uniqueId() } return idRef.current } React.useEffect(() => { const id = getId() if (!wrappedInToolbarParent) { dispatch({ type: 'REGISTER_CHILD', child: children, displayOn, id, }) } return () => { dispatch({ type: 'UNREGISTER_CHILD', id }) } // eslint-disable-next-line react-hooks/exhaustive-deps }, []) React.useEffect(() => { if (!wrappedInToolbarParent) { dispatch({ type: 'UPDATE_CHILD', child: children, id: getId(), displayOn, }) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [children, displayOn]) return null } ) ToolbarItemCollapsedView.displayName = 'ToolbarItemCollapsedView'