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.