feat: add packer

This commit is contained in:
2026-10-03 23:11:51 +02:00
parent e82561862a
commit 5452f72087
14 changed files with 976 additions and 25 deletions
+11
View File
@@ -0,0 +1,11 @@
<script setup lang="ts">
// The "Save as PDF" button under a page's content (CV, Packer); pair it with usePdfExport
withDefaults(defineProps<{ label?: string }>(), { label: 'Als PDF speichern' })
defineEmits<{ click: [] }>()
</script>
<template>
<div class="mt-16 flex justify-center print:hidden">
<UButton :label="label" icon="i-lucide-download" color="primary" variant="outline" @click="$emit('click')" />
</div>
</template>
+35
View File
@@ -0,0 +1,35 @@
/**
* "Save as PDF" through the browser's print dialog. While printing (also with ⌘ P) the page title is `fileName`, which
* browsers name the PDF after, and dark mode is off, so the PDF is dark text on white.
*/
export function usePdfExport(fileName: MaybeRefOrGetter<string>, onBeforePrint?: () => void) {
// What to restore after printing; null while not printing. Browsers can fire beforeprint twice before afterprint.
let screen: { title: string, dark: boolean } | null = null
function beforePrint() {
onBeforePrint?.()
if (screen) return
screen = { title: document.title, dark: document.documentElement.classList.contains('dark') }
document.title = toValue(fileName)
document.documentElement.classList.remove('dark')
}
function afterPrint() {
if (!screen) return
document.title = screen.title
if (screen.dark) document.documentElement.classList.add('dark')
screen = null
}
onMounted(() => {
window.addEventListener('beforeprint', beforePrint)
window.addEventListener('afterprint', afterPrint)
})
onBeforeUnmount(() => {
window.removeEventListener('beforeprint', beforePrint)
window.removeEventListener('afterprint', afterPrint)
})
// Opens the browser's print dialog, which offers "Save as PDF"
return { savePdf: () => window.print() }
}