@whatsaaaa/form-builder-react 0.3.0 → 0.3.2
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/README.md +31 -335
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
# @whatsaaaa/form-builder-react
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/@whatsaaaa/form-builder-react)
|
|
4
|
-
|
|
5
3
|
Render JSON form definitions with [Formisch](https://formisch.dev) and your own React components.
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/@whatsaaaa/form-builder-react)
|
|
6
|
+
[](https://www.npmjs.com/package/@whatsaaaa/form-builder-react)
|
|
7
|
+
[](https://github.com/whatsaaaa/form-builder/actions/workflows/ci.yml)
|
|
8
|
+
[](https://codecov.io/gh/whatsaaaa/form-builder)
|
|
9
|
+
[](https://react.dev)
|
|
10
|
+
[](https://www.npmjs.com/package/@whatsaaaa/form-builder-react)
|
|
11
|
+
[](https://github.com/whatsaaaa/form-builder/blob/main/LICENSE)
|
|
12
|
+
|
|
13
|
+
This is the React adapter of [form-builder](https://github.com/whatsaaaa/form-builder). It is headless: it reads the definition, connects every field to Formisch and turns input into the values the schema expects, but renders nothing of its own. You give it a component per field type, so it works with plain HTML, shadcn/ui or any other UI library.
|
|
8
14
|
|
|
9
15
|
## Install
|
|
10
16
|
|
|
11
17
|
```sh
|
|
12
|
-
pnpm add @whatsaaaa/form-builder-react @formisch/react valibot
|
|
18
|
+
pnpm add @whatsaaaa/form-builder-react @whatsaaaa/form-builder-schema @formisch/react valibot
|
|
13
19
|
```
|
|
14
20
|
|
|
15
|
-
React 18 or 19, `@formisch/react` 1.2 and Valibot 1.4.1 or later are required. `@whatsaaaa/form-builder-schema`
|
|
21
|
+
React 18 or 19, `@formisch/react` 1.2 and Valibot 1.4.1 or later are required. Install `@whatsaaaa/form-builder-schema` too: the examples import its types, such as `JsonForm`.
|
|
16
22
|
|
|
17
|
-
##
|
|
23
|
+
## Example
|
|
18
24
|
|
|
19
25
|
```tsx
|
|
20
26
|
import { Form } from '@formisch/react'
|
|
@@ -38,60 +44,7 @@ export function DefinitionForm({ definition }: { definition: JsonForm }) {
|
|
|
38
44
|
}
|
|
39
45
|
```
|
|
40
46
|
|
|
41
|
-
|
|
42
|
-
- `<JsonFields>` renders the fields inside your `<Form>`. The form element, the submit button and anything around them are yours.
|
|
43
|
-
- A definition with issues throws the builder's `DefinitionError` while rendering, so an error boundary can catch it. Run `validate()` first when the definition comes from outside your code.
|
|
44
|
-
- Like Formisch's `useForm`, `useJsonForm` reads the definition on the first render. To show another one, give the component that calls `useJsonForm` a new `key`: `<DefinitionForm key={id} definition={definition} />`.
|
|
45
|
-
|
|
46
|
-
### Options
|
|
47
|
-
|
|
48
|
-
```ts
|
|
49
|
-
useJsonForm(definition, {
|
|
50
|
-
builder: createSchemaBuilder({ fieldTypes: { money } }), // your own types, rules and messages
|
|
51
|
-
components, // your component per field type, see below
|
|
52
|
-
layoutComponents, // your component per layout type, see Layout
|
|
53
|
-
validate: 'blur', // when a field is validated the first time, as in Formisch
|
|
54
|
-
revalidate: 'input', // when it is validated again
|
|
55
|
-
})
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
`builder`, `validate` and `revalidate` are read on the first render, with the definition. `components` and `layoutComponents` are read on every render.
|
|
59
|
-
|
|
60
|
-
## Components
|
|
61
|
-
|
|
62
|
-
`components` has one component per field type, by type name. Pass it to `useJsonForm`, or to `<JsonFields>` and `<JsonField>` as a prop, which wins. Several types can share one:
|
|
63
|
-
|
|
64
|
-
```ts
|
|
65
|
-
import type { FieldComponents } from '@whatsaaaa/form-builder-react'
|
|
66
|
-
|
|
67
|
-
export const components: FieldComponents = {
|
|
68
|
-
text: TextInput,
|
|
69
|
-
email: TextInput,
|
|
70
|
-
number: TextInput,
|
|
71
|
-
select: SelectInput,
|
|
72
|
-
group: Fieldset,
|
|
73
|
-
array: Repeater,
|
|
74
|
-
heading: Heading,
|
|
75
|
-
// …one for every type your definitions use
|
|
76
|
-
}
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
A type that a definition uses but `components` doesn't have throws a `TypeError` that names every missing type, when `<JsonFields>` or `<JsonField>` renders. Only the fields it renders count.
|
|
80
|
-
|
|
81
|
-
What a component gets depends on the field's role:
|
|
82
|
-
|
|
83
|
-
| Role | Which fields | Props |
|
|
84
|
-
| ------- | ------------------------------ | -------------------------------------------------------------------------------- |
|
|
85
|
-
| value | every field with a value | `field`, `path`, `kind`, `required`, `input`, `errors`, `inputProps`, `setInput` |
|
|
86
|
-
| group | a container of kind `object` | `field`, `path`, `children`: the group's fields |
|
|
87
|
-
| array | a container of kind `array` | `field`, `path`, `items`, `errors`, `add`, `remove`, `move`, `children(index)` |
|
|
88
|
-
| display | a display element, kind `none` | `field` |
|
|
89
|
-
|
|
90
|
-
The props are typed as `ValueFieldProps`, `GroupFieldProps`, `ArrayFieldProps` and `DisplayFieldProps`.
|
|
91
|
-
|
|
92
|
-
Your own container types render through the group or array role too, by their kind.
|
|
93
|
-
|
|
94
|
-
### A value field
|
|
47
|
+
`components` maps each field type to a component of yours. A text input looks like this:
|
|
95
48
|
|
|
96
49
|
```tsx
|
|
97
50
|
import type { ValueFieldProps } from '@whatsaaaa/form-builder-react'
|
|
@@ -113,286 +66,29 @@ export function TextInput({ field, kind, input, errors, inputProps, ...props }:
|
|
|
113
66
|
}
|
|
114
67
|
```
|
|
115
68
|
|
|
116
|
-
|
|
117
|
-
- `path` is its Formisch path with real indexes, like `['lines', 0, 'quantity']`.
|
|
118
|
-
- `inputProps` are Formisch's element props: the field's name, a ref, and focus, change and blur handlers. Spread them on the input element, so Formisch knows when the field is touched and can focus it after a failed submit. Your own `onChange` after the spread replaces Formisch's, and calls `setInput` instead.
|
|
119
|
-
- `required` is true when the definition makes the field required.
|
|
120
|
-
|
|
121
|
-
### setInput
|
|
122
|
-
|
|
123
|
-
`setInput` sets the field's input after turning what an input element gives into what the schema expects, by the field's kind:
|
|
124
|
-
|
|
125
|
-
| Kind | Input | Value set |
|
|
126
|
-
| ------------------- | ----------------------- | ------------------------------ |
|
|
127
|
-
| `number` | `''` or only spaces | `undefined` |
|
|
128
|
-
| `number` | a numeric string, `'5'` | `5` |
|
|
129
|
-
| `file` | a `FileList` | its first file, or `undefined` |
|
|
130
|
-
| `array` of `file` | a `FileList` | an array of its files |
|
|
131
|
-
| `array` of `number` | numeric strings | numbers |
|
|
132
|
-
|
|
133
|
-
Anything else is set as it is, and the schema reports it. For a choice, like a radio or a select, set the option's value from `field.options` rather than the element's value: that keeps `2` a number and `true` a boolean.
|
|
134
|
-
|
|
135
|
-
```tsx
|
|
136
|
-
const options = field.options as { value: string | number | boolean; label: string }[]
|
|
137
|
-
|
|
138
|
-
<select
|
|
139
|
-
{...inputProps}
|
|
140
|
-
value={options.findIndex((option) => option.value === input)}
|
|
141
|
-
onChange={(e) => setInput(options[Number(e.target.value)]?.value)}
|
|
142
|
-
>
|
|
143
|
-
<option value={-1}>Choose…</option>
|
|
144
|
-
{options.map((option, i) => (
|
|
145
|
-
<option key={i} value={i}>
|
|
146
|
-
{option.label}
|
|
147
|
-
</option>
|
|
148
|
-
))}
|
|
149
|
-
</select>
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
For a file input, pass the element's `files` with `onChange={(e) => setInput(e.target.files)}`, and never set its `value`.
|
|
153
|
-
|
|
154
|
-
`setInput` stays the same function while the field is the same, so it is safe in an effect's or a memo's dependencies.
|
|
155
|
-
|
|
156
|
-
### A group
|
|
157
|
-
|
|
158
|
-
```tsx
|
|
159
|
-
import type { GroupFieldProps } from '@whatsaaaa/form-builder-react'
|
|
160
|
-
|
|
161
|
-
export function Fieldset({ field, children }: GroupFieldProps) {
|
|
162
|
-
return (
|
|
163
|
-
<fieldset>
|
|
164
|
-
<legend>{field.label}</legend>
|
|
165
|
-
{children}
|
|
166
|
-
</fieldset>
|
|
167
|
-
)
|
|
168
|
-
}
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
### An array
|
|
172
|
-
|
|
173
|
-
```tsx
|
|
174
|
-
import type { ArrayFieldProps } from '@whatsaaaa/form-builder-react'
|
|
175
|
-
|
|
176
|
-
export function Repeater({ field, items, errors, add, remove, children }: ArrayFieldProps) {
|
|
177
|
-
return (
|
|
178
|
-
<fieldset>
|
|
179
|
-
<legend>{field.label}</legend>
|
|
180
|
-
{items.map((item, index) => (
|
|
181
|
-
<div key={item}>
|
|
182
|
-
{children(index)}
|
|
183
|
-
<button type="button" onClick={() => remove(index)}>
|
|
184
|
-
Remove
|
|
185
|
-
</button>
|
|
186
|
-
</div>
|
|
187
|
-
))}
|
|
188
|
-
<button type="button" onClick={add}>
|
|
189
|
-
Add
|
|
190
|
-
</button>
|
|
191
|
-
{errors && <small>{errors[0]}</small>}
|
|
192
|
-
</fieldset>
|
|
193
|
-
)
|
|
194
|
-
}
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
- `children(index)` renders the fields of the item at `index`.
|
|
198
|
-
- `items` has one id per item. Use it as the `key`, so each item keeps its inputs when one is removed or moved.
|
|
199
|
-
- `add()` adds an item at the end, with the defaults its fields have in the definition.
|
|
200
|
-
- `errors` are the array's own messages, like a required array's or `maxLength`'s. Its items' fields show their own.
|
|
201
|
-
|
|
202
|
-
### A display element
|
|
203
|
-
|
|
204
|
-
```tsx
|
|
205
|
-
import type { DisplayFieldProps } from '@whatsaaaa/form-builder-react'
|
|
206
|
-
|
|
207
|
-
export function Heading({ field }: DisplayFieldProps) {
|
|
208
|
-
return <h2>{String(field.text ?? '')}</h2>
|
|
209
|
-
}
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
## Layout
|
|
213
|
-
|
|
214
|
-
A definition's [`layout`](https://github.com/whatsaaaa/form-builder/tree/main/packages/schema#layout) puts its fields in sections, rows of a 12-column grid and steps, and leaves slots for content of yours. `<JsonFields>` renders the current step of it. Give `useJsonForm` a component for each layout type the definition uses, and `<JsonFields>` the content of its slots:
|
|
215
|
-
|
|
216
|
-
```tsx
|
|
217
|
-
import type { LayoutComponents, RowProps, SectionProps } from '@whatsaaaa/form-builder-react'
|
|
218
|
-
|
|
219
|
-
function Section({ section, children }: SectionProps) {
|
|
220
|
-
return (
|
|
221
|
-
<fieldset>
|
|
222
|
-
<legend>{section.label}</legend>
|
|
223
|
-
{children}
|
|
224
|
-
</fieldset>
|
|
225
|
-
)
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// One line of a 12-column grid. On a narrow screen, give each cell the whole row.
|
|
229
|
-
function Row({ spans, children }: RowProps) {
|
|
230
|
-
return (
|
|
231
|
-
<div className="row">
|
|
232
|
-
{spans.map((span, index) => (
|
|
233
|
-
<div key={index} style={{ gridColumn: `span ${span}` }}>
|
|
234
|
-
{children(index)}
|
|
235
|
-
</div>
|
|
236
|
-
))}
|
|
237
|
-
</div>
|
|
238
|
-
)
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
const layoutComponents: LayoutComponents = { section: Section, row: Row }
|
|
242
|
-
|
|
243
|
-
function Checkout({ definition }: { definition: JsonForm }) {
|
|
244
|
-
const jsonForm = useJsonForm(definition, { components, layoutComponents })
|
|
245
|
-
return (
|
|
246
|
-
<Form of={jsonForm.form} onSubmit={save}>
|
|
247
|
-
<JsonFields of={jsonForm} slots={{ submit: <button type="submit">Place order</button> }} />
|
|
248
|
-
</Form>
|
|
249
|
-
)
|
|
250
|
-
}
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
```css
|
|
254
|
-
.row {
|
|
255
|
-
display: grid;
|
|
256
|
-
grid-template-columns: repeat(12, 1fr);
|
|
257
|
-
gap: 1rem;
|
|
258
|
-
}
|
|
259
|
-
```
|
|
69
|
+
`jsonForm.form` is a normal Formisch form, so every Formisch method works on it.
|
|
260
70
|
|
|
261
|
-
|
|
262
|
-
| ----------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
263
|
-
| `section` | `section`, as written, with its `id`, `label`, `description` and `ui`; `children` |
|
|
264
|
-
| `row` | `row`, as written, with its `id` and `ui`; `spans`, the span of each cell; `children(index)` renders the cell at `index` |
|
|
71
|
+
## Highlights
|
|
265
72
|
|
|
266
|
-
-
|
|
267
|
-
-
|
|
268
|
-
-
|
|
269
|
-
-
|
|
270
|
-
-
|
|
73
|
+
- Headless: one component of yours per field type, and per layout type
|
|
74
|
+
- `setInput` turns what an element gives into the value the schema expects
|
|
75
|
+
- Groups, arrays and display elements, with stable keys for array items
|
|
76
|
+
- Sections, 12-column rows, slots and multi-step forms from the definition's layout
|
|
77
|
+
- Steps that validate on Next and only show errors the user has seen
|
|
78
|
+
- Conditions from the affects package, re-rendering only when what is hidden changes
|
|
79
|
+
- Fields placed in your own markup with `<JsonField>`, `only` and `except`
|
|
271
80
|
|
|
272
|
-
|
|
81
|
+
## Documentation
|
|
273
82
|
|
|
274
|
-
|
|
83
|
+
- [Guide](https://whatsaaaa.github.io/form-builder/frameworks/react): options, components for every role, layout, steps, conditions, placing fields yourself and typing the form
|
|
84
|
+
- [API reference](https://whatsaaaa.github.io/form-builder/api/react/)
|
|
275
85
|
|
|
276
|
-
|
|
277
|
-
function Signup({ definition }: { definition: JsonForm }) {
|
|
278
|
-
const jsonForm = useJsonForm(definition, { components, layoutComponents })
|
|
279
|
-
const { steps } = jsonForm
|
|
280
|
-
return (
|
|
281
|
-
<Form of={jsonForm.form} onSubmit={save}>
|
|
282
|
-
<ol>
|
|
283
|
-
{steps.list.map((step, i) => (
|
|
284
|
-
<li key={step.step.id ?? i} aria-current={i === steps.index ? 'step' : undefined}>
|
|
285
|
-
{step.step.label}
|
|
286
|
-
</li>
|
|
287
|
-
))}
|
|
288
|
-
</ol>
|
|
289
|
-
<JsonFields of={jsonForm} />
|
|
290
|
-
{!steps.isFirst && (
|
|
291
|
-
<button type="button" onClick={steps.back}>
|
|
292
|
-
Back
|
|
293
|
-
</button>
|
|
294
|
-
)}
|
|
295
|
-
{steps.isLast ? (
|
|
296
|
-
<button type="submit">Sign up</button>
|
|
297
|
-
) : (
|
|
298
|
-
<button type="button" onClick={() => void steps.next()}>
|
|
299
|
-
Next
|
|
300
|
-
</button>
|
|
301
|
-
)}
|
|
302
|
-
</Form>
|
|
303
|
-
)
|
|
304
|
-
}
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
| Member | |
|
|
308
|
-
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
309
|
-
| `list` | the steps on show, each with its `step` as written (`id`, `label`, `description`, `ui`), `children` and `fields`: a step that [conditions](#conditions) hide is left out, unless the user is on it |
|
|
310
|
-
| `index`, `current` | the step `<JsonFields>` renders |
|
|
311
|
-
| `isFirst`, `isLast` | |
|
|
312
|
-
| `next()` | validates, and moves on when the step's fields have no issues. Resolves to whether it moved |
|
|
313
|
-
| `back()` | moves back, without validating |
|
|
314
|
-
| `goTo(index)` | back freely; forward through each step on the way, stopping at the first with issues |
|
|
315
|
-
|
|
316
|
-
The form is one Formisch form, so Formisch validates all of it at once. The steps make that work:
|
|
317
|
-
|
|
318
|
-
- **Next** validates the whole form, and only the issues on the current step's fields keep the user there. It focuses the first one, in layout order.
|
|
319
|
-
- **A step shows what the user left**: the errors it had when they left it, and none the first time they get to it, so the issues of steps nobody saw yet stay out of sight.
|
|
320
|
-
- **A step that failed Next revalidates** as the user fixes it, on the `revalidate` event, like a form after a failed submit.
|
|
321
|
-
- **A submit before the last step is a Next**, so Enter in a step with a single text input doesn't submit the form early. On the last step, Formisch submits as usual.
|
|
322
|
-
- **A submit that fails because of an earlier step**, like a form rule that reads fields of two steps, goes back to that step.
|
|
323
|
-
- `<JsonFields step={2} />` renders a given step instead of the current one, e.g. on a review page. A form without steps has one, and nothing changes for it.
|
|
324
|
-
|
|
325
|
-
## Conditions
|
|
326
|
-
|
|
327
|
-
With the [affects package](https://github.com/whatsaaaa/form-builder/tree/main/packages/affects), fields, sections and steps show and hide by the values of other fields. Pass `useJsonForm` a builder with the extension:
|
|
328
|
-
|
|
329
|
-
```tsx
|
|
330
|
-
import { affects } from '@whatsaaaa/form-builder-affects'
|
|
331
|
-
|
|
332
|
-
const builder = createSchemaBuilder({ extensions: [affects()] })
|
|
333
|
-
|
|
334
|
-
function DefinitionForm({ definition }: { definition: JsonForm }) {
|
|
335
|
-
const jsonForm = useJsonForm(definition, { builder, components, layoutComponents })
|
|
336
|
-
// ...
|
|
337
|
-
}
|
|
338
|
-
```
|
|
339
|
-
|
|
340
|
-
- **`<JsonFields>` and `<JsonField>` leave out what the conditions hide**: a hidden field, a hidden section, and a group, section or row whose fields are all hidden. A field hidden in a row drops out of it, and the others keep their spans.
|
|
341
|
-
- **Steps skip the hidden ones.** `steps.list` holds the steps on show, so a step whose fields are all hidden is left out, and Next and Back go past it. The step the user is on stays, until they leave it.
|
|
342
|
-
- **`useJsonForm` clears what `hideAndClear` clears**, with Formisch's `setInput`, as soon as it is cleared, wherever the field renders: in `<JsonFields>`, with `<JsonField>`, or by your own code. A field that starts hidden this way starts blank.
|
|
343
|
-
- **The schema skips hidden fields**, so they never block the form, and submits what the affects package says.
|
|
344
|
-
- **The form renders again only when what is hidden changes**, not on every keystroke: `useJsonForm` watches the input outside React, through `@formisch/react/internals`.
|
|
345
|
-
- **`jsonForm.visibility`** is the state for the form's input now, for your own renderers: `isHidden(node, indexes)`, `isStepHidden(step)`, `shownNodes(nodes, indexes)`. It is a new object only when what is hidden changes.
|
|
346
|
-
|
|
347
|
-
Without conditions, nothing is hidden, nothing is watched, and nothing changes.
|
|
348
|
-
|
|
349
|
-
## Placing fields yourself
|
|
350
|
-
|
|
351
|
-
Without a `layout`, `<JsonFields>` renders every field in the order of the definition. To put some of them somewhere else, in code rather than in the definition, place them with `<JsonField>` and leave them out of `<JsonFields>` with `except`:
|
|
352
|
-
|
|
353
|
-
```tsx
|
|
354
|
-
<Form of={jsonForm.form} onSubmit={save}>
|
|
355
|
-
<main>
|
|
356
|
-
<JsonFields of={jsonForm} except={['coupon', 'acceptTerms']} />
|
|
357
|
-
</main>
|
|
358
|
-
<aside>
|
|
359
|
-
<JsonField of={jsonForm} path="coupon" />
|
|
360
|
-
<JsonField of={jsonForm} path="acceptTerms" />
|
|
361
|
-
<button type="submit">Place order</button>
|
|
362
|
-
</aside>
|
|
363
|
-
</Form>
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
- A path is the field's names joined with dots: `'email'`, or `'address.city'` for a field of a group. A placed field validates, focuses and submits like any other, because it is still part of the one Formisch form.
|
|
367
|
-
- A group or an array comes with all its fields. A field of an array's items can't be placed on its own, because it has no index outside its item, so place the array. To leave such a field out of every item, use `'*'` for the index: `except={['lines.*.note']}`.
|
|
368
|
-
- `only` renders just the fields it names, in the order of the definition: `<JsonFields of={jsonForm} only={['name', 'email']} />`. Display elements have no dot path, even with a name, so `only` leaves them out.
|
|
369
|
-
- A path that names no field throws a `TypeError`, so a typo shows up at once. `only` and `except` are read on every render, so they can change, and a field keeps what was typed while it is hidden.
|
|
370
|
-
|
|
371
|
-
## Typing the form
|
|
372
|
-
|
|
373
|
-
The definition is data, so TypeScript doesn't know its fields, and `jsonForm.form` is typed loosely: Formisch's own functions accept only top-level paths on it. Give `useJsonForm` your input type, and your output type when it differs, and they check paths and values as in any Formisch form:
|
|
374
|
-
|
|
375
|
-
```ts
|
|
376
|
-
import { getInput, useFieldArray } from '@formisch/react'
|
|
377
|
-
|
|
378
|
-
interface CheckoutInput {
|
|
379
|
-
name: string
|
|
380
|
-
address: { city: string }
|
|
381
|
-
lines: { product: string; quantity: number }[]
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
const jsonForm = useJsonForm<CheckoutInput>(definition, { components })
|
|
385
|
-
|
|
386
|
-
getInput(jsonForm.form, { path: ['address', 'city'] }) // string | undefined
|
|
387
|
-
useFieldArray(jsonForm.form, { path: ['lines'] })
|
|
388
|
-
```
|
|
86
|
+
## Related packages
|
|
389
87
|
|
|
390
|
-
-
|
|
391
|
-
-
|
|
392
|
-
-
|
|
88
|
+
- [`@whatsaaaa/form-builder-schema`](https://github.com/whatsaaaa/form-builder/tree/main/packages/schema): build Formisch-ready Valibot schemas from JSON definitions
|
|
89
|
+
- [`@whatsaaaa/form-builder-affects`](https://github.com/whatsaaaa/form-builder/tree/main/packages/affects): show, hide and clear fields by conditions
|
|
90
|
+
- [`@whatsaaaa/form-builder-vue`](https://github.com/whatsaaaa/form-builder/tree/main/frameworks/vue): the same adapter for Vue
|
|
393
91
|
|
|
394
|
-
##
|
|
92
|
+
## License
|
|
395
93
|
|
|
396
|
-
-
|
|
397
|
-
- `ui.widget` doesn't pick a component. A component can read `field.ui` itself, e.g. to show a multiselect as checkboxes.
|
|
398
|
-
- Showing and hiding fields, or making one required because of another, belongs to a future affects package. The layout already hides a section, a row or a step whose fields are all hidden, through `shownNodes` in the schema package.
|
|
94
|
+
[MIT](https://github.com/whatsaaaa/form-builder/blob/main/LICENSE)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@whatsaaaa/form-builder-react",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Render JSON form definitions with Formisch and your own React components.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"form",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@whatsaaaa/form-builder-schema": "^0.15.
|
|
36
|
+
"@whatsaaaa/form-builder-schema": "^0.15.2"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@arethetypeswrong/cli": "^0.18.5",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"@types/react": "^19.3.0",
|
|
43
43
|
"@types/react-dom": "^19.3.0",
|
|
44
44
|
"@vitest/coverage-v8": "^5.0.5",
|
|
45
|
-
"@whatsaaaa/form-builder-affects": "^0.1.
|
|
45
|
+
"@whatsaaaa/form-builder-affects": "^0.1.2",
|
|
46
46
|
"happy-dom": "^20.0.0",
|
|
47
47
|
"publint": "^0.3.25",
|
|
48
48
|
"react": "^19.3.1",
|