Composables

useShortcuts

Composable singleton per registrare scorciatoie da tastiera con cleanup automatico per scope.

Panoramica

useShortcuts gestisce la registrazione e il binding delle scorciatoie da tastiera. Lo state è condiviso tra tutte le istanze (pattern singleton): qualsiasi componente che lo invoca accede allo stesso registro globale. Il listener keydown su window viene installato una sola volta, lazily, alla prima chiamata. Le scorciatoie passate in initialShortcuts vengono rimosse automaticamente al dispose dello scope corrente (onUnmounted).

Firma

function useShortcuts(
  initialShortcuts?: Shortcut[],
  config?: ShortcutConfig
): UseShortcutsReturn

Parametri

ParametroTipoDefaultDescrizione
initialShortcutsShortcut[][]Scorciatoie da registrare per lo scope corrente. Vengono rimosse al dispose
configShortcutConfigConfigurazione globale. Viene fusa nello state globale ad ogni chiamata che la passa

ShortcutConfig

CampoTipoDefaultDescrizione
preventDefaultbooleantrueChiama event.preventDefault() quando una scorciatoia matcha
stopPropagationbooleantrueChiama event.stopPropagation() quando una scorciatoia matcha
enabledboolean | Ref<boolean>trueAbilitazione globale del sistema. Accetta Ref reattivo

Shortcut

interface Shortcut {
  id: string
  key: string
  ctrl?: boolean
  alt?: boolean
  shift?: boolean
  meta?: boolean
  description: string
  handler: () => void | Promise<void>
  enabled?: boolean
  allowInInput?: boolean
}

Vedi Registrazione scorciatoie per i dettagli sui singoli campi.

Return

ProprietàTipoDescrizione
shortcutsReadonly<Ref<Shortcut[]>>Registro globale corrente delle scorciatoie
addShortcut(shortcut: Shortcut) => voidAggiunge una scorciatoia. Se l'id esiste già, l'invocazione è ignorata
removeShortcut(id: string) => voidRimuove la scorciatoia con l'id specificato

Il return type è UseShortcutsReturn.

Esempio base

<script setup lang="ts">
import { useShortcuts } from '@pzeta/vue-scorciatoie'

useShortcuts([
  {
    id: 'salva',
    key: 's',
    ctrl: true,
    description: 'Salva',
    handler: () => salva(),
    allowInInput: true,
  },
  {
    id: 'annulla',
    key: 'Escape',
    description: 'Annulla',
    handler: () => annulla(),
  },
])
</script>

Esempio dinamico

const { addShortcut, removeShortcut, shortcuts } = useShortcuts()

addShortcut({
  id: 'rinomina',
  key: 'F2',
  description: 'Rinomina elemento',
  handler: avviaRinomina,
})

// Lista corrente (readonly, non mutare)
console.log(`${shortcuts.value.length} scorciatoie registrate`)

removeShortcut('rinomina')

Esempio con disabilitazione reattiva

import { ref } from 'vue'
import { useShortcuts } from '@pzeta/vue-scorciatoie'

const shortcutsAttive = ref(true)

useShortcuts(
  [
    {
      id: 'nuovo',
      key: 'n',
      alt: true,
      description: 'Nuovo elemento',
      handler: creaNuovo,
    },
  ],
  {
    enabled: shortcutsAttive, // Disabilita tutto quando false
  }
)

// Disabilita temporaneamente (es. apertura di una modale)
shortcutsAttive.value = false

Logica di matching

L'evento keydown viene confrontato con ogni scorciatoia registrata; il primo match esegue l'handler e termina il loop. Il matching:

  1. Confronta event.key (case-insensitive) con shortcut.key
  2. Verifica i modificatori secondo la piattaforma:
    • Windows/Linux: matching diretto di ctrl, alt, meta, shift
    • macOS (BR-17/BR-18): alt definito → richiede event.ctrlKey; ctrl definito → richiede event.metaKey. event.altKey (Option fisico) deve essere non premuto
  3. Salta la scorciatoia se il focus è in un elemento editabile e allowInInput è false
  4. Salta se enabled === false sulla scorciatoia o nel config globale

Gli handler asincroni (Promise) sono supportati: errori asincroni vengono loggati con console.error("[useShortcuts] Errore handler asincrono shortcut <id>") senza interrompere il flusso.

Cleanup automatico

Le scorciatoie passate in initialShortcuts sono tracciate e rimosse automaticamente quando lo scope effect del composable viene disposto (componente smontato). Le scorciatoie aggiunte successivamente con addShortcut sullo stesso scope subiscono lo stesso cleanup; quelle aggiunte da scope diversi richiedono removeShortcut esplicito.

API di reset (testing)

import { _resetShortcutsState } from '@pzeta/vue-scorciatoie'

// Resetta lo state globale e disinstalla il listener.
// Solo per test unitari, NON usare in produzione.
_resetShortcutsState()

Note

  • Il listener keydown è installato su window con bubbling standard. Eventi catturati in fase di capture da altri listener possono prevenire il match
  • key è la proprietà DOM standard KeyboardEvent.key: usare 'Enter', 'ArrowUp', 'Escape', ' ' (spazio), ecc.
  • Per visualizzare la combinazione corretta in UI usa useOS e le sue label modificatore