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

@vasakgroup/plugin-vsk-contextual-menu

v2.0.3

Published

The VasakOS contextual menu: one look and one behaviour for every right click.

Readme

Tauri Plugin vsk-contextual-menu

El menú del clic derecho de VasakOS. Las aplicaciones describen qué opciones ofrecen; el plugin decide cómo se ven, cómo responden al teclado y cómo se cierran. Un solo menú para todo el escritorio en vez de uno por aplicación.

  • Sigue el tema del sistema —colores y redondeo— sin que la aplicación haga nada.
  • Iconos del sistema, atajos, casillas, submenús, separadores y títulos.
  • Teclado completo: flechas, Inicio/Fin, Escape, y escribir para saltar a una opción.
  • Dos modos de dibujo, con el mismo aspecto y el mismo comportamiento.

Requisitos

  • Rust 1.77.2+
  • Tauri v2

Instalación

1. El crate

[dependencies]
tauri-plugin-vsk-contextual-menu = { git = "https://github.com/Vasak-OS/tauri-plugin-vsk-contextual-menu", branch = "main" }
tauri::Builder::default()
    .plugin(tauri_plugin_vsk_contextual_menu::init())

2. El paquete de JavaScript

bun add @vasakgroup/plugin-vsk-contextual-menu

3. Los permisos

En src-tauri/capabilities/default.json:

{
  "windows": ["main", "vsk_context_menu"],
  "permissions": ["vsk-contextual-menu:default", "config-manager:default"]
}

vsk_context_menu es la ventana del modo ventana. Si falta, el menú se abre sin permisos: sin tema y sin traducciones. Alcanza con no usar el modo ventana para no necesitarla, pero declararla no cuesta nada.

Uso

import { showContextMenu } from "@vasakgroup/plugin-vsk-contextual-menu";

const elegido = await showContextMenu(
  [
    { id: "abrir", label: t("actions.open"), icon: "document-open", accelerator: "Enter" },
    { id: "copiar", label: t("actions.copy"), icon: "edit-copy", accelerator: "Ctrl+C" },
    { type: "separator" },
    { type: "checkbox", id: "ocultos", label: t("view.hidden"), checked: mostrarOcultos },
    { type: "submenu", label: t("actions.openWith"), items: aplicaciones },
    { type: "separator" },
    { id: "borrar", label: t("actions.delete"), icon: "edit-delete", danger: true },
  ],
  evento,
);

if (elegido?.id === "borrar") borrar();

showContextMenu devuelve { id, checked? } con lo elegido, o null si se cerró sin elegir nada. Si se le pasa el evento del clic derecho, además le corta el menú que dibuja WebKit.

El texto de las opciones va ya traducido: el menú no traduce nada por su cuenta, porque las claves son de cada aplicación.

En Vue

const { show } = useContextMenu();
// El menú se cierra solo cuando se desmonta el componente que lo abrió.

Al arrancar la aplicación

import { getIconSource } from "@vasakgroup/plugin-vicons";
import { setupContextMenu } from "@vasakgroup/plugin-vsk-contextual-menu";

setupContextMenu({ iconResolver: getIconSource });

El plugin no depende de vicons a propósito, así se puede usar en cualquier aplicación. Enseñarle a resolver nombres de iconos es una línea, y a partir de ahí los ítems pueden nombrar iconos del sistema (edit-copy) además de pasar una imagen ya lista (data:, blob:, una ruta).

El tema

Los colores y el radio de las esquinas salen de config-manager: el esquema que el sistema tiene elegido, la variante clara u oscura según darkmode, y el radius de la configuración. Los mismos que usa el resto del escritorio, sin que la aplicación tenga que pasarle nada.

No alcanzaba con leer las variables CSS de la aplicación. El menú se dibuja también antes de que la aplicación haya cargado su configuración —la ventana del modo ventana monta y dibuja en ese hueco—, y ahí las variables todavía no están.

Cada color se busca en tres lados, en este orden:

  1. Lo que el plugin leyó de config-manager.
  2. La variable del sistema que define la aplicación (--use-ui-background, …).
  3. El color de fábrica.

Así que si config-manager no está instalado, o esta ventana no tiene su permiso, el menú se ve igual: cae al tema de la aplicación. La configuración se lee una vez y se recuerda; el evento config-changed —el mismo que escuchan las aplicaciones— la vuelve a pedir.

Los dos modos

Adentro del DOM, que es lo normal: el menú se dibuja en la ventana que lo pide. No cuesta nada y no necesita permisos extra.

En una ventana propia, con { window: true }: para cuando el menú no entra en la ventana que lo pide —el panel mide unos treinta píxeles de alto— o cuando tiene que poder salirse de ella. Abre un webview, así que no conviene por costumbre.

El modo ventana necesita una ruta donde dibujarse, porque la ventana carga la aplicación:

// routes/index.ts
{ path: "/vsk-context-menu", component: () => import("@/views/ContextMenuView.vue") }
<!-- ContextMenuView.vue -->
<script setup lang="ts">
import { useContextMenuWindow } from "@vasakgroup/plugin-vsk-contextual-menu";
useContextMenuWindow();
</script>

<template><div /></template>

Si la ruta por omisión no sirve, init_with_route("#/otra-ruta").

Lo que no hace

Submenús en modo ventana. La ventana se hace del tamaño exacto del menú, así que un submenú se abriría afuera y quedaría recortado. El plugin lo rechaza con un error claro en vez de dibujarlo mal. En modo DOM andan, porque ahí el único límite es la pantalla.

Cambiarle el menú a las aplicaciones ajenas. En Wayland cada cliente dibuja el suyo en su propia superficie y no hay protocolo para reemplazarlo: ni este plugin ni ninguno puede tocar el menú de Firefox o de LibreOffice. Para esas la vía es el tema de GTK y el de Qt.

Las medidas

El alto de cada renglón está en dos lados a la vez: en el CSS (guest-js/style.ts) y en Rust (src/models.rs), que lo necesita para que la ventana del modo ventana nazca del tamaño exacto del menú. Si cambia uno, cambia el otro.

Licencia

GPL-3.0-only