torch-glare 2.5.5 → 2.6.0
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 +4 -3
- package/dist/bin/index.js +9 -24
- package/dist/bin/index.js.map +1 -1
- package/dist/src/commands/add.d.ts +2 -2
- package/dist/src/commands/add.d.ts.map +1 -1
- package/dist/src/commands/add.js +4 -70
- package/dist/src/commands/add.js.map +1 -1
- package/dist/src/commands/hook.d.ts +5 -4
- package/dist/src/commands/hook.d.ts.map +1 -1
- package/dist/src/commands/hook.js +7 -75
- package/dist/src/commands/hook.js.map +1 -1
- package/dist/src/commands/init.js +1 -1
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/layout.d.ts +5 -4
- package/dist/src/commands/layout.d.ts.map +1 -1
- package/dist/src/commands/layout.js +7 -75
- package/dist/src/commands/layout.js.map +1 -1
- package/dist/src/commands/provider.d.ts +5 -4
- package/dist/src/commands/provider.d.ts.map +1 -1
- package/dist/src/commands/provider.js +7 -75
- package/dist/src/commands/provider.js.map +1 -1
- package/dist/src/commands/update.d.ts.map +1 -1
- package/dist/src/commands/update.js +78 -43
- package/dist/src/commands/update.js.map +1 -1
- package/dist/src/commands/utils.d.ts +5 -4
- package/dist/src/commands/utils.d.ts.map +1 -1
- package/dist/src/commands/utils.js +7 -80
- package/dist/src/commands/utils.js.map +1 -1
- package/dist/src/shared/addFromRegistry.d.ts +16 -0
- package/dist/src/shared/addFromRegistry.d.ts.map +1 -0
- package/dist/src/shared/addFromRegistry.js +88 -0
- package/dist/src/shared/addFromRegistry.js.map +1 -0
- package/dist/src/shared/getInstallCommand.d.ts.map +1 -1
- package/dist/src/shared/getInstallCommand.js +5 -0
- package/dist/src/shared/getInstallCommand.js.map +1 -1
- package/dist/src/shared/installDependencies.d.ts +0 -10
- package/dist/src/shared/installDependencies.d.ts.map +1 -1
- package/dist/src/shared/installDependencies.js +0 -17
- package/dist/src/shared/installDependencies.js.map +1 -1
- package/dist/src/shared/installFromPlan.d.ts +7 -5
- package/dist/src/shared/installFromPlan.d.ts.map +1 -1
- package/dist/src/shared/installFromPlan.js +103 -36
- package/dist/src/shared/installFromPlan.js.map +1 -1
- package/dist/src/shared/loadRegistry.d.ts +12 -3
- package/dist/src/shared/loadRegistry.d.ts.map +1 -1
- package/dist/src/shared/loadRegistry.js +19 -20
- package/dist/src/shared/loadRegistry.js.map +1 -1
- package/dist/src/shared/registryClient.d.ts +19 -0
- package/dist/src/shared/registryClient.d.ts.map +1 -0
- package/dist/src/shared/registryClient.js +128 -0
- package/dist/src/shared/registryClient.js.map +1 -0
- package/dist/src/shared/resolveEntry.d.ts +10 -7
- package/dist/src/shared/resolveEntry.d.ts.map +1 -1
- package/dist/src/shared/resolveEntry.js +18 -13
- package/dist/src/shared/resolveEntry.js.map +1 -1
- package/dist/src/shared/suggestOtherCommand.d.ts +7 -1
- package/dist/src/shared/suggestOtherCommand.d.ts.map +1 -1
- package/dist/src/shared/suggestOtherCommand.js +29 -23
- package/dist/src/shared/suggestOtherCommand.js.map +1 -1
- package/dist/src/types/main.d.ts +31 -2
- package/dist/src/types/main.d.ts.map +1 -1
- package/package.json +6 -11
- package/apps/lib/components/ActionButton.tsx +0 -93
- package/apps/lib/components/ActionsGroup.tsx +0 -27
- package/apps/lib/components/AlertDialog.tsx +0 -204
- package/apps/lib/components/Avatar.tsx +0 -46
- package/apps/lib/components/Badge.tsx +0 -250
- package/apps/lib/components/BadgeField.tsx +0 -338
- package/apps/lib/components/Breadcrumb.tsx +0 -280
- package/apps/lib/components/Button.tsx +0 -317
- package/apps/lib/components/ButtonGroup.tsx +0 -190
- package/apps/lib/components/Calendar.tsx +0 -115
- package/apps/lib/components/Card.tsx +0 -95
- package/apps/lib/components/Checkbox.tsx +0 -42
- package/apps/lib/components/ColorPicker.tsx +0 -441
- package/apps/lib/components/ConclusionHeader.tsx +0 -148
- package/apps/lib/components/ContextMenu.tsx +0 -571
- package/apps/lib/components/CountBadge.tsx +0 -52
- package/apps/lib/components/DataTable.tsx +0 -213
- package/apps/lib/components/DataViews/badge.ts +0 -49
- package/apps/lib/components/DataViews/cell.tsx +0 -324
- package/apps/lib/components/DataViews/context.ts +0 -144
- package/apps/lib/components/DataViews/data-views.tsx +0 -383
- package/apps/lib/components/DataViews/filters/children.tsx +0 -98
- package/apps/lib/components/DataViews/filters/custom.tsx +0 -34
- package/apps/lib/components/DataViews/filters/filters.tsx +0 -157
- package/apps/lib/components/DataViews/filters/index.ts +0 -4
- package/apps/lib/components/DataViews/filters/labelled.tsx +0 -20
- package/apps/lib/components/DataViews/filters/presets.tsx +0 -65
- package/apps/lib/components/DataViews/filters/sync.tsx +0 -35
- package/apps/lib/components/DataViews/filters/values.ts +0 -173
- package/apps/lib/components/DataViews/header.tsx +0 -220
- package/apps/lib/components/DataViews/hooks/index.ts +0 -5
- package/apps/lib/components/DataViews/hooks/useActiveRow.ts +0 -22
- package/apps/lib/components/DataViews/hooks/useControllable.ts +0 -52
- package/apps/lib/components/DataViews/index.ts +0 -84
- package/apps/lib/components/DataViews/panel/columns.tsx +0 -153
- package/apps/lib/components/DataViews/panel/controls.tsx +0 -106
- package/apps/lib/components/DataViews/panel/index.ts +0 -3
- package/apps/lib/components/DataViews/panel/panel.tsx +0 -164
- package/apps/lib/components/DataViews/panel/saved-views.tsx +0 -67
- package/apps/lib/components/DataViews/panel/section.tsx +0 -81
- package/apps/lib/components/DataViews/panel/sort.tsx +0 -42
- package/apps/lib/components/DataViews/panel/tab.tsx +0 -31
- package/apps/lib/components/DataViews/slots.ts +0 -63
- package/apps/lib/components/DataViews/states.tsx +0 -38
- package/apps/lib/components/DataViews/types.ts +0 -510
- package/apps/lib/components/DataViews/views/board-view.tsx +0 -381
- package/apps/lib/components/DataViews/views/card-rows.tsx +0 -36
- package/apps/lib/components/DataViews/views/inbox-view.tsx +0 -260
- package/apps/lib/components/DataViews/views/pane-views.tsx +0 -196
- package/apps/lib/components/DataViews/views/table-view.tsx +0 -493
- package/apps/lib/components/DataViews/views/tree-view.tsx +0 -367
- package/apps/lib/components/DatePicker.tsx +0 -232
- package/apps/lib/components/Dialog.tsx +0 -116
- package/apps/lib/components/Divider.tsx +0 -28
- package/apps/lib/components/Drawer.tsx +0 -420
- package/apps/lib/components/DropdownMenu.tsx +0 -540
- package/apps/lib/components/FieldHint.tsx +0 -69
- package/apps/lib/components/Form.tsx +0 -182
- package/apps/lib/components/FormBuilder/context.ts +0 -73
- package/apps/lib/components/FormBuilder/field-kind.ts +0 -28
- package/apps/lib/components/FormBuilder/fields/ChoiceFields.tsx +0 -60
- package/apps/lib/components/FormBuilder/fields/ColorField.tsx +0 -59
- package/apps/lib/components/FormBuilder/fields/CustomField.tsx +0 -11
- package/apps/lib/components/FormBuilder/fields/DateField.tsx +0 -32
- package/apps/lib/components/FormBuilder/fields/FieldArray.tsx +0 -74
- package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +0 -163
- package/apps/lib/components/FormBuilder/fields/FileField.tsx +0 -39
- package/apps/lib/components/FormBuilder/fields/OptionListFields.tsx +0 -132
- package/apps/lib/components/FormBuilder/fields/OtpField.tsx +0 -31
- package/apps/lib/components/FormBuilder/fields/PhoneField.tsx +0 -109
- package/apps/lib/components/FormBuilder/fields/RichTextEditorField.tsx +0 -31
- package/apps/lib/components/FormBuilder/fields/SelectField.tsx +0 -91
- package/apps/lib/components/FormBuilder/fields/SignatureField.tsx +0 -157
- package/apps/lib/components/FormBuilder/fields/SliderField.tsx +0 -67
- package/apps/lib/components/FormBuilder/fields/SwitchBoxField.tsx +0 -41
- package/apps/lib/components/FormBuilder/fields/TableField.tsx +0 -336
- package/apps/lib/components/FormBuilder/fields/TextField.tsx +0 -213
- package/apps/lib/components/FormBuilder/fields/TreeSelectField.tsx +0 -43
- package/apps/lib/components/FormBuilder/fields/countries.ts +0 -303
- package/apps/lib/components/FormBuilder/fields/index.ts +0 -25
- package/apps/lib/components/FormBuilder/form-builder.tsx +0 -198
- package/apps/lib/components/FormBuilder/index.ts +0 -31
- package/apps/lib/components/FormBuilder/numberFormat.ts +0 -16
- package/apps/lib/components/FormBuilder/submit.tsx +0 -47
- package/apps/lib/components/FormBuilder/types.ts +0 -311
- package/apps/lib/components/FormRenderer/FormDrawer.tsx +0 -128
- package/apps/lib/components/FormRenderer/detail.tsx +0 -207
- package/apps/lib/components/FormRenderer/form-renderer.tsx +0 -297
- package/apps/lib/components/FormRenderer/header.tsx +0 -88
- package/apps/lib/components/FormRenderer/index.ts +0 -15
- package/apps/lib/components/FormRenderer/section.tsx +0 -39
- package/apps/lib/components/FormRenderer/stepper.tsx +0 -339
- package/apps/lib/components/FormRenderer/types.ts +0 -78
- package/apps/lib/components/FormSummary.tsx +0 -282
- package/apps/lib/components/HeaderBar.tsx +0 -117
- package/apps/lib/components/ImageAttachment.tsx +0 -209
- package/apps/lib/components/InnerLabelField.tsx +0 -154
- package/apps/lib/components/Input.tsx +0 -224
- package/apps/lib/components/InputField.tsx +0 -147
- package/apps/lib/components/InputOTP.tsx +0 -84
- package/apps/lib/components/Label.tsx +0 -129
- package/apps/lib/components/LabelField.tsx +0 -76
- package/apps/lib/components/LabeledCheckBox.tsx +0 -51
- package/apps/lib/components/LabeledRadio.tsx +0 -51
- package/apps/lib/components/LinkButton.tsx +0 -94
- package/apps/lib/components/LoginButton.tsx +0 -51
- package/apps/lib/components/PasswordLevel.tsx +0 -58
- package/apps/lib/components/Popover.tsx +0 -312
- package/apps/lib/components/ProfileMenu.tsx +0 -85
- package/apps/lib/components/Radio.tsx +0 -59
- package/apps/lib/components/RadioCard.tsx +0 -50
- package/apps/lib/components/ScrollArea.tsx +0 -54
- package/apps/lib/components/SearchField.tsx +0 -62
- package/apps/lib/components/SearchableSelect.tsx +0 -318
- package/apps/lib/components/SearchableTable.tsx +0 -344
- package/apps/lib/components/SearchableTree.tsx +0 -485
- package/apps/lib/components/SearchableTreeDialog.tsx +0 -502
- package/apps/lib/components/SectionBlock.tsx +0 -147
- package/apps/lib/components/Select.tsx +0 -347
- package/apps/lib/components/SimpleSelect.tsx +0 -225
- package/apps/lib/components/Skeleton.tsx +0 -12
- package/apps/lib/components/SlideDatePicker.tsx +0 -253
- package/apps/lib/components/SpinLoading.tsx +0 -174
- package/apps/lib/components/Stepper.tsx +0 -480
- package/apps/lib/components/Switch.tsx +0 -82
- package/apps/lib/components/TabFormItem.tsx +0 -153
- package/apps/lib/components/TabSwitch.tsx +0 -172
- package/apps/lib/components/Table.tsx +0 -610
- package/apps/lib/components/TextEditor/ChartBlockTool.ts +0 -676
- package/apps/lib/components/TextEditor/RichTextField.tsx +0 -46
- package/apps/lib/components/TextEditor/TableDnDWrapper.ts +0 -462
- package/apps/lib/components/TextEditor/TextEditor.tsx +0 -1164
- package/apps/lib/components/TextEditor/TextEditorToolbar.tsx +0 -429
- package/apps/lib/components/TextEditor/editor-tools/AlignmentTune.ts +0 -70
- package/apps/lib/components/TextEditor/editor-tools/ColorInlineTool.ts +0 -50
- package/apps/lib/components/TextEditor/editor-tools/StrikethroughInlineTool.ts +0 -48
- package/apps/lib/components/TextEditor/editor-tools/inlineFormat.ts +0 -98
- package/apps/lib/components/TextEditor/editorjs.d.ts +0 -60
- package/apps/lib/components/TextEditor/index.ts +0 -7
- package/apps/lib/components/TextEditor/markdownParser.ts +0 -346
- package/apps/lib/components/Textarea.tsx +0 -117
- package/apps/lib/components/Timeline.tsx +0 -263
- package/apps/lib/components/Toast.tsx +0 -87
- package/apps/lib/components/Toggle.tsx +0 -125
- package/apps/lib/components/ToggleButton.tsx +0 -140
- package/apps/lib/components/Tooltip.tsx +0 -116
- package/apps/lib/components/TransparentLabel.tsx +0 -71
- package/apps/lib/components/TreeDropDown.tsx +0 -115
- package/apps/lib/components/TreeFolder/TreeFolder.tsx +0 -380
- package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +0 -75
- package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +0 -354
- package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +0 -60
- package/apps/lib/components/TreeFolder/icons.tsx +0 -60
- package/apps/lib/components/TreeFolder/index.ts +0 -24
- package/apps/lib/components/TreeFolder/treeFolderUtils.ts +0 -109
- package/apps/lib/components/TreeFolder/types.ts +0 -77
- package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +0 -118
- package/apps/lib/hooks/useActiveTreeItem.ts +0 -58
- package/apps/lib/hooks/useClickOutside.ts +0 -27
- package/apps/lib/hooks/useDragDrop.tsx +0 -365
- package/apps/lib/hooks/useInfiniteScroll.ts +0 -108
- package/apps/lib/hooks/useIsMobile.ts +0 -21
- package/apps/lib/hooks/useResize.ts +0 -67
- package/apps/lib/hooks/useTagSelection.ts +0 -214
- package/apps/lib/layouts/CNLayout.tsx +0 -372
- package/apps/lib/layouts/DataViewCard.tsx +0 -62
- package/apps/lib/layouts/FieldSection.tsx +0 -91
- package/apps/lib/layouts/TreeSubLayout.tsx +0 -173
- package/apps/lib/providers/ThemeProvider.tsx +0 -84
- package/apps/lib/registry.json +0 -1201
- package/apps/lib/tsconfig.json +0 -9
- package/apps/lib/tsconfig.tsbuildinfo +0 -1
- package/apps/lib/utils/cn.ts +0 -6
- package/apps/lib/utils/color.ts +0 -175
- package/apps/lib/utils/dataViews/path.ts +0 -67
- package/apps/lib/utils/dataViews/query.ts +0 -73
- package/apps/lib/utils/dataViews/types.ts +0 -187
- package/apps/lib/utils/dateFormat.ts +0 -108
- package/apps/lib/utils/resize.ts +0 -31
- package/apps/lib/utils/types.ts +0 -16
- package/docs/BLOCKS.md +0 -129
- package/docs/CHANGELOG-1.1.16.md +0 -108
- package/docs/Cover.png +0 -0
- package/docs/README.md +0 -215
- package/docs/components/action-button.md +0 -638
- package/docs/components/actions-group.md +0 -708
- package/docs/components/alert-dialog.md +0 -920
- package/docs/components/avatar.md +0 -709
- package/docs/components/badge-field.md +0 -712
- package/docs/components/badge.md +0 -301
- package/docs/components/breadcrumb.md +0 -930
- package/docs/components/button-group.md +0 -650
- package/docs/components/button.md +0 -639
- package/docs/components/calendar.md +0 -555
- package/docs/components/card.md +0 -622
- package/docs/components/chart-block-tool.md +0 -129
- package/docs/components/checkbox.md +0 -699
- package/docs/components/cn-layout.md +0 -854
- package/docs/components/color-picker.md +0 -101
- package/docs/components/conclusion-header.md +0 -80
- package/docs/components/context-menu.md +0 -483
- package/docs/components/count-badge.md +0 -560
- package/docs/components/data-table.md +0 -854
- package/docs/components/data-views/backend-response.md +0 -324
- package/docs/components/data-views/examples/a11y-rtl.md +0 -250
- package/docs/components/data-views/examples/api-orders-route.md +0 -130
- package/docs/components/data-views/examples/fields.md +0 -362
- package/docs/components/data-views/examples/filters.md +0 -307
- package/docs/components/data-views/examples/inbox-routing.md +0 -218
- package/docs/components/data-views/examples/index.md +0 -29
- package/docs/components/data-views/examples/overview.md +0 -244
- package/docs/components/data-views/examples/panel.md +0 -212
- package/docs/components/data-views/examples/scale.md +0 -231
- package/docs/components/data-views/examples/server-side.md +0 -210
- package/docs/components/data-views/examples/state.md +0 -250
- package/docs/components/data-views/examples/tree-custom.md +0 -388
- package/docs/components/data-views/examples/view-registry.md +0 -313
- package/docs/components/data-views/examples/views.md +0 -534
- package/docs/components/data-views/guide.md +0 -405
- package/docs/components/data-views/index.md +0 -1495
- package/docs/components/data-views/migration.md +0 -79
- package/docs/components/date-picker.md +0 -857
- package/docs/components/dialog.md +0 -929
- package/docs/components/divider.md +0 -766
- package/docs/components/drawer.md +0 -654
- package/docs/components/dropdown-menu.md +0 -668
- package/docs/components/field-hint.md +0 -898
- package/docs/components/field-section.md +0 -781
- package/docs/components/form-builder.md +0 -276
- package/docs/components/form-renderer.md +0 -326
- package/docs/components/form-summary.md +0 -138
- package/docs/components/form.md +0 -785
- package/docs/components/header-bar.md +0 -188
- package/docs/components/image-attachment.md +0 -906
- package/docs/components/inner-label-field.md +0 -819
- package/docs/components/input-field.md +0 -623
- package/docs/components/input-otp.md +0 -756
- package/docs/components/input.md +0 -634
- package/docs/components/label-field.md +0 -770
- package/docs/components/label.md +0 -761
- package/docs/components/labeled-check-box.md +0 -642
- package/docs/components/labeled-radio.md +0 -796
- package/docs/components/link-button.md +0 -685
- package/docs/components/login-button.md +0 -872
- package/docs/components/password-level.md +0 -803
- package/docs/components/popover.md +0 -649
- package/docs/components/profile-menu.md +0 -656
- package/docs/components/radio-card.md +0 -801
- package/docs/components/radio.md +0 -735
- package/docs/components/scroll-area.md +0 -691
- package/docs/components/search-field.md +0 -702
- package/docs/components/searchable-select.md +0 -368
- package/docs/components/searchable-table.md +0 -438
- package/docs/components/searchable-tree-dialog.md +0 -190
- package/docs/components/searchable-tree.md +0 -200
- package/docs/components/section-block.md +0 -477
- package/docs/components/select.md +0 -709
- package/docs/components/simple-select.md +0 -741
- package/docs/components/skeleton.md +0 -706
- package/docs/components/slide-date-picker.md +0 -837
- package/docs/components/spin-loading.md +0 -696
- package/docs/components/stepper.md +0 -316
- package/docs/components/switch.md +0 -770
- package/docs/components/tab-form-item.md +0 -773
- package/docs/components/tab-switch.md +0 -170
- package/docs/components/table-dnd-wrapper.md +0 -107
- package/docs/components/table.md +0 -1088
- package/docs/components/text-editor.md +0 -735
- package/docs/components/textarea.md +0 -681
- package/docs/components/timeline.md +0 -254
- package/docs/components/toast.md +0 -773
- package/docs/components/toggle-button.md +0 -643
- package/docs/components/toggle.md +0 -882
- package/docs/components/tooltip.md +0 -513
- package/docs/components/transparent-label.md +0 -721
- package/docs/components/tree-drop-down.md +0 -740
- package/docs/components/tree-folder.md +0 -110
- package/docs/components/tree-sub-layout.md +0 -707
- package/docs/explanation/architecture.md +0 -54
- package/docs/explanation/design-system.md +0 -52
- package/docs/how-to/form-and-list-recipes.md +0 -386
- package/docs/how-to/forms-with-form-builder.md +0 -472
- package/docs/how-to/guides.md +0 -1027
- package/docs/migration/changelog.md +0 -54
- package/docs/migration/form-builder-2.5.2.md +0 -113
- package/docs/reference/cli.md +0 -112
- package/docs/reference/components.md +0 -572
- package/docs/reference/hooks.md +0 -1500
- package/docs/reference/providers.md +0 -866
- package/docs/reference/tailwind-plugins.md +0 -942
- package/docs/reference/theme.md +0 -85
- package/docs/reference/types.md +0 -1016
- package/docs/reference/utilities.md +0 -704
- package/docs/tutorials/building-first-form.md +0 -846
- package/docs/tutorials/component-composition.md +0 -882
- package/docs/tutorials/getting-started.md +0 -302
- package/docs/tutorials/theming-basics.md +0 -785
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: FormBuilder
|
|
3
|
-
description: The fields. A compound, composition-based form — author fields as JSX children (FormBuilder.Text, FormBuilder.Select, …) wired to any react-hook-form resolver. All chrome around the fields lives in FormRenderer.
|
|
4
|
-
component: true
|
|
5
|
-
group: Forms
|
|
6
|
-
keywords:
|
|
7
|
-
[
|
|
8
|
-
form-builder,
|
|
9
|
-
form,
|
|
10
|
-
compound,
|
|
11
|
-
composition,
|
|
12
|
-
react-hook-form,
|
|
13
|
-
resolver,
|
|
14
|
-
fields,
|
|
15
|
-
validation,
|
|
16
|
-
table,
|
|
17
|
-
field-array,
|
|
18
|
-
submit,
|
|
19
|
-
]
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
# FormBuilder
|
|
23
|
-
|
|
24
|
-
A **compound, composition-based** form. You author a form as JSX children — each
|
|
25
|
-
field is a `FormBuilder.*` component wired to [react-hook-form](https://react-hook-form.com/)
|
|
26
|
-
for you.
|
|
27
|
-
|
|
28
|
-
```tsx
|
|
29
|
-
<FormBuilder onSubmit={save} resolver={zodResolver(schema)} defaultValues={d}>
|
|
30
|
-
<FormBuilder.Text name="name" label="Name" required />
|
|
31
|
-
<FormBuilder.Currency name="price" label="Price" currencySymbol="$" />
|
|
32
|
-
</FormBuilder>
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## FormBuilder is the fields — nothing else
|
|
36
|
-
|
|
37
|
-
FormBuilder renders a `<form>`, its react-hook-form context, and your fields. Each field draws
|
|
38
|
-
its own row (label, required marker, hint). Beyond that it draws **no frame at all**: no titled
|
|
39
|
-
section cards, no page gutters, no scroll shell, no title header, no stepper rail, no summary
|
|
40
|
-
column. Rendered bare it simply fills its container — which is what an embedded form wants (a
|
|
41
|
-
settings rail, a `DataViews` filter panel).
|
|
42
|
-
|
|
43
|
-
Everything drawn *around* the fields lives in **[FormRenderer](./form-renderer.md)**:
|
|
44
|
-
|
|
45
|
-
| You want | Use |
|
|
46
|
-
| ------------------------------------- | ---------------------------------------------------- |
|
|
47
|
-
| A titled card grouping fields | `FormRenderer.Section` |
|
|
48
|
-
| A page title header + Save action bar | `FormRenderer`'s `header` and `actions` props |
|
|
49
|
-
| A wizard | `FormRenderer.Stepper` + `FormRenderer.Step` |
|
|
50
|
-
| A drawer | `FormRenderer` with `display="drawer"` |
|
|
51
|
-
| Live totals beside the form | `FormRenderer`'s `summary` prop + [FormSummary](./form-summary.md) |
|
|
52
|
-
| A read-only detail page | `FormRenderer.Sidebar` + `FormRenderer.Tab` |
|
|
53
|
-
|
|
54
|
-
> **For real forms, reach for [FormRenderer](./form-renderer.md), not raw FormBuilder.** You still
|
|
55
|
-
> author the fields as `FormBuilder.*` children — FormRenderer just wraps them.
|
|
56
|
-
|
|
57
|
-
`FormBuilder.Submit` is the one non-field part that stays here — see
|
|
58
|
-
[Field components](#field-components) for what it does. It renders the **primary action**: the blue
|
|
59
|
-
filled button. There is deliberately no `variant` prop — a form has one primary action, and letting
|
|
60
|
-
each call site pick a style is how that stops being true.
|
|
61
|
-
|
|
62
|
-
## Installation
|
|
63
|
-
|
|
64
|
-
TORCH Glare is a copy-in library: the CLI copies this component's source into your project.
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
npx torch-glare@latest init
|
|
68
|
-
npx torch-glare@latest add FormBuilder
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
## Imports
|
|
72
|
-
|
|
73
|
-
```tsx
|
|
74
|
-
import { FormBuilder } from "@/components/FormBuilder";
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
## Root props
|
|
78
|
-
|
|
79
|
-
| Prop | Type | Notes |
|
|
80
|
-
| ---------------- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
|
81
|
-
| `onSubmit` | `(values) => void \| Promise<void>` | Called on a valid submit. |
|
|
82
|
-
| `onInvalid` | `(errors) => void` | Called when validation fails. |
|
|
83
|
-
| `resolver` | `Resolver` | Any react-hook-form resolver, e.g. `zodResolver(schema)`. |
|
|
84
|
-
| `defaultValues` | `DefaultValues` | Initial values (create). |
|
|
85
|
-
| `values` | `T` | Controlled values (edit) — the form re-syncs when this changes. |
|
|
86
|
-
| `loading` | `boolean` | Submit shows a spinner; inputs disable. |
|
|
87
|
-
| `fieldDirection` | `'horizontal' \| 'vertical' \| 'flexible'` | Row layout. Unset is responsive; a `FormRenderer` drawer pins `'vertical'`, and `'flexible'` asks for the responsive layout back. |
|
|
88
|
-
| `resetOnSuccess` | `boolean` | Reset to defaults after a successful submit. |
|
|
89
|
-
| `form` | `UseFormReturn` | A hoisted `useForm` to bind to — pass when something outside the form must read the same values. |
|
|
90
|
-
| `id` | `string` | Sets the underlying `<form id>`, so a button outside the form can submit it via `form={id}` (e.g. a drawer header's Save). |
|
|
91
|
-
| `className` | `string` | Lands on the `<form>` element itself — e.g. `"min-w-0 flex-1"` to fill a flex parent. |
|
|
92
|
-
|
|
93
|
-
There is no `layout` prop and no `conclusion` prop: the fields always fill their container, and a
|
|
94
|
-
panel beside the form is `FormRenderer`'s `summary`.
|
|
95
|
-
|
|
96
|
-
## Field components
|
|
97
|
-
|
|
98
|
-
Each is a JSX child taking at least `name`, plus `label`, `placeholder`,
|
|
99
|
-
`description`, `required`, `disabled`, `hidden`, `fullWidth`, `hints`.
|
|
100
|
-
|
|
101
|
-
### Hints
|
|
102
|
-
|
|
103
|
-
`hints` stacks alerts under a field — helper text, a caveat, a confirmation. Each entry mirrors
|
|
104
|
-
`FieldHint`: `label`, an optional `state` of `info` (default) / `warning` / `error` / `success`, and
|
|
105
|
-
an optional `icon`.
|
|
106
|
-
|
|
107
|
-
```tsx
|
|
108
|
-
<FormBuilder.Text
|
|
109
|
-
name="sku"
|
|
110
|
-
label="SKU"
|
|
111
|
-
required
|
|
112
|
-
hints={[
|
|
113
|
-
{ state: "info", label: "Must be unique across the catalogue." },
|
|
114
|
-
{ state: "warning", label: "Changing this breaks existing links." },
|
|
115
|
-
]}
|
|
116
|
-
/>
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
The validation error is not one of these — it is rendered automatically and always comes **first**,
|
|
120
|
-
because it is the actionable message; your hints follow in the order given. A field with no `hints`
|
|
121
|
-
renders exactly as before.
|
|
122
|
-
|
|
123
|
-
Hints are ignored inside a `FormBuilder.Table` cell (and any other `bare` context): there errors
|
|
124
|
-
surface as a tooltip on the control so a row stays one line tall, and stacking alerts would defeat
|
|
125
|
-
that.
|
|
126
|
-
|
|
127
|
-
| Component | Input | Value |
|
|
128
|
-
| --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
|
|
129
|
-
| `FormBuilder.Text` / `.Email` / `.Password` | `InputField` | `string` |
|
|
130
|
-
| `FormBuilder.Number` | numeric `InputField` | `number` |
|
|
131
|
-
| `FormBuilder.Currency` (`currencySymbol`) | `InputField` + symbol | `number` |
|
|
132
|
-
| `FormBuilder.Textarea` | `Textarea` | `string` |
|
|
133
|
-
| `FormBuilder.Slider` (`min,max,step,range`) | `@radix-ui/react-slider` | `number` / `[number,number]` |
|
|
134
|
-
| `FormBuilder.Color` (`presets`, `alpha`) | `ColorPicker` (full palette: SV area, hue, opacity, eyedropper, HEX/RGB/HSL, presets) | hex `string` (`#rrggbb`, or `#rrggbbaa` when opacity < 100%) |
|
|
135
|
-
| `FormBuilder.Phone` (`defaultCountry`) | `SearchableSelect` + `InputField` | `string` |
|
|
136
|
-
| `FormBuilder.Select` (`options`) | `Select` | `string` |
|
|
137
|
-
| `FormBuilder.SearchableSelect` (`options`, async: `onSearchChange`/`onLoadMore`/`hasMore`) | `SearchableSelect` | `string` |
|
|
138
|
-
| `FormBuilder.MultiSelect` / `.Tags` (`options`) | `BadgeField` | `string[]` |
|
|
139
|
-
| `FormBuilder.RadioList` (`options`, each with optional `description`) | boxed radio list | `string` |
|
|
140
|
-
| `FormBuilder.CheckboxGroup` (`options`, each with optional `description`) | boxed checkbox list | `string[]` |
|
|
141
|
-
| `FormBuilder.RadioCards` (`options` with `description`) | `RadioCard` | `string` |
|
|
142
|
-
| `FormBuilder.Checkbox` (`subLabel`) | `Checkbox` + inline label | `boolean` |
|
|
143
|
-
| `FormBuilder.SwitchBox` (`subLabel`) | `Switch` in a `#f9f9f9` box | `boolean` |
|
|
144
|
-
| `FormBuilder.Otp` (`length`) | `InputOTP` | `string` |
|
|
145
|
-
| `FormBuilder.Date` | `DatePicker` | `Date` |
|
|
146
|
-
| `FormBuilder.DateRange` | `DatePicker` (range) | `{from,to}` |
|
|
147
|
-
| `FormBuilder.DateMultiple` | `DatePicker` (multiple) | `Date[]` |
|
|
148
|
-
| `FormBuilder.DateTime` | `DatePicker` (timePicker) | `Date` |
|
|
149
|
-
| `FormBuilder.TreeSelect` (`nodes`, `getNodeId`, `getNodeLabel`, …) | `SearchableTree` | node id (`string`) |
|
|
150
|
-
| `FormBuilder.File` / `.Image` (`accept`, `multiple`) | `ImageAttachment` | `File \| File[]` |
|
|
151
|
-
| `FormBuilder.RichText` | `TextEditor` (EditorJS) | `OutputData` |
|
|
152
|
-
| `FormBuilder.Signature` (`penColor`) | canvas pad | PNG data-URL `string` |
|
|
153
|
-
| `FormBuilder.FieldArray` (`children` render fn, `defaultItem`) | RHF `useFieldArray` | `object[]` |
|
|
154
|
-
| `FormBuilder.Table` (`columns`, `selectable`, `reorderable`, `defaultItem`) | editable grid in a `SectionBlock` | `object[]` |
|
|
155
|
-
| `FormBuilder.Custom` (`render`) | your control | anything |
|
|
156
|
-
|
|
157
|
-
`FormBuilder.Password` accepts `strengthMeter` (shows a `PasswordLevel` meter). `FormBuilder.FieldArray`
|
|
158
|
-
renders a repeating list — its `children` is a render fn `(rowName, index, remove) => …` and sub-fields
|
|
159
|
-
are named `${rowName}.field`.
|
|
160
|
-
|
|
161
|
-
`FormBuilder.Table` is the **table-shaped** counterpart of `FieldArray` (value `object[]`): an editable
|
|
162
|
-
grid where each row is a record and each column cell is any `FormBuilder.*` field. It renders its own
|
|
163
|
-
`SectionBlock` (`variant="Table"` — the full-bleed table shell), so place it as a **top-level child** of
|
|
164
|
-
the form, **not** inside a `FormRenderer.Section` — nesting produces a card inside a card. When you need a
|
|
165
|
-
table that isn't a form field, compose the shell yourself with `SectionBlock variant="Table"` (see
|
|
166
|
-
[SectionBlock → Table Variant](./section-block.md#table-variant)).
|
|
167
|
-
|
|
168
|
-
Each column pairs a `header` with a `cell(rowName, index)` renderer — name the cell's field
|
|
169
|
-
`${rowName}.<key>`. Set `width` to size a column; it is applied to both the header and the body cells.
|
|
170
|
-
The section header carries the actions: an **Add New** button and a **Delete Row** button that's disabled
|
|
171
|
-
until rows are checkbox-selected. A second **+ Add New** sits below the grid. Both live *outside* the
|
|
172
|
-
horizontal scroll container, so they stay put when a wide table is scrolled sideways. Rows support
|
|
173
|
-
**checkbox selection** (+ select-all), **drag-drop reordering**, and — per column, via `sortKey` — a
|
|
174
|
-
sort toggle in the header. Cells render
|
|
175
|
-
"bare" (control only) with validation errors shown as a tooltip on the control, so a row stays one line
|
|
176
|
-
tall, and each field passes `onTable` so it's borderless and blends into the grid. Practical cell fields
|
|
177
|
-
are the compact ones — `Text`, `Number`, `Currency`, `Select`, `SearchableSelect`, `Date`, `Phone`,
|
|
178
|
-
`Checkbox`, `SwitchBox`; wide fields (`RichText`, `Signature`, `File`) work but aren't suited to a cell.
|
|
179
|
-
`FormBuilder.Phone` collapses to a **plain number input** in a cell — two controls in one cell is not a
|
|
180
|
-
table column, so add a separate column (e.g. a `FormBuilder.Select` of dial codes) if you need the
|
|
181
|
-
country code.
|
|
182
|
-
|
|
183
|
-
```tsx
|
|
184
|
-
<FormBuilder.Table
|
|
185
|
-
name="items"
|
|
186
|
-
title="Items"
|
|
187
|
-
color="Green"
|
|
188
|
-
addLabel="Add item"
|
|
189
|
-
defaultItem={{ item: "", category: "hardware", qty: 1, price: 0 }}
|
|
190
|
-
columns={[
|
|
191
|
-
{
|
|
192
|
-
header: "Item",
|
|
193
|
-
width: 200,
|
|
194
|
-
cell: (row) => <FormBuilder.Text name={`${row}.item`} required />,
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
header: "Category",
|
|
198
|
-
cell: (row) => <FormBuilder.Select name={`${row}.category`} options={CATEGORY} required />,
|
|
199
|
-
},
|
|
200
|
-
{
|
|
201
|
-
header: "Qty",
|
|
202
|
-
width: 110,
|
|
203
|
-
cell: (row) => <FormBuilder.Number name={`${row}.qty`} required />,
|
|
204
|
-
},
|
|
205
|
-
{
|
|
206
|
-
header: "Price",
|
|
207
|
-
width: 140,
|
|
208
|
-
cell: (row) => <FormBuilder.Currency name={`${row}.price`} currencySymbol="$" required />,
|
|
209
|
-
},
|
|
210
|
-
]}
|
|
211
|
-
/>
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
`FormBuilder.RadioList` (single-select, `string`) and `FormBuilder.CheckboxGroup` (multi-select,
|
|
215
|
-
`string[]`) render their `options` as a boxed, divided list — control on the left, primary
|
|
216
|
-
label, and an optional per-option `description` shown as a secondary label. The whole row is
|
|
217
|
-
clickable. Multi-select is also available as `.MultiSelect` / `.Tags` (a tag-chip picker).
|
|
218
|
-
|
|
219
|
-
`FormBuilder.SwitchBox` (value `boolean`) is a switch wrapped in a `#f9f9f9` field box. It
|
|
220
|
-
renders like any other field — the `label` sits in the normal label column — and the box holds
|
|
221
|
-
an optional inline `subLabel`, a vertical divider, and the switch.
|
|
222
|
-
|
|
223
|
-
To group fields into a titled card, use [`FormRenderer.Section`](./form-renderer.md) — it is
|
|
224
|
-
presentation, so it lives there.
|
|
225
|
-
|
|
226
|
-
`FormBuilder.Submit` is a loading-aware submit button. It **auto-associates with the enclosing
|
|
227
|
-
form** (via context), so it submits even when placed in a header / action bar that renders
|
|
228
|
-
_outside_ the `<form>` — no manual `form={id}` wiring.
|
|
229
|
-
|
|
230
|
-
## Moved to FormRenderer
|
|
231
|
-
|
|
232
|
-
These all used to live here. They are chrome, so they now live on
|
|
233
|
-
[FormRenderer](./form-renderer.md):
|
|
234
|
-
|
|
235
|
-
| Was | Now |
|
|
236
|
-
| --- | --- |
|
|
237
|
-
| `FormBuilder.Section` | `FormRenderer.Section` |
|
|
238
|
-
| `FormBuilder.Stepper` / `.Step` / `.Back` / `.Next` | `FormRenderer.Stepper` / `.Step` / `.Back` / `.Next` |
|
|
239
|
-
| `FormBuilder.Header` | `FormRenderer`'s `header` prop |
|
|
240
|
-
| the `layout` prop | gone — the fields always fill their container |
|
|
241
|
-
| the `conclusion` prop | `FormRenderer`'s `summary` prop |
|
|
242
|
-
|
|
243
|
-
See [the migration note](../migration/form-builder-2.5.2.md) for the full upgrade path.
|
|
244
|
-
|
|
245
|
-
## Calculation panel
|
|
246
|
-
|
|
247
|
-
To show computed totals **beside** the form, render a [FormSummary](./form-summary.md)
|
|
248
|
-
next to it (not inside it) and share one hoisted form via the `form` prop:
|
|
249
|
-
|
|
250
|
-
```tsx
|
|
251
|
-
const form = useForm({ resolver: r, defaultValues: d })
|
|
252
|
-
|
|
253
|
-
<div className="flex items-start gap-4">
|
|
254
|
-
<FormBuilder form={form} onSubmit={save} className="min-w-0 flex-1">…fields…</FormBuilder>
|
|
255
|
-
<FormSummary form={form} title="Invoice">…rows…</FormSummary>
|
|
256
|
-
</div>
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
`form` makes FormBuilder use an existing react-hook-form instance instead of creating its
|
|
260
|
-
own — that's what lets something outside the form read the same live values.
|
|
261
|
-
|
|
262
|
-
## Editing a record
|
|
263
|
-
|
|
264
|
-
Pass `values` (not just `defaultValues`); the form repopulates when the data loads. Use a
|
|
265
|
-
remount `key` so initial-only inputs (date, rich text) re-seed.
|
|
266
|
-
|
|
267
|
-
```tsx
|
|
268
|
-
<FormBuilder key={entity.id} values={entity} onSubmit={save} resolver={r} defaultValues={d}>
|
|
269
|
-
…the same fields…
|
|
270
|
-
</FormBuilder>
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
## Validation
|
|
274
|
-
|
|
275
|
-
Resolver-agnostic — pass any react-hook-form `resolver` (`zodResolver`, a plain
|
|
276
|
-
resolver function, etc.). The library never depends on zod.
|
|
@@ -1,326 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: FormRenderer
|
|
3
|
-
description: The chrome around a FormBuilder. Author fields as JSX children; FormRenderer owns page-vs-drawer display, the title header, the actions bar, titled Sections, the stepper, and the summary panel. Prefer it over raw FormBuilder for real forms.
|
|
4
|
-
component: true
|
|
5
|
-
group: Forms
|
|
6
|
-
keywords:
|
|
7
|
-
[form-renderer, form, drawer, header, display, actions, section, stepper, summary, react-hook-form]
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# FormRenderer
|
|
11
|
-
|
|
12
|
-
The **chrome** around a [FormBuilder](./form-builder.md). You author the fields as **JSX
|
|
13
|
-
children** (`FormBuilder.Text`, `FormBuilder.Select`, …); `FormRenderer` draws everything
|
|
14
|
-
around them:
|
|
15
|
-
|
|
16
|
-
- **page vs drawer** display (`display="drawer"` hosts the form in a `FormDrawer`),
|
|
17
|
-
- the **absolute title header** + `actions` bar,
|
|
18
|
-
- **`FormRenderer.Section`** — the titled cards that group fields,
|
|
19
|
-
- the **stepper** (`FormRenderer.Stepper` / `.Step`) and its nav rail,
|
|
20
|
-
- the **`summary`** panel beside the form,
|
|
21
|
-
- the page gutters and scroll shell, and **vertical field layout** inside a drawer.
|
|
22
|
-
|
|
23
|
-
`FormBuilder` on its own is the fields and nothing else — no card, no header, no frame — so it
|
|
24
|
-
fills whatever it is placed in. **For real forms, use `FormRenderer`**; reach for bare
|
|
25
|
-
`FormBuilder` only when you are embedding fields inside something that already provides its own
|
|
26
|
-
chrome (a settings rail, a filter panel).
|
|
27
|
-
|
|
28
|
-
FormRenderer has **two modes**: a **form** (author fields as children, as below), or a display-only
|
|
29
|
-
**detail page** — give it `FormRenderer.Sidebar` + `FormRenderer.Tab` children instead of fields and the
|
|
30
|
-
sidebar swaps `FormRenderer.Tab` panels, whose content is `FormRenderer.Section` blocks (no `<form>`,
|
|
31
|
-
no submit — see [Detail tabs](#detail-tabs-sidebar)).
|
|
32
|
-
|
|
33
|
-
FormRenderer never manufactures a Submit — **you compose the Save and hand it to `actions`**.
|
|
34
|
-
It renders in the form's header action pill (page) or the drawer header (drawer), and a bare
|
|
35
|
-
`<FormBuilder.Submit>` auto-targets this form (even though the header sits outside the `<form>`).
|
|
36
|
-
|
|
37
|
-
```tsx
|
|
38
|
-
<FormRenderer
|
|
39
|
-
onSubmit={save}
|
|
40
|
-
resolver={zodResolver(schema)}
|
|
41
|
-
defaultValues={d}
|
|
42
|
-
header={{ title: "Item", variant: "new" }}
|
|
43
|
-
actions={<FormBuilder.Submit>Save</FormBuilder.Submit>}
|
|
44
|
-
>
|
|
45
|
-
<FormRenderer.Section title="Identity" color="Blue">
|
|
46
|
-
<FormBuilder.Text name="name" label="Name" required />
|
|
47
|
-
<FormBuilder.Currency name="price" label="Price" currencySymbol="$" />
|
|
48
|
-
</FormRenderer.Section>
|
|
49
|
-
</FormRenderer>
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## Compound parts
|
|
53
|
-
|
|
54
|
-
| Part | What it is |
|
|
55
|
-
| ------------------------------------------- | ------------------------------------------------------------------------------ |
|
|
56
|
-
| `FormRenderer.Section` | A titled `SectionBlock` card grouping fields (or display rows). |
|
|
57
|
-
| `FormRenderer.Stepper` / `.Step` | The wizard — see [Stepper](#stepper). |
|
|
58
|
-
| `FormRenderer.Back` / `.Next` | Chevron step controls. The header's action bar prepends them for you. |
|
|
59
|
-
| `FormRenderer.Sidebar` / `.Tab` | The display-only [detail-tabs](#detail-tabs-sidebar) view. |
|
|
60
|
-
| `FormRenderer.Grid` / `.Row` | Read-only display cells inside a detail tab. |
|
|
61
|
-
|
|
62
|
-
### `FormRenderer.Section`
|
|
63
|
-
|
|
64
|
-
Props `title`, `color`, `icon`, `action`, `variant`. It groups fields in a Glare `SectionBlock`:
|
|
65
|
-
`color` is one of `Blue`, `Yellow`, `Green`, `Red`, `Orange`, `Purple`, `Pink`, `Gray`; `action`
|
|
66
|
-
puts buttons on the title row; `variant="Table"` switches to the full-bleed table shell (what
|
|
67
|
-
`FormBuilder.Table` uses internally).
|
|
68
|
-
|
|
69
|
-
It holds no form state, which is why it lives here and not on `FormBuilder` — the same component
|
|
70
|
-
groups editable fields on a form and read-only `FormRenderer.Row` cells on a detail page.
|
|
71
|
-
|
|
72
|
-
Because it reads no context, it also works **outside** `<FormRenderer>` — e.g. wrapping fields in a
|
|
73
|
-
bare `<FormBuilder>` that you are laying out yourself. It is the one compound part that does.
|
|
74
|
-
|
|
75
|
-
> Not to be confused with `FieldSection`, the per-field row layout (label · control) that every
|
|
76
|
-
> field draws for itself. That one stays inside FormBuilder.
|
|
77
|
-
|
|
78
|
-
## Installation
|
|
79
|
-
|
|
80
|
-
```bash
|
|
81
|
-
npx torch-glare@latest init
|
|
82
|
-
npx torch-glare@latest add FormRenderer
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
`add` also pulls in `FormBuilder`, which FormRenderer renders through.
|
|
86
|
-
|
|
87
|
-
## Imports
|
|
88
|
-
|
|
89
|
-
```tsx
|
|
90
|
-
import { FormRenderer, FormDrawer } from "@/components/FormRenderer";
|
|
91
|
-
import { FormBuilder } from "@/components/FormBuilder";
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## Props
|
|
95
|
-
|
|
96
|
-
| Prop | Type | Notes |
|
|
97
|
-
| -------------------------------------------------------------- | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
98
|
-
| `children` | `ReactNode` | The form body — `FormRenderer.Section` / field / `FormRenderer.Stepper` JSX. |
|
|
99
|
-
| `onSubmit?` / `onInvalid?` | fns | Submit / validation-fail callbacks. Optional — a detail-tabs view has no form, so omit them there. |
|
|
100
|
-
| `resolver` | `Resolver` | Any react-hook-form resolver, e.g. `zodResolver(schema)`. |
|
|
101
|
-
| `defaultValues` / `values` | `DefaultValues` / `T` | Initial values; `values` re-syncs on change (edit). |
|
|
102
|
-
| `loading` / `resetOnSuccess` | `boolean` | Forwarded to `FormBuilder`. |
|
|
103
|
-
| `fieldDirection` | `'horizontal' \| 'vertical' \| 'flexible'` | Unset means responsive: stacked, then label-beside-control once the field row passes the container `md` breakpoint. A drawer defaults to `'vertical'` — pass `'flexible'` there to get the responsive layout back. |
|
|
104
|
-
| `form` | `UseFormReturn<T>` | A hoisted `useForm` to bind to — pass when a sibling (e.g. a `summary` `FormSummary`) must read the same live values; the caller owns `resolver`/`defaultValues` on it. Omit to let FormRenderer create its own. |
|
|
105
|
-
| `className` | `string` | Lands on FormRenderer's outermost element (page display) — e.g. `"min-h-0 flex-1"` to fill a flex column. Note this is the page frame, not the `<form>`; `FormBuilder`'s own `className` lands on the `<form>` element itself. |
|
|
106
|
-
| `display` | `'page' \| 'drawer'` | `'drawer'` wraps the form in `FormDrawer`. |
|
|
107
|
-
| `header` | `{ title; label?; variant? }` | Absolute title header + action bar (page display); `actions` render in it. |
|
|
108
|
-
| `summary` | `ReactNode` | A live panel (typically `FormSummary`) rendered beside the form (page) or in the drawer tray (drawer). Give the same hoisted `form` so it reads live values. On a page, a `summary` **plus** a `FormRenderer.Stepper` lays out as three columns — stepper nav · fields · summary. |
|
|
109
|
-
| `actions` | `ReactNode` | The form's action bar — rendered in the header action pill (page) or drawer header (drawer). Put the Save here: `actions={<FormBuilder.Submit>Save</FormBuilder.Submit>}`. A bare `FormBuilder.Submit` auto-targets this form. |
|
|
110
|
-
| `id` | `string` | `id` on the underlying `<form>`. Optional — FormRenderer generates and wires one otherwise. |
|
|
111
|
-
| `open` / `onOpenChange` / `title` / `badge` / `onOpenInNewTab` | — | Drawer control (when `display="drawer"`). `title` / `badge` are strings that override `header.title` / `header.label`. |
|
|
112
|
-
|
|
113
|
-
## Drawer
|
|
114
|
-
|
|
115
|
-
```tsx
|
|
116
|
-
// drawer — pass the Save via `actions`; it renders in the drawer header
|
|
117
|
-
<FormRenderer
|
|
118
|
-
display="drawer"
|
|
119
|
-
open={open}
|
|
120
|
-
onOpenChange={setOpen}
|
|
121
|
-
title="New item"
|
|
122
|
-
badge="New"
|
|
123
|
-
onSubmit={save}
|
|
124
|
-
resolver={r}
|
|
125
|
-
defaultValues={d}
|
|
126
|
-
actions={<FormBuilder.Submit>Save</FormBuilder.Submit>}
|
|
127
|
-
>
|
|
128
|
-
{fields}
|
|
129
|
-
</FormRenderer>
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
## Stepper
|
|
133
|
-
|
|
134
|
-
Drop a `FormRenderer.Stepper` in as the child. The Save lives in the header `actions` and
|
|
135
|
-
submits every step's registered fields at once (steps stay mounted, so the whole form is live).
|
|
136
|
-
|
|
137
|
-
For a stepper, FormRenderer **automatically prepends chevron Back/Next nav + a divider** before
|
|
138
|
-
your Submit, so the action bar reads `[◀] [▶] │ Save`. Back is disabled on the first step; Next
|
|
139
|
-
validates the current step, then advances (disabled on the last step). A step that passes
|
|
140
|
-
validation **stays checked** in the rail — even after you navigate back — while a live validation
|
|
141
|
-
error overrides it to red. You still pass just the Submit; the nav is wired for you:
|
|
142
|
-
|
|
143
|
-
```tsx
|
|
144
|
-
<FormRenderer
|
|
145
|
-
onSubmit={save}
|
|
146
|
-
resolver={r}
|
|
147
|
-
defaultValues={d}
|
|
148
|
-
header={{ title: "New item", variant: "new" }}
|
|
149
|
-
actions={<FormBuilder.Submit>Save</FormBuilder.Submit>}
|
|
150
|
-
>
|
|
151
|
-
<FormRenderer.Stepper>
|
|
152
|
-
<FormRenderer.Step title="Basics">
|
|
153
|
-
<FormBuilder.Text name="name" label="Name" required />
|
|
154
|
-
</FormRenderer.Step>
|
|
155
|
-
</FormRenderer.Stepper>
|
|
156
|
-
</FormRenderer>
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
## Detail tabs (sidebar)
|
|
160
|
-
|
|
161
|
-
Give FormRenderer `FormRenderer.Sidebar` + `FormRenderer.Tab` children (instead of fields) and it
|
|
162
|
-
switches to a **display-only detail page**: a left **sidebar** where each item swaps in its matching
|
|
163
|
-
tab panel — no `<form>`, no submit. The sidebar sits **where a stepper's rail would**, and only the
|
|
164
|
-
active panel shows (built on the same Radix Tabs primitive shadcn uses, so it's keyboard-accessible).
|
|
165
|
-
Pair it with `header` (`variant="detail"` → a "View" badge) + `actions` (Print / Approve / …).
|
|
166
|
-
|
|
167
|
-
Each `Tab` holds read-only `FormRenderer.Section` blocks; `FormRenderer.Grid` + `FormRenderer.Row` lay
|
|
168
|
-
out the label/value display cells (the display counterpart of form fields).
|
|
169
|
-
|
|
170
|
-
```tsx
|
|
171
|
-
<FormRenderer
|
|
172
|
-
header={{ title: "Order DE-344", variant: "detail" }}
|
|
173
|
-
actions={<Button variant="BorderStyle">Print</Button>}
|
|
174
|
-
>
|
|
175
|
-
{/* The rail — one Item per tab, tied to a Tab by `value`. */}
|
|
176
|
-
<FormRenderer.Sidebar>
|
|
177
|
-
<FormRenderer.Sidebar.Item value="overview" icon={<i className="ri-layout-grid-line" />}>
|
|
178
|
-
Overview
|
|
179
|
-
</FormRenderer.Sidebar.Item>
|
|
180
|
-
<FormRenderer.Sidebar.Item value="items" icon={<i className="ri-table-line" />}>
|
|
181
|
-
Items Table
|
|
182
|
-
</FormRenderer.Sidebar.Item>
|
|
183
|
-
</FormRenderer.Sidebar>
|
|
184
|
-
|
|
185
|
-
{/* One panel per tab — read-only Section blocks. */}
|
|
186
|
-
<FormRenderer.Tab value="overview">
|
|
187
|
-
<FormRenderer.Section title="Main Information" color="Blue">
|
|
188
|
-
<FormRenderer.Grid>
|
|
189
|
-
<FormRenderer.Row label="PO Number" value="PO-000123" />
|
|
190
|
-
<FormRenderer.Row label="Status" value={<Badge label="Submitted" color="yellow" />} />
|
|
191
|
-
</FormRenderer.Grid>
|
|
192
|
-
</FormRenderer.Section>
|
|
193
|
-
</FormRenderer.Tab>
|
|
194
|
-
|
|
195
|
-
<FormRenderer.Tab value="items">…</FormRenderer.Tab>
|
|
196
|
-
</FormRenderer>
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
| Component | Props | Renders |
|
|
200
|
-
| -------------- | -------------------------- | ------------------------------------------------------------------ |
|
|
201
|
-
| `Sidebar` | `children` | The tab rail (a Radix `Tabs.List`), fixed at the stepper's place. |
|
|
202
|
-
| `Sidebar.Item` | `value`, `icon?`, children | A rail nav row (a `Tabs.Trigger`); the active one is a black pill. |
|
|
203
|
-
| `Tab` | `value`, children | A content panel (a `Tabs.Content`) shown when its tab is active. |
|
|
204
|
-
| `Grid` | `columns?` (1–3), children | A padded grid of display `Row`s (default 2 columns). |
|
|
205
|
-
| `Row` | `label`, `value` | A read-only label/value display cell. |
|
|
206
|
-
|
|
207
|
-
The first `Tab` is active by default. Only the active panel is visible; the rail stays fixed while the
|
|
208
|
-
content column scrolls.
|
|
209
|
-
|
|
210
|
-
## Summary panel
|
|
211
|
-
|
|
212
|
-
Pass a hoisted `useForm` as `form` and a `FormSummary` as `summary` — FormRenderer binds
|
|
213
|
-
the form to that instance and lays the panel beside the form (page) or in the drawer tray
|
|
214
|
-
(drawer), so it recomputes live as fields change.
|
|
215
|
-
|
|
216
|
-
```tsx
|
|
217
|
-
const form = useForm<Invoice>({ resolver, defaultValues })
|
|
218
|
-
|
|
219
|
-
<FormRenderer
|
|
220
|
-
form={form}
|
|
221
|
-
onSubmit={save}
|
|
222
|
-
header={{ title: 'Invoice', variant: 'new' }}
|
|
223
|
-
actions={<FormBuilder.Submit>Save invoice</FormBuilder.Submit>}
|
|
224
|
-
summary={
|
|
225
|
-
<FormSummary form={form} title="Invoice" subtitle="Summary">
|
|
226
|
-
<FormSummary.Group title="Total">
|
|
227
|
-
<FormSummary.Row label="Overall Total" emphasized compute={overallTotal} />
|
|
228
|
-
</FormSummary.Group>
|
|
229
|
-
</FormSummary>
|
|
230
|
-
}
|
|
231
|
-
>
|
|
232
|
-
{fields}
|
|
233
|
-
</FormRenderer>
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
Works with `display="drawer"` too — the summary moves into the drawer's tray.
|
|
237
|
-
|
|
238
|
-
## `FormDrawer` — the drawer wrapper
|
|
239
|
-
|
|
240
|
-
`FormRenderer` uses `FormDrawer` internally for `display: 'drawer'`. It's also exported
|
|
241
|
-
so you can put a hand-composed `FormBuilder` in a drawer directly. Since the header sits
|
|
242
|
-
outside the `<form>`, wire the Save button to the form via `id` / `form={id}`:
|
|
243
|
-
|
|
244
|
-
```tsx
|
|
245
|
-
<FormDrawer
|
|
246
|
-
open={open}
|
|
247
|
-
onOpenChange={setOpen}
|
|
248
|
-
title="New item"
|
|
249
|
-
badge="New"
|
|
250
|
-
actions={
|
|
251
|
-
<Button type="submit" form="item-form" is_loading={saving}>
|
|
252
|
-
Save
|
|
253
|
-
</Button>
|
|
254
|
-
}
|
|
255
|
-
>
|
|
256
|
-
<FormBuilder
|
|
257
|
-
id="item-form"
|
|
258
|
-
onSubmit={save}
|
|
259
|
-
resolver={r}
|
|
260
|
-
defaultValues={d}
|
|
261
|
-
fieldDirection="vertical"
|
|
262
|
-
>
|
|
263
|
-
…fields…
|
|
264
|
-
</FormBuilder>
|
|
265
|
-
</FormDrawer>
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
`FormDrawer` props: `open`, `onOpenChange`, `title`, `badge`, `variant`, `actions`,
|
|
269
|
-
`onOpenInNewTab`, `children`, `summary`. It owns no form state.
|
|
270
|
-
|
|
271
|
-
### The title
|
|
272
|
-
|
|
273
|
-
The drawer renders the **same floating header as the page form** — a [HeaderBar](./header-bar.md)
|
|
274
|
-
title pill on the left, a dark action pill on the right — so a form's title looks identical in
|
|
275
|
-
either display. `title` is the plain (uppercased) text, `badge` the colored emphasis pill, and
|
|
276
|
-
`variant` (`new` / `edit` / `detail`) picks the badge colors; `badge` defaults from it
|
|
277
|
-
(New / Edit / View).
|
|
278
|
-
|
|
279
|
-
```tsx
|
|
280
|
-
<FormDrawer title="Sales Invoice" badge="New" variant="new" … />
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
Driving it through `FormRenderer`, the `header` prop feeds both displays — including
|
|
284
|
-
`header.variant`, which the drawer previously ignored:
|
|
285
|
-
|
|
286
|
-
```tsx
|
|
287
|
-
<FormRenderer display="drawer" header={{ title: "Sales Invoice", variant: "edit" }} … />
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
`title` and `badge` are **plain strings** (they were `ReactNode` before this shared-header
|
|
291
|
-
change) because they render through `HeaderBar`'s uppercase text treatment.
|
|
292
|
-
|
|
293
|
-
### A summary beside the form
|
|
294
|
-
|
|
295
|
-
`summary` renders a conclusion panel — typically a [FormSummary](./form-summary.md) — _beside_
|
|
296
|
-
the form rather than inside its scrollable body. `FormDrawer` puts the form in a
|
|
297
|
-
[`DrawerPanel`](./drawer.md#drawerpanel) (the light surface) and the summary next to it with a
|
|
298
|
-
6px gutter; the tray paints nothing, so the summary keeps its own dark background and full
|
|
299
|
-
height, scrolling internally when it outruns the drawer.
|
|
300
|
-
|
|
301
|
-
Hoist the form so both read the same instance:
|
|
302
|
-
|
|
303
|
-
```tsx
|
|
304
|
-
const form = useForm({ resolver, defaultValues })
|
|
305
|
-
|
|
306
|
-
<FormDrawer
|
|
307
|
-
open={open} onOpenChange={setOpen} title="New item" badge="New"
|
|
308
|
-
summary={
|
|
309
|
-
<FormSummary form={form} title="Item" subtitle="Summary">
|
|
310
|
-
<FormSummary.Group title="Pricing">…rows…</FormSummary.Group>
|
|
311
|
-
</FormSummary>
|
|
312
|
-
}
|
|
313
|
-
>
|
|
314
|
-
<FormBuilder form={form} id="item-form" onSubmit={save} fieldDirection="vertical">
|
|
315
|
-
…fields…
|
|
316
|
-
</FormBuilder>
|
|
317
|
-
</FormDrawer>
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
> `childrenOutside` is the deprecated former name for `FormDrawer`'s `summary`. It still
|
|
321
|
-
> works — it long predates the FormBuilder/FormRenderer split and is unrelated to it (that
|
|
322
|
-
> move ships no aliases; see the
|
|
323
|
-
> [migration note](../migration/form-builder-2.5.2.md)).
|
|
324
|
-
|
|
325
|
-
`FormRenderer` forwards `summary` straight into the drawer tray, so you rarely need
|
|
326
|
-
`FormDrawer` directly — reach for it only when you want the drawer without a form.
|