@@ -20,14 +20,14 @@ type ChartData = {
2020 downloads : number ;
2121 publishedAt ?: string ;
2222 isAggregate ?: boolean ;
23+ distTags ?: string [ ] ;
2324} ;
2425
2526const VERSIONS_LIMIT = 12 ;
2627const OTHER_VERSION_LABEL = 'Other' ;
27- const AXIS_LABEL_STYLE = {
28- fontSize : 12 ,
28+ const DIST_TAG_LABEL_STYLE = {
2929 fontWeight : 400 ,
30- letterSpacing : 0 ,
30+ fontSize : 10 ,
3131} ;
3232
3333export default function VersionDownloadsChart ( {
@@ -37,12 +37,13 @@ export default function VersionDownloadsChart({
3737 limit = VERSIONS_LIMIT ,
3838} : Props ) {
3939 const isDark = tw . prefixMatch ( 'dark' ) ;
40+ const versionDistTags = useMemo ( ( ) => mapVersionDistTags ( registryData ) , [ registryData ] ) ;
4041 const series = useMemo (
41- ( ) => buildChartSeries ( npmDownloads , registryData , limit ) ,
42- [ limit , npmDownloads , registryData ]
42+ ( ) => buildChartSeries ( npmDownloads , registryData , versionDistTags , limit ) ,
43+ [ limit , npmDownloads , registryData , versionDistTags ]
4344 ) ;
4445
45- const chartHeight = height ?? Math . max ( 120 , series . length * 26 + 42 ) ;
46+ const chartHeight = height ?? Math . max ( 120 , series . length * 27 + 42 ) ;
4647 const maxDownloads = Math . max ( ...series . map ( item => item . downloads ) , 0 ) ;
4748 const xDomain = maxDownloads ? [ 0 , maxDownloads + Math . max ( 1 , maxDownloads * 0.05 ) ] : undefined ;
4849 const gridColor = isDark ? '#374151' : '#e5e7eb' ;
@@ -67,8 +68,8 @@ export default function VersionDownloadsChart({
6768 width = { width }
6869 height = { chartHeight }
6970 xScale = { { type : 'linear' , domain : xDomain } }
70- yScale = { { type : 'band' , paddingInner : 0.3 , paddingOuter : 0.3 } }
71- margin = { { top : 6 , right : 8 , bottom : 20 , left : 54 } } >
71+ yScale = { { type : 'band' , paddingInner : 0.23 , paddingOuter : 0.15 } }
72+ margin = { { top : 6 , right : 2 , bottom : 20 , left : 60 } } >
7273 < Grid
7374 columns
7475 rows = { false }
@@ -84,35 +85,83 @@ export default function VersionDownloadsChart({
8485 hideAxisLine
8586 hideTicks
8687 tickFormat = { value => formatNumberToString ( value ) }
87- tickLabelProps = { ( ) => ( {
88- fill : 'var(--secondary)' ,
89- textAnchor : 'middle' ,
90- ...AXIS_LABEL_STYLE ,
91- } ) }
88+ tickComponent = { ( { formattedValue = 'unknown' , x, y } ) => {
89+ return (
90+ < text
91+ x = { x }
92+ y = { y }
93+ textAnchor = "middle"
94+ dominantBaseline = "middle"
95+ style = { tw `select-none tabular-nums` }
96+ fill = "var(--secondary)" >
97+ < tspan x = { x } style = { tw `text-[12px] font-light` } >
98+ { formattedValue }
99+ </ tspan >
100+ </ text >
101+ ) ;
102+ } }
92103 />
93104 < Axis
94105 orientation = "left"
95106 hideAxisLine
96107 hideTicks
97108 numTicks = { series . length }
98- tickLabelProps = { ( ) => ( {
99- fill : isDark ? 'var(--white)' : 'var(--black)' ,
100- textAnchor : 'end' ,
101- ...AXIS_LABEL_STYLE ,
102- } ) }
109+ tickComponent = { ( { formattedValue = 'unknown' , x, y } ) => {
110+ const labelX = ( x ?? 0 ) - 4 ;
111+ const data = series . find ( item => item . version === formattedValue ) ;
112+ const hasDistTags = Boolean ( data ?. distTags ?. length ) ;
113+ const [ version , suffix ] = formattedValue . split ( '-' ) ;
114+
115+ return (
116+ < text
117+ x = { labelX }
118+ y = { y }
119+ textAnchor = "end"
120+ dominantBaseline = "middle"
121+ style = { tw `select-none tabular-nums` }
122+ fill = { isDark ? 'var(--white)' : 'var(--black)' } >
123+ < tspan
124+ x = { labelX }
125+ dy = { hasDistTags || suffix ? '-0.44em' : '0' }
126+ style = { tw `text-[12px]` } >
127+ { version }
128+ </ tspan >
129+ { hasDistTags && (
130+ < tspan
131+ x = { labelX }
132+ dy = "1.2em"
133+ fill = "var(--secondary)"
134+ style = { DIST_TAG_LABEL_STYLE } >
135+ { data ?. distTags ?. join ( ', ' ) }
136+ </ tspan >
137+ ) }
138+ { suffix && ! hasDistTags && (
139+ < tspan
140+ x = { labelX }
141+ dy = "1.2em"
142+ fill = "var(--secondary)"
143+ style = { DIST_TAG_LABEL_STYLE } >
144+ { suffix }
145+ </ tspan >
146+ ) }
147+ </ text >
148+ ) ;
149+ } }
103150 />
104151 < BarSeries
105152 dataKey = "downloads"
106153 data = { series }
107154 xAccessor = { item => item . downloads }
108155 yAccessor = { item => item . version }
109- colorAccessor = { ( { isAggregate } ) =>
110- isAggregate
111- ? 'var(--pewter)'
112- : isDark
113- ? 'var(--primary-dark)'
114- : 'var(--primary-darker)'
115- }
156+ colorAccessor = { ( { isAggregate, distTags } ) => {
157+ if ( isAggregate ) {
158+ return 'var(--pewter)' ;
159+ }
160+ if ( distTags ?. length ) {
161+ return isDark ? 'var(--primary)' : 'var(--primary-dark)' ;
162+ }
163+ return isDark ? 'var(--primary-darker)' : 'var(--primary-darker)' ;
164+ } }
116165 radius = { 3 }
117166 radiusAll
118167 />
@@ -138,6 +187,7 @@ export default function VersionDownloadsChart({
138187function buildChartSeries (
139188 npmDownloads : NpmPerVersionDownloads ,
140189 registryData : NpmRegistryData ,
190+ versionDistTags : Record < string , string [ ] > ,
141191 limit : number
142192) : ChartData [ ] {
143193 const sortedVersions = Object . entries ( npmDownloads . downloads )
@@ -151,6 +201,7 @@ function buildChartSeries(
151201 version,
152202 downloads,
153203 publishedAt : registryData . time [ version ] ,
204+ distTags : versionDistTags [ version ] ,
154205 } ) ) ;
155206
156207 const normalizedLimit = Math . max ( 1 , limit ) ;
@@ -184,8 +235,15 @@ function renderTooltipContent(data?: ChartData) {
184235
185236 return (
186237 < Text
187- style = { tw `font-sans flex flex-col rounded bg-black px-2.5 py-1.5 text-xs font-light text-white dark:border dark:border-default` } >
188- < span style = { tw `font-medium` } > { data . version } </ span >
238+ style = { tw `font-sans flex flex-col gap-px rounded bg-black px-2.5 py-1.5 text-xs font-light text-white dark:border dark:border-default` } >
239+ < span style = { tw `text-[14px] font-medium tabular-nums` } >
240+ { data . version }
241+ { data . distTags ?. length && (
242+ < span style = { tw `text-palette-gray3 dark:text-secondary` } >
243+ { ` ` } • { data . distTags . join ( ', ' ) }
244+ </ span >
245+ ) }
246+ </ span >
189247 < span > { data . downloads . toLocaleString ( ) } downloads last week</ span >
190248 { data . publishedAt && ! data . isAggregate ? (
191249 < span style = { tw `text-palette-gray3 dark:text-secondary` } >
@@ -195,3 +253,13 @@ function renderTooltipContent(data?: ChartData) {
195253 </ Text >
196254 ) ;
197255}
256+
257+ function mapVersionDistTags ( registryData : NpmRegistryData ) {
258+ return Object . entries ( registryData [ 'dist-tags' ] ) . reduce < Record < string , string [ ] > > (
259+ ( acc , [ tag , version ] ) => {
260+ acc [ version ] = [ ...( acc [ version ] ?? [ ] ) , tag ] ;
261+ return acc ;
262+ } ,
263+ { }
264+ ) ;
265+ }
0 commit comments