@@ -5,7 +5,7 @@ import { scaleTime } from '@visx/scale';
55import { XYChart , AreaSeries , Grid , Axis , DataContext } from '@visx/xychart' ;
66import { __ } from '@wordpress/i18n' ;
77import clsx from 'clsx' ;
8- import { differenceInHours } from 'date-fns' ;
8+ import { differenceInHours , differenceInYears } from 'date-fns' ;
99import { useMemo , useContext , forwardRef , useImperativeHandle , useState , useRef } from 'react' ;
1010import {
1111 useXYChartTheme ,
@@ -101,6 +101,13 @@ const renderDefaultTooltip = ( params: RenderTooltipParams< DataPointDate > ) =>
101101 ) ;
102102} ;
103103
104+ const formatYearTick = ( timestamp : number ) => {
105+ const date = new Date ( timestamp ) ;
106+ return date . toLocaleDateString ( undefined , {
107+ year : 'numeric' ,
108+ } ) ;
109+ } ;
110+
104111const formatDateTick = ( timestamp : number ) => {
105112 const date = new Date ( timestamp ) ;
106113 return date . toLocaleDateString ( undefined , {
@@ -117,6 +124,23 @@ const formatHourTick = ( timestamp: number ) => {
117124 } ) ;
118125} ;
119126
127+ const getFormatter = ( sortedData : ReturnType < typeof useChartDataTransform > ) => {
128+ const minX = Math . min ( ...sortedData . map ( datom => datom . data . at ( 0 ) ?. date ) ) ;
129+ const maxX = Math . max ( ...sortedData . map ( datom => datom . data . at ( - 1 ) ?. date ) ) ;
130+
131+ const diffInHours = Math . abs ( differenceInHours ( maxX , minX ) ) ;
132+ if ( diffInHours <= 24 ) {
133+ return formatHourTick ;
134+ }
135+
136+ const diffInYears = Math . abs ( differenceInYears ( maxX , minX ) ) ;
137+ if ( diffInYears <= 1 ) {
138+ return formatDateTick ;
139+ }
140+
141+ return formatYearTick ;
142+ } ;
143+
120144const guessOptimalNumTicks = (
121145 data : ReturnType < typeof useChartDataTransform > ,
122146 chartWidth : number ,
@@ -146,8 +170,13 @@ const guessOptimalNumTicks = (
146170 return 1 ;
147171 }
148172
149- const hasDuplicate = uniqueTicks . length < ticks . length ;
150- if ( hasDuplicate ) {
173+ // Example: OCT 1 JAN 1 APR 1 JUL 1 OCT 1
174+ // Here, the two OCTs are not duplicates as they represent October of two different years.
175+ const hasConsecutiveDuplicate = ticks . some (
176+ ( tick , idx ) => idx > 0 && tick === ticks [ idx - 1 ]
177+ ) ;
178+
179+ if ( hasConsecutiveDuplicate ) {
151180 continue ;
152181 }
153182
@@ -278,12 +307,7 @@ const LineChartInternal = forwardRef< SingleChartRef, LineChartProps >(
278307 } ) ;
279308
280309 const chartOptions = useMemo ( ( ) => {
281- const minX = Math . min ( ...dataSorted . map ( datom => datom . data . at ( 0 ) ?. date ) ) ;
282- const maxX = Math . max ( ...dataSorted . map ( datom => datom . data . at ( - 1 ) ?. date ) ) ;
283- const diffInHours = Math . abs ( differenceInHours ( maxX , minX ) ) ;
284-
285- // Show the difference in hours if less than 24 hours; otherwise, display the date.
286- const formatter = diffInHours <= 24 ? formatHourTick : formatDateTick ;
310+ const formatter = getFormatter ( dataSorted ) ;
287311
288312 return {
289313 axis : {
0 commit comments