/** * @fileOverview Default Legend Content */ import React, { PureComponent, ReactNode, MouseEvent, ReactText, ReactElement } from 'react'; import classNames from 'classnames'; import { Surface } from '../container/Surface'; import { Symbols } from '../shape/Symbols'; import { DataKey, LegendType, LayoutType, SymbolType, adaptEventsOfChild, PresentationAttributesAdaptChildEvent, } from '../util/types'; const SIZE = 32; export type ContentType = ReactElement | ((props: Props) => ReactNode); export type IconType = Omit; export type HorizontalAlignmentType = 'center' | 'left' | 'right'; export type VerticalAlignmentType = 'top' | 'bottom' | 'middle'; export type Formatter = ( value: any, entry: { value: any; id?: string; type?: LegendType; color?: string; payload?: { strokeDasharray: ReactText; }; }, index: number, ) => ReactNode; export interface Payload { value: any; id?: string; type?: LegendType; color?: string; payload?: { strokeDasharray: ReactText; }; formatter?: Formatter; inactive?: boolean; legendIcon?: ReactElement; } interface InternalProps { content?: ContentType; iconSize?: number; iconType?: IconType; layout?: LayoutType; align?: HorizontalAlignmentType; verticalAlign?: VerticalAlignmentType; payload?: Array; inactiveColor?: string; formatter?: Formatter; onMouseEnter?: (data: Payload & { dataKey?: DataKey }, index: number, event: MouseEvent) => void; onMouseLeave?: (data: Payload & { dataKey?: DataKey }, index: number, event: MouseEvent) => void; onClick?: (data: Payload & { dataKey?: DataKey }, index: number, event: MouseEvent) => void; } export type Props = InternalProps & PresentationAttributesAdaptChildEvent; export class DefaultLegendContent extends PureComponent { static displayName = 'Legend'; static defaultProps = { iconSize: 14, layout: 'horizontal', align: 'center', verticalAlign: 'middle', inactiveColor: '#ccc', }; /** * Render the path of icon * @param {Object} data Data of each legend item * @return {String} Path element */ renderIcon(data: Payload) { const { inactiveColor } = this.props; const halfSize = SIZE / 2; const sixthSize = SIZE / 6; const thirdSize = SIZE / 3; const color = data.inactive ? inactiveColor : data.color; if (data.type === 'plainline') { return ( ); } if (data.type === 'line') { return ( ); } if (data.type === 'rect') { return ( ); } if (React.isValidElement(data.legendIcon)) { const iconProps: any = { ...data }; delete iconProps.legendIcon; return React.cloneElement(data.legendIcon, iconProps); } return ( ); } /** * Draw items of legend * @return {ReactElement} Items */ renderItems() { const { payload, iconSize, layout, formatter, inactiveColor } = this.props; const viewBox = { x: 0, y: 0, width: SIZE, height: SIZE }; const itemStyle = { display: layout === 'horizontal' ? 'inline-block' : 'block', marginRight: 10, }; const svgStyle = { display: 'inline-block', verticalAlign: 'middle', marginRight: 4 }; return payload.map((entry, i) => { const finalFormatter = entry.formatter || formatter; const className = classNames({ 'recharts-legend-item': true, [`legend-item-${i}`]: true, inactive: entry.inactive, }); if (entry.type === 'none') { return null; } const color = entry.inactive ? inactiveColor : entry.color; return (
  • {this.renderIcon(entry)} {finalFormatter ? finalFormatter(entry.value, entry, i) : entry.value}
  • ); }); } render() { const { payload, layout, align } = this.props; if (!payload || !payload.length) { return null; } const finalStyle = { padding: 0, margin: 0, textAlign: layout === 'horizontal' ? align : 'left', }; return (
      {this.renderItems()}
    ); } }