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

@benjaminor-dev/quasar-app-extension-dialog-file-preview

v0.2.2

Published

Dialog file preview for Quasar — images, PDF, video, audio and text via useDialogFilePreview()

Downloads

1,177

Readme

Dialog File Preview para Quasar

Extensión Quasar para previsualizar archivos en un diálogo modal desde cualquier parte de tu app, con una API imperativa basada en composable.

Tabla de contenidos

Resumen

Flujo recomendado:

  1. Instalar la extensión en tu app Quasar (quasar ext add).
  2. Asegurar que el boot de Pinia del host corre antes que el boot de esta extensión.
  3. Importar useDialogFilePreview() donde necesites abrir la vista previa.
  4. Llamar preview.show(archivo) — el diálogo se monta globalmente; no hace falta añadir componentes a tus plantillas.

Qué es y alcance

Dialog File Preview abre un modal a pantalla casi completa con:

  • Visor según el tipo MIME (imagen, PDF con controles, video, audio, texto).
  • Navegación anterior / siguiente cuando pasas varios archivos (contador en la toolbar).
  • Botones de imprimir y descarga del archivo actual (según tipo y opciones de sesión; visibles cuando el visor terminó de cargar).
  • Modo fallback (sin visor embebido) para tipos no soportados, con opción de descargar.
  • Overlay de carga centralizado en el área del visor (preparación de fuentes + carga del visor activo).
  • Opciones de sesión al abrir (showPrint, showDownload, restrictInteraction, etc.) como segundo argumento de show().

No es un componente embebible para pegar en una página: la API pública es el composable useDialogFilePreview(), que controla un diálogo global.

Features principales

  • API imperativa: show(), hide(), canPreview().
  • Acepta File, Blob, URL (string) u objeto { source, name?, mimeType? }.
  • Lista de archivos en una sola llamada: show([file1, file2]).
  • Opciones de sesión opcionales en show(input, options) (toolbar, título, restricción de copia).
  • Detección automática del visor según MIME (con heurísticas por nombre/URL y sondeo remoto al abrir).
  • Indicador de carga unificado en el viewport (QInnerLoading, «Cargando archivo...») mientras se normalizan las fuentes y mientras el visor activo termina de cargar.
  • El diálogo se abre de inmediato al llamar show(); no hace falta esperar fuera del modal a que termine el sondeo MIME.
  • PDF con pdf.js (vue-pdf-embed): paginación, zoom, impresión y carga remota vía fetch → blob.
  • Impresión integrada para PDF, imágenes y texto (no video/audio).
  • Descarga e impresión en toolbar solo cuando el visor terminó de cargar (ready).
  • Toolbar responsive: título centrado, galería ‹ N / total › y acciones imprimir/descargar/cierre.
  • Gestión interna de URLs blob: (creación y liberación al cerrar).
  • Estilos del diálogo incluidos vía CSS de la extensión.

Requisitos y compatibilidad

| Ítem | Valor | | --- | --- | | Node | >= 20.0.0 | | Quasar | ^2.6.0 | | Vue | ^3.4.18 | | Pinia | ^2.0.11 | ^3.0.0 | | Formato del paquete | ES modules | | CLI recomendado | @quasar/app-vite ^2.x o ^3.x | | PDF en el paquete | vue-pdf-embed / pdf.js incluidos (sin dependencia extra en el host) |

El boot de Pinia del host debe ejecutarse antes del boot de esta extensión.

Instalación

Agregar la extensión en tu app Quasar:

quasar ext add @benjaminor-dev/dialog-file-preview

Remover:

quasar ext remove @benjaminor-dev/dialog-file-preview

Tras quasar ext add, la extensión registra boots y CSS en tu app automáticamente. No necesitas pasos adicionales en una instalación normal desde npm.

Qué agrega la extensión al host

Al instalar o invocar, la extensión registra en quasar.config:

| Recurso | Ruta npm | | --- | --- | | Boot del diálogo | ~@benjaminor-dev/quasar-app-extension-dialog-file-preview/boot/dialog | | Estilos | ~@benjaminor-dev/quasar-app-extension-dialog-file-preview/main.css |

