ChartToolbox.tsx 4.3 KB
Newer Older
P
Peter Pan 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/**
 * Copyright 2020 Baidu Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

17
import React, {FunctionComponent, useCallback, useState} from 'react';
P
Peter Pan 已提交
18
import {WithStyled, em, rem, transitionProps} from '~/utils/style';
19 20

import Icon from '~/components/Icon';
21
import type {Icons} from '~/components/Icon';
22
import Tippy from '@tippyjs/react';
23 24
import styled from 'styled-components';

P
Peter Pan 已提交
25
const Toolbox = styled.div<{size?: number; reversed?: boolean}>`
26 27
    font-size: ${em(16)};
    line-height: 1;
28
    height: 1em;
P
Peter Pan 已提交
29 30 31 32 33 34
    display: grid;
    grid-template-columns: ${props => (props.size == null ? 'repeat(auto-fill, 1em)' : `repeat(${props.size}, 1em)`)};
    grid-gap: ${rem(14)};
    place-items: center;
    justify-content: ${props => (props.reversed ? 'end' : 'start')};
    align-content: center;
35 36
`;

P
Peter Pan 已提交
37
const ToolboxItem = styled.a<{active?: boolean}>`
38
    cursor: pointer;
P
Peter Pan 已提交
39
    color: ${props => (props.active ? 'var(--primary-color)' : 'var(--text-lighter-color)')};
40 41 42
    ${transitionProps('color')}

    &:hover {
P
Peter Pan 已提交
43
        color: ${props => (props.active ? 'var(--primary-focused-color)' : 'var(--text-light-color)')};
44 45 46
    }

    &:active {
P
Peter Pan 已提交
47
        color: ${props => (props.active ? 'var(--primary-active-color)' : 'var(--text-color)')};
48 49 50 51
    }
`;

type BaseChartToolboxItem = {
52
    icon: Icons;
53 54 55 56 57 58 59 60 61 62
    tooltip?: string;
};

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

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

P
Peter Pan 已提交
68
export type ChartToolboxItem = NormalChartToolboxItem | ToggleChartToolboxItem;
69 70

type ChartToolboxProps = {
P
Peter Pan 已提交
71
    items: ChartToolboxItem[];
P
Peter Pan 已提交
72
    reversed?: boolean;
73
    tooltipPlacement?: 'top' | 'bottom' | 'left' | 'right';
74 75
};

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

100
    const getToolboxItem = useCallback(
P
Peter Pan 已提交
101
        (item: ChartToolboxItem, index: number) => (
102 103 104 105 106 107 108 109
            <ToolboxItem
                key={index}
                active={item.toggle && !item.activeIcon && activeStatus[index]}
                onClick={() => onClick(index)}
            >
                <Icon type={item.toggle ? (activeStatus[index] && item.activeIcon) || item.icon : item.icon} />
            </ToolboxItem>
        ),
P
Peter Pan 已提交
110
        [activeStatus, onClick]
111
    );
112 113 114

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

export default ChartToolbox;