import React, { FC, createContext, useContext, useMemo, ReactNode, } from 'react'; import classnames from 'classnames'; import { Icon } from './Icon'; import { useControlledValue, useEventCallback } from './hooks'; import { createFC } from './common'; import { Bivariant } from './typeUtils'; /** * */ type SalesPathItemType = 'complete' | 'current' | 'incomplete'; type SalesPathKey = string | number; /** * */ const SalesPathTypeContext = createContext('incomplete'); const SalesPathContext = createContext<{ onSelect?: Bivariant<(eventKey: SalesPathKey) => void>; activeKey?: SalesPathKey | null; }>({}); /** * */ export type SalesPathItemProps = { className?: string; eventKey?: SalesPathKey; type?: SalesPathItemType; title?: string; completedTitle?: string; }; /** * */ export const SalesPathItem: FC = (props) => { const { className, eventKey, type: type_, title, completedTitle } = props; const evaluatedType = useContext(SalesPathTypeContext); const { onSelect, activeKey } = useContext(SalesPathContext); const type = type_ ?? evaluatedType; const onItemClick = useEventCallback(() => { if (eventKey != null) { onSelect?.(eventKey); } }); const isSelected = activeKey === eventKey; const isCurrent = type === 'current'; const isActive = isSelected || (isCurrent && activeKey == null); const pathItemClassName = classnames( 'slds-path__item', { 'slds-is-complete': type === 'complete', 'slds-is-current': isCurrent, 'slds-is-incomplete': type === 'incomplete', 'slds-is-active': isActive, }, className ); const tabIndex = isActive ? 0 : -1; const completedText = completedTitle || 'Stage Complete'; return (
  • {type === 'complete' ? ( {completedText} ) : null} {isCurrent ? ( Current Stage: ) : null} {title}
  • ); }; /** * */ export type SalesPathProps = { className?: string; activeKey?: SalesPathKey; defaultActiveKey?: SalesPathKey; onSelect?: Bivariant<(itemKey: SalesPathKey) => void>; children?: ReactNode; }; /** * */ export const SalesPath = createFC< SalesPathProps, { PathItem: typeof SalesPathItem } >( (props) => { const { activeKey: activeKey_, defaultActiveKey, className, children, onSelect: onSelect_, } = props; const [activeKey, setActiveKey] = useControlledValue( activeKey_, defaultActiveKey ?? null ); const salesPathClassNames = classnames(className, 'slds-path'); const onSelect = useEventCallback((itemKey: SalesPathKey) => { onSelect_?.(itemKey); setActiveKey(itemKey); }); let activeIdx = -1; React.Children.forEach(children, (child, idx) => { if (React.isValidElement(child)) { const { eventKey } = child.props as { eventKey?: SalesPathKey; }; if (eventKey != null && eventKey === activeKey) { activeIdx = idx; } } }); const ctx = useMemo(() => ({ onSelect, activeKey }), [onSelect, activeKey]); return (
      {React.Children.map(children, (child, idx) => { const evaluatedType = idx === activeIdx ? 'current' : idx < activeIdx ? 'complete' : 'incomplete'; return ( {child} ); })}
    ); }, { PathItem: SalesPathItem } );