useShortcuts
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
| Parametro | Tipo | Default | Descrizione |
|---|---|---|---|
initialShortcuts | Shortcut[] | [] | Scorciatoie da registrare per lo scope corrente. Vengono rimosse al dispose |
config | ShortcutConfig | — | Configurazione globale. Viene fusa nello state globale ad ogni chiamata che la passa |
ShortcutConfig
| Campo | Tipo | Default | Descrizione |
|---|---|---|---|
preventDefault | boolean | true | Chiama event.preventDefault() quando una scorciatoia matcha |
stopPropagation | boolean | true | Chiama event.stopPropagation() quando una scorciatoia matcha |
enabled | boolean | Ref<boolean> | true | Abilitazione globale del sistema. Un Ref viene letto a ogni tasto |
macOSMapping | 'auto' | 'native' | (event, shortcut) => boolean | 'auto' | Matching su macOS: 'auto' rimappa alt → Ctrl e ctrl → Cmd, 'native' confronta i tasti così come sono, una funzione decide da sé |
La configurazione vale anche per il Ctrl+K della command palette, che è una scorciatoia di questo registro.
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à | Tipo | Descrizione |
|---|---|---|
shortcuts | Readonly<Ref<Shortcut[]>> | Registro globale corrente delle scorciatoie |
addShortcut | (shortcut: Shortcut) => void | Aggiunge una scorciatoia. Se l'id esiste già, l'invocazione è ignorata |
removeShortcut | (id: string) => void | Rimuove 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:
- Confronta
event.key(case-insensitive) conshortcut.key - Verifica i modificatori secondo la piattaforma (un modificatore non definito non deve essere premuto):
- Windows/Linux: matching diretto di
ctrl,alt,meta,shift - macOS con
macOSMapping: 'auto'(BR-17/BR-18):altdefinito → richiedeevent.ctrlKey;ctrldefinito → richiedeevent.metaKey.event.altKey(Option fisico) deve essere non premuto, emetanon è supportato
- Windows/Linux: matching diretto di
- Salta la scorciatoia se il focus è in un elemento editabile (anche dentro un antenato
[contenteditable]o[role="textbox"]) eallowInInputèfalse - Salta se
enabled === falsesulla scorciatoia o nel config globale
Al match vengono applicati preventDefault e stopPropagation secondo la configurazione. Gli handler asincroni (Promise) sono supportati: un errore, sincrono o asincrono, non interrompe il listener e viene loggato in console solo in sviluppo.
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.
Test
Lo state è a livello di modulo e la funzione di reset usata dai test della libreria non è esportata dal pacchetto. Nei test di un'applicazione si ottiene un registro pulito smontando i componenti che hanno registrato le scorciatoie (vengono rimosse al dispose dello scope).
Note
- Il listener
keydownè installato suwindowcon bubbling standard. Eventi catturati in fase dicaptureda altri listener possono prevenire il match keyè la proprietà DOM standardKeyboardEvent.key: usare'Enter','ArrowUp','Escape',' '(spazio), ecc.- Per visualizzare la combinazione corretta in UI usa
useOSe le sue label modificatore