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

import Icon from '~/components/Icon';
16
import type {Icons} from '~/components/Icon';
17
import Tippy from '@tippyjs/react';
18 19
import styled from 'styled-components';

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

P
Peter Pan 已提交
29
const ToolboxItem = styled.a<{active?: boolean; reversed?: boolean}>`
30 31 32 33 34 35 36 37 38 39 40 41 42
    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 已提交
43
        ${props => `margin-${props.reversed ? 'right' : 'left'}: ${rem(14)};`}
44 45 46 47
    }
`;

type BaseChartToolboxItem = {
48
    icon: Icons;
49 50 51 52 53 54 55 56 57 58
    tooltip?: string;
};

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

type ToggleChartToolboxItem = {
    toggle: true;
59
    activeIcon?: Icons;
60 61 62 63 64 65 66 67
    activeTooltip?: string;
    onClick?: (value: boolean) => unknown;
} & BaseChartToolboxItem;

export type ChartTooboxItem = NormalChartToolboxItem | ToggleChartToolboxItem;

type ChartToolboxProps = {
    items: ChartTooboxItem[];
P
Peter Pan 已提交
68
    reversed?: boolean;
69
    tooltipPlacement?: 'top' | 'bottom' | 'left' | 'right';
70 71
};

P
Peter Pan 已提交
72
const ChartToolbox: FunctionComponent<ChartToolboxProps & WithStyled> = ({
73
    tooltipPlacement,
P
Peter Pan 已提交
74 75 76 77
    items,
    reversed,
    className
}) => {
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
    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]
    );

96 97 98 99 100 101 102 103 104 105 106 107 108
    const getToolboxItem = useCallback(
        (item: ChartTooboxItem, index: number) => (
            <ToolboxItem
                key={index}
                reversed={reversed}
                active={item.toggle && !item.activeIcon && activeStatus[index]}
                onClick={() => onClick(index)}
            >
                <Icon type={item.toggle ? (activeStatus[index] && item.activeIcon) || item.icon : item.icon} />
            </ToolboxItem>
        ),
        [activeStatus, onClick, reversed]
    );
109 110 111

    return (
        <>
P
Peter Pan 已提交
112
            <Toolbox className={className} reversed={reversed}>
113 114 115 116 117 118 119
                {items.map((item, index) =>
                    item.tooltip ? (
                        <Tippy
                            content={
                                item.toggle ? (activeStatus[index] && item.activeTooltip) || item.tooltip : item.tooltip
                            }
                            placement={tooltipPlacement || 'top'}
P
Peter Pan 已提交
120
                            theme="tooltip"
121 122 123 124 125 126 127 128
                            key={index}
                        >
                            {getToolboxItem(item, index)}
                        </Tippy>
                    ) : (
                        getToolboxItem(item, index)
                    )
                )}
129 130 131 132 133 134
            </Toolbox>
        </>
    );
};

export default ChartToolbox;