iGRPIGRP 3.0Documentation

Formulários

IGRPForm com validação Zod e os campos do Design System — texto, seleção, datas, ficheiros e listas repetitivas — vistos pelo código e pelas props.

Um formulário do iGRP é sempre um IGRPForm com um esquema Zod, e cada campo é um componente IGRP* ligado ao formulário pelo name. É isto que o Studio gera quando arrastas o widget Form e os seus campos no Page Builder; esta página mostra o mesmo do lado do código.

Secção em construção

Esta página cobre os componentes principais; o resto do catálogo será completado. Para configurar estes componentes no Studio (sem código), vê Widgets do Page Builder.

Como funciona um formulário

O IGRPForm cria o formulário (react-hook-form + zodResolver) e partilha-o com os campos que tem dentro. Cada campo funciona num de dois modos:

ModoQuandoComo
Ligado ao formulárioDentro de um IGRPFormLê e escreve o valor pelo name, que tem de existir no esquema; o erro de validação aparece no campo
ControladoFora de um IGRPFormO valor é teu, por value / onChange (ou onValueChange, onDateChange…)
'use client';

import { useRef } from 'react';
import { z } from 'zod';
import {
  IGRPButton,
  IGRPForm,
  type IGRPFormHandle,
  IGRPInputText,
  IGRPSelect,
  IGRPDatePickerSingle,
} from '@igrp/igrp-framework-react-design-system';

const schema = z.object({
  nome: z.string().min(1, 'Obrigatório'),
  email: z.string().email('Email inválido'),
  categoria: z.string().min(1, 'Escolhe uma categoria'),
  dataInicio: z.date(),
});

export function RegistoForm() {
  const formRef = useRef<IGRPFormHandle<typeof schema>>(null);

  return (
    <IGRPForm
      schema={schema}
      formRef={formRef}
      defaultValues={{ nome: '', email: '', categoria: '' }}
      onSubmit={async (values) => {
        await guardar(values); // values já validados e tipados pelo esquema
      }}
      showToastOnError
    >
      <IGRPInputText name="nome" label="Nome" required />
      <IGRPInputText name="email" type="email" label="Email" />
      <IGRPSelect
        name="categoria"
        label="Categoria"
        options={[
          { label: 'Geral', value: 'geral' },
          { label: 'Urgente', value: 'urgente' },
        ]}
      />
      <IGRPDatePickerSingle name="dataInicio" label="Data de início" />
      <IGRPButton type="submit">Guardar</IGRPButton>
    </IGRPForm>
  );
}

O formRef dá acesso ao formulário a partir de fora — por exemplo, um botão no cabeçalho da página que submete: formRef.current?.submit().

Componentes principais

IGRPForm

O contentor do formulário: valida com o esquema Zod, chama onSubmit só com valores válidos e mostra o erro global se a submissão falhar.

Gerado pelo Studio
PropTipoPor defeitoDescrição
schemaz.ZodType—Esquema Zod de validação (obrigatório)
onSubmit(values) => void | Promise<void>—Chamado com os valores validados (obrigatório)
formRefRefObject<IGRPFormHandle | null>—Acesso a submit(), reset(), setGlobalError(), isSubmitting e à API do react-hook-form (obrigatório)
defaultValuesz.input<schema>—Valores iniciais
validationMode'onSubmit' | 'onChange' | 'onBlur' | 'onTouched' | 'all''onSubmit'Quando validar
resetAfterSubmitbooleanfalseRepõe os defaultValues depois de submeter com sucesso
showToastOnErrorbooleanfalseMostra um toast quando o onSubmit lança erro
resetKeyReact.Key—Muda-o (por exemplo, o id do registo) para recarregar o formulário com novos defaultValues

Se o onSubmit lançar uma exceção, a mensagem aparece no topo do formulário; também a podes definir tu com formRef.current?.setGlobalError('…'). Para a configuração no Page Builder, ver Widget Formulário.

IGRPInputText

Campo de texto com label, texto de ajuda, ícone opcional e mensagem de erro.

Gerado pelo Studio
PropTipoPor defeitoDescrição
namestring—Nome do campo no esquema
labelstring—Label do campo
type'text' | 'email' | 'number''text'Tipo do input
helperTextstring—Texto de ajuda por baixo do campo
requiredboolean—Marca o campo como obrigatório
showIcon / iconNameboolean / string—Ícone Lucide dentro do campo
iconPlacement'start' | 'end' | 'center'—Posição do ícone
errorstring—Mensagem de erro que sobrepõe a do formulário
<IGRPInputText
  name="email"
  type="email"
  label="Email"
  helperText="Usado para notificações"
  showIcon
  iconName="Mail"
/>

IGRPSelect

Lista de escolha única a partir de um array de opções, com pesquisa e agrupamento opcionais.

Gerado pelo Studio
PropTipoPor defeitoDescrição
namestring—Nome do campo no esquema
optionsIGRPOptionsProps[]—Opções (label, value e opcionalmente group, icon, status, description, disabled)
labelstring—Label do campo
placeholderstring—Texto quando não há valor
showSearchboolean—Campo de pesquisa dentro da lista
showGroupboolean—Agrupa as opções pelo seu group
value / onValueChangestring / (value: string) => void—Modo controlado, fora de um IGRPForm
<IGRPSelect
  name="distrito"
  label="Distrito"
  placeholder="Escolhe…"
  showSearch
  options={[
    { label: 'Norte', value: 'norte', group: 'Continente' },
    { label: 'Sul', value: 'sul', group: 'Continente' },
  ]}
  showGroup
