diff --git a/app/components/Package/TrendsChart.vue b/app/components/Package/TrendsChart.vue
index dd6efebd9..a1e4158c9 100644
--- a/app/components/Package/TrendsChart.vue
+++ b/app/components/Package/TrendsChart.vue
@@ -5,6 +5,7 @@ import { useDebounceFn, useElementSize } from '@vueuse/core'
import { useCssVariables } from '~/composables/useColors'
import { OKLCH_NEUTRAL_FALLBACK, transparentizeOklch } from '~/utils/colors'
import { getFrameworkColor, isListedFramework } from '~/utils/frameworks'
+import { drawNpmxLogoAndTaglineWatermark } from '~/composables/useChartWatermark'
const props = defineProps<{
// For single package downloads history
@@ -100,6 +101,12 @@ const accent = computed(() => {
: (colors.value.fgSubtle ?? OKLCH_NEUTRAL_FALLBACK)
})
+const watermarkColors = computed(() => ({
+ fg: colors.value.fg ?? OKLCH_NEUTRAL_FALLBACK,
+ bg: colors.value.bg ?? OKLCH_NEUTRAL_FALLBACK,
+ fgSubtle: colors.value.fgSubtle ?? OKLCH_NEUTRAL_FALLBACK,
+}))
+
const mobileBreakpointWidth = 640
const isMobile = computed(() => width.value > 0 && width.value < mobileBreakpointWidth)
@@ -1241,31 +1248,6 @@ function drawSvgPrintLegend(svg: Record
) {
return seriesNames.join('\n')
}
-/**
- * Build and return npmx svg logo and tagline, to be injected during PNG & SVG exports
- */
-function drawNpmxLogoAndTaglineWatermark(svg: Record) {
- if (!svg?.drawingArea) return ''
- const npmxLogoWidthToHeight = 2.64
- const npmxLogoWidth = 100
- const npmxLogoHeight = npmxLogoWidth / npmxLogoWidthToHeight
-
- return `
-
-
- ${$t('tagline')}
-
- `
-}
-
// VueUiXy chart component configuration
const chartConfig = computed(() => {
return {
@@ -1563,7 +1545,7 @@ watch(selectedMetric, value => {
diff --git a/app/components/Package/VersionDistribution.vue b/app/components/Package/VersionDistribution.vue
new file mode 100644
index 000000000..b071d4a71
--- /dev/null
+++ b/app/components/Package/VersionDistribution.vue
@@ -0,0 +1,594 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('package.versions.distribution_title') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ legend[0]?.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ $t('package.trends.no_data') }}
+
+
+
+
+
+
+
+
{{ error.message }}
+
Package: {{ packageName }}
+
+
+
+
+
+
+ {{ $t('common.loading') }}
+
+
+
+
+
+
+
diff --git a/app/components/Package/Versions.vue b/app/components/Package/Versions.vue
index 0951f1d21..9f21c540c 100644
--- a/app/components/Package/Versions.vue
+++ b/app/components/Package/Versions.vue
@@ -19,6 +19,45 @@ const props = defineProps<{
time: Record
}>()
+const chartModal = useModal('chart-modal')
+const hasDistributionModalTransitioned = shallowRef(false)
+const isDistributionModalOpen = shallowRef(false)
+let distributionModalFallbackTimer: ReturnType | null = null
+
+function clearDistributionModalFallbackTimer() {
+ if (distributionModalFallbackTimer) {
+ clearTimeout(distributionModalFallbackTimer)
+ distributionModalFallbackTimer = null
+ }
+}
+
+async function openDistributionModal() {
+ isDistributionModalOpen.value = true
+ hasDistributionModalTransitioned.value = false
+ // ensure the component renders before opening the dialog
+ await nextTick()
+ chartModal.open()
+
+ // Fallback: Force mount if transition event doesn't fire
+ clearDistributionModalFallbackTimer()
+ distributionModalFallbackTimer = setTimeout(() => {
+ if (!hasDistributionModalTransitioned.value) {
+ hasDistributionModalTransitioned.value = true
+ }
+ }, 500)
+}
+
+function closeDistributionModal() {
+ isDistributionModalOpen.value = false
+ hasDistributionModalTransitioned.value = false
+ clearDistributionModalFallbackTimer()
+}
+
+function handleDistributionModalTransitioned() {
+ hasDistributionModalTransitioned.value = true
+ clearDistributionModalFallbackTimer()
+}
+
/** Maximum number of dist-tag rows to show before collapsing into "Other versions" */
const MAX_VISIBLE_TAGS = 10
@@ -304,14 +343,15 @@ function getTagVersions(tag: string): VersionDisplay[] {
id="versions"
>
-
{{ $t('package.downloads.community_distribution') }}
-
+
@@ -569,7 +609,7 @@ function getTagVersions(tag: string): VersionDisplay[] {