zormy 0.0.1 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AI_SPEC.md +224 -0
- package/README.md +126 -21
- package/dist/src/components/Form.cjs +35 -0
- package/dist/src/components/Form.d.cts +45 -0
- package/dist/src/components/Form.d.cts.map +1 -0
- package/dist/src/components/Form.d.ts +45 -0
- package/dist/src/components/Form.d.ts.map +1 -0
- package/dist/src/components/Form.js +31 -0
- package/dist/src/components/Step.cjs +17 -0
- package/dist/src/components/Step.d.cts +16 -0
- package/dist/src/components/Step.d.cts.map +1 -0
- package/dist/src/components/Step.d.ts +16 -0
- package/dist/src/components/Step.d.ts.map +1 -0
- package/dist/src/components/Step.js +14 -0
- package/dist/src/components/Wizard.cjs +36 -0
- package/dist/src/components/Wizard.d.cts +45 -0
- package/dist/src/components/Wizard.d.cts.map +1 -0
- package/dist/src/components/Wizard.d.ts +45 -0
- package/dist/src/components/Wizard.d.ts.map +1 -0
- package/dist/src/components/Wizard.js +32 -0
- package/dist/src/fields/dependency/extractor.cjs +90 -0
- package/dist/src/fields/dependency/extractor.d.cts +16 -0
- package/dist/src/fields/dependency/extractor.d.cts.map +1 -0
- package/dist/src/fields/dependency/extractor.d.ts +16 -0
- package/dist/src/fields/dependency/extractor.d.ts.map +1 -0
- package/dist/src/fields/dependency/extractor.js +87 -0
- package/dist/src/fields/dependency/types/dependency.cjs +2 -0
- package/dist/src/fields/dependency/types/dependency.d.cts +37 -0
- package/dist/src/fields/dependency/types/dependency.d.cts.map +1 -0
- package/dist/src/fields/dependency/types/dependency.d.ts +37 -0
- package/dist/src/fields/dependency/types/dependency.d.ts.map +1 -0
- package/dist/src/fields/dependency/types/dependency.js +1 -0
- package/dist/src/fields/dependency/types/extractors.cjs +2 -0
- package/dist/src/fields/dependency/types/extractors.d.cts +116 -0
- package/dist/src/fields/dependency/types/extractors.d.cts.map +1 -0
- package/dist/src/fields/dependency/types/extractors.d.ts +116 -0
- package/dist/src/fields/dependency/types/extractors.d.ts.map +1 -0
- package/dist/src/fields/dependency/types/extractors.js +1 -0
- package/dist/src/fields/field/builder/builder.cjs +86 -0
- package/dist/src/fields/field/builder/builder.d.cts +41 -0
- package/dist/src/fields/field/builder/builder.d.cts.map +1 -0
- package/dist/src/fields/field/builder/builder.d.ts +41 -0
- package/dist/src/fields/field/builder/builder.d.ts.map +1 -0
- package/dist/src/fields/field/builder/builder.js +82 -0
- package/dist/src/fields/field/builder/factory.cjs +115 -0
- package/dist/src/fields/field/builder/factory.d.cts +63 -0
- package/dist/src/fields/field/builder/factory.d.cts.map +1 -0
- package/dist/src/fields/field/builder/factory.d.ts +63 -0
- package/dist/src/fields/field/builder/factory.d.ts.map +1 -0
- package/dist/src/fields/field/builder/factory.js +112 -0
- package/dist/src/fields/field/builder/handlers.cjs +2 -0
- package/dist/src/fields/field/builder/handlers.d.cts +38 -0
- package/dist/src/fields/field/builder/handlers.d.cts.map +1 -0
- package/dist/src/fields/field/builder/handlers.d.ts +38 -0
- package/dist/src/fields/field/builder/handlers.d.ts.map +1 -0
- package/dist/src/fields/field/builder/handlers.js +1 -0
- package/dist/src/fields/field/builder/helpers.cjs +153 -0
- package/dist/src/fields/field/builder/helpers.d.cts +89 -0
- package/dist/src/fields/field/builder/helpers.d.cts.map +1 -0
- package/dist/src/fields/field/builder/helpers.d.ts +89 -0
- package/dist/src/fields/field/builder/helpers.d.ts.map +1 -0
- package/dist/src/fields/field/builder/helpers.js +148 -0
- package/dist/src/fields/field/hooks/use-field.cjs +89 -0
- package/dist/src/fields/field/hooks/use-field.d.cts +106 -0
- package/dist/src/fields/field/hooks/use-field.d.cts.map +1 -0
- package/dist/src/fields/field/hooks/use-field.d.ts +106 -0
- package/dist/src/fields/field/hooks/use-field.d.ts.map +1 -0
- package/dist/src/fields/field/hooks/use-field.js +85 -0
- package/dist/src/fields/field/types/builder.cjs +2 -0
- package/dist/src/fields/field/types/builder.d.cts +195 -0
- package/dist/src/fields/field/types/builder.d.cts.map +1 -0
- package/dist/src/fields/field/types/builder.d.ts +195 -0
- package/dist/src/fields/field/types/builder.d.ts.map +1 -0
- package/dist/src/fields/field/types/builder.js +1 -0
- package/dist/src/fields/field/types/extractors.cjs +2 -0
- package/dist/src/fields/field/types/extractors.d.cts +82 -0
- package/dist/src/fields/field/types/extractors.d.cts.map +1 -0
- package/dist/src/fields/field/types/extractors.d.ts +82 -0
- package/dist/src/fields/field/types/extractors.d.ts.map +1 -0
- package/dist/src/fields/field/types/extractors.js +1 -0
- package/dist/src/fields/field/types/field.cjs +2 -0
- package/dist/src/fields/field/types/field.d.cts +119 -0
- package/dist/src/fields/field/types/field.d.cts.map +1 -0
- package/dist/src/fields/field/types/field.d.ts +119 -0
- package/dist/src/fields/field/types/field.d.ts.map +1 -0
- package/dist/src/fields/field/types/field.js +1 -0
- package/dist/src/fields/index.cjs +22 -0
- package/dist/src/fields/index.d.cts +19 -0
- package/dist/src/fields/index.d.cts.map +1 -0
- package/dist/src/fields/index.d.ts +19 -0
- package/dist/src/fields/index.d.ts.map +1 -0
- package/dist/src/fields/index.js +15 -0
- package/dist/src/index.cjs +50 -0
- package/dist/src/index.d.cts +26 -0
- package/dist/src/index.d.cts.map +1 -0
- package/dist/src/index.d.ts +26 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +23 -0
- package/dist/src/integrations/react-hook-form.cjs +5 -0
- package/dist/src/integrations/react-hook-form.d.cts +3 -0
- package/dist/src/integrations/react-hook-form.d.cts.map +1 -0
- package/dist/src/integrations/react-hook-form.d.ts +3 -0
- package/dist/src/integrations/react-hook-form.d.ts.map +1 -0
- package/dist/src/integrations/react-hook-form.js +1 -0
- package/dist/src/resolver/helpers/nested-objects.cjs +239 -0
- package/dist/src/resolver/helpers/nested-objects.d.cts +89 -0
- package/dist/src/resolver/helpers/nested-objects.d.cts.map +1 -0
- package/dist/src/resolver/helpers/nested-objects.d.ts +89 -0
- package/dist/src/resolver/helpers/nested-objects.d.ts.map +1 -0
- package/dist/src/resolver/helpers/nested-objects.js +231 -0
- package/dist/src/resolver/helpers/shape-to-zod-schema.cjs +28 -0
- package/dist/src/resolver/helpers/shape-to-zod-schema.d.cts +20 -0
- package/dist/src/resolver/helpers/shape-to-zod-schema.d.cts.map +1 -0
- package/dist/src/resolver/helpers/shape-to-zod-schema.d.ts +20 -0
- package/dist/src/resolver/helpers/shape-to-zod-schema.d.ts.map +1 -0
- package/dist/src/resolver/helpers/shape-to-zod-schema.js +25 -0
- package/dist/src/resolver/resolver.cjs +40 -0
- package/dist/src/resolver/resolver.d.cts +40 -0
- package/dist/src/resolver/resolver.d.cts.map +1 -0
- package/dist/src/resolver/resolver.d.ts +40 -0
- package/dist/src/resolver/resolver.d.ts.map +1 -0
- package/dist/src/resolver/resolver.js +37 -0
- package/dist/src/resolver/types/nested-helpers.cjs +2 -0
- package/dist/src/resolver/types/nested-helpers.d.cts +109 -0
- package/dist/src/resolver/types/nested-helpers.d.cts.map +1 -0
- package/dist/src/resolver/types/nested-helpers.d.ts +109 -0
- package/dist/src/resolver/types/nested-helpers.d.ts.map +1 -0
- package/dist/src/resolver/types/nested-helpers.js +1 -0
- package/dist/src/types/dot-notation.cjs +2 -0
- package/dist/src/types/dot-notation.d.cts +8 -0
- package/dist/src/types/dot-notation.d.cts.map +1 -0
- package/dist/src/types/dot-notation.d.ts +8 -0
- package/dist/src/types/dot-notation.d.ts.map +1 -0
- package/dist/src/types/dot-notation.js +1 -0
- package/dist/src/types/object.cjs +2 -0
- package/dist/src/types/object.d.cts +18 -0
- package/dist/src/types/object.d.cts.map +1 -0
- package/dist/src/types/object.d.ts +18 -0
- package/dist/src/types/object.d.ts.map +1 -0
- package/dist/src/types/object.js +1 -0
- package/dist/src/wizards/step/hooks/use-step-machine.cjs +155 -0
- package/dist/src/wizards/step/hooks/use-step-machine.d.cts +104 -0
- package/dist/src/wizards/step/hooks/use-step-machine.d.cts.map +1 -0
- package/dist/src/wizards/step/hooks/use-step-machine.d.ts +104 -0
- package/dist/src/wizards/step/hooks/use-step-machine.d.ts.map +1 -0
- package/dist/src/wizards/step/hooks/use-step-machine.js +151 -0
- package/dist/src/wizards/step/types/step.cjs +2 -0
- package/dist/src/wizards/step/types/step.d.cts +59 -0
- package/dist/src/wizards/step/types/step.d.cts.map +1 -0
- package/dist/src/wizards/step/types/step.d.ts +59 -0
- package/dist/src/wizards/step/types/step.d.ts.map +1 -0
- package/dist/src/wizards/step/types/step.js +1 -0
- package/dist/src/wizards/step/utils/step-effects.cjs +73 -0
- package/dist/src/wizards/step/utils/step-effects.d.cts +54 -0
- package/dist/src/wizards/step/utils/step-effects.d.cts.map +1 -0
- package/dist/src/wizards/step/utils/step-effects.d.ts +54 -0
- package/dist/src/wizards/step/utils/step-effects.d.ts.map +1 -0
- package/dist/src/wizards/step/utils/step-effects.js +68 -0
- package/dist/src/wizards/step/utils/step.cjs +326 -0
- package/dist/src/wizards/step/utils/step.d.cts +119 -0
- package/dist/src/wizards/step/utils/step.d.cts.map +1 -0
- package/dist/src/wizards/step/utils/step.d.ts +119 -0
- package/dist/src/wizards/step/utils/step.d.ts.map +1 -0
- package/dist/src/wizards/step/utils/step.js +312 -0
- package/dist/src/wizards/wizard/builder/components.cjs +75 -0
- package/dist/src/wizards/wizard/builder/components.d.cts +106 -0
- package/dist/src/wizards/wizard/builder/components.d.cts.map +1 -0
- package/dist/src/wizards/wizard/builder/components.d.ts +106 -0
- package/dist/src/wizards/wizard/builder/components.d.ts.map +1 -0
- package/dist/src/wizards/wizard/builder/components.js +72 -0
- package/dist/src/wizards/wizard/builder/config.cjs +33 -0
- package/dist/src/wizards/wizard/builder/config.d.cts +35 -0
- package/dist/src/wizards/wizard/builder/config.d.cts.map +1 -0
- package/dist/src/wizards/wizard/builder/config.d.ts +35 -0
- package/dist/src/wizards/wizard/builder/config.d.ts.map +1 -0
- package/dist/src/wizards/wizard/builder/config.js +30 -0
- package/dist/src/wizards/wizard/builder/helpers.cjs +145 -0
- package/dist/src/wizards/wizard/builder/helpers.d.cts +85 -0
- package/dist/src/wizards/wizard/builder/helpers.d.cts.map +1 -0
- package/dist/src/wizards/wizard/builder/helpers.d.ts +85 -0
- package/dist/src/wizards/wizard/builder/helpers.d.ts.map +1 -0
- package/dist/src/wizards/wizard/builder/helpers.js +138 -0
- package/dist/src/wizards/wizard/context.cjs +77 -0
- package/dist/src/wizards/wizard/context.d.cts +84 -0
- package/dist/src/wizards/wizard/context.d.cts.map +1 -0
- package/dist/src/wizards/wizard/context.d.ts +84 -0
- package/dist/src/wizards/wizard/context.d.ts.map +1 -0
- package/dist/src/wizards/wizard/context.js +72 -0
- package/dist/src/wizards/wizard/hooks/use-auto-save.cjs +175 -0
- package/dist/src/wizards/wizard/hooks/use-auto-save.d.cts +30 -0
- package/dist/src/wizards/wizard/hooks/use-auto-save.d.cts.map +1 -0
- package/dist/src/wizards/wizard/hooks/use-auto-save.d.ts +30 -0
- package/dist/src/wizards/wizard/hooks/use-auto-save.d.ts.map +1 -0
- package/dist/src/wizards/wizard/hooks/use-auto-save.js +171 -0
- package/dist/src/wizards/wizard/hooks/use-wizard-form.cjs +490 -0
- package/dist/src/wizards/wizard/hooks/use-wizard-form.d.cts +39 -0
- package/dist/src/wizards/wizard/hooks/use-wizard-form.d.cts.map +1 -0
- package/dist/src/wizards/wizard/hooks/use-wizard-form.d.ts +39 -0
- package/dist/src/wizards/wizard/hooks/use-wizard-form.d.ts.map +1 -0
- package/dist/src/wizards/wizard/hooks/use-wizard-form.js +486 -0
- package/dist/src/wizards/wizard/hooks/use-wizard.cjs +341 -0
- package/dist/src/wizards/wizard/hooks/use-wizard.d.cts +112 -0
- package/dist/src/wizards/wizard/hooks/use-wizard.d.cts.map +1 -0
- package/dist/src/wizards/wizard/hooks/use-wizard.d.ts +112 -0
- package/dist/src/wizards/wizard/hooks/use-wizard.d.ts.map +1 -0
- package/dist/src/wizards/wizard/hooks/use-wizard.js +337 -0
- package/dist/src/wizards/wizard/types/extractors.cjs +2 -0
- package/dist/src/wizards/wizard/types/extractors.d.cts +67 -0
- package/dist/src/wizards/wizard/types/extractors.d.cts.map +1 -0
- package/dist/src/wizards/wizard/types/extractors.d.ts +67 -0
- package/dist/src/wizards/wizard/types/extractors.d.ts.map +1 -0
- package/dist/src/wizards/wizard/types/extractors.js +1 -0
- package/dist/src/wizards/wizard/types/hooks.cjs +8 -0
- package/dist/src/wizards/wizard/types/hooks.d.cts +136 -0
- package/dist/src/wizards/wizard/types/hooks.d.cts.map +1 -0
- package/dist/src/wizards/wizard/types/hooks.d.ts +136 -0
- package/dist/src/wizards/wizard/types/hooks.d.ts.map +1 -0
- package/dist/src/wizards/wizard/types/hooks.js +7 -0
- package/dist/src/wizards/wizard/types/wizard.cjs +32 -0
- package/dist/src/wizards/wizard/types/wizard.d.cts +79 -0
- package/dist/src/wizards/wizard/types/wizard.d.cts.map +1 -0
- package/dist/src/wizards/wizard/types/wizard.d.ts +79 -0
- package/dist/src/wizards/wizard/types/wizard.d.ts.map +1 -0
- package/dist/src/wizards/wizard/types/wizard.js +31 -0
- package/dist/src/wizards/wizard/utils/navigation.cjs +32 -0
- package/dist/src/wizards/wizard/utils/navigation.d.cts +43 -0
- package/dist/src/wizards/wizard/utils/navigation.d.cts.map +1 -0
- package/dist/src/wizards/wizard/utils/navigation.d.ts +43 -0
- package/dist/src/wizards/wizard/utils/navigation.d.ts.map +1 -0
- package/dist/src/wizards/wizard/utils/navigation.js +29 -0
- package/dist/src/wizards/wizard/utils/resolver-helpers.cjs +150 -0
- package/dist/src/wizards/wizard/utils/resolver-helpers.d.cts +35 -0
- package/dist/src/wizards/wizard/utils/resolver-helpers.d.cts.map +1 -0
- package/dist/src/wizards/wizard/utils/resolver-helpers.d.ts +35 -0
- package/dist/src/wizards/wizard/utils/resolver-helpers.d.ts.map +1 -0
- package/dist/src/wizards/wizard/utils/resolver-helpers.js +144 -0
- package/package.json +59 -31
- package/LICENSE +0 -15
- package/index.js +0 -1
package/AI_SPEC.md
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# Zormy — AI Spec
|
|
2
|
+
|
|
3
|
+
> Especificação para assistentes de IA: como usar o pacote **zormy** em projetos React.
|
|
4
|
+
|
|
5
|
+
## O que é
|
|
6
|
+
|
|
7
|
+
**Zormy** é uma biblioteca para formulários tipados e reutilizáveis em React. Combina:
|
|
8
|
+
|
|
9
|
+
- **React Hook Form** — controle de formulário
|
|
10
|
+
- **Zod** — validação e schemas
|
|
11
|
+
- **TypeScript** — inferência de tipos end-to-end
|
|
12
|
+
|
|
13
|
+
Conceitos principais:
|
|
14
|
+
|
|
15
|
+
- **Campos reutilizáveis**: criados com `field("key")` ou `abstractField()`, com `.schema()` e `.render()`.
|
|
16
|
+
- **Resolver**: `formyResolver({ fields: [...] })` monta o schema Zod a partir dos campos e integra com react-hook-form.
|
|
17
|
+
- **Form**: componente `<Form methods={...}>` que fornece contexto (FormProvider).
|
|
18
|
+
- **Wizards**: fluxos multi-step com `createWizardConfig`, `createWizardComponents` e `useWizard`.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Instalação e dependências
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pnpm add zormy zod react-hook-form @hookform/resolvers
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Peer dependencies: `react` (^18), `react-hook-form` (^7.71.1), `zod` (^3.25.28), `@hookform/resolvers` (^5.2.2).
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## API principal (import de `zormy`)
|
|
33
|
+
|
|
34
|
+
| Exportação | Uso |
|
|
35
|
+
|------------|-----|
|
|
36
|
+
| `field(key)` | Builder para campo com chave fixa (ex: `"name"`, `"user.email"`) |
|
|
37
|
+
| `abstractField()` | Builder para campo sem chave; usar `.extend({ key: "..." })` para obter um campo concreto |
|
|
38
|
+
| `formyResolver({ fields })` | Resolver para `useForm`; recebe array de campos e infere tipo do formulário |
|
|
39
|
+
| `Form` | `<Form methods={form}>` — fornece contexto do formulário (e opcionalmente `<form>`) |
|
|
40
|
+
| `useForm` | Re-export do react-hook-form (para tipagem consistente) |
|
|
41
|
+
| `createWizardConfig({ steps, fields, shouldIncludeStep? })` | Configuração do wizard (steps e campos por step) |
|
|
42
|
+
| `createWizardComponents(config)` | Retorna `{ Wizard, Step }` tipados |
|
|
43
|
+
| `useWizard(config & { defaultValues, onSubmit?, ... })` | Hook do wizard (form + navegação entre steps) |
|
|
44
|
+
| `useWizardContext` | Acesso ao contexto do wizard |
|
|
45
|
+
| `useAutoSaveContext`, `AutoSaveStatus` | Auto-save no wizard |
|
|
46
|
+
| `Controller`, `SubmitHandler` | Re-export do react-hook-form |
|
|
47
|
+
|
|
48
|
+
Tipos úteis: `FieldKey`, `FieldsToObject`, `FieldValue`.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Padrão: formulário simples
|
|
53
|
+
|
|
54
|
+
1. Definir campos com `field("key").schema(zodSchema).render(...)`.
|
|
55
|
+
2. Criar o form com `useForm({ resolver: formyResolver({ fields: [...] }), defaultValues })`.
|
|
56
|
+
3. Envolver a UI em `<Form methods={form}>` e renderizar os campos como componentes.
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import { z } from "zod";
|
|
60
|
+
import { field, Form, formyResolver, useForm } from "zormy";
|
|
61
|
+
|
|
62
|
+
const NameField = field("name")
|
|
63
|
+
.schema(z.string().min(3, "Mín. 3 caracteres"))
|
|
64
|
+
.render(({ register, fieldState }) => (
|
|
65
|
+
<div>
|
|
66
|
+
<input {...register()} />
|
|
67
|
+
{fieldState.error && <span>{fieldState.error.message}</span>}
|
|
68
|
+
</div>
|
|
69
|
+
));
|
|
70
|
+
|
|
71
|
+
function MyForm() {
|
|
72
|
+
const form = useForm({
|
|
73
|
+
resolver: formyResolver({ fields: [NameField] }),
|
|
74
|
+
defaultValues: { name: "" },
|
|
75
|
+
});
|
|
76
|
+
return (
|
|
77
|
+
<Form methods={form} onSubmit={form.handleSubmit((data) => console.log(data))}>
|
|
78
|
+
<NameField />
|
|
79
|
+
<button type="submit">Enviar</button>
|
|
80
|
+
</Form>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
- **Importante**: o `resolver` deve usar exatamente os campos que serão renderizados; `defaultValues` deve cobrir todas as chaves dos campos (incluindo aninhadas, se houver).
|
|
86
|
+
- No `render`, use `register()` sem argumentos para usar a chave do campo; para sobrescrever: `register({ name: "outra.chave" })`.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Campos aninhados (dot-notation)
|
|
91
|
+
|
|
92
|
+
Chaves com ponto são suportadas: o resolver monta um schema aninhado e os valores são acessados como `address.street`, etc.
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
const StreetField = field("address.street")
|
|
96
|
+
.schema(z.string().min(1))
|
|
97
|
+
.render(({ register }) => <input {...register()} />);
|
|
98
|
+
// defaultValues: { address: { street: "" } }
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Campos com dependências (dinâmicos)
|
|
104
|
+
|
|
105
|
+
Use `.dependsOn(OutroCampo, ...)` e depois `.schema()` com função que recebe `formValues` para schema condicional.
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
const PhoneField = field("phone")
|
|
109
|
+
.dependsOn(NameField)
|
|
110
|
+
.schema((formValues) => {
|
|
111
|
+
const name = formValues?.name;
|
|
112
|
+
return name?.length ? z.string().min(10, "Telefone obrigatório") : z.string().optional();
|
|
113
|
+
})
|
|
114
|
+
.render(({ register, fieldState, getValues }) => {
|
|
115
|
+
const name = getValues("name");
|
|
116
|
+
const required = Boolean(name?.length);
|
|
117
|
+
return <input {...register()} required={required} />;
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
O array passado para `formyResolver({ fields })` deve incluir todos os campos usados (incluindo os de `dependsOn`).
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Campo abstrato (template)
|
|
126
|
+
|
|
127
|
+
Use quando vários campos compartilham schema e UI, mudando só a chave.
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
const BaseText = abstractField()
|
|
131
|
+
.schema(z.string().min(3))
|
|
132
|
+
.render(({ register, fieldState }) => (
|
|
133
|
+
<div>
|
|
134
|
+
<input {...register()} />
|
|
135
|
+
{fieldState.error && <span>{fieldState.error.message}</span>}
|
|
136
|
+
</div>
|
|
137
|
+
));
|
|
138
|
+
|
|
139
|
+
const NameField = BaseText.extend({ key: "name" });
|
|
140
|
+
const EmailField = BaseText.extend({ key: "email" });
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Wizard multi-step
|
|
146
|
+
|
|
147
|
+
1. Definir `steps` (array de strings literais, ex: `["personal", "contact"] as const`).
|
|
148
|
+
2. Mapear cada step para um array de campos em `fields`: `{ personal: [NameField], contact: [EmailField] }`.
|
|
149
|
+
3. `createWizardConfig({ steps, fields, shouldIncludeStep? })`.
|
|
150
|
+
4. `createWizardComponents(config)` → `{ Wizard, Step }`.
|
|
151
|
+
5. `useWizard({ ...config, defaultValues, onSubmit?, initialStep?, mode?, autoSave?, ... })`.
|
|
152
|
+
6. Renderizar: `<Wizard wizard={wizard}>` e dentro `<Step step="personal">` etc.; usar `wizard.nextStep`, `wizard.prevStep` para navegação.
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
const config = createWizardConfig({
|
|
156
|
+
steps: ["personal", "contact"] as const,
|
|
157
|
+
fields: { personal: [NameField], contact: [EmailField] },
|
|
158
|
+
});
|
|
159
|
+
const { Wizard, Step } = createWizardComponents(config);
|
|
160
|
+
|
|
161
|
+
function MyWizard() {
|
|
162
|
+
const wizard = useWizard({
|
|
163
|
+
...config,
|
|
164
|
+
defaultValues: { name: "", email: "" },
|
|
165
|
+
onSubmit: (data) => console.log(data),
|
|
166
|
+
});
|
|
167
|
+
return (
|
|
168
|
+
<Wizard wizard={wizard}>
|
|
169
|
+
<Step step="personal">
|
|
170
|
+
<NameField />
|
|
171
|
+
<button type="button" onClick={wizard.nextStep}>Próximo</button>
|
|
172
|
+
</Step>
|
|
173
|
+
<Step step="contact">
|
|
174
|
+
<EmailField />
|
|
175
|
+
<button type="button" onClick={wizard.prevStep}>Voltar</button>
|
|
176
|
+
<button type="submit">Enviar</button>
|
|
177
|
+
</Step>
|
|
178
|
+
</Wizard>
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
- `defaultValues` deve cobrir todas as chaves de todos os campos de todos os steps.
|
|
184
|
+
- Steps condicionais: use `shouldIncludeStep: (step, formValues) => boolean` em `createWizardConfig`.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Form sem elemento `<form>`
|
|
189
|
+
|
|
190
|
+
Use `<Form methods={form} contextOnly>` e um único filho que receberá **apenas o contexto** (FormProvider). Props HTML passadas ao `Form` **não** são repassadas automaticamente ao filho (ex.: componente customizado ou Radix Slot).
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## O que evitar
|
|
195
|
+
|
|
196
|
+
- Não passar para `formyResolver` campos que não serão renderizados no formulário (ou o tipo e o schema podem ficar inconsistentes).
|
|
197
|
+
- Não misturar chaves flat e aninhadas de forma inconsistente em `defaultValues` (ex.: campo `"user.email"` exige `defaultValues.user.email`).
|
|
198
|
+
- Em wizards, não esquecer de incluir todos os campos de todos os steps em `defaultValues`.
|
|
199
|
+
- Para campos com `dependsOn`, sempre incluir os campos dependentes no array `fields` do resolver (e no wizard, no step correto).
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Estrutura de testes (manutenção)
|
|
204
|
+
|
|
205
|
+
Em `packages/zormy/__tests__/`:
|
|
206
|
+
|
|
207
|
+
- **`unit/`** — testes unitários por módulo: `unit/fields/`, `unit/wizard/`, `unit/utils/`, `unit/resolvers/`.
|
|
208
|
+
- **`types/`** — testes de tipo (`.test-d.ts`): `types/fields/`, `types/wizard/`.
|
|
209
|
+
- **`performance/`** — benchmarks e testes de re-render (mantido como está).
|
|
210
|
+
- **`integration/`** — reservado para testes end-to-end futuros (vários módulos).
|
|
211
|
+
|
|
212
|
+
Comandos: `pnpm test`, `pnpm test:typecheck`, `pnpm test:bench`.
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Resumo para geração de código
|
|
217
|
+
|
|
218
|
+
1. **Formulário simples**: `field("key").schema(z...).render(({ register, fieldState }) => ...)` → `formyResolver({ fields: [...] })` → `useForm` → `<Form methods={form}>` + campos.
|
|
219
|
+
2. **Aninhado**: chave `"a.b.c"` e `defaultValues: { a: { b: { c: "" } } }`.
|
|
220
|
+
3. **Condicional**: `.dependsOn(OutroCampo).schema((formValues) => z...)` e incluir dependentes em `fields`.
|
|
221
|
+
4. **Template**: `abstractField().schema(...).render(...)` e `.extend({ key: "..." })`.
|
|
222
|
+
5. **Wizard**: `createWizardConfig` → `createWizardComponents` → `useWizard` → `<Wizard>` + `<Step step="...">` e botões com `nextStep`/`prevStep`.
|
|
223
|
+
|
|
224
|
+
Versão do pacote: ver `package.json`. Requer React 18+, TypeScript 5+ recomendado.
|
package/README.md
CHANGED
|
@@ -1,21 +1,126 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
# Zormy
|
|
2
|
+
|
|
3
|
+
Sistema de formulários tipados e reutilizáveis para React, com validação Zod, campos aninhados e wizards multi-step.
|
|
4
|
+
|
|
5
|
+
## Instalação
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add zormy zod react-hook-form @hookform/resolvers
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Ou com npm/yarn:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install zormy zod react-hook-form @hookform/resolvers
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Uso rápido
|
|
18
|
+
|
|
19
|
+
### Formulário simples
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { field, Form, formyResolver, useForm } from "zormy";
|
|
23
|
+
import { z } from "zod";
|
|
24
|
+
|
|
25
|
+
const NameField = field("name")
|
|
26
|
+
.schema(z.string().min(3, "Mínimo 3 caracteres"))
|
|
27
|
+
.render(({ register, fieldState }) => (
|
|
28
|
+
<div>
|
|
29
|
+
<input {...register()} />
|
|
30
|
+
{fieldState.error && <span>{fieldState.error.message}</span>}
|
|
31
|
+
</div>
|
|
32
|
+
));
|
|
33
|
+
|
|
34
|
+
function MyForm() {
|
|
35
|
+
const form = useForm({
|
|
36
|
+
resolver: formyResolver({ fields: [NameField] }),
|
|
37
|
+
defaultValues: { name: "" },
|
|
38
|
+
mode: "onChange", // ou "onBlur" | "onSubmit" | "onTouched" | "all"
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<Form methods={form} onSubmit={form.handleSubmit((data) => console.log(data))}>
|
|
43
|
+
<NameField />
|
|
44
|
+
<button type="submit">Enviar</button>
|
|
45
|
+
</Form>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Wizard multi-step
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
import { createWizardConfig, createWizardComponents, useWizard, field } from "zormy";
|
|
54
|
+
import { z } from "zod";
|
|
55
|
+
|
|
56
|
+
const NameField = field("name").schema(z.string().min(3)).render(({ register, fieldState }) => (
|
|
57
|
+
<div>
|
|
58
|
+
<input {...register()} />
|
|
59
|
+
{fieldState.error && <span>{fieldState.error.message}</span>}
|
|
60
|
+
</div>
|
|
61
|
+
));
|
|
62
|
+
|
|
63
|
+
const EmailField = field("email").schema(z.string().email()).render(({ register, fieldState }) => (
|
|
64
|
+
<div>
|
|
65
|
+
<input type="email" {...register()} />
|
|
66
|
+
{fieldState.error && <span>{fieldState.error.message}</span>}
|
|
67
|
+
</div>
|
|
68
|
+
));
|
|
69
|
+
|
|
70
|
+
const config = createWizardConfig({
|
|
71
|
+
steps: ["personal", "contact"] as const,
|
|
72
|
+
fields: {
|
|
73
|
+
personal: [NameField],
|
|
74
|
+
contact: [EmailField],
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const { Wizard, Step } = createWizardComponents(config);
|
|
79
|
+
|
|
80
|
+
function MyWizard() {
|
|
81
|
+
const wizard = useWizard({
|
|
82
|
+
...config,
|
|
83
|
+
defaultValues: { name: "", email: "" },
|
|
84
|
+
mode: "onChange", // opcional: modo de validação do wizard
|
|
85
|
+
onSubmit: (data) => console.log(data),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<Wizard methods={wizard} onSubmit={wizard.handleSubmit()}>
|
|
90
|
+
<Step step="personal"><NameField /></Step>
|
|
91
|
+
<Step step="contact"><EmailField /></Step>
|
|
92
|
+
<div>
|
|
93
|
+
{!wizard.isFirstStep && <button type="button" onClick={wizard.back}>Voltar</button>}
|
|
94
|
+
{wizard.isLastStep ? (
|
|
95
|
+
<button type="submit">Finalizar</button>
|
|
96
|
+
) : (
|
|
97
|
+
<button type="button" onClick={() => void wizard.next()}>Próximo</button>
|
|
98
|
+
)}
|
|
99
|
+
</div>
|
|
100
|
+
</Wizard>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Recursos
|
|
106
|
+
|
|
107
|
+
- **TypeScript**: inferência de tipos a partir dos campos e do Zod
|
|
108
|
+
- **Validação**: schemas Zod estáticos ou dinâmicos (por valores do formulário)
|
|
109
|
+
- **Campos reutilizáveis**: `field("key")` e `abstractField()` com `.extend()`
|
|
110
|
+
- **Wizards**: steps, validação por etapa, steps condicionais, auto-save opcional
|
|
111
|
+
- **Resolver**: `formyResolver({ fields })` com suporte a chaves aninhadas (`"user.email"`)
|
|
112
|
+
|
|
113
|
+
## Documentação
|
|
114
|
+
|
|
115
|
+
Para guias completos, exemplos e API reference, consulte a [documentação do projeto](https://github.com/your-org/zormy) (ou o site de docs quando disponível).
|
|
116
|
+
|
|
117
|
+
## Peer dependencies
|
|
118
|
+
|
|
119
|
+
- `react` (catalog)
|
|
120
|
+
- `react-hook-form` ^7.71.1
|
|
121
|
+
- `zod` ^3.25.28
|
|
122
|
+
- `@hookform/resolvers` ^5.2.2
|
|
123
|
+
|
|
124
|
+
## Licença
|
|
125
|
+
|
|
126
|
+
Private / conforme o projeto.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Form = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_hook_form_1 = require("react-hook-form");
|
|
6
|
+
/**
|
|
7
|
+
* Componente de formulário integrado ao react-hook-form.
|
|
8
|
+
*
|
|
9
|
+
* Permite controle flexível do elemento raiz usando a prop `contextOnly`.
|
|
10
|
+
* - Por padrão, renderiza um `<form>`.
|
|
11
|
+
* - Com `contextOnly`, fornece apenas o contexto do formulário e renderiza o filho customizado, repassando as props do formulário para ele (não renderiza `<form>`).
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* // Modo padrão:
|
|
16
|
+
* <Form methods={formMethods}>
|
|
17
|
+
* <input name="foo" />
|
|
18
|
+
* </Form>
|
|
19
|
+
*
|
|
20
|
+
* // Com contextOnly (ex: usando Radix Slot ou wrapper customizado):
|
|
21
|
+
* <Form methods={formMethods} contextOnly>
|
|
22
|
+
* <CustomFormComponent />
|
|
23
|
+
* </Form>
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
const Form = (props) => {
|
|
27
|
+
const { methods, contextOnly, children, ...formProps } = props;
|
|
28
|
+
if (contextOnly) {
|
|
29
|
+
// Tipagem garante que contextOnly==true implica filhos ReactElement.
|
|
30
|
+
return (0, jsx_runtime_1.jsx)(react_hook_form_1.FormProvider, { ...methods, children: children });
|
|
31
|
+
}
|
|
32
|
+
// Padrão: renderiza <form>
|
|
33
|
+
return ((0, jsx_runtime_1.jsx)(react_hook_form_1.FormProvider, { ...methods, children: (0, jsx_runtime_1.jsx)("form", { ...formProps, children: children }) }));
|
|
34
|
+
};
|
|
35
|
+
exports.Form = Form;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ComponentPropsWithoutRef, ReactElement, ReactNode } from "react";
|
|
2
|
+
import type { FieldValues, UseFormReturn } from "react-hook-form";
|
|
3
|
+
/**
|
|
4
|
+
* Props do componente Form.
|
|
5
|
+
*
|
|
6
|
+
* @template TFieldValues - Tipo dos valores do formulário
|
|
7
|
+
* @template TContextOnly - Define se o formulário fornece apenas o contexto (sem envolver em `<form>`). Se true, espera um elemento filho do tipo ReactElement que receberá as props do formulário.
|
|
8
|
+
*
|
|
9
|
+
* @property methods - Instância de UseFormReturn do react-hook-form.
|
|
10
|
+
* @property contextOnly - Se verdadeiro, fornece apenas o contexto do formulário e renderiza o filho customizado **sem envolver em `<form>` e sem repassar props HTML do `Form` para o filho**. Útil para integração com bibliotecas como @radix-ui/react-slot, wrappers customizados, ou cenários avançados de composição.
|
|
11
|
+
*/
|
|
12
|
+
export type FormProps<TFieldValues extends FieldValues = FieldValues, TContextOnly extends boolean = false> = TContextOnly extends true ? {
|
|
13
|
+
methods: UseFormReturn<TFieldValues>;
|
|
14
|
+
/** Fornece apenas o contexto do formulário em vez de envolver em um <form>. Veja descrição acima. */
|
|
15
|
+
contextOnly: true;
|
|
16
|
+
/** Elemento filho único que recebe as props do formulário. */
|
|
17
|
+
children: ReactElement;
|
|
18
|
+
} & Omit<ComponentPropsWithoutRef<"form">, "children" | "ref"> : {
|
|
19
|
+
methods: UseFormReturn<TFieldValues>;
|
|
20
|
+
/** Renderiza formulário padrão <form> (valor default). */
|
|
21
|
+
contextOnly?: false | undefined;
|
|
22
|
+
children?: ReactNode;
|
|
23
|
+
} & ComponentPropsWithoutRef<"form">;
|
|
24
|
+
/**
|
|
25
|
+
* Componente de formulário integrado ao react-hook-form.
|
|
26
|
+
*
|
|
27
|
+
* Permite controle flexível do elemento raiz usando a prop `contextOnly`.
|
|
28
|
+
* - Por padrão, renderiza um `<form>`.
|
|
29
|
+
* - Com `contextOnly`, fornece apenas o contexto do formulário e renderiza o filho customizado, repassando as props do formulário para ele (não renderiza `<form>`).
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* // Modo padrão:
|
|
34
|
+
* <Form methods={formMethods}>
|
|
35
|
+
* <input name="foo" />
|
|
36
|
+
* </Form>
|
|
37
|
+
*
|
|
38
|
+
* // Com contextOnly (ex: usando Radix Slot ou wrapper customizado):
|
|
39
|
+
* <Form methods={formMethods} contextOnly>
|
|
40
|
+
* <CustomFormComponent />
|
|
41
|
+
* </Form>
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare const Form: <TFieldValues extends FieldValues = FieldValues, TContextOnly extends boolean = false>(props: FormProps<TFieldValues, TContextOnly>) => import("react/jsx-runtime").JSX.Element;
|
|
45
|
+
//# sourceMappingURL=Form.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Form.d.ts","sourceRoot":"","sources":["../../../src/components/Form.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,wBAAwB,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC/E,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAElE;;;;;;;;GAQG;AACH,MAAM,MAAM,SAAS,CACpB,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,YAAY,SAAS,OAAO,GAAG,KAAK,IACjC,YAAY,SAAS,IAAI,GAC1B;IACA,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,qGAAqG;IACrG,WAAW,EAAE,IAAI,CAAC;IAClB,8DAA8D;IAC9D,QAAQ,EAAE,YAAY,CAAC;CACvB,GAAG,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,KAAK,CAAC,GAC7D;IACA,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,0DAA0D;IAC1D,WAAW,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;IAChC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACrB,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC;AAEvC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,IAAI,GAChB,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,YAAY,SAAS,OAAO,GAAG,KAAK,EAEpC,OAAO,SAAS,CAAC,YAAY,EAAE,YAAY,CAAC,4CAc5C,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ComponentPropsWithoutRef, ReactElement, ReactNode } from "react";
|
|
2
|
+
import type { FieldValues, UseFormReturn } from "react-hook-form";
|
|
3
|
+
/**
|
|
4
|
+
* Props do componente Form.
|
|
5
|
+
*
|
|
6
|
+
* @template TFieldValues - Tipo dos valores do formulário
|
|
7
|
+
* @template TContextOnly - Define se o formulário fornece apenas o contexto (sem envolver em `<form>`). Se true, espera um elemento filho do tipo ReactElement que receberá as props do formulário.
|
|
8
|
+
*
|
|
9
|
+
* @property methods - Instância de UseFormReturn do react-hook-form.
|
|
10
|
+
* @property contextOnly - Se verdadeiro, fornece apenas o contexto do formulário e renderiza o filho customizado **sem envolver em `<form>` e sem repassar props HTML do `Form` para o filho**. Útil para integração com bibliotecas como @radix-ui/react-slot, wrappers customizados, ou cenários avançados de composição.
|
|
11
|
+
*/
|
|
12
|
+
export type FormProps<TFieldValues extends FieldValues = FieldValues, TContextOnly extends boolean = false> = TContextOnly extends true ? {
|
|
13
|
+
methods: UseFormReturn<TFieldValues>;
|
|
14
|
+
/** Fornece apenas o contexto do formulário em vez de envolver em um <form>. Veja descrição acima. */
|
|
15
|
+
contextOnly: true;
|
|
16
|
+
/** Elemento filho único que recebe as props do formulário. */
|
|
17
|
+
children: ReactElement;
|
|
18
|
+
} & Omit<ComponentPropsWithoutRef<"form">, "children" | "ref"> : {
|
|
19
|
+
methods: UseFormReturn<TFieldValues>;
|
|
20
|
+
/** Renderiza formulário padrão <form> (valor default). */
|
|
21
|
+
contextOnly?: false | undefined;
|
|
22
|
+
children?: ReactNode;
|
|
23
|
+
} & ComponentPropsWithoutRef<"form">;
|
|
24
|
+
/**
|
|
25
|
+
* Componente de formulário integrado ao react-hook-form.
|
|
26
|
+
*
|
|
27
|
+
* Permite controle flexível do elemento raiz usando a prop `contextOnly`.
|
|
28
|
+
* - Por padrão, renderiza um `<form>`.
|
|
29
|
+
* - Com `contextOnly`, fornece apenas o contexto do formulário e renderiza o filho customizado, repassando as props do formulário para ele (não renderiza `<form>`).
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* // Modo padrão:
|
|
34
|
+
* <Form methods={formMethods}>
|
|
35
|
+
* <input name="foo" />
|
|
36
|
+
* </Form>
|
|
37
|
+
*
|
|
38
|
+
* // Com contextOnly (ex: usando Radix Slot ou wrapper customizado):
|
|
39
|
+
* <Form methods={formMethods} contextOnly>
|
|
40
|
+
* <CustomFormComponent />
|
|
41
|
+
* </Form>
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare const Form: <TFieldValues extends FieldValues = FieldValues, TContextOnly extends boolean = false>(props: FormProps<TFieldValues, TContextOnly>) => import("react/jsx-runtime").JSX.Element;
|
|
45
|
+
//# sourceMappingURL=Form.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Form.d.ts","sourceRoot":"","sources":["../../../src/components/Form.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,wBAAwB,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC/E,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAElE;;;;;;;;GAQG;AACH,MAAM,MAAM,SAAS,CACpB,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,YAAY,SAAS,OAAO,GAAG,KAAK,IACjC,YAAY,SAAS,IAAI,GAC1B;IACA,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,qGAAqG;IACrG,WAAW,EAAE,IAAI,CAAC;IAClB,8DAA8D;IAC9D,QAAQ,EAAE,YAAY,CAAC;CACvB,GAAG,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,KAAK,CAAC,GAC7D;IACA,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,0DAA0D;IAC1D,WAAW,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;IAChC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACrB,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC;AAEvC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,IAAI,GAChB,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,YAAY,SAAS,OAAO,GAAG,KAAK,EAEpC,OAAO,SAAS,CAAC,YAAY,EAAE,YAAY,CAAC,4CAc5C,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { FormProvider } from "react-hook-form";
|
|
3
|
+
/**
|
|
4
|
+
* Componente de formulário integrado ao react-hook-form.
|
|
5
|
+
*
|
|
6
|
+
* Permite controle flexível do elemento raiz usando a prop `contextOnly`.
|
|
7
|
+
* - Por padrão, renderiza um `<form>`.
|
|
8
|
+
* - Com `contextOnly`, fornece apenas o contexto do formulário e renderiza o filho customizado, repassando as props do formulário para ele (não renderiza `<form>`).
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* // Modo padrão:
|
|
13
|
+
* <Form methods={formMethods}>
|
|
14
|
+
* <input name="foo" />
|
|
15
|
+
* </Form>
|
|
16
|
+
*
|
|
17
|
+
* // Com contextOnly (ex: usando Radix Slot ou wrapper customizado):
|
|
18
|
+
* <Form methods={formMethods} contextOnly>
|
|
19
|
+
* <CustomFormComponent />
|
|
20
|
+
* </Form>
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export const Form = (props) => {
|
|
24
|
+
const { methods, contextOnly, children, ...formProps } = props;
|
|
25
|
+
if (contextOnly) {
|
|
26
|
+
// Tipagem garante que contextOnly==true implica filhos ReactElement.
|
|
27
|
+
return _jsx(FormProvider, { ...methods, children: children });
|
|
28
|
+
}
|
|
29
|
+
// Padrão: renderiza <form>
|
|
30
|
+
return (_jsx(FormProvider, { ...methods, children: _jsx("form", { ...formProps, children: children }) }));
|
|
31
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Step = Step;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const context_1 = require("../wizards/wizard/context.cjs");
|
|
6
|
+
/**
|
|
7
|
+
* Step para wizard, renderiza somente se ativo e com tipagem dinâmica no as
|
|
8
|
+
*/
|
|
9
|
+
function Step(props) {
|
|
10
|
+
const { step, as, children, ...rest } = props;
|
|
11
|
+
const { currentStep } = (0, context_1.useWizardContext)();
|
|
12
|
+
const Component = as || "div";
|
|
13
|
+
if (currentStep !== step) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
return (0, jsx_runtime_1.jsx)(Component, { ...rest, children: children });
|
|
17
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ComponentPropsWithoutRef, ElementType, ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* StepProps tipada para permitir definir dinamicamente o componente raíz
|
|
4
|
+
*
|
|
5
|
+
* @template TAs - Tipo do componente (padrão: 'div')
|
|
6
|
+
*/
|
|
7
|
+
export type StepProps<TAs extends ElementType = "div"> = {
|
|
8
|
+
step: string;
|
|
9
|
+
as?: TAs;
|
|
10
|
+
children?: ReactNode;
|
|
11
|
+
} & Omit<ComponentPropsWithoutRef<TAs>, "as" | "children">;
|
|
12
|
+
/**
|
|
13
|
+
* Step para wizard, renderiza somente se ativo e com tipagem dinâmica no as
|
|
14
|
+
*/
|
|
15
|
+
export declare function Step<TAs extends ElementType = "div">(props: StepProps<TAs>): import("react/jsx-runtime").JSX.Element | null;
|
|
16
|
+
//# sourceMappingURL=Step.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Step.d.ts","sourceRoot":"","sources":["../../../src/components/Step.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,wBAAwB,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE9E;;;;GAIG;AACH,MAAM,MAAM,SAAS,CAAC,GAAG,SAAS,WAAW,GAAG,KAAK,IAAI;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,GAAG,CAAC;IACT,QAAQ,CAAC,EAAE,SAAS,CAAC;CACrB,GAAG,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,EAAE,IAAI,GAAG,UAAU,CAAC,CAAC;AAE3D;;GAEG;AACH,wBAAgB,IAAI,CAAC,GAAG,SAAS,WAAW,GAAG,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,kDAU1E"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ComponentPropsWithoutRef, ElementType, ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* StepProps tipada para permitir definir dinamicamente o componente raíz
|
|
4
|
+
*
|
|
5
|
+
* @template TAs - Tipo do componente (padrão: 'div')
|
|
6
|
+
*/
|
|
7
|
+
export type StepProps<TAs extends ElementType = "div"> = {
|
|
8
|
+
step: string;
|
|
9
|
+
as?: TAs;
|
|
10
|
+
children?: ReactNode;
|
|
11
|
+
} & Omit<ComponentPropsWithoutRef<TAs>, "as" | "children">;
|
|
12
|
+
/**
|
|
13
|
+
* Step para wizard, renderiza somente se ativo e com tipagem dinâmica no as
|
|
14
|
+
*/
|
|
15
|
+
export declare function Step<TAs extends ElementType = "div">(props: StepProps<TAs>): import("react/jsx-runtime").JSX.Element | null;
|
|
16
|
+
//# sourceMappingURL=Step.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Step.d.ts","sourceRoot":"","sources":["../../../src/components/Step.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,wBAAwB,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE9E;;;;GAIG;AACH,MAAM,MAAM,SAAS,CAAC,GAAG,SAAS,WAAW,GAAG,KAAK,IAAI;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,GAAG,CAAC;IACT,QAAQ,CAAC,EAAE,SAAS,CAAC;CACrB,GAAG,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,EAAE,IAAI,GAAG,UAAU,CAAC,CAAC;AAE3D;;GAEG;AACH,wBAAgB,IAAI,CAAC,GAAG,SAAS,WAAW,GAAG,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,kDAU1E"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useWizardContext } from "../wizards/wizard/context.js";
|
|
3
|
+
/**
|
|
4
|
+
* Step para wizard, renderiza somente se ativo e com tipagem dinâmica no as
|
|
5
|
+
*/
|
|
6
|
+
export function Step(props) {
|
|
7
|
+
const { step, as, children, ...rest } = props;
|
|
8
|
+
const { currentStep } = useWizardContext();
|
|
9
|
+
const Component = as || "div";
|
|
10
|
+
if (currentStep !== step) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
return _jsx(Component, { ...rest, children: children });
|
|
14
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Wizard = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_hook_form_1 = require("react-hook-form");
|
|
6
|
+
const context_1 = require("../wizards/wizard/context.cjs");
|
|
7
|
+
/**
|
|
8
|
+
* Componente de formulário integrado ao react-hook-form.
|
|
9
|
+
*
|
|
10
|
+
* Permite controle flexível do elemento raiz usando a prop `contextOnly`.
|
|
11
|
+
* - Por padrão, renderiza um `<form>`.
|
|
12
|
+
* - Com `contextOnly`, fornece apenas o contexto do formulário e renderiza o filho customizado, repassando as props do formulário para ele (não renderiza `<form>`).
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* // Modo padrão:
|
|
17
|
+
* <Form methods={formMethods}>
|
|
18
|
+
* <input name="foo" />
|
|
19
|
+
* </Form>
|
|
20
|
+
*
|
|
21
|
+
* // Com contextOnly (ex: usando Radix Slot ou wrapper customizado):
|
|
22
|
+
* <Form methods={formMethods} contextOnly>
|
|
23
|
+
* <CustomFormComponent />
|
|
24
|
+
* </Form>
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
const Wizard = (props) => {
|
|
28
|
+
const { methods, contextOnly, children, ...formProps } = props;
|
|
29
|
+
if (contextOnly) {
|
|
30
|
+
// Tipagem garante que contextOnly==true implica filhos ReactElement.
|
|
31
|
+
return ((0, jsx_runtime_1.jsx)(react_hook_form_1.FormProvider, { ...methods, children: (0, jsx_runtime_1.jsx)(context_1.WizardProvider, { value: methods, children: children }) }));
|
|
32
|
+
}
|
|
33
|
+
// Padrão: renderiza <form>
|
|
34
|
+
return ((0, jsx_runtime_1.jsx)(react_hook_form_1.FormProvider, { ...methods, children: (0, jsx_runtime_1.jsx)(context_1.WizardProvider, { value: methods, children: (0, jsx_runtime_1.jsx)("form", { onSubmit: props?.onSubmit ? methods.handleSubmit(props.onSubmit) : undefined, ...formProps, children: children }) }) }));
|
|
35
|
+
};
|
|
36
|
+
exports.Wizard = Wizard;
|