/>

O mesmo formato de opções (IGRPOptionsProps) serve IGRPCombobox, IGRPMultiSelect, IGRPRadioGroup e o seletor do IGRPInputAddOn.

IGRPDatePickerSingle

Seleção de uma data num calendário em popover, com botão para limpar.

Gerado pelo Studio
PropTipoPor defeitoDescrição
namestring—Nome do campo no esquema (o valor é um Date)
labelstring—Label do campo
dateFormatstring'dd-MM-yyyy'Formato de apresentação (date-fns)
placeholderstring—Texto quando não há data
disableBefore / disableAfterDate—Limita as datas que se podem escolher
disableDayOfWeeknumber | number[]—Dias da semana bloqueados (0 = domingo)
date / onDateChangeDate / (date?: Date) => void—Modo controlado, fora de um IGRPForm
<IGRPDatePickerSingle
  name="dataInicio"
  label="Data de início"
  disableBefore={new Date()}
  disableDayOfWeek={[0, 6]}
/>

Quando a data é limpa, o valor do campo fica null — o esquema deve aceitá-lo se o campo for opcional (z.date().nullable()).

IGRPFormList

Lista repetitiva dentro de um formulário: cada item é um cartão colapsável com os seus campos, com botões para adicionar e remover.

Gerado pelo Studio
PropTipoPor defeitoDescrição
idstring—Nome do array no esquema (obrigatório)
renderItem(item, index) => ReactNode—Os campos de cada item (obrigatório)
defaultItemTItem—Valores de um item novo
label / descriptionstring—Título e descrição da lista
computeLabel(item, index) => string—Título de cada cartão
addButtonLabelstring—Texto do botão de adicionar
allowEmptybooleanfalsePermite ficar sem itens (por defeito mantém pelo menos um)
allowMultipleOpenbooleanfalseVários itens abertos ao mesmo tempo
const schema = z.object({
  contactos: z.array(z.object({ nome: z.string().min(1), telefone: z.string() })),
});

<IGRPFormList
  id="contactos"
  label="Contactos"
  addButtonLabel="Adicionar contacto"
  defaultItem={{ nome: '', telefone: '' }}
  computeLabel={(item, i) => item.nome || `Contacto ${i + 1}`}
  renderItem={(_item, index) => (
    <>
      <IGRPInputText name={`contactos.${index}.nome`} label="Nome" />
      <IGRPInputPhone name={`contactos.${index}.telefone`} label="Telefone" />
    </>
  )}
/>

Dentro de um IGRPForm, cada campo do item escreve no formulário pelo seu próprio name (contactos.0.nome…). Fora de um formulário, usa value / onChange e o terceiro argumento de renderItem.

Outros componentes de formulário

Todos seguem o mesmo padrão: name, label, helperText, required e ligação automática ao IGRPForm.

ComponentePara quêWidget no Studio
IGRPInputNumberNúmero formatado (Intl.NumberFormatOptions), com min / maxNumber
IGRPInputPasswordPalavra-passe com botão para mostrar (showPasswordToggle)Password
IGRPInputUrlURL com seletor de protocoloURL
IGRPInputSearchPesquisa com debounce e botão de submeterInput Search
IGRPInputPhoneTelefone com país e formato internacionalPhone
IGRPInputColorSeletor de cor (oklch, hex…)Color
IGRPInputAddOnCampo de texto com um seletor acopladoAdd On
IGRPInputHiddenValor escondido que segue no formulárioInput Hidden
IGRPTextareaTexto em várias linhasTextarea
IGRPComboboxEscolha com pesquisa sobre muitas opçõesCombobox
IGRPMultiSelectEscolha múltipla—
IGRPCheckboxCaixa de verificaçãoCheckbox
IGRPSwitchInterruptor ligado/desligadoSwitch
IGRPRadioGroupEscolha única visível; variant="card" mostra cartões de opçãoRadio
IGRPInputTimeHora (HH:mm)Time
IGRPDateTimeInputData e hora num só campo—
IGRPDatePickerRange / IGRPDatePickerMultipleIntervalo de datas / várias datasDate Range / Date Multiple
IGRPDatePickerInputSingleData escrita à mão, com calendário de apoioDate Picker Input Single
IGRPCalendarSingle / Range / Multiple (+ Time)Calendário sempre visível, com ou sem horaCalendar Single / Range / Multiple…
IGRPInputFileUpload de ficheiros com zona de arrastarUpload File
IGRPRepetitiveComponentRepete um bloco por cada item de um array (só apresentação)Repetitive Component
IGRPLabelLabel isoladaLabel
IGRPRichTextEditor / IGRPRichTextViewEditor e visualizador de texto rico, importados de …/rich-text—

Componentes descontinuados

IGRPCalendar e IGRPDatePicker ainda existem, mas usa as variantes Single, Range ou Multiple — ver Instalação e tema.

How is this guide?

Última atualização: