@@ -17,9 +17,16 @@ const marginRight = 4
1717const marginBottom = 32
1818const marginLeft = 32
1919
20+ type RevenueMetric = {
21+ short : string
22+ value : number
23+ long : string
24+ currency : string
25+ }
26+
2027type ResultItem = {
2128 dimensions : [ string ] // one item
22- metrics : null | [ number ] | [ { value : number } ] // one item
29+ metrics : null | [ number ] | [ RevenueMetric ] // one item
2330}
2431type MainGraphResponse = {
2532 results : Array < ResultItem | null >
@@ -168,59 +175,8 @@ export const MainGraph = ({
168175 . attr ( 'class' , tickLineClass )
169176 )
170177
171- const addGradient = ( {
172- id,
173- stopTop,
174- stopBottom
175- } : {
176- id : string
177- stopTop : { color : string ; opacity : number }
178- stopBottom : { color : string ; opacity : number }
179- } ) : string => {
180- const grad = svg
181- . append ( 'defs' )
182- . append ( 'linearGradient' )
183- . attr ( 'id' , id )
184- . attr ( 'x1' , '0%' )
185- . attr ( 'y1' , '0%' ) // top
186- . attr ( 'x2' , '0%' )
187- . attr ( 'y2' , `100%` ) // bottom
188-
189- grad
190- . append ( 'stop' )
191- . attr ( 'offset' , '0%' )
192- . attr ( 'stop-color' , stopTop . color )
193- . attr ( 'stop-opacity' , stopTop . opacity )
194-
195- grad
196- . append ( 'stop' )
197- . attr ( 'offset' , '100%' )
198- . attr ( 'stop-color' , stopBottom . color )
199- . attr ( 'stop-opacity' , stopBottom . opacity )
200- return id
201- }
202-
203- const paintUnderLine = (
204- gradientId : string ,
205- isDefined : ( d : GraphDatum ) => boolean ,
206- y1Accessor : ( d : GraphDatum , index : number ) => number
207- ) => {
208- const area = d3
209- . area < GraphDatum > ( )
210- . x ( ( _d , index ) => x ( index ) )
211- . defined ( isDefined )
212- . y0 ( height - marginBottom ) // bottom edge
213- . y1 ( y1Accessor ) // top edge follows the data
214-
215- // draw the filled area with the gradient
216- svg
217- . append ( 'path' )
218- . datum ( remappedData )
219- . attr ( 'fill' , `url(#${ gradientId } )` )
220- . attr ( 'd' , area )
221- }
222-
223178 const drawLine = (
179+ svg : SelectedSVG ,
224180 dataset : GraphDatum [ ] ,
225181 isDefined : ( d : GraphDatum ) => boolean ,
226182 yAccessor : ( d : GraphDatum , index : number ) => number ,
@@ -249,36 +205,50 @@ export const MainGraph = ({
249205 }
250206
251207 const mainGradientId = addGradient ( {
208+ svg,
252209 id : 'main' ,
253210 stopTop : primaryGradient . stopTop ,
254211 stopBottom : primaryGradient . stopBottom
255212 } )
256213 const comparisonGradientId = addGradient ( {
214+ svg,
257215 id : 'comparisonGradient' ,
258216 stopTop : secondaryGradient . stopTop ,
259217 stopBottom : secondaryGradient . stopBottom
260218 } )
261219
220+ const yBottomEdge = height - marginBottom
221+
262222 paintUnderLine (
223+ svg ,
263224 mainGradientId ,
264225 ( d ) => d . timeLabel !== null ,
265- ( d ) => y ( d . value ! )
226+ ( _d , index ) => x ( index ) ,
227+ yBottomEdge ,
228+ ( d ) => y ( d . value ! ) ,
229+ remappedData
266230 )
267231
268232 paintUnderLine (
233+ svg ,
269234 comparisonGradientId ,
270235 ( d ) => d . comparisonTimeLabel !== null ,
271- ( d ) => y ( d . comparisonValue ! )
236+ ( _d , index ) => x ( index ) ,
237+ yBottomEdge ,
238+ ( d ) => y ( d . comparisonValue ! ) ,
239+ remappedData
272240 )
273241
274242 drawLine (
243+ svg ,
275244 remappedData ,
276245 ( d ) => d . timeLabel !== null ,
277246 ( d ) => y ( d . value ! ) ,
278247 mainPathClass
279248 )
280249
281250 drawLine (
251+ svg ,
282252 remappedData ,
283253 ( d ) => d . comparisonTimeLabel !== null ,
284254 ( d ) => y ( d . comparisonValue ! ) ,
@@ -667,7 +637,6 @@ const tickClass = 'fill-gray-500 dark:fill-gray-400 text-xs'
667637const mainDotClass = 'fill-indigo-500 dark:fill-indigo-400'
668638const comparisonDotClass = 'fill-indigo-500/20 dark:fill-indigo-400/20'
669639
670- // const pathClass = 'stroke-[#6366f1] stroke-2 z-1' // custom color like indigo-400
671640const sharedPathClass = 'stroke-2'
672641const mainPathClass = 'stroke-indigo-500 dark:stroke-indigo-400 z-2'
673642const comparisonPathClass = 'stroke-indigo-500/20 dark:stroke-indigo-400/20 z-1'
@@ -687,3 +656,63 @@ const METRIC_LABELS = {
687656 scroll_depth : 'Scroll depth' ,
688657 time_on_page : 'Time on page'
689658}
659+
660+ const addGradient = ( {
661+ svg,
662+ id,
663+ stopTop,
664+ stopBottom
665+ } : {
666+ svg : SelectedSVG
667+ id : string
668+ stopTop : { color : string ; opacity : number }
669+ stopBottom : { color : string ; opacity : number }
670+ } ) : string => {
671+ const grad = svg
672+ . append ( 'defs' )
673+ . append ( 'linearGradient' )
674+ . attr ( 'id' , id )
675+ . attr ( 'x1' , '0%' )
676+ . attr ( 'y1' , '0%' ) // top
677+ . attr ( 'x2' , '0%' )
678+ . attr ( 'y2' , `100%` ) // bottom
679+
680+ grad
681+ . append ( 'stop' )
682+ . attr ( 'offset' , '0%' )
683+ . attr ( 'stop-color' , stopTop . color )
684+ . attr ( 'stop-opacity' , stopTop . opacity )
685+
686+ grad
687+ . append ( 'stop' )
688+ . attr ( 'offset' , '100%' )
689+ . attr ( 'stop-color' , stopBottom . color )
690+ . attr ( 'stop-opacity' , stopBottom . opacity )
691+ return id
692+ }
693+
694+ const paintUnderLine = (
695+ svg : SelectedSVG ,
696+ gradientId : string ,
697+ isDefined : ( d : GraphDatum ) => boolean ,
698+ xAccessor : ( d : GraphDatum , index : number ) => number ,
699+ y0Accessor : number ,
700+ y1Accessor : ( d : GraphDatum , index : number ) => number ,
701+ datum : GraphDatum [ ]
702+ ) => {
703+ const area = d3
704+ . area < GraphDatum > ( )
705+ . x ( xAccessor )
706+ . defined ( isDefined )
707+ . y0 ( y0Accessor ) // bottom edge
708+ . y1 ( y1Accessor ) // top edge follows the data
709+
710+ // draw the filled area with the gradient
711+ svg
712+ . append ( 'path' )
713+ . datum ( datum )
714+ . attr ( 'fill' , `url(#${ gradientId } )` )
715+ . attr ( 'd' , area )
716+ }
717+
718+ type SelectedSVG = d3 . Selection < SVGSVGElement , unknown , null , undefined >
0 commit comments