npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

v-file-preview

v0.1.3

Published

Production ready file viewer for Vue 3

Readme

Preview PDFs, Word documents, Excel spreadsheets, images, videos, audio, and code/text files — all from a single component. Just pass a URL or a File/Blob object and v-file-preview picks the right viewer automatically.

✨ Features

  • 📄 PDF — Rendered with pdfjs-dist. Built-in toolbar with pagination, zoom, fullscreen, and download.
  • 📝 DOCX — Rendered via @vue-office/docx.
  • 📊 Excel / CSV — Rendered via @vue-office/excel (.xlsx, .xls, .csv).
  • 🖼️ Images — Native <img> tag (.jpg, .jpeg, .png, .webp, .gif, .svg).
  • 🎬 Video — Native <video> tag (.mp4, .webm, .ogg, .mov).
  • 🎵 Audio — Native <audio> tag (.mp3, .wav).
  • 💻 Code / Text — Syntax-highlighted with CodeMirror (.json, .js, .ts, .vue, .html, .css, .txt, .md).
  • 🔒 Download protection — Optionally disable right-click save and the browser download button.
  • KeepAlive caching — Switching between files doesn't re-render previously loaded previews.
  • 🧩 Vue 3 plugin — Register globally or import the component locally.
  • 📦 TypeScript — Full type definitions included out of the box.

📦 Installation

npm

npm install v-file-preview

yarn

yarn add v-file-preview

pnpm

pnpm add v-file-preview

Don't forget to follow me on GitHub!


🚀 Quick Start

Global Registration (Plugin)

// main.ts
import { createApp } from 'vue'
import VFileViewerPlugin from 'v-file-preview'
import App from './App.vue'

const app = createApp(App)
app.use(VFileViewerPlugin) // registers <VFileViewer> globally
app.mount('#app')

Local Import (Recommended)

<script setup lang="ts">
import { VFileViewer } from 'v-file-preview'
</script>

<template>
	<VFileViewer
		url="https://example.com/sample.pdf"
		name="report.pdf" />
</template>

📖 Usage Examples

Preview a File from URL

<template>
	<VFileViewer
		url="https://example.com/document.pdf"
		name="document.pdf"
		width="100%"
		height="600px" />
</template>

Preview a File / Blob Object

<script setup lang="ts">
import { ref } from 'vue'
import { VFileViewer } from 'v-file-preview'

const selectedFile = ref<File | null>(null)

const onFileChange = (e: Event) => {
	const input = e.target as HTMLInputElement
	selectedFile.value = input.files?.[0] ?? null
}
</script>

<template>
	<input
		type="file"
		@change="onFileChange" />
	<VFileViewer
		v-if="selectedFile"
		:file="selectedFile"
		:name="selectedFile.name" />
</template>

Disable Download

<template>
	<VFileViewer
		url="/confidential-report.pdf"
		name="report.pdf"
		:can-download="false" />
</template>

Handle Events

<script setup lang="ts">
import { VFileViewer, useViewer } from 'v-file-preview'

const {
	isLoading,
	isError,
	errorMessage,
	handleLoadStart,
	handleLoadSuccess,
	handleLoadError,
} = useViewer()
</script>

<template>
	<p v-if="isLoading">Loading preview…</p>
	<p
		v-if="isError"
		style="color: red;">
		{{ errorMessage }}
	</p>

	<VFileViewer
		url="/presentation.docx"
		name="presentation.docx"
		@rendered="handleLoadSuccess"
		@error="handleLoadError" />
</template>

⚙️ Props

| Prop | Type | Default | Description | | ------------- | ---------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | file | File \| Blob \| null | undefined | A File or Blob object to preview. Takes priority over url. | | url | string \| null | undefined | A URL pointing to the file to preview. | | name | string \| null | undefined | An explicit file name (with extension) used to determine the file type when it can't be inferred from the file or url. | | width | string | '100%' | CSS width of the viewer wrapper. | | height | string | '100%' | CSS height of the viewer wrapper. | | canDownload | boolean | true | When false, disables right-click saving (images/PDFs), hides the download button (PDFs), and removes the browser download control (video/audio). |

