import { IEmojiIcon } from '@vev/utils'; import { isString } from 'lodash'; import React, { ReactNode, useEffect, useMemo, useRef, useState } from 'react'; import { SilkeButton } from '../silke-button'; import { BoxButtonProps, BoxLinkProps, SilkeBox } from '../silke-box'; import ButtonContext from '../silke-button/context'; import { SilkeIcon, SilkeIcons } from '../silke-icon'; import { SilkeImage } from '../silke-image'; import { SilkeText } from '../silke-text'; import styles from './silke-navigation-link.scss'; import { SilkeColor } from '../../silke-theme-provider'; import { SilkeContextMenu, SilkeContextMenuItems } from '../silke-context-menu'; type SilkeNavigationLinkProps = { active?: boolean; icon?: IEmojiIcon | SilkeIcons | React.ReactElement; label: ReactNode; subLabel?: string; linkClassName?: string; draggable?: boolean; color?: SilkeColor; items?: React.ReactElement[]; menu?: SilkeContextMenuItems; /** * Buttons/icons shown only on hover */ rightButtons?: ReactNode; expanded?: boolean; } & ( | ({ link: string } & Omit) | ({ link?: undefined } & Omit) ); export const SilkeNavigationLink = React.forwardRef( ( { active, icon, label, subLabel, className, linkClassName, children, link, rightButtons, color, draggable, expanded, items, menu = [], ...rest }: SilkeNavigationLinkProps, ref: React.ForwardedRef, ) => { const [expand, setExpand] = useState(false); const [openMenu, setOpenMenu] = useState(false); const menuRef = useRef(null); const cl = [styles.main]; const linkClass = [styles.link]; const hasItems = !!items?.length; if (className) cl.push(className); if (active) cl.push(styles.active); if (rightButtons) cl.push(styles.hasRightButtons); if (color) linkClass.push(styles[color]); if (linkClassName) linkClass.push(linkClassName); if (expanded) cl.push(styles.expanded); const toggleExpand = useMemo( () => (e: React.MouseEvent) => { e.stopPropagation(); e.preventDefault(); setExpand(!expand); }, [expand], ); const toggleMenu = useMemo( () => (e: React.MouseEvent) => { e.stopPropagation(); e.preventDefault(); setOpenMenu(!openMenu); }, [openMenu], ); useEffect(() => { if (active) setExpand(true); }, [active]); return ( setExpand(true)} > ), } : { tag: 'button', type: 'button', ...(rest as Omit), })} className={linkClass.join(' ')} flex vAlign="center" gap="s" vPad={subLabel ? 'xxs' : undefined} > {draggable && ( )} {icon ? ( {React.isValidElement(icon) || isString(icon) ? ( ) : ( )} ) : ( )} {label || 'just a link'} {subLabel && ( {subLabel} )} {children || rightButtons ? ( {children} {rightButtons && (
e.stopPropagation()} > {rightButtons}
)}
) : null} {(hasItems || !!menu.length) && ( {!!menu.length && ( { e.stopPropagation(); e.preventDefault(); }} ref={menuRef} icon="menuMore" kind="ghost" size="s" /> )} {hasItems && ( )} )} {openMenu && ( setOpenMenu(false)} /> )}
{hasItems && expand && ( {items?.map((item) => { if (React.isValidElement(item)) { return item; } return false; })} )}
); }, ); SilkeNavigationLink.displayName = 'SilkeNavigationLink';