@@ -19,7 +19,7 @@ import type {
1919} from ' ~/types/chart'
2020import { DATE_INPUT_MAX } from ' ~/utils/input'
2121import { applyDataCorrection } from ' ~/utils/chart-data-correction'
22- import { applyBlocklistCorrection } from ' ~/utils/download-anomalies'
22+ import { applyBlocklistCorrection , getAnomaliesForPackages } from ' ~/utils/download-anomalies'
2323import { copyAltTextForTrendLineChart } from ' ~/utils/charts'
2424
2525const props = withDefaults (
@@ -1633,6 +1633,17 @@ const chartConfig = computed<VueUiXyConfig>(() => {
16331633const isDownloadsMetric = computed (() => selectedMetric .value === ' downloads' )
16341634const showCorrectionControls = shallowRef (false )
16351635
1636+ const packageAnomalies = computed (() => getAnomaliesForPackages (effectivePackageNames .value ))
1637+ const hasAnomalies = computed (() => packageAnomalies .value .length > 0 )
1638+
1639+ function formatAnomalyDate(dateStr : string ) {
1640+ return new Date (dateStr ).toLocaleDateString (locale .value , {
1641+ year: ' numeric' ,
1642+ month: ' short' ,
1643+ day: ' numeric' ,
1644+ })
1645+ }
1646+
16361647// Trigger data loading when the metric is switched
16371648watch (selectedMetric , value => {
16381649 if (! isMounted .value ) return
@@ -1764,16 +1775,61 @@ watch(selectedMetric, value => {
17641775 class =" accent-[var(--accent-color,var(--fg-subtle))]"
17651776 />
17661777 </label >
1767- <label
1768- class =" flex items-center gap-1.5 text-2xs font-mono text-fg-subtle tracking-wide uppercase cursor-pointer shrink-0 -mb-0.5"
1769- >
1770- <input
1771- v-model =" settings.chartFilter.anomaliesFixed"
1772- type =" checkbox"
1773- class =" accent-[var(--accent-color,var(--fg-subtle))]"
1774- />
1775- {{ $t('package.trends.anomalies_fixed') }}
1776- </label >
1778+ <div class =" flex flex-col gap-1 shrink-0" >
1779+ <span
1780+ class =" text-2xs font-mono text-fg-subtle tracking-wide uppercase flex items-center justify-between"
1781+ >
1782+ {{ $t('package.trends.known_anomalies') }}
1783+ <TooltipApp interactive :to =" inModal ? '#chart-modal' : undefined" >
1784+ <span class =" i-lucide:info w-3.5 h-3.5 text-fg-muted cursor-help" tabindex =" 0" />
1785+ <template #content >
1786+ <div class =" flex flex-col gap-3" >
1787+ <p class =" text-xs text-fg-muted" >
1788+ {{ $t('package.trends.known_anomalies_description') }}
1789+ </p >
1790+ <div v-if =" hasAnomalies" >
1791+ <p class =" text-xs text-fg-subtle font-medium" >
1792+ {{ $t('package.trends.known_anomalies_ranges') }}
1793+ </p >
1794+ <ul class =" text-xs text-fg-subtle list-disc list-inside" >
1795+ <li v-for =" a in packageAnomalies" :key =" `${a.packageName}-${a.start}`" >
1796+ {{
1797+ $t('package.trends.known_anomalies_range', {
1798+ start: formatAnomalyDate(a.start),
1799+ end: formatAnomalyDate(a.end),
1800+ })
1801+ }}
1802+ </li >
1803+ </ul >
1804+ </div >
1805+ <p v-else class =" text-xs text-fg-muted" >
1806+ {{ $t('package.trends.known_anomalies_none') }}
1807+ </p >
1808+ <div class =" flex justify-end" >
1809+ <LinkBase
1810+ to =" https://github.com/npmx-dev/npmx.dev/edit/main/app/utils/download-anomalies.data.ts"
1811+ class =" text-xs text-accent"
1812+ >
1813+ {{ $t('package.trends.known_anomalies_contribute') }}
1814+ </LinkBase >
1815+ </div >
1816+ </div >
1817+ </template >
1818+ </TooltipApp >
1819+ </span >
1820+ <label
1821+ class =" flex items-center gap-1.5 text-2xs font-mono text-fg-subtle cursor-pointer"
1822+ :class =" { 'opacity-50 pointer-events-none': !hasAnomalies }"
1823+ >
1824+ <input
1825+ v-model =" settings.chartFilter.anomaliesFixed"
1826+ type =" checkbox"
1827+ :disabled =" !hasAnomalies"
1828+ class =" accent-[var(--accent-color,var(--fg-subtle))]"
1829+ />
1830+ {{ $t('package.trends.apply_correction') }}
1831+ </label >
1832+ </div >
17771833 </div >
17781834 </div >
17791835
0 commit comments