1+ "use client"
2+
3+ import { cn } from "@/lib/utils"
4+ import React from "react"
5+ import {
6+ Area ,
7+ AreaChart as RechartsAreaChart ,
8+ CartesianGrid ,
9+ ResponsiveContainer ,
10+ Tooltip ,
11+ XAxis ,
12+ YAxis ,
13+ } from "recharts"
14+
15+ interface AreaChartProps extends React . HTMLAttributes < HTMLDivElement > {
16+ data : Record < string , any > [ ]
17+ index : string
18+ categories : string [ ]
19+ strokeColors ?: string [ ]
20+ fillColors ?: string [ ]
21+ tooltipBgColor ?: string
22+ tooltipBorderColor ?: string
23+ gridColor ?: string
24+ valueFormatter ?: ( value : number ) => string
25+ showGrid ?: boolean
26+ showTooltip ?: boolean
27+ fill ?: "gradient" | "solid"
28+ className ?: string
29+ }
30+
31+ const AreaChart = React . forwardRef < HTMLDivElement , AreaChartProps > (
32+ (
33+ {
34+ data = [ ] ,
35+ index,
36+ categories = [ ] ,
37+ strokeColors = [ "var(--foreground)" ] ,
38+ fillColors = [ "var(--primary)" ] ,
39+ tooltipBgColor = "var(--background)" ,
40+ tooltipBorderColor = "var(--border)" ,
41+ gridColor = "var(--muted)" ,
42+ valueFormatter = ( value : number ) => value . toString ( ) ,
43+ showGrid = true ,
44+ showTooltip = true ,
45+ fill = "gradient" ,
46+ className,
47+ ...props
48+ } ,
49+ ref
50+ ) => {
51+ const chartId = React . useId ( )
52+
53+ return (
54+ < div ref = { ref } className = { cn ( "h-80 w-full" , className ) } { ...props } >
55+ < ResponsiveContainer width = "100%" height = "100%" >
56+ < RechartsAreaChart data = { data } margin = { { top : 10 , right : 30 , left : 0 , bottom : 0 } } >
57+ < defs >
58+ { categories . map ( ( category , index ) => {
59+ const fillColor = fillColors [ index ] || fillColors [ 0 ]
60+ const gradientId = `gradient-${ chartId } -${ category } `
61+ return (
62+ < linearGradient key = { category } id = { gradientId } x1 = "0" y1 = "0" x2 = "0" y2 = "1" >
63+ { fill === "gradient" ? (
64+ < >
65+ < stop offset = "5%" stopColor = { fillColor } stopOpacity = { 0.8 } />
66+ < stop offset = "95%" stopColor = { fillColor } stopOpacity = { 0 } />
67+ </ >
68+ ) : (
69+ < stop stopColor = { fillColor } stopOpacity = { 0.6 } />
70+ ) }
71+ </ linearGradient >
72+ )
73+ } ) }
74+ </ defs >
75+
76+ { showGrid && (
77+ < CartesianGrid strokeDasharray = "3 3" stroke = { gridColor } />
78+ ) }
79+
80+ < XAxis
81+ dataKey = { index }
82+ axisLine = { false }
83+ tickLine = { false }
84+ className = "text-xs fill-muted-foreground"
85+ />
86+
87+ < YAxis
88+ axisLine = { false }
89+ tickLine = { false }
90+ className = "text-xs fill-muted-foreground"
91+ tickFormatter = { valueFormatter }
92+ />
93+
94+ { showTooltip && (
95+ < Tooltip
96+ content = { ( { active, payload, label } ) => {
97+ if ( ! active || ! payload ?. length ) return null
98+
99+ return (
100+ < div
101+ className = "border p-2 shadow"
102+ style = { {
103+ backgroundColor : tooltipBgColor ,
104+ borderColor : tooltipBorderColor
105+ } }
106+ >
107+ < div className = "grid grid-cols-2 gap-2" >
108+ < div className = "flex flex-col" >
109+ < span className = "text-[0.70rem] uppercase text-muted-foreground" >
110+ { index }
111+ </ span >
112+ < span className = "font-bold text-muted-foreground" >
113+ { label }
114+ </ span >
115+ </ div >
116+ { payload . map ( ( entry , index ) => (
117+ < div key = { index } className = "flex flex-col" >
118+ < span className = "text-[0.70rem] uppercase text-muted-foreground" >
119+ { entry . dataKey }
120+ </ span >
121+ < span className = "font-bold" style = { { color : strokeColors [ 0 ] } } >
122+ { valueFormatter ( entry . value as number ) }
123+ </ span >
124+ </ div >
125+ ) ) }
126+ </ div >
127+ </ div >
128+ )
129+ } }
130+ />
131+ ) }
132+
133+ { categories . map ( ( category , index ) => {
134+ const strokeColor = strokeColors [ index ] || strokeColors [ 0 ]
135+ const gradientId = `gradient-${ chartId } -${ category } `
136+
137+ return (
138+ < Area
139+ key = { category }
140+ dataKey = { category }
141+ stroke = { strokeColor }
142+ fill = { `url(#${ gradientId } )` }
143+ strokeWidth = { 2 }
144+ />
145+ )
146+ } ) }
147+ </ RechartsAreaChart >
148+ </ ResponsiveContainer >
149+ </ div >
150+ )
151+ }
152+ )
153+
154+ AreaChart . displayName = "AreaChart"
155+
156+ export { AreaChart , type AreaChartProps }
0 commit comments