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

@evojewel/file-preview

v1.1.0

Published

React component for previewing any file from a URL. Zero runtime dependencies.

Readme

file-preview

React component for previewing any type of file from a URL.

Give it a URL; it picks the right element — image, video, audio, PDF, Office document — and falls back to a download link for anything it can't render inline. No runtime dependencies.

import { FilePreview } from '@evojewel/file-preview';
import '@evojewel/file-preview/styles.css'; // optional

<FilePreview url={fileUrl} />;

Install

npm install @evojewel/file-preview

Requires React 17 or newer as a peer dependency.

Or copy one file. standalone/FilePreview.jsx is the whole component built into a single dependency-free JSX file. Drop it into a project, optionally copy standalone/styles.css beside it, and import it directly — no install, no build config.

Supported formats

| Kind | Extensions | Rendered with | |---|---|---| | image | jpg, jpeg, png, gif, webp, avif, bmp, svg, ico, heic, heif | <img> + click-to-zoom lightbox | | video | mp4, webm, ogv, mov, m4v, avi, mkv, mpeg, mpg, 3gp, flv, wmv, vob | <video controls> | | audio | mp3, wav, flac, m4a, aac, oga, ogg, opus, weba, amr, wma | <audio controls> | | pdf | pdf | <object> — the browser's own PDF viewer | | office | doc, docx, rtf, odt, xls, xlsx, ods, csv, ppt, pptx, odp | Google or Microsoft embed viewer | | text | txt, md, log, json, xml, yml, yaml | sandboxed <iframe> | | unknown | anything else | download link |

Query strings, fragments, uppercase extensions, data: URLs and relative paths are all handled — a signed S3 URL like .../report.pdf?X-Amz-Signature=… is detected as a PDF.

Props

| Prop | Type | Default | Description | |---|---|---|---| | url | string | — | Required. URL of the file. | | kind | FileKind | auto-detected | Force a category. Use when the URL has no extension. | | fileName | string | last path segment | Display name for link fallbacks. | | className | string | — | Added to the wrapper element. | | officeViewer | 'google' \| 'microsoft' \| false | 'google' | Viewer for Office documents, or false to disable. | | alt | string | fileName | Alt text for images. | | controls | boolean | true | Native playback controls on audio/video. | | lightbox | boolean | true | Click an image to view it full-screen. | | onError | (event) => void | — | Called when the media element fails to load. | | onEvent | (event: FilePreviewEvent) => void | — | Report what the component did, for your own analytics. | | renderFallback | (info: FallbackInfo) => ReactNode | built-in link | Replace the fallback UI. |

detectKind, getExtension, getFileName, getMimeType, isSafeUrl and getOfficeViewerUrl are exported too, if you want the detection logic without the component.

Analytics

The component makes no network requests of its own. If you want to measure how previews are used, pass onEvent and send it wherever you already send events:

<FilePreview url={fileUrl} onEvent={(event) => analytics.track('file_preview', event)} />
{ type: 'render',   kind: 'pdf',    extension: 'pdf' }
{ type: 'render',   kind: 'office', extension: 'docx', viewer: 'google' }
{ type: 'fallback', kind: 'unknown', extension: 'zip', reason: 'unsupported-format' }
{ type: 'error',    kind: 'video',  extension: 'mp4' }
{ type: 'lightbox-open', kind: 'image', extension: 'png' }

Events carry the file's category and extension and never the URL or the file name — a preview URL is routinely a signed link to a document whose name and location are themselves sensitive. A render or fallback event fires once per outcome, not once per React render, and passing an inline arrow function does not cause repeat events.

Two things worth knowing

Office documents leave your origin. Word, Excel and PowerPoint have no native browser renderer, so those files are embedded through Google's viewer by default. That means the file URL is sent to Google, and the file must be publicly reachable for the viewer to fetch it. Pass officeViewer={false} to render a download link instead. Images, video, audio and PDFs never touch a third party.

Unsafe URLs are refused. Only http:, https:, data:, blob: and relative URLs are rendered. Anything else — javascript: included, with or without control-character obfuscation — renders a neutral "cannot be displayed" message instead of reaching the DOM. New-tab links carry rel="noopener noreferrer".

Styling

The component renders usable markup with no CSS at all. styles.css is cosmetic, namespaced under fp-, assumes no grid framework, and supports dark mode. Or skip it and target the class names yourself: fp-root, fp-root--{kind}, fp-image, fp-video, fp-audio, fp-pdf, fp-office, fp-text, fp-fallback, fp-lightbox.

Development

npm install
npm run verify   # typecheck + lint + test + build + standalone sync check

standalone/ is generated from src/ by npm run build. Don't edit it by hand — CI fails if it has drifted.

Licence

MIT