Pular para o conteúdo principal

Primeiros Passos

Forma mais rápida de começar

Rodando npx @schema-forms-data/create meu-app você obtém um Studio completo com builder drag-and-drop, visualizador JSON e preview ao vivo — sem configuração manual. Veja o guia do Studio.

1. Instalação

npm install @schema-forms-data/renderer react-hook-form lucide-react

2. Defina um schema

import type { FormSchema } from "@schema-forms-data/core";
import { FieldType } from "@schema-forms-data/core";

const schema: FormSchema = {
id: "formulario-contato",
nome: "Formulário de Contato",
status: "ativo",
steps: [
{
id: "step-1",
titulo: "Suas informações",
ordem: 1,
containers: [
{
id: "container-1",
titulo: "Dados",
ordem: 1,
campos: [
{
id: "f-nome",
nome: "nome",
label: "Nome completo",
tipo: FieldType.TEXTO,
obrigatorio: true,
tamanho: 6,
ordem: 1,
},
{
id: "f-email",
nome: "email",
label: "E-mail",
tipo: FieldType.EMAIL,
obrigatorio: true,
tamanho: 6,
ordem: 2,
},
{
id: "f-msg",
nome: "mensagem",
label: "Mensagem",
tipo: FieldType.TEXTAREA,
obrigatorio: true,
tamanho: 12,
ordem: 3,
},
],
},
],
},
],
};

3. Renderize

import { FormRenderer } from "@schema-forms-data/renderer";

export default function PaginaContato() {
return (
<FormRenderer
schema={schema}
formTitle="Fale Conosco"
template="moderno"
onComplete={async (values) => {
console.log("Enviado:", values);
// values = { nome: '...', email: '...', mensagem: '...' }
}}
/>
);
}

O FormRenderer cuida de:

  • Renderizar cada tipo de campo com o componente correto
  • Validação built-in (obrigatório, regex, min/max) e validators assíncronos customizados
  • Navegação multi-step com indicador animado
  • Visibilidade condicional de campos e containers
  • Estilização por template via variáveis CSS

4. Formulário multi-step

Adicione mais steps — cada step é submetido individualmente via onSubmitStep e o último step chama onComplete:

<FormRenderer
schema={schemaMultiStep}
formTitle="Cadastro"
template="moderno"
onSubmitStep={async (stepIndex, values) => {
// Chamado quando o usuário clica em Próximo em cada step
await api.salvarRascunho(stepIndex, values);
}}
onComplete={async (todosValues) => {
// Chamado no último step com TODOS os valores acumulados
await api.finalizar(todosValues);
}}
/>

5. Upload de arquivo (opcional)

O renderer nunca faz chamadas HTTP diretamente — você injeta a sua própria:

<FormRenderer
schema={schema}
uploadFile={async (file, fieldName) => {
const formData = new FormData();
formData.append("file", file);
const res = await fetch("/api/upload", { method: "POST", body: formData });
const { url } = await res.json();
return url; // armazenado como valor do campo
}}
onComplete={async (values) => console.log(values)}
/>

6. Observar estado do formulário

Use <FormSpy> dentro da árvore do renderer para reagir a qualquer mudança de campo:

import { FormSpy } from "@schema-forms-data/renderer";

// Dentro de um componente renderizado dentro do <FormRenderer>:
<FormSpy
onChange={(state) => {
if (state.dirty)
sessionStorage.setItem("rascunho", JSON.stringify(state.values));
}}
/>;

Ou use a prop onValuesChange para um callback mais simples:

<FormRenderer
schema={schema}
onValuesChange={(values) => console.log("ao vivo:", values)}
onComplete={handleComplete}
/>

7. Use o Builder

Deixe usuários criarem seus próprios schemas visualmente:

import {
BuilderProvider,
Canvas,
Palette,
ConfigPanel,
} from "@schema-forms-data/builder";

export default function PaginaBuilder() {
return (
<BuilderProvider onSchemaChange={(schema) => api.salvar(schema)}>
<div style={{ display: "flex", height: "100vh" }}>
<Palette />
<Canvas />
<ConfigPanel />
</div>
</BuilderProvider>
);
}

Veja a documentação completa do Builder.