Composables

useCommandPalette

Composable singleton per gestire stato apertura, ricerca ed esecuzione comandi della command palette.

Panoramica

useCommandPalette espone lo state e le API della command palette. Lo state è singleton: tutte le istanze condividono isOpen, searchQuery, registro comandi e binding Ctrl+K/Cmd+K. Il binding viene installato lazily alla prima invocazione tramite useMagicKeys di @vueuse/core. I comandi passati in initialCommands sono rimossi automaticamente al dispose dello scope corrente.

Firma

function useCommandPalette(
  initialCommands?: Command[]
): UseCommandPaletteReturn

Parametri

ParametroTipoDefaultDescrizione
initialCommandsCommand[][]Comandi da registrare per lo scope corrente. Vengono rimossi al dispose

Command

interface Command {
  id: string
  label: string
  description?: string
  category?: string
  icon?: string
  keywords?: string[]
  handler: () => void | Promise<void>
  enabled?: boolean
}
CampoTipoDescrizione
idstringIdentificatore univoco. Una seconda registrazione con lo stesso id viene ignorata
labelstringEtichetta principale visualizzata nel CommandPalette
descriptionstringDescrizione secondaria opzionale
categorystringCategoria visualizzata in alto a destra del comando
iconstringIcona visualizzata a sinistra (testo o classe icon font come pi pi-home)
keywordsstring[]Keyword aggiuntive non visualizzate ma incluse nel filtro
handler() => void | Promise<void>Funzione invocata all'esecuzione. Errori vengono loggati ma non bloccano la chiusura
enabledbooleanSe false, il comando è filtrato dai risultati

Return

ProprietàTipoDescrizione
isOpenRef<boolean>Stato apertura della palette
searchQueryRef<string>Testo del filtro corrente. Bindato automaticamente all'input di CommandPalette
filteredCommandsComputedRef<Command[]>Comandi filtrati dal searchQuery corrente. Esclude comandi enabled: false
allCommandsReadonly<Ref<Command[]>>Registro completo dei comandi registrati
toggle() => voidInverte isOpen. Se apre, azzera searchQuery
open() => voidApre la palette e azzera searchQuery
close() => voidChiude la palette
executeCommand(command: Command) => Promise<void>Esegue l'handler del comando e chiude la palette (anche in caso di errore)
addCommand(command: Command) => voidAggiunge un comando. Idempotente sull'id
removeCommand(id: string) => voidRimuove il comando con l'id specificato

Il return type è UseCommandPaletteReturn.

Logica di filtro

filteredCommands confronta il searchQuery (case-insensitive) contro:

  • command.label
  • command.description
  • ogni elemento di command.keywords

Il match è di tipo includes (substring). Comandi con enabled: false sono esclusi. Quando searchQuery è vuoto, restituisce tutti i comandi del registro globale.

Binding Ctrl+K / Cmd+K

Alla prima chiamata di useCommandPalette il composable installa un watch su useMagicKeys() di @vueuse/core che ascolta ctrl_k e meta_k. Quando uno dei due passa a true, viene chiamato toggle(). Il binding è installato una sola volta indipendentemente da quante volte il composable viene invocato.

Esempio: registrazione di base

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

useCommandPalette([
  {
    id: 'nav-dashboard',
    label: 'Dashboard',
    icon: 'pi pi-home',
    handler: () => router.push('/'),
  },
  {
    id: 'nav-anagrafica',
    label: 'Anagrafiche',
    category: 'Navigazione',
    keywords: ['clienti', 'fornitori'],
    handler: () => router.push('/anagrafica'),
  },
])
</script>

<template>
  <CommandPalette />
</template>

Esempio: apertura programmatica

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

const { open, close, toggle, isOpen } = useCommandPalette()

// Apertura da un pulsante o evento esterno
function apriPalette() {
  open()
}

// Apertura/chiusura
toggle()

// Lettura stato
watch(isOpen, (aperta) => {
  console.log(aperta ? 'palette aperta' : 'palette chiusa')
})

Esempio: comandi dinamici per modulo

const { addCommand, removeCommand } = useCommandPalette()

// Modulo CRM caricato on-demand
function registraComandiCRM() {
  addCommand({
    id: 'crm-pipeline',
    label: 'Pipeline vendite',
    category: 'CRM',
    handler: () => router.push('/crm/pipeline'),
  })
  addCommand({
    id: 'crm-leads',
    label: 'Lead aperti',
    category: 'CRM',
    handler: () => router.push('/crm/leads'),
  })
}

function deregistraComandiCRM() {
  removeCommand('crm-pipeline')
  removeCommand('crm-leads')
}

Esempio: esecuzione manuale

executeCommand è normalmente invocato da CommandPalette quando l'utente preme Enter o clicca un risultato, ma può essere chiamato programmaticamente:

const { allCommands, executeCommand } = useCommandPalette()

const cmd = allCommands.value.find((c) => c.id === 'nav-dashboard')
if (cmd) await executeCommand(cmd)

API di reset (testing)

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

// Resetta state, comandi, binding magic keys.
// Solo per test unitari, NON usare in produzione.
_resetCommandPaletteState()

Note

  • L'apertura via toggle/open azzera sempre searchQuery per partire da elenco completo
  • executeCommand chiama close() nel finally: la palette si chiude sempre, anche se l'handler lancia un'eccezione
  • searchQuery è esposto come Ref mutabile: può essere modificato dall'esterno (es. ricerca pre-filtrata da un altro componente)
  • L'integrazione con CommandPalette è automatica: registrare i comandi è sufficiente, il rendering è gestito dal componente