Forms

SignatureInput

Canvas interattivo per l'acquisizione di firme digitali tramite mouse o touch. Il valore emesso e un data URL base64 in formato PNG.

Import

import { SignatureInput } from '@pzeta/vue-components'

Esempio Base

<script setup lang="ts">
import { ref } from 'vue'
import { SignatureInput } from '@pzeta/vue-components'

const signature = ref<string | null>(null)
</script>

<template>
  <SignatureInput v-model="signature" label="Firma" />

  <img v-if="signature" :src="signature" alt="Anteprima firma" />
</template>

Il valore e un data URL PNG in formato data:image/png;base64,.... Il canvas e vuoto finche l'utente non disegna. Il pulsante clear (icona X) cancella il canvas e emette null.

Props

PropTipoDefaultDescrizione
modelValuestring | nullnullData URL PNG della firma (v-model)
labelstringLabel del componente
widthnumber400Larghezza del canvas in pixel
heightnumber150Altezza del canvas in pixel
penColorstring'#000000'Colore della penna (qualsiasi valore CSS color)
penWidthnumber2Spessore della penna in pixel
backgroundColorstring'#ffffff'Colore di sfondo del canvas
placeholderstringlocaleTesto placeholder quando il canvas e vuoto
helperTextstringTesto di aiuto sotto il componente
errorstringMessaggio di errore
requiredbooleanfalseCampo obbligatorio
disabledbooleanfalseDisabilita il disegno sul canvas
loadingbooleanfalseMostra overlay di caricamento
invalidbooleanfalseForza stato errore
clearIconstringconfigClasse icona pulsante clear
loadingIconstringconfigClasse icona loading spinner
inputIdstringautoID dell'elemento canvas
namestringNome del campo per form submission
classstringClasse CSS aggiuntiva

Emits

EventoPayloadDescrizione
update:modelValuestring | nullAggiornamento valore (v-model) — emesso al termine del disegno
beginInizio del tratto (mousedown/touchstart)
endFine del tratto (mouseup/touchend) — valore aggiornato
clearCanvas cancellato

Esempi

Dimensioni personalizzate

<SignatureInput
  v-model="signature"
  label="Firma contratto"
  :width="600"
  :height="200"
/>

Penna colorata su sfondo scuro

<SignatureInput
  v-model="signature"
  label="Firma"
  pen-color="#ffffff"
  background-color="#1a1a2e"
  :pen-width="3"
/>

Con validazione

<script setup lang="ts">
const signature = ref<string | null>(null)
const signatureError = ref('')

function validateSignature() {
  if (!signature.value) {
    signatureError.value = 'La firma e obbligatoria'
  } else {
    signatureError.value = ''
  }
}
</script>

<template>
  <SignatureInput
    v-model="signature"
    label="Firma *"
    required
    :error="signatureError"
    :invalid="!!signatureError"
    @end="validateSignature"
  />
</template>

Integrazione con form e invio server

<script setup lang="ts">
const signature = ref<string | null>(null)

async function submit() {
  if (!signature.value) return

  // Il valore e gia un data URL PNG, inviabile direttamente
  await fetch('/api/firma', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ firma: signature.value }),
  })
}
</script>

<template>
  <SignatureInput v-model="signature" label="Firma digitale" required />
  <button @click="submit" :disabled="!signature">Invia</button>
</template>

Comportamento

  • Il canvas usa lineCap: 'round' e lineJoin: 'round' per tratti fluidi
  • Supporta sia mouse che touch (mobile)
  • Il valore viene aggiornato a ogni mouseup/touchend (fine tratto)
  • Se modelValue contiene un data URL valido al mount, viene disegnato sul canvas
  • Quando si fa clear, modelValue diventa null

Accessibilita

  • Il canvas e associato alla label tramite id
  • Il pulsante clear e navigabile da tastiera
  • In stato disabled, il canvas non accetta eventi pointer

TypeScript

import type { SignatureInputProps, SignatureInputEmits } from '@pzeta/vue-components'

// Il valore e sempre un data URL PNG o null
const signature = ref<string | null>(null)

// Per controllare se la firma e presente
const hasSignature = computed(() => signature.value !== null)