Orden recomendado de boots:

  1. Boot Pinia del host (por ejemplo src/boot/pinia.ts).
  2. Boot dialog de esta extensión (lo registra la extensión automáticamente).
  3. Resto de boots de tu app.

El boot monta el diálogo en el documento y conecta la store de Pinia del host. No necesitas importar DialogFilePreview en App.vue.

Uso rápido

<script setup lang="ts">import { useDialogFilePreview } from "@benjaminor-dev/quasar-app-extension-dialog-file-preview";

const preview = useDialogFilePreview();

function onViewPdf(file: File) {
  if (preview.canPreview(file)) {
    void preview.show(file);
  }
}
</script>

<template>
  <q-btn label="Ver PDF" @click="onViewPdf(selectedFile)" />
</template>

Varios archivos (galería o adjuntos):

void preview.show([imageFile, pdfFile, anotherImage]);

URL remota con nombre explícito:

void preview.show({
  source:
    "https://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf",
  name: "tracemonkey-pldi-09.pdf",
  mimeType: "application/pdf",
});

API: useDialogFilePreview()

import { useDialogFilePreview } from "@benjaminor-dev/quasar-app-extension-dialog-file-preview";

const preview = useDialogFilePreview();

Métodos

| Método | Descripción | | --- | --- | | show(input, options?) | Abre el diálogo de inmediato y devuelve una Promise que resuelve cuando terminó la normalización/sondeo MIME de las fuentes. El segundo argumento options configura la sesión (toolbar, título, restricciones). Mientras tanto, y hasta que el visor emita estado listo, el viewport muestra «Cargando archivo...». | | hide() | Cierra el diálogo y libera URLs blob: creadas por la extensión. | | next() | Siguiente archivo (si hay varios). | | previous() | Archivo anterior. | | downloadCurrent() | Descarga el archivo visible (desde File/Blob o enlace si solo hay URL). | | canPreview(source) | true si el MIME tiene visor en el diálogo. | | canPreviewAll(sources) | true si todos los ítems del arreglo son previsualizables. |

Estado reactivo (solo lectura)

| Ref | Descripción | | --- | --- | | visible | Si el diálogo está abierto. | | current | Metadatos del ítem actual (PreviewItem) o null. | | hasPrevious / hasNext | Navegación en listas multi-archivo. | | hasMultiple | Hay más de un archivo en la sesión actual. |

Usa canPreview() para mostrar u ocultar botones «Ver» en tu UI sin abrir el diálogo.

Comportamiento al abrir (show)

  1. El diálogo se hace visible al instante.
  2. Un único QInnerLoading cubre el viewport mientras:
    • se enriquecen las fuentes (File/Blob/URL → ítems con MIME y URL de visualización), y
    • el visor del ítem actual (imagen, PDF, texto, etc.) reporta estado de carga.
  3. Los botones imprimir y descargar en la toolbar aparecen solo cuando el visor emite estado listo (ready) y la opción de sesión correspondiente está activa (showPrint / showDownload).
  4. Imprimir solo se ofrece para PDF, imágenes y texto; video y audio no muestran el botón aunque showPrint sea true.
  5. Al cambiar de archivo en una galería (next / previous), el loader vuelve hasta que el nuevo visor esté listo.

El estado interno de preparación no se expone en useDialogFilePreview(); basta con visible y la UX del overlay.

Opciones de sesión (PreviewSessionOptions)

Segundo argumento opcional de show(). Aplica a toda la sesión del diálogo (incluida la galería multi-archivo).

import type { PreviewSessionOptions } from "@benjaminor-dev/quasar-app-extension-dialog-file-preview";

void preview.show(confidentialPdf, {
  showPrint: false,
  showDownload: true,
  restrictInteraction: true,
  title: "Contrato confidencial",
});

void preview.show([scan1, scan2], {
  showGalleryNav: true,
  showPdfZoom: false,
});

| Opción | Default | Descripción | | --- | --- | --- | | showPrint | true | Muestra el botón imprimir cuando el tipo lo permite (PDF, imagen, texto). | | showDownload | true | Muestra el botón descargar en la toolbar. | | showGalleryNav | true | Muestra navegación anterior/siguiente si hay varios archivos. | | showPdfZoom | true | Muestra «Zoom: N%» en la toolbar para PDF. | | title | nombre del archivo | Título centrado en la toolbar. | | restrictInteraction | false | Bloquea copiar, cortar, seleccionar, menú contextual y atajos comunes en el visor. No evita capturas de pantalla ni herramientas avanzadas del navegador. |

