import React, { type ReactNode, useMemo } from 'react'; import cx from 'classnames'; import { Icon } from '../../ui/icon'; import { HoverCard } from '../../ui/hover-card'; import { Tooltip } from '../../ui/tooltip'; import { Skeleton } from '../../ui/skeleton'; import { FlexStack } from '../../layout/flex-stack'; import { Stack } from '../../layout/stack'; import { Metric } from '../metric'; import { Delta } from '../delta'; import css from './run-info.module.css'; // Separate value and unit const EXTRACT_VALUE_UNIT_PATTERN = /([\d|.|,| ]*)(\w*|%)$/; const getMetricParams = (value: string): [string, string?] => { const matches = value.match(EXTRACT_VALUE_UNIT_PATTERN); if (!matches) { return [value]; } return [matches[1], matches[2]]; }; export interface RunInfoProps { title?: ReactNode; titleHoverCard?: ReactNode; titleTooltip?: ReactNode; current?: ReactNode; baseline?: string; delta?: string; deltaPercentage?: string; deltaType?: string; as?: React.ElementType; size?: 'small' | 'medium' | 'large' | 'xlarge'; showBaseline?: boolean; loading?: boolean; enhance?: boolean; } export const RunInfo = ({ className = '', title = null, titleHoverCard = null, titleTooltip = null, current = '', baseline = '', delta = '', deltaPercentage = '', deltaType = '', as: Component = 'div', size = 'medium', showBaseline = true, loading = false, enhance = false, ...restProps }: RunInfoProps & Omit, 'title'>) => { const rootClassName = cx( css.root, className, css[size], (delta || deltaPercentage) && css.showDelta, ); const currentValueParams: [ReactNode, string?] = useMemo(() => { if (!enhance || typeof current !== 'string') { return [current]; } return getMetricParams(current); }, [current, enhance]); return ( {title && ( {title} {titleHoverCard && ( } className={cx(css.titleIcon, css.titleHoverCardIcon)} > {titleHoverCard} )} {titleTooltip && ( )} )} {!loading ? ( {(delta || deltaPercentage) && ( {deltaPercentage && ( )} {delta && ( )} )} {showBaseline && } ) : ( {showBaseline && } )} ); };