@@ -3,6 +3,8 @@ import { ref, computed, shallowRef, watch } from 'vue'
33import type { VueUiXyDatasetItem } from ' vue-data-ui'
44import { VueUiXy } from ' vue-data-ui/vue-ui-xy'
55import { useDebounceFn , useElementSize } from ' @vueuse/core'
6+ import { useCssVariables } from ' ../composables/useColors'
7+ import { OKLCH_NEUTRAL_FALLBACK , transparentizeOklch } from ' ../utils/colors'
68
79const {
810 weeklyDownloads,
@@ -24,9 +26,19 @@ const rootEl = shallowRef<HTMLElement | null>(null)
2426const { width } = useElementSize (rootEl )
2527
2628onMounted (() => {
29+ rootEl .value = document .documentElement
2730 resolvedMode .value = colorMode .value === ' dark' ? ' dark' : ' light'
2831})
2932
33+ const { colors } = useCssVariables (
34+ [' --bg' , ' --bg-subtle' , ' --bg-elevated' , ' --fg-subtle' , ' --border' , ' --border-subtle' ],
35+ {
36+ element: rootEl ,
37+ watchHtmlAttributes: true ,
38+ watchResize: false , // set to true only if a var changes color on resize
39+ },
40+ )
41+
3042watch (
3143 () => colorMode .value ,
3244 value => {
@@ -49,7 +61,9 @@ const accentColorValueById = computed<Record<string, string>>(() => {
4961
5062const accent = computed (() => {
5163 const id = selectedAccentColor .value
52- return id ? (oklchToHex (accentColorValueById .value [id ]! ) ?? ' #8A8A8A' ) : ' #8A8A8A'
64+ return id
65+ ? (accentColorValueById .value [id ] ?? colors .value .fgSubtle ?? OKLCH_NEUTRAL_FALLBACK )
66+ : (colors .value .fgSubtle ?? OKLCH_NEUTRAL_FALLBACK )
5367})
5468
5569const mobileBreakpointWidth = 640
@@ -58,10 +72,6 @@ const isMobile = computed(() => {
5872 return width .value > 0 && width .value < mobileBreakpointWidth
5973})
6074
61- onMounted (() => {
62- rootEl .value = document .documentElement
63- })
64-
6575type ChartTimeGranularity = ' daily' | ' weekly' | ' monthly' | ' yearly'
6676type EvolutionData =
6777 | DailyDownloadPoint []
@@ -444,119 +454,121 @@ const loadFile = (link: string, filename: string) => {
444454 a .remove ()
445455}
446456
447- const config = computed (() => ({
448- theme: isDarkMode .value ? ' dark' : ' default' ,
449- chart: {
450- height: isMobile .value ? 850 : 600 ,
451- userOptions: {
452- buttons: {
453- pdf: false ,
454- labels: false ,
455- fullscreen: false ,
456- table: false ,
457- tooltip: false ,
458- },
459- callbacks: {
460- img : ({ imageUri }: { imageUri: string }) => {
461- loadFile (
462- imageUri ,
463- ` ${packageName }-${selectedGranularity .value }_${startDate .value }_${endDate .value }.png ` ,
464- )
465- },
466- csv : (csvStr : string ) => {
467- const blob = new Blob ([csvStr .replace (' data:text/csv;charset=utf-8,' , ' ' )])
468- const url = URL .createObjectURL (blob )
469- loadFile (
470- url ,
471- ` ${packageName }-${selectedGranularity .value }_${startDate .value }_${endDate .value }.csv ` ,
472- )
473- URL .revokeObjectURL (url )
457+ const config = computed (() => {
458+ return {
459+ theme: isDarkMode .value ? ' dark' : ' default' ,
460+ chart: {
461+ height: isMobile .value ? 850 : 600 ,
462+ userOptions: {
463+ buttons: {
464+ pdf: false ,
465+ labels: false ,
466+ fullscreen: false ,
467+ table: false ,
468+ tooltip: false ,
474469 },
475- svg : ({ blob }: { blob: Blob }) => {
476- const url = URL .createObjectURL (blob )
477- loadFile (
478- url ,
479- ` ${packageName }-${selectedGranularity .value }_${startDate .value }_${endDate .value }.svg ` ,
480- )
481- URL .revokeObjectURL (url )
470+ callbacks: {
471+ img : ({ imageUri }: { imageUri: string }) => {
472+ loadFile (
473+ imageUri ,
474+ ` ${packageName }-${selectedGranularity .value }_${startDate .value }_${endDate .value }.png ` ,
475+ )
476+ },
477+ csv : (csvStr : string ) => {
478+ const blob = new Blob ([csvStr .replace (' data:text/csv;charset=utf-8,' , ' ' )])
479+ const url = URL .createObjectURL (blob )
480+ loadFile (
481+ url ,
482+ ` ${packageName }-${selectedGranularity .value }_${startDate .value }_${endDate .value }.csv ` ,
483+ )
484+ URL .revokeObjectURL (url )
485+ },
486+ svg : ({ blob }: { blob: Blob }) => {
487+ const url = URL .createObjectURL (blob )
488+ loadFile (
489+ url ,
490+ ` ${packageName }-${selectedGranularity .value }_${startDate .value }_${endDate .value }.svg ` ,
491+ )
492+ URL .revokeObjectURL (url )
493+ },
482494 },
483495 },
484- } ,
485- backgroundColor: isDarkMode . value ? ' #0A0A0A ' : ' #FFFFFF ' ,
486- grid: {
487- stroke: isDarkMode . value ? ' #4A4A4A ' : ' #a3a3a3 ' ,
488- labels : {
489- axis: {
490- yLabel : $t (' package.downloads.y_axis_label ' , {
491- granularity: $t ( ` package.downloads.granularity_${ selectedGranularity . value } ` ),
492- }) ,
493- xLabel: packageName ,
494- yLabelOffsetX: 12 ,
495- fontSize: 24 ,
496- },
497- xAxisLabels: {
498- values: chartData . value ?. dates ,
499- showOnlyAtModulo: true ,
500- modulo: 12 ,
501- },
502- yAxis: {
503- formatter ,
504- useNiceScale: true ,
496+ backgroundColor: colors . value . bg ,
497+ grid: {
498+ stroke: colors . value . border ,
499+ labels: {
500+ axis : {
501+ yLabel: $t ( ' package.downloads.y_axis_label ' , {
502+ granularity : $t (` package.downloads.granularity_${ selectedGranularity . value } ` ),
503+ } ),
504+ xLabel: packageName ,
505+ yLabelOffsetX: 12 ,
506+ fontSize: 24 ,
507+ } ,
508+ xAxisLabels: {
509+ values: chartData . value ?. dates ,
510+ showOnlyAtModulo: true ,
511+ modulo: 12 ,
512+ } ,
513+ yAxis: {
514+ formatter ,
515+ useNiceScale: true ,
516+ } ,
505517 },
506518 },
507- },
508- highlighter: {
509- useLine: true ,
510- },
511- legend: {
512- show: false , // As long as a single package is displayed
513- },
514- tooltip: {
515- borderColor: ' transparent' ,
516- backdropFilter: false ,
517- backgroundColor: ' transparent' ,
518- customFormat : ({
519- absoluteIndex ,
520- datapoint ,
521- }: {
522- absoluteIndex: number
523- datapoint: Record <string , any >
524- }) => {
525- if (! datapoint ) return ' '
526- const displayValue = formatter ({ value: datapoint [0 ]?.value ?? 0 })
527- return ` <div class="flex flex-col font-mono text-xs p-3 border border-border rounded-md bg-white/10 dark:bg-[#0A0A0A]/10 backdrop-blur-md">
519+ highlighter: {
520+ useLine: true ,
521+ },
522+ legend: {
523+ show: false , // As long as a single package is displayed
524+ },
525+ tooltip: {
526+ borderColor: ' transparent' ,
527+ backdropFilter: false ,
528+ backgroundColor: ' transparent' ,
529+ customFormat : ({
530+ absoluteIndex ,
531+ datapoint ,
532+ }: {
533+ absoluteIndex: number
534+ datapoint: Record <string , any >
535+ }) => {
536+ if (! datapoint ) return ' '
537+ const displayValue = formatter ({ value: datapoint [0 ]?.value ?? 0 })
538+ return ` <div class="flex flex-col font-mono text-xs p-3 border border-border rounded-md bg-[var(--bg)]/10 backdrop-blur-md">
528539 <span class="text-fg-subtle">${chartData .value ?.dates [absoluteIndex ]}</span>
529540 <span class="text-xl">${displayValue }</span>
530541 </div>
531542 `
543+ },
532544 },
533- },
534- zoom: {
535- maxWidth: 500 ,
536- customFormat:
537- displayedGranularity . value !== ' weekly '
538- ? undefined
539- : ({ absoluteIndex , side } : { absoluteIndex : number ; side : ' left ' | ' right ' }) => {
540- const parts = extractDates ( chartData . value . dates [ absoluteIndex ] ?? ' ' )
541- return side === ' left ' ? parts [ 0 ] : parts . at ( - 1 )
542- } ,
543- highlightColor: isDarkMode . value ? ' #2A2A2A ' : ' #E1E5E8 ' ,
544- minimap: {
545- show: true ,
546- lineColor: ' #FAFAFA ' ,
547- selectedColor: accent . value ,
548- selectedColorOpacity: 0.06 ,
549- frameColor: isDarkMode . value ? ' #3A3A3A ' : ' #a3a3a3 ' ,
550- },
551- preview: {
552- fill: accent .value + 10 ,
553- stroke: accent . value + 60 ,
554- strokeWidth: 1 ,
555- strokeDasharray: 3 ,
545+ zoom: {
546+ maxWidth: 500 ,
547+ customFormat:
548+ displayedGranularity . value !== ' weekly '
549+ ? undefined
550+ : ({ absoluteIndex , side } : { absoluteIndex : number ; side : ' left ' | ' right ' }) => {
551+ const parts = extractDates ( chartData . value . dates [ absoluteIndex ] ?? ' ' )
552+ return side === ' left ' ? parts [ 0 ] : parts . at ( - 1 )
553+ },
554+ highlightColor: colors . value . bgElevated ,
555+ minimap: {
556+ show: true ,
557+ lineColor: ' #FAFAFA ' ,
558+ selectedColor: accent . value ,
559+ selectedColorOpacity: 0.06 ,
560+ frameColor: colors . value . border ,
561+ } ,
562+ preview: {
563+ fill: transparentizeOklch ( accent . value , isDarkMode . value ? 0.95 : 0.92 ),
564+ stroke: transparentizeOklch ( accent .value , 0.5 ) ,
565+ strokeWidth: 1 ,
566+ strokeDasharray: 3 ,
567+ } ,
556568 },
557569 },
558- },
559- }))
570+ }
571+ })
560572 </script >
561573
562574<template >
0 commit comments