Si omites options, se usan los valores por defecto de la tabla.

Fuentes de archivo aceptadas

Tipo unificado PreviewSourceInput:

| Forma | Ejemplo | | --- | --- | | File | Archivo de <input type="file"> o new File(...) | | Blob | Blob de API o canvas | | string | URL https://... o blob:... | | Objeto descriptor | Ver abajo |

// File o Blob directo
void preview.show(file);
void preview.show([imageFile, pdfFile]);

// URL con metadatos explícitos (recomendado sin extensión clara)
void preview.show({
  source: "https://ejemplo.com/documento",
  name: "contrato.pdf",
  mimeType: "application/pdf",
});

// Descriptor con File
void preview.show({
  source: selectedFile,
  name: "anexo-renombrado.pdf",
});

| Situación | Qué hacer | | --- | --- | | File / Blob | Nombre y MIME se infieren del objeto | | URL sin extensión | Pasa name y mimeType en el descriptor | | URL remota al abrir | Puede sondearse (HEAD/GET parcial) para inferir MIME | | canPreview() devuelve false | Evalúa de forma síncrona; con mimeType explícito o tras sondeo, show() puede abrir igual | | URLs blob: externas | La extensión no las revoca; solo libera las que crea desde File/Blob |

Tipos de archivo soportados

