feat: time event chart legend add some interaction

This commit is contained in:
moonrailgun 2024-10-04 22:01:43 +08:00
parent f3d8f5543d
commit 4b7877155f
2 changed files with 31 additions and 4 deletions

View File

@ -1,6 +1,6 @@
import { useTheme } from '../hooks/useTheme'; import { useTheme } from '../hooks/useTheme';
import { DateUnit } from '@tianji/shared'; import { DateUnit } from '@tianji/shared';
import React from 'react'; import React, { useState } from 'react';
import { formatDateWithUnit } from '../utils/date'; import { formatDateWithUnit } from '../utils/date';
import { import {
Area, Area,
@ -42,6 +42,7 @@ export const TimeEventChart: React.FC<{
const lineDasharray = strokeDasharray.find((s) => s.name === name); const lineDasharray = strokeDasharray.find((s) => s.name === name);
return lineDasharray ? lineDasharray.strokeDasharray : undefined; return lineDasharray ? lineDasharray.strokeDasharray : undefined;
}; };
const [selectedItem, setSelectedItem] = useState<string[]>(['pv', 'uv']);
return ( return (
<ChartContainer config={chartConfig}> <ChartContainer config={chartConfig}>
@ -65,10 +66,27 @@ export const TimeEventChart: React.FC<{
tickFormatter={(text) => formatDateWithUnit(text, props.unit)} tickFormatter={(text) => formatDateWithUnit(text, props.unit)}
/> />
<YAxis mirror /> <YAxis mirror />
<ChartLegend content={<ChartLegendContent />} /> <ChartLegend
content={
<ChartLegendContent
selectedItem={selectedItem}
onItemClick={(item) => {
setSelectedItem((selected) => {
if (selected.includes(item.value)) {
return selected.filter((s) => s !== item.value);
} else {
return [...selected, item.value];
}
});
}}
/>
}
/>
<CartesianGrid vertical={false} /> <CartesianGrid vertical={false} />
<ChartTooltip content={<ChartTooltipContent />} /> <ChartTooltip content={<ChartTooltipContent />} />
<Area <Area
hide={!selectedItem.includes('pv')}
type="monotone" type="monotone"
dataKey="pv" dataKey="pv"
stroke={colors.chart.pv} stroke={colors.chart.pv}
@ -78,7 +96,9 @@ export const TimeEventChart: React.FC<{
strokeDasharray={getStrokeDasharray('pv')} strokeDasharray={getStrokeDasharray('pv')}
onAnimationEnd={handleAnimationEnd} onAnimationEnd={handleAnimationEnd}
/> />
<Area <Area
hide={!selectedItem.includes('uv')}
type="monotone" type="monotone"
dataKey="uv" dataKey="uv"
stroke={colors.chart.uv} stroke={colors.chart.uv}

View File

@ -261,16 +261,20 @@ ChartTooltipContent.displayName = "ChartTooltip"
const ChartLegend = RechartsPrimitive.Legend const ChartLegend = RechartsPrimitive.Legend
type Payload = NonNullable<RechartsPrimitive.LegendProps['payload']>[number]
const ChartLegendContent = React.forwardRef< const ChartLegendContent = React.forwardRef<
HTMLDivElement, HTMLDivElement,
React.ComponentProps<"div"> & React.ComponentProps<"div"> &
Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & { Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & {
hideIcon?: boolean hideIcon?: boolean
nameKey?: string nameKey?: string
} & {
selectedItem?: string[]
onItemClick?: (item: Payload) => void
} }
>( >(
( (
{ className, hideIcon = false, payload, verticalAlign = "bottom", nameKey }, { className, hideIcon = false, payload, verticalAlign = "bottom", nameKey, selectedItem, onItemClick },
ref ref
) => { ) => {
const { config } = useChart() const { config } = useChart()
@ -296,8 +300,11 @@ const ChartLegendContent = React.forwardRef<
<div <div
key={item.value} key={item.value}
className={cn( className={cn(
"flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground" "flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground",
typeof onItemClick === 'function' && 'cursor-pointer',
selectedItem?.includes(item.value) && 'font-bold',
)} )}
onClick={() => onItemClick?.(item)}
> >
{itemConfig?.icon && !hideIcon ? ( {itemConfig?.icon && !hideIcon ? (
<itemConfig.icon /> <itemConfig.icon />