import * as React from 'react' import { ButtonPrimary, ButtonEmpty, ButtonGhost, ButtonDestructive, ButtonEmptyInverse, ButtonAnviPrimary, ButtonAnviEmpty, ButtonAnviEmptyInverse, ButtonAnviGhost, ListItem, } from '@planview/pv-uikit' import type { ButtonProps } from '@planview/pv-uikit' import { ToolbarItem, ToolbarItemCollapsedView, ToolbarItemView, } from '../wrapper/' import type { DisplayOnType } from '../utils/' import { useMergeRefs } from '../utils/refs' export type ToolbarButtonProps = Omit< ButtonProps, 'tabIndex' | 'children' | 'onClick' | 'size' > & { /** * Target display of the button. Choose 'phone' to prevent collapsing. */ displayOn?: DisplayOnType /** * Opt-in to override built-in behavior to remove the visible label of buttons in mobile breakpoint. * Set this to true to always show the visible label of button */ preventLabelCollapse?: boolean /** * Limit the children more strictly since a string is required when converting to a list item and for adding an aria-label */ children?: string | number /** Callback for when a user clicks on the button or activates it in the mobile menu. When activated from the collapsed menu, no event will be passed. */ onClick?: (e?: React.MouseEvent) => void } const getAriaLabel = ( props: ToolbarButtonProps, showLabels: boolean, children?: string | number, preventLabelCollapse = false ): string | undefined => { if (props['aria-label']) { return props['aria-label'] } if (!children && props.tooltip) { return props.tooltip } else if (!showLabels && children && !preventLabelCollapse) { return children as string } return undefined } const asToolbarButton = (ElementType: typeof ButtonPrimary) => { const ForwardRefComponent: React.ForwardRefRenderFunction< HTMLButtonElement | undefined, ToolbarButtonProps > = ( { children, onClick, onKeyDown, preventLabelCollapse = false, displayOn, ...otherProps }: ToolbarButtonProps, ref ) => { const buttonRef = React.useRef(null) const mergedRef = useMergeRefs([ref, buttonRef]) return ( refOverride={buttonRef}> {( _ref, { toolbarItemProps: { focused: _focused, ...toolbarItemProps }, showLabels, } ) => { const showTooltip = !!otherProps.tooltip || (!showLabels && !!children && !!otherProps.icon) const disabled = !!otherProps.disabled return ( { toolbarItemProps.onClick(ev) if (onClick && !disabled) { onClick(ev) } }} disabled={false} //otherProps can/will contain disabled flag we do NOT want on the button since it will mess with the listeners for roving tab index management aria-disabled={ !!disabled || otherProps['aria-disabled'] } //We explicitly pass the aria-disabled to the ui-kit button to make it look disabled. onKeyDown={(ev) => { toolbarItemProps.onKeyDown(ev) if (onKeyDown && !disabled) { onKeyDown(ev) } }} tooltip={ showTooltip ? otherProps.tooltip || (children as string) : undefined } aria-label={getAriaLabel( otherProps, showLabels, children, preventLabelCollapse )} > {!showLabels && otherProps.icon && !preventLabelCollapse ? undefined : children} ) }} { if (onClick) { onClick() } }} /> ) } return ForwardRefComponent } export const ToolbarButtonDestructive = React.forwardRef( asToolbarButton(ButtonDestructive) ) export const ToolbarButtonPrimary = React.forwardRef( asToolbarButton(ButtonPrimary) ) export const ToolbarButtonEmpty = React.forwardRef(asToolbarButton(ButtonEmpty)) export const ToolbarButtonGhost = React.forwardRef(asToolbarButton(ButtonGhost)) export const ToolbarButtonEmptyInverse = React.forwardRef( asToolbarButton(ButtonEmptyInverse) ) export const ToolbarButtonAnviPrimary = React.forwardRef( asToolbarButton(ButtonAnviPrimary) ) export const ToolbarButtonAnviEmpty = React.forwardRef( asToolbarButton(ButtonAnviEmpty) ) export const ToolbarButtonAnviEmptyInverse = React.forwardRef( asToolbarButton(ButtonAnviEmptyInverse) ) export const ToolbarButtonAnviGhost = React.forwardRef( asToolbarButton(ButtonAnviGhost) )