feat: enhance chart tooltip and legend components with improved type definitions and payload handling

This commit is contained in:
Julien Froidefond
2025-11-27 10:02:27 +01:00
parent 66c4ead350
commit c6299de8b2
5 changed files with 2405 additions and 18 deletions

View File

@@ -104,6 +104,15 @@ ${colorConfig
const ChartTooltip = RechartsPrimitive.Tooltip
type TooltipPayloadItem = {
dataKey?: string | number
name?: string
value?: number | string
color?: string
payload?: Record<string, unknown> & { fill?: string }
fill?: string
}
function ChartTooltipContent({
active,
payload,
@@ -118,13 +127,15 @@ function ChartTooltipContent({
color,
nameKey,
labelKey,
}: React.ComponentProps<typeof RechartsPrimitive.Tooltip> &
}: Omit<React.ComponentProps<typeof RechartsPrimitive.Tooltip>, 'payload' | 'label'> &
React.ComponentProps<'div'> & {
hideLabel?: boolean
hideIndicator?: boolean
indicator?: 'line' | 'dot' | 'dashed'
nameKey?: string
labelKey?: string
payload?: TooltipPayloadItem[]
label?: string | number
}) {
const { config } = useChart()
@@ -179,10 +190,10 @@ function ChartTooltipContent({
>
{!nestLabel ? tooltipLabel : null}
<div className="grid gap-1.5">
{payload.map((item, index) => {
{payload.map((item: TooltipPayloadItem, index: number) => {
const key = `${nameKey || item.name || item.dataKey || 'value'}`
const itemConfig = getPayloadConfigFromPayload(config, item, key)
const indicatorColor = color || item.payload.fill || item.color
const indicatorColor = color || item.payload?.fill || item.color
return (
<div
@@ -193,7 +204,7 @@ function ChartTooltipContent({
)}
>
{formatter && item?.value !== undefined && item.name ? (
formatter(item.value, item.name, item, index, item.payload)
formatter(item.value, item.name, item as never, index, item.payload as never)
) : (
<>
{itemConfig?.icon ? (
@@ -250,16 +261,23 @@ function ChartTooltipContent({
const ChartLegend = RechartsPrimitive.Legend
type LegendPayloadItem = {
value?: string
dataKey?: string | number
color?: string
}
function ChartLegendContent({
className,
hideIcon = false,
payload,
verticalAlign = 'bottom',
nameKey,
}: React.ComponentProps<'div'> &
Pick<RechartsPrimitive.LegendProps, 'payload' | 'verticalAlign'> & {
}: React.ComponentProps<'div'> & {
hideIcon?: boolean
nameKey?: string
payload?: LegendPayloadItem[]
verticalAlign?: 'top' | 'bottom' | 'middle'
}) {
const { config } = useChart()
@@ -275,7 +293,7 @@ function ChartLegendContent({
className,
)}
>
{payload.map((item) => {
{payload.map((item: LegendPayloadItem) => {
const key = `${nameKey || item.dataKey || 'value'}`
const itemConfig = getPayloadConfigFromPayload(config, item, key)

36
eslint.config.mjs Normal file
View File

@@ -0,0 +1,36 @@
import nextPlugin from '@next/eslint-plugin-next'
import reactPlugin from 'eslint-plugin-react'
import hooksPlugin from 'eslint-plugin-react-hooks'
import tseslint from 'typescript-eslint'
export default [
{
ignores: ['node_modules/**', '.next/**', 'out/**', 'build/**'],
},
...tseslint.configs.recommended,
{
files: ['**/*.{js,jsx,ts,tsx}'],
plugins: {
'@next/next': nextPlugin,
react: reactPlugin,
'react-hooks': hooksPlugin,
},
rules: {
...nextPlugin.configs.recommended.rules,
...nextPlugin.configs['core-web-vitals'].rules,
'react/react-in-jsx-scope': 'off',
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
'@typescript-eslint/no-unused-vars': [
'warn',
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
],
'@typescript-eslint/no-explicit-any': 'warn',
},
settings: {
react: {
version: 'detect',
},
},
},
]

View File

@@ -42,7 +42,7 @@ export function parseOFX(content: string): OFXAccount | null {
amount: Number.parseFloat(amountStr),
name: cleanString(name),
memo: memo ? cleanString(memo) : undefined,
checkNum,
checkNum: checkNum ?? undefined,
type,
})
}

View File

@@ -71,15 +71,22 @@
"zod": "3.25.76"
},
"devDependencies": {
"@eslint/eslintrc": "^3.3.1",
"@next/eslint-plugin-next": "^16.0.5",
"@tailwindcss/postcss": "^4.1.9",
"@types/node": "^22",
"@types/react": "^19",
"@types/react-dom": "^19",
"dotenv": "^17.2.3",
"eslint": "^9.39.1",
"eslint-config-next": "^16.0.5",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.0.1",
"postcss": "^8.5",
"tailwindcss": "^4.1.9",
"tsx": "^4.20.6",
"tw-animate-css": "1.3.3",
"typescript": "^5"
"typescript": "^5",
"typescript-eslint": "^8.48.0"
}
}

2344
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff