ChartToolbox.tsx 3.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
import React, {FunctionComponent, useCallback, useState} from 'react';
import {
    WithStyled,
    em,
    primaryActiveColor,
    primaryColor,
    primaryFocusedColor,
    rem,
    textColor,
    textLightColor,
    textLighterColor,
    tooltipBackgroundColor,
    tooltipTextColor,
    transitionProps
} from '~/utils/style';

import Icon from '~/components/Icon';
import ReactTooltip from 'react-tooltip';
import {nanoid} from 'nanoid';
import styled from 'styled-components';

P
Peter Pan 已提交
22
const Toolbox = styled.div<{reversed?: boolean}>`
23 24 25
    font-size: ${em(16)};
    line-height: 1;
    display: flex;
P
Peter Pan 已提交
26 27
    flex-direction: ${props => (props.reversed ? 'row-reverse' : 'row')};
    align-items: center;
28 29
`;

P
Peter Pan 已提交
30
const ToolboxItem = styled.a<{active?: boolean; reversed?: boolean}>`
31 32 33 34 35 36 37 38 39 40 41 42 43
    cursor: pointer;
    color: ${props => (props.active ? primaryColor : textLighterColor)};
    ${transitionProps('color')}

    &:hover {
        color: ${props => (props.active ? primaryFocusedColor : textLightColor)};
    }

    &:active {
        color: ${props => (props.active ? primaryActiveColor : textColor)};
    }

    & + & {
P
Peter Pan 已提交
44
        ${props => `margin-${props.reversed ? 'right' : 'left'}: ${rem(14)};`}
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
    }
`;

type BaseChartToolboxItem = {
    icon: string;
    tooltip?: string;
};

type NormalChartToolboxItem = {
    toggle?: false;
    onClick?: () => unknown;
} & BaseChartToolboxItem;

type ToggleChartToolboxItem = {
    toggle: true;
    activeIcon?: string;
    activeTooltip?: string;
    onClick?: (value: boolean) => unknown;
} & BaseChartToolboxItem;

export type ChartTooboxItem = NormalChartToolboxItem | ToggleChartToolboxItem;

type ChartToolboxProps = {
    cid?: string;
    items: ChartTooboxItem[];
P
Peter Pan 已提交
70 71
    reversed?: boolean;
    tooltipPlace?: 'top' | 'bottom' | 'left' | 'right';
72 73
};

P
Peter Pan 已提交
74 75 76 77 78 79 80
const ChartToolbox: FunctionComponent<ChartToolboxProps & WithStyled> = ({
    cid,
    items,
    reversed,
    tooltipPlace,
    className
}) => {
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
    const [activeStatus, setActiveStatus] = useState<boolean[]>(new Array(items.length).fill(false));
    const onClick = useCallback(
        (index: number) => {
            const item = items[index];
            if (item.toggle) {
                item.onClick?.(!activeStatus[index]);
                setActiveStatus(m => {
                    const n = [...m];
                    n.splice(index, 1, !m[index]);
                    return n;
                });
            } else {
                item.onClick?.();
            }
        },
        [items, activeStatus]
    );

    const [id] = useState(`chart-toolbox-tooltip-${cid || nanoid()}`);

    return (
        <>
P
Peter Pan 已提交
103
            <Toolbox className={className} reversed={reversed}>
104 105 106
                {items.map((item, index) => (
                    <ToolboxItem
                        key={index}
P
Peter Pan 已提交
107
                        reversed={reversed}
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
                        active={item.toggle && !item.activeIcon && activeStatus[index]}
                        onClick={() => onClick(index)}
                        data-for={item.tooltip ? id : null}
                        data-tip={
                            item.tooltip
                                ? item.toggle
                                    ? (activeStatus[index] && item.activeTooltip) || item.tooltip
                                    : item.tooltip
                                : null
                        }
                    >
                        <Icon type={item.toggle ? (activeStatus[index] && item.activeIcon) || item.icon : item.icon} />
                    </ToolboxItem>
                ))}
            </Toolbox>
            <ReactTooltip
                id={id}
P
Peter Pan 已提交
125
                place={tooltipPlace ?? 'top'}
126 127 128 129 130 131 132 133 134
                textColor={tooltipTextColor}
                backgroundColor={tooltipBackgroundColor}
                effect="solid"
            />
        </>
    );
};

export default ChartToolbox;