| Categoría | MIME / prefijos | Visor en el diálogo | Imprimible | | --- | --- | --- | --- | | Imágenes | image/* | Imagen centrada con object-fit: contain (sin scroll en el viewport) | Sí | | PDF | application/pdf | pdf.js (vue-pdf-embed): páginas, zoom, capas de texto/anotaciones | Sí | | Video | video/mp4, video/webm, video/ogg | <video controls> | No | | Audio | audio/mpeg, audio/wav, audio/ogg, audio/webm | <audio controls> con icono central y ecualizador al reproducir | No | | Texto | text/plain, text/csv, application/json, application/xml, text/xml | Texto monoespaciado con scroll | Sí | | Otros | — | Mensaje + botón descargar | No |

Si el MIME no tiene visor, show() igual puede abrir el diálogo en modo fallback para permitir la descarga.

Tipos TypeScript exportados

Desde el entrypoint principal:

import type {
  PreviewSourceInput,
  PreviewItemInput,
  PreviewItem,
  PreviewKind,
  PreviewSessionOptions,
} from "@benjaminor-dev/quasar-app-extension-dialog-file-preview";

| Tipo | Uso | | --- | --- | | PreviewSourceInput | Primer argumento de show() y argumento de canPreview() | | PreviewSessionOptions | Segundo argumento opcional de show() | | PreviewItemInput | Descriptor con metadatos opcionales | | PreviewItem | Ítem normalizado del estado reactivo | | PreviewKind | "image" \| "pdf" \| "video" \| "audio" \| "text" \| "unknown" |

type PreviewItemInput = {
  source: File | Blob | string;
  name?: string;
  mimeType?: string;
};

Utilidades MIME

También se exportan para validar en tu UI sin abrir el diálogo:

import {
  isPreviewableMime,
  PREVIEWABLE_MIME_PREFIXES,
} from "@benjaminor-dev/quasar-app-extension-dialog-file-preview";

if (isPreviewableMime(file.type)) {
  // mostrar botón de vista previa
}

Integración opcional con Form Builder

Si usas @benjaminor-dev/quasar-app-extension-form-builder, instala también esta extensión:

quasar ext add @benjaminor-dev/dialog-file-preview

Orden de boots en el host: Pinia → Form Builder → Dialog File Preview.

InputFile e InputFileMultiple detectan la extensión automáticamente cuando showPreview no es false (default true): botones ver/descargar en el append o en la tabla de gestión, sin llamar useDialogFilePreview() en tu pantalla. Form Builder no depende de este paquete; sin la extensión, esos campos usan el clear nativo de Quasar.

Uso manual desde un callback o botón custom:

<script setup lang="ts">import { useDialogFilePreview } from "@benjaminor-dev/quasar-app-extension-dialog-file-preview";

const preview = useDialogFilePreview();

function onPreviewFile(file: File) {
  void preview.show(file);
}
</script>

El boot también expone la API vía provide para integraciones de librerías hermanas (misma instancia que useDialogFilePreview()).

Entrypoints públicos

| Import | Contenido | | --- | --- | | @benjaminor-dev/quasar-app-extension-dialog-file-preview | useDialogFilePreview, tipos (PreviewSessionOptions, etc.), isPreviewableMime, PREVIEWABLE_MIME_PREFIXES | | @benjaminor-dev/quasar-app-extension-dialog-file-preview/boot/dialog | Boot Quasar (registrado automáticamente por la extensión) | | @benjaminor-dev/quasar-app-extension-dialog-file-preview/main.css | Estilos del diálogo (registrado automáticamente) |

Troubleshooting

Boots o estilos no aparecen en quasar.config

Si tras instalar desde npm no ves el boot dialog ni main.css de la extensión en la config de tu app, re-invócala en el host:

npx quasar ext invoke @benjaminor-dev/dialog-file-preview

Error: Pinia no inicializada / store no disponible

  • Verifica que exista un boot de Pinia en el host (app.use(pinia) o equivalente).
  • En quasar.config, el boot de Pinia debe ir antes que el boot dialog de esta extensión.

useDialogFilePreview() fuera de setup

Llámalo dentro de setup, otro composable o <script setup>. Si necesitas usarlo fuera del contexto de componente, asegúrate de que el boot de la extensión ya se ejecutó (app montada).

El botón «Ver» no debería mostrarse

Usa preview.canPreview(file) o isPreviewableMime(file.type) antes de renderizar la acción.

canPreview() devuelve false en una URL sin extensión

canPreview() no hace sondeo remoto. Si la URL no tiene extensión ni heurística conocida, pasa mimeType en el descriptor o llama show() directamente.

PDF o texto desde URL externa no carga

  • CORS: el servidor debe permitir fetch desde tu origen (PDF remoto se descarga como blob antes de renderizar).
  • Pasa mimeType explícito si la URL no tiene extensión.
  • Verifica que la URL responda 200 (enlaces rotos muestran el error en el visor).
  • Para dominios sin CORS, descarga en tu backend y pasa un File/Blob local.

Ejemplo de URL pública que funciona en pruebas:

preview.show({
  source:
    "https://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf",
  name: "tracemonkey-pldi-09.pdf",
  mimeType: "application/pdf",
});

El botón de descarga no aparece al abrir

Es esperado al inicio: la descarga en la toolbar solo se habilita cuando el visor emite estado listo (ready) y showDownload no es false. Mientras prepara fuentes o carga PDF/imagen/texto verás «Cargando archivo...» en el viewport. Si el loader no desaparece, revisa errores de red/CORS en la consola.

No aparece el botón imprimir

  • Comprueba que showPrint no sea false en las opciones de sesión.
  • Solo PDF, imágenes y texto son imprimibles; en video/audio el botón no se muestra.
  • Igual que la descarga, requiere estado listo (ready) del visor.

restrictInteraction no bloquea todo

La opción reduce copia, selección y menú contextual en el visor, pero no sustituye DRM ni impide capturas de pantalla. Un usuario con conocimientos técnicos puede seguir accediendo al contenido.

El diálogo abre vacío un instante o tarda en mostrar el archivo

show() abre el modal de inmediato y normaliza las fuentes en segundo plano. Con URLs remotas o varios archivos, el overlay puede permanecer unos segundos; no indica fallo por sí solo.

La vista previa de imagen/PDF funciona en local pero no en producción

Revisa que la extensión esté instalada/invocada en el build de producción y que main.css de la extensión esté en la config generada.

Varios archivos: no aparece navegación

Pasa un arreglo a show([...]). La barra anterior/siguiente solo se muestra cuando hay más de un ítem y showGalleryNav no es false.

Desinstalar

quasar ext remove @benjaminor-dev/dialog-file-preview

MIT © Benjamín Olvera R.