From 165172de96c3777d112299e7d2166de1f48d575b Mon Sep 17 00:00:00 2001 From: BlankParticle Date: Tue, 4 Aug 2026 13:43:23 +0530 Subject: [PATCH 1/4] feat: add copy PNG buttons to charts - Copy chart PNG exports directly to the clipboard - Preserve chart watermarks during clipboard export --- app/components/Chart/CopyPngButton.vue | 23 ++++++++++ app/components/Compare/FacetBarChart.vue | 11 ++++- app/components/Compare/FacetScatterChart.vue | 10 ++++- app/components/Package/TimelineChart.vue | 10 +++++ .../Package/TimelineChartDepSizeSvgSlot.vue | 5 ++- .../Package/TimelineChartXySvgSlot.vue | 3 +- app/components/Package/TrendsChart.vue | 7 +++- .../Package/VersionDistribution.vue | 15 ++++++- app/composables/useCopyChartPng.ts | 42 +++++++++++++++++++ i18n/locales/en.json | 1 + i18n/schema.json | 3 ++ 11 files changed, 120 insertions(+), 10 deletions(-) create mode 100644 app/components/Chart/CopyPngButton.vue create mode 100644 app/composables/useCopyChartPng.ts diff --git a/app/components/Chart/CopyPngButton.vue b/app/components/Chart/CopyPngButton.vue new file mode 100644 index 0000000000..c16747c28b --- /dev/null +++ b/app/components/Chart/CopyPngButton.vue @@ -0,0 +1,23 @@ + + + diff --git a/app/components/Compare/FacetBarChart.vue b/app/components/Compare/FacetBarChart.vue index 181786f1f0..3e45c64fec 100644 --- a/app/components/Compare/FacetBarChart.vue +++ b/app/components/Compare/FacetBarChart.vue @@ -11,6 +11,7 @@ import { createPatternDef } from 'vue-data-ui/utils' import { drawSmallNpmxLogoAndTaglineWatermark } from '~/composables/useChartWatermark' import { useColors } from '~/composables/useColors' import { downloadFileLink } from '~/utils/download' +import { useCopyChartPng } from '~/composables/useCopyChartPng' import { insertLineBreaks, @@ -35,6 +36,8 @@ const resolvedMode = shallowRef<'light' | 'dark'>('light') const rootEl = shallowRef(null) const { width } = useElementSize(rootEl) const { copy, copied } = useClipboard() +const chartRef = useTemplateRef('chartRef') +const { copiedPng, isCopyingPng, copyChartPng } = useCopyChartPng(chartRef) const mobileBreakpointWidth = 640 const isMobile = computed(() => width.value > 0 && width.value < mobileBreakpointWidth) @@ -271,7 +274,7 @@ const config = computed(() => {