import * as React from 'react' import { align, theme, cursor, overflow, sizePx, spacingPx, states, text, iconSizes, useIsFocusVisible, } from '@planview/pv-utilities' import { Tooltip } from '@planview/pv-uikit' import styled from 'styled-components' //Logos import { Adaptivework, Ea, Ideaplace, Okrs, Portfolios, Projectplace, Roadmaps, Agileplace, Changepoint, Viz, Admin, PpmPro, ProjectAdvantage, ReleaseAndVerify, } from '../logos' import type { ProductType } from '../types' const MainWrap = styled.li` list-style: none; background-color: ${theme.backgroundNeutral0}; &:hover { background-color: ${theme.backgroundNeutral0Hover}; ${cursor.pointer}; } ` const StyledAnchor = styled.a<{ $focusVisible: boolean; $hasLogo: boolean }>` ${align.centerV}; box-sizing: border-box; padding-right: ${spacingPx.small}; padding-left: ${(props) => (props.$hasLogo ? '0' : spacingPx.small)}; width: 100%; height: ${sizePx.medium}; min-height: ${sizePx.medium}; overflow: hidden; text-decoration: none; ${(props) => props['aria-checked'] ? states.activeTranslucent() : 'border: 1px solid transparent'}; ${(props) => states.focus({ focusVisible: props.$focusVisible })} ` const LogoContainer = styled.div` ${align.center}; height: 100%; width: ${sizePx.medium}; flex-shrink: 0; svg { height: ${iconSizes.large}px; } ` const LabelWrap = styled.div` ${align.centerH}; flex-direction: column; overflow: hidden; ` const Label = styled.span` ${text.regular}; color: ${theme.textPrimary}; min-width: ${sizePx.medium}; ${overflow.ellipsis}; margin-right: ${spacingPx.small}; ` const SecondaryLabel = styled.span<{ $active: boolean }>` ${text.small}; color: ${({ $active }) => $active ? theme.textPrimary : theme.textSecondary}; min-width: ${sizePx.medium}; ${overflow.ellipsis}; margin-right: ${spacingPx.small}; ` type Props = { /** Primary text: Generally the product or capability name */ label: string /** Secondary, complementary label to describe what instance of the product/capability */ secondaryLabel?: string /** Used to indicate the current application the user is in */ active?: boolean /** Called when the user selects the item */ onActivate?: () => void /** A product short code which ultimately maps to an icon */ app: ProductType /** @internal Used to manage the roving tab index */ tabIndex?: number /** URL of the application. Used to enable browser shortcuts for opening in a new tab, etc, by rendering as an anchor element. */ url?: string } const getAppLogo = (app: ProductType): React.JSX.Element | null => { switch (app) { case 'adaptivework': return case 'changepoint': return case 'e1_prm': return case 'e1_ctm': case 'ea': return case 'leankit': return case 'teamtap': case 'spigit': return case 'ppmpro': return case 'pvadmin': return case 'projectplace': return case 'roadmaps': return case 'okrs': return case 'viz': return case 'project_advantage': return case 'plutora': case 'release_and_verify': return case 'planview_me': default: return null } } /** * Implements the [Design System specs](https://design.planview.com/components/product-switcher/product-switcher-list-item) * */ const ProductSwitcherListItem = ({ app, label, secondaryLabel, active, onActivate, tabIndex = -1, url, }: Props): React.ReactElement => { const outerRef = React.useRef(undefined) const { innerRef: _innerRef, focusVisible, ...focusProps } = useIsFocusVisible() const SetOuterRef = React.useCallback( (el: HTMLAnchorElement) => { if (el) { outerRef.current = el if (tabIndex === 0) { el.focus() } } }, [tabIndex] ) const handleKeyDown: React.KeyboardEventHandler = React.useCallback( (ev) => { if ( ev.key === 'Enter' || ev.key === 'Space' || ev.key === ' ' ) { if (ev.key === ' ') { ev.preventDefault() } onActivate?.() } }, [onActivate] ) React.useEffect(() => { if (tabIndex === 0 && outerRef.current) { outerRef.current.focus() } }, [tabIndex]) const logo = getAppLogo(app) return ( { ev.preventDefault() onActivate?.() }} href={url} $hasLogo={!!logo} > {logo && {logo}} {secondaryLabel ? ( {secondaryLabel} ) : null} ) } export { ProductSwitcherListItem } export default ProductSwitcherListItem