How is the file type detected?
The extension is extracted from (in order of priority):

  1. file.name (if file is a File with a name)
  2. The name prop
  3. The pathname of the url

The extracted extension is then matched against the built-in extension map.


📡 Events

| Event | Payload | Description | | ---------- | ------- | ----------------------------------------------------------------------------------------------------- | | rendered | — | Emitted when the file has been successfully loaded and rendered. | | error | Error | Emitted when loading or rendering fails. The payload is an Error object with a descriptive message. |


🪝 useViewer Composable

A convenience composable that provides reactive loading/error state for pairing with VFileViewer events.

import { useViewer } from 'v-file-preview'

const {
	isLoading, // Ref<boolean>
	isError, // Ref<boolean>
	errorMessage, // Ref<string>
	handleLoadStart, // () => void — call when switching files
	handleLoadSuccess, // () => void — bind to @rendered
	handleLoadError, // (err: Error) => void — bind to @error
} = useViewer()

🗂️ Supported File Types

| Category | Extensions | Viewer Engine | | --------------- | ------------------------------------------------------------- | ----------------------------------------------------------------------- | | PDF | .pdf | pdfjs-dist — custom canvas renderer with pagination, zoom, fullscreen | | Word | .docx | @vue-office/docx | | Spreadsheet | .xlsx, .xls, .csv | @vue-office/excel | | Image | .jpg, .jpeg, .png, .webp, .gif, .svg | Native <img> | | Video | .mp4, .webm, .ogg, .mov | Native <video> | | Audio | .mp3, .wav | Native <audio> | | Code / Text | .json, .js, .ts, .vue, .html, .css, .txt, .md | CodeMirror 6 (read-only) | | Unknown | everything else | Friendly "unsupported" placeholder |


🎨 CSS Customization

The wrapper element uses the class v-file-preview-wrapper. You can override its styles to match your design system:

/* Override the wrapper border, radius, and background */
.v-file-preview-wrapper {
	border-radius: 12px;
	border: 1px solid #d1d5db;
	background-color: #fafafa;
}

Internal CSS Classes Reference

Each sub-viewer exposes scoped CSS classes. Because they are scoped, target them through the wrapper using :deep() if you need fine-grained control.

| Viewer | Key Classes | Description | | --------------- | --------------------------------------------------------------------------------------------- | ---------------------------------------------- | | PDF | .pdf-viewer-container, .pdf-toolbar, .toolbar-btn, .pdf-canvas-wrapper, .pdf-canvas | PDF viewer layout, toolbar buttons, and canvas | | Office | .office-viewer-container | DOCX / Excel container | | Image | .image-viewer-container, .image-content | Image wrapper and the <img> element | | Media | .media-viewer-container, .media-video, .media-audio | Video & audio wrapper and elements | | Code | .code-viewer-container, .cm-wrapper | Code viewer and CodeMirror wrapper | | Unsupported | .unsupported-container, .icon-wrapper, .title, .subtitle | Unsupported file fallback UI |

Example — customizing the PDF toolbar:

<style>
.v-file-preview-wrapper :deep(.pdf-toolbar) {
	background-color: #1f2937;
	color: #f9fafb;
}

.v-file-preview-wrapper :deep(.toolbar-btn) {
	color: #d1d5db;
}

.v-file-preview-wrapper :deep(.toolbar-btn:hover:not(:disabled)) {
	background-color: #374151;
	color: #ffffff;
}
</style>

Example — dark theme for the image viewer:

<style>
.v-file-preview-wrapper :deep(.image-viewer-container) {
	background-color: #111827;
}
</style>

🏗️ TypeScript

All public types are exported and available for direct import:

import type { VFileViewerProps } from 'v-file-preview'
import { FileCategory } from 'v-file-preview'

// FileCategory enum values
FileCategory.PDF // 'pdf'
FileCategory.DOCX // 'docx'
FileCategory.EXCEL // 'excel'
FileCategory.IMAGE // 'image'
FileCategory.VIDEO // 'video'
FileCategory.AUDIO // 'audio'
FileCategory.CODE // 'code'
FileCategory.UNKNOWN // 'unknown'

📄 License

MIT © Safdar Azeem