/** * @fileOverview Default Tooltip Content */ import _ from 'lodash'; import React, { PureComponent, CSSProperties, ReactNode } from 'react'; import classNames from 'classnames'; import { isNumOrStr } from '../util/DataUtils'; function defaultFormatter(value: TValue) { return _.isArray(value) && isNumOrStr(value[0]) && isNumOrStr(value[1]) ? (value.join(' ~ ') as TValue) : value; } export type TooltipType = 'none'; export type ValueType = number | string | Array; export type NameType = number | string; export type Formatter = ( value: TValue, name: TName, item: Payload, index: number, payload: Array>, ) => [TValue, TName] | TValue; export interface Payload { type?: TooltipType; color?: string; formatter?: Formatter; name?: TName; value?: TValue; unit?: ReactNode; dataKey?: string | number; payload?: any; chartType?: string; } export interface Props { separator?: string; wrapperClassName?: string; labelClassName?: string; formatter?: Formatter; contentStyle?: CSSProperties; itemStyle?: CSSProperties; labelStyle?: CSSProperties; labelFormatter?: (label: any, payload: Array>) => ReactNode; label?: any; payload?: Array>; itemSorter?: (item: Payload) => number | string; } export class DefaultTooltipContent extends PureComponent< Props > { static displayName = 'DefaultTooltipContent'; static defaultProps = { separator: ' : ', contentStyle: {}, itemStyle: {}, labelStyle: {}, }; renderContent() { const { payload, separator, formatter, itemStyle, itemSorter } = this.props; if (payload && payload.length) { const listStyle = { padding: 0, margin: 0 }; const items = (itemSorter ? _.sortBy(payload, itemSorter) : payload).map((entry, i) => { if (entry.type === 'none') { return null; } const finalItemStyle = { display: 'block', paddingTop: 4, paddingBottom: 4, color: entry.color || '#000', ...itemStyle, }; const finalFormatter = entry.formatter || formatter || defaultFormatter; let { value, name } = entry; if (finalFormatter && value && name) { const formatted = finalFormatter(value, name, entry, i, payload); if (Array.isArray(formatted)) { [value, name] = formatted as [TValue, TName]; } else { value = formatted; } } return ( // eslint-disable-next-line react/no-array-index-key
  • {isNumOrStr(name) ? {name} : null} {isNumOrStr(name) ? {separator} : null} {value} {entry.unit || ''}
  • ); }); return (
      {items}
    ); } return null; } render() { const { wrapperClassName, contentStyle, labelClassName, labelStyle, label, labelFormatter, payload } = this.props; const finalStyle: CSSProperties = { margin: 0, padding: 10, backgroundColor: '#fff', border: '1px solid #ccc', whiteSpace: 'nowrap', ...contentStyle, }; const finalLabelStyle = { margin: 0, ...labelStyle, }; const hasLabel = !_.isNil(label); let finalLabel = hasLabel ? label : ''; const wrapperCN = classNames('recharts-default-tooltip', wrapperClassName); const labelCN = classNames('recharts-tooltip-label', labelClassName); if (hasLabel && labelFormatter && payload !== undefined && payload !== null) { finalLabel = labelFormatter(label, payload); } return (

    {React.isValidElement(finalLabel) ? finalLabel : `${finalLabel}`}

    {this.renderContent()}
    ); } }