Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions src/components/npm-stats/BaselineSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import { twMerge } from 'tailwind-merge'
import { Tooltip } from '~/components/Tooltip'
import { PackageSearch } from './PackageSearch'
import type { PackageGroup } from './shared'
import { getBaselineDisplayName, type PackageGroup } from './shared'
import type { BaselinePreset } from '~/routes/stats/npm/-comparisons'

export const BASELINE_LINE_COLOR = '#3b82f6'
Expand Down Expand Up @@ -39,9 +39,7 @@ export function BaselineSection({
}: BaselineSectionProps) {
const baselineGroups = packageGroups.filter((pg) => pg.baseline)
const [showSearch, setShowSearch] = React.useState(false)
const names = baselineGroups
.map((pg) => pg.packages[0]?.name)
.filter((n): n is string => !!n)
const baselineDisplayName = getBaselineDisplayName(baselineGroups)
const hasBaselines = baselineGroups.length > 0
const normalizeActive = hasBaselines && normalizeBaseline

Expand Down Expand Up @@ -100,7 +98,7 @@ export function BaselineSection({
<span
className={twMerge('font-medium', !showBaseline && 'opacity-70')}
>
{names.join(', ')}
{baselineDisplayName}
</span>
</button>
</Tooltip>
Expand Down
35 changes: 26 additions & 9 deletions src/components/npm-stats/NPMStatsChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import type {
TimeRange,
TransformMode,
} from './shared'
import { getPackageColor } from './shared'
import { getBaselineDisplayName, getPackageColor } from './shared'
import { BASELINE_LINE_COLOR } from './BaselineSection'

const BASELINE_LINE_NAME = '__baseline__'
const BASELINE_LINE_SERIES = '__baseline__'

// Plot figure component
function PlotFigure({ options }: { options: Parameters<typeof Plot.plot>[0] }) {
Expand Down Expand Up @@ -169,6 +169,9 @@ export function NPMStatsChart({
const baselineGroups = binnedPackageData.filter(
(_, index) => packages[index]?.baseline,
)
const baselineLineName = getBaselineDisplayName(
packages.filter((packageGroup) => packageGroup.baseline),
)
const isMultiBaseline = baselineGroups.length > 1

const baselineDivisorByDate = baselineGroups.length
Expand Down Expand Up @@ -243,13 +246,19 @@ export function NPMStatsChart({
return !isHidden
})

const plotData = filteredPackageData.flatMap((d) => d.downloads)
const plotData = filteredPackageData.flatMap((d) =>
d.downloads.map((download) => ({
...download,
seriesName: download.name,
})),
)

if (showBaseline && baselineDivisorByDate) {
const baselinePoints = [...baselineDivisorByDate.entries()]
.sort((a, b) => a[0] - b[0])
.map(([time, divisor]) => ({
name: BASELINE_LINE_NAME,
name: baselineLineName,
seriesName: BASELINE_LINE_SERIES,
date: d3.utcDay(new Date(time)),
// When normalized, baseline / baseline = 1 at every point.
// When raw, multi-baseline shows the growth-index multiplier (~1.0+);
Expand All @@ -271,6 +280,14 @@ export function NPMStatsChart({
fx: facetX,
fy: facetY,
} as const
const lineOptions: Plot.LineYOptions = {
...baseOptions,
z: 'seriesName',
}
const getStrokeColor = (d: { name?: string; seriesName?: string }) => {
if (d.seriesName === BASELINE_LINE_SERIES) return BASELINE_LINE_COLOR
return d.name ? getPackageColor(d.name, packages) : 'currentColor'
}

const partialBinEnd = binUnit.floor(now)
const partialBinStart = binUnit.offset(partialBinEnd, -1)
Expand Down Expand Up @@ -305,8 +322,8 @@ export function NPMStatsChart({
? Plot.lineY(
plotData.filter((d) => d.date >= partialBinStart),
{
...baseOptions,
stroke: 'name',
...lineOptions,
stroke: getStrokeColor,
strokeWidth: 1.5,
strokeDasharray: '2 4',
strokeOpacity: 0.8,
Expand All @@ -317,8 +334,8 @@ export function NPMStatsChart({
Plot.lineY(
plotData.filter((d) => d.date < partialBinEnd),
{
...baseOptions,
stroke: 'name',
...lineOptions,
stroke: getStrokeColor,
strokeWidth: 2,
curve: 'monotone-x',
},
Expand Down Expand Up @@ -363,7 +380,7 @@ export function NPMStatsChart({
range: [...new Set(plotData.map((d) => d.name))]
.filter((pkg): pkg is string => pkg !== undefined)
.map((pkg) =>
pkg === BASELINE_LINE_NAME
pkg === baselineLineName
? BASELINE_LINE_COLOR
: getPackageColor(pkg, packages),
),
Expand Down
14 changes: 14 additions & 0 deletions src/components/npm-stats/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,20 @@ export function getPackageColor(
return defaultColors[packageIndex % defaultColors.length]
}

export function getBaselineDisplayName(packageGroups: PackageGroup[]): string {
const baselineNames = packageGroups
.filter((packageGroup) => packageGroup.baseline)
.flatMap((packageGroup) => {
const label = packageGroup.baselineLabel?.trim()
if (label) return [label]

const packageNames = packageGroup.packages.map((pkg) => pkg.name)
return packageNames.length ? [packageNames.join(', ')] : []
})

return [...new Set(baselineNames)].join(', ') || 'Baseline'
}

export const formatNumber = (num: number) => {
if (num >= 1_000_000) {
return `${(num / 1_000_000).toFixed(1)}M`
Expand Down
1 change: 1 addition & 0 deletions src/routes/$libraryId/$version.docs.npm-stats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ function RouteComponent() {
packages: [{ name: p.name, hidden: true }],
color: p.color,
baseline: true,
baselineLabel: preset.title,
})),
],
}
Expand Down
1 change: 1 addition & 0 deletions src/routes/stats/npm/-comparisons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const packageGroupSchema = v.object({
),
color: v.optional(v.nullable(v.string())),
baseline: v.optional(v.boolean()),
baselineLabel: v.optional(v.string()),
})

export const packageComparisonSchema = v.object({
Expand Down
2 changes: 2 additions & 0 deletions src/routes/stats/npm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ type _NpmStatsSearch = {
name?: string
color?: string
baseline?: boolean
baselineLabel?: string
packages: Array<{ name?: string; hidden?: boolean }>
}>
range?: TimeRange
Expand Down Expand Up @@ -308,6 +309,7 @@ function RouteComponent() {
packages: [{ name: p.name, hidden: true }],
color: p.color,
baseline: true,
baselineLabel: preset.title,
})),
],
}
Expand Down
Loading