diff --git a/packages/app/package.json b/packages/app/package.json index 94cf7fb5..d82eecb7 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -22,6 +22,7 @@ "@aiui/core": "workspace:*", "@tanstack/vue-virtual": "^3.13.19", "markdown-it": "^14.1.1", + "pdfjs-dist": "^5.5.207", "pinia": "^3.0.4", "plyr": "^3.8.4", "vue": "^3.5.29", diff --git a/packages/app/src/components/content/ContentPanel.vue b/packages/app/src/components/content/ContentPanel.vue index 9d58950a..11cf495e 100644 --- a/packages/app/src/components/content/ContentPanel.vue +++ b/packages/app/src/components/content/ContentPanel.vue @@ -93,6 +93,12 @@ :title="longFormArticle.title" @back="closeLongFormArticle" /> + - !!(selectedFilm.value || selectedBook.value || selectedTVSeries.value || selectedSong.value || selectedPodcast.value || selectedArticle.value || selectedDesignSystemItem.value || longFormArticle.value) + !!(selectedFilm.value || selectedBook.value || selectedTVSeries.value || selectedSong.value || selectedPodcast.value || selectedArticle.value || selectedDesignSystemItem.value || longFormArticle.value || pdfUrl.value) ) const windowWidth = ref(window.innerWidth) diff --git a/packages/app/src/components/renderers/PdfViewer.vue b/packages/app/src/components/renderers/PdfViewer.vue new file mode 100644 index 00000000..c7147e67 --- /dev/null +++ b/packages/app/src/components/renderers/PdfViewer.vue @@ -0,0 +1,170 @@ + + + diff --git a/packages/app/src/composables/useContentPanel.ts b/packages/app/src/composables/useContentPanel.ts index 78ceed13..b125dde5 100644 --- a/packages/app/src/composables/useContentPanel.ts +++ b/packages/app/src/composables/useContentPanel.ts @@ -51,6 +51,7 @@ const activeTab = ref('film') const availableTabs = ref([]) const selectedDesignSystemItem = ref(null) const longFormArticle = ref<{ content: string; title?: string } | null>(null) +const pdfUrl = ref<{ url: string; title?: string } | null>(null) export interface DesignSystemItem { id: string @@ -273,6 +274,7 @@ export function useContentPanel() { selectedMagazineSection.value = null selectedDesignSystemItem.value = null longFormArticle.value = null + pdfUrl.value = null } function openFilmDetail(film: Film) { clearAllSelections(); selectedFilm.value = film } @@ -296,6 +298,9 @@ export function useContentPanel() { function openLongFormArticle(content: string, title?: string) { clearAllSelections(); longFormArticle.value = { content, title }; panelOpen.value = true } function closeLongFormArticle() { longFormArticle.value = null } + function openPdfViewer(url: string, title?: string) { clearAllSelections(); pdfUrl.value = { url, title }; panelOpen.value = true } + function closePdfViewer() { pdfUrl.value = null } + function openMagazineSectionDetail(section: MagazineSection, index: number) { clearAllSelections() selectedMagazineSection.value = section @@ -443,6 +448,9 @@ export function useContentPanel() { longFormArticle, openLongFormArticle, closeLongFormArticle, + pdfUrl, + openPdfViewer, + closePdfViewer, enterDesignSystemMode, closePanel, showAllFilms, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 14e55265..769e13bf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,6 +7,10 @@ settings: importers: .: + dependencies: + pdfjs-dist: + specifier: ^5.5.207 + version: 5.5.207 devDependencies: turbo: specifier: ^2.8.12 @@ -26,6 +30,9 @@ importers: markdown-it: specifier: ^14.1.1 version: 14.1.1 + pdfjs-dist: + specifier: ^5.5.207 + version: 5.5.207 pinia: specifier: ^3.0.4 version: 3.0.4(typescript@5.8.3)(vue@3.5.29(typescript@5.8.3)) @@ -867,6 +874,81 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@napi-rs/canvas-android-arm64@0.1.95': + resolution: {integrity: sha512-SqTh0wsYbetckMXEvHqmR7HKRJujVf1sYv1xdlhkifg6TlCSysz1opa49LlS3+xWuazcQcfRfmhA07HxxxGsAA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@napi-rs/canvas-darwin-arm64@0.1.95': + resolution: {integrity: sha512-F7jT0Syu+B9DGBUBcMk3qCRIxAWiDXmvEjamwbYfbZl7asI1pmXZUnCOoIu49Wt0RNooToYfRDxU9omD6t5Xuw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@napi-rs/canvas-darwin-x64@0.1.95': + resolution: {integrity: sha512-54eb2Ho15RDjYGXO/harjRznBrAvu+j5nQ85Z4Qd6Qg3slR8/Ja+Yvvy9G4yo7rdX6NR9GPkZeSTf2UcKXwaXw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@napi-rs/canvas-linux-arm-gnueabihf@0.1.95': + resolution: {integrity: sha512-hYaLCSLx5bmbnclzQc3ado3PgZ66blJWzjXp0wJmdwpr/kH+Mwhj6vuytJIomgksyJoCdIqIa4N6aiqBGJtJ5Q==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@napi-rs/canvas-linux-arm64-gnu@0.1.95': + resolution: {integrity: sha512-J7VipONahKsmScPZsipHVQBqpbZx4favaD8/enWzzlGcjiwycOoymL7f4tNeqdjK0su19bDOUt6mjp9gsPWYlw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@napi-rs/canvas-linux-arm64-musl@0.1.95': + resolution: {integrity: sha512-PXy0UT1J/8MPG8UAkWp6Fd51ZtIZINFzIjGH909JjQrtCuJf3X6nanHYdz1A+Wq9o4aoPAw1YEUpFS1lelsVlg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@napi-rs/canvas-linux-riscv64-gnu@0.1.95': + resolution: {integrity: sha512-2IzCkW2RHRdcgF9W5/plHvYFpc6uikyjMb5SxjqmNxfyDFz9/HB89yhi8YQo0SNqrGRI7yBVDec7Pt+uMyRWsg==} + engines: {node: '>= 10'} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@napi-rs/canvas-linux-x64-gnu@0.1.95': + resolution: {integrity: sha512-OV/ol/OtcUr4qDhQg8G7SdViZX8XyQeKpPsVv/j3+7U178FGoU4M+yIocdVo1ih/A8GQ63+LjF4jDoEjaVU8Pw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@napi-rs/canvas-linux-x64-musl@0.1.95': + resolution: {integrity: sha512-Z5KzqBK/XzPz5+SFHKz7yKqClEQ8pOiEDdgk5SlphBLVNb8JFIJkxhtJKSvnJyHh2rjVgiFmvtJzMF0gNwwKyQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@napi-rs/canvas-win32-arm64-msvc@0.1.95': + resolution: {integrity: sha512-aj0YbRpe8qVJ4OzMsK7NfNQePgcf9zkGFzNZ9mSuaxXzhpLHmlF2GivNdCdNOg8WzA/NxV6IU4c5XkXadUMLeA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@napi-rs/canvas-win32-x64-msvc@0.1.95': + resolution: {integrity: sha512-GA8leTTCfdjuHi8reICTIxU0081PhXvl3lzIniLUjeLACx9GubUiyzkwFb+oyeKLS5IAGZFLKnzAf4wm2epRlA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@napi-rs/canvas@0.1.95': + resolution: {integrity: sha512-lkg23ge+rgyhgUwXmlbkPEhuhHq/hUi/gXKH+4I7vO+lJrbNfEYcQdJLIGjKyXLQzgFiiyDAwh5vAe/tITAE+w==} + engines: {node: '>= 10'} + '@playwright/test@1.58.2': resolution: {integrity: sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==} engines: {node: '>=18'} @@ -2250,6 +2332,9 @@ packages: engines: {node: '>= 4.4.x'} hasBin: true + node-readable-to-web-readable-stream@0.4.2: + resolution: {integrity: sha512-/cMZNI34v//jUTrI+UIo4ieHAB5EZRY/+7OmXZgBxaWBMcW2tGdceIw06RFxWxrKZ5Jp3sI2i5TsRo+CBhtVLQ==} + node-releases@2.0.27: resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} @@ -2311,6 +2396,10 @@ packages: pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + pdfjs-dist@5.5.207: + resolution: {integrity: sha512-WMqqw06w1vUt9ZfT0gOFhMf3wHsWhaCrxGrckGs5Cci6ybDW87IvPaOd2pnBwT6BJuP/CzXDZxjFgmSULLdsdw==} + engines: {node: '>=20.19.0 || >=22.13.0 || >=24'} + perfect-debounce@1.0.0: resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} @@ -3852,6 +3941,54 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@napi-rs/canvas-android-arm64@0.1.95': + optional: true + + '@napi-rs/canvas-darwin-arm64@0.1.95': + optional: true + + '@napi-rs/canvas-darwin-x64@0.1.95': + optional: true + + '@napi-rs/canvas-linux-arm-gnueabihf@0.1.95': + optional: true + + '@napi-rs/canvas-linux-arm64-gnu@0.1.95': + optional: true + + '@napi-rs/canvas-linux-arm64-musl@0.1.95': + optional: true + + '@napi-rs/canvas-linux-riscv64-gnu@0.1.95': + optional: true + + '@napi-rs/canvas-linux-x64-gnu@0.1.95': + optional: true + + '@napi-rs/canvas-linux-x64-musl@0.1.95': + optional: true + + '@napi-rs/canvas-win32-arm64-msvc@0.1.95': + optional: true + + '@napi-rs/canvas-win32-x64-msvc@0.1.95': + optional: true + + '@napi-rs/canvas@0.1.95': + optionalDependencies: + '@napi-rs/canvas-android-arm64': 0.1.95 + '@napi-rs/canvas-darwin-arm64': 0.1.95 + '@napi-rs/canvas-darwin-x64': 0.1.95 + '@napi-rs/canvas-linux-arm-gnueabihf': 0.1.95 + '@napi-rs/canvas-linux-arm64-gnu': 0.1.95 + '@napi-rs/canvas-linux-arm64-musl': 0.1.95 + '@napi-rs/canvas-linux-riscv64-gnu': 0.1.95 + '@napi-rs/canvas-linux-x64-gnu': 0.1.95 + '@napi-rs/canvas-linux-x64-musl': 0.1.95 + '@napi-rs/canvas-win32-arm64-msvc': 0.1.95 + '@napi-rs/canvas-win32-x64-msvc': 0.1.95 + optional: true + '@playwright/test@1.58.2': dependencies: playwright: 1.58.2 @@ -5280,6 +5417,9 @@ snapshots: iconv-lite: 0.6.3 sax: 1.5.0 + node-readable-to-web-readable-stream@0.4.2: + optional: true + node-releases@2.0.27: {} nth-check@2.1.1: @@ -5341,6 +5481,11 @@ snapshots: pathe@2.0.3: {} + pdfjs-dist@5.5.207: + optionalDependencies: + '@napi-rs/canvas': 0.1.95 + node-readable-to-web-readable-stream: 0.4.2 + perfect-debounce@1.0.0: {} perfect-debounce@2.1.0: {}