torch-glare 2.5.6 → 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 -403
- package/apps/lib/components/Breadcrumb.tsx +0 -280
- package/apps/lib/components/Button.tsx +0 -325
- 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 -395
- 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 -88
- 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 -72
- package/apps/lib/components/DataViews/states.tsx +0 -73
- 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 -451
- package/apps/lib/components/DropdownMenu.tsx +0 -554
- package/apps/lib/components/FieldHint.tsx +0 -69
- package/apps/lib/components/Form.tsx +0 -182
- package/apps/lib/components/FormBuilder/context.ts +0 -85
- 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 -168
- 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 -114
- 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 -67
- package/apps/lib/components/FormBuilder/types.ts +0 -316
- package/apps/lib/components/FormRenderer/FormDrawer.tsx +0 -250
- package/apps/lib/components/FormRenderer/detail.tsx +0 -256
- package/apps/lib/components/FormRenderer/form-renderer.tsx +0 -358
- package/apps/lib/components/FormRenderer/header.tsx +0 -88
- package/apps/lib/components/FormRenderer/index.ts +0 -17
- package/apps/lib/components/FormRenderer/notch-action.tsx +0 -64
- package/apps/lib/components/FormRenderer/section.tsx +0 -39
- package/apps/lib/components/FormRenderer/stepper.tsx +0 -393
- package/apps/lib/components/FormRenderer/types.ts +0 -115
- 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 -168
- 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 -255
- 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 -597
- 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 -61
- package/apps/lib/hooks/useClickOutside.ts +0 -27
- package/apps/lib/hooks/useDragDrop.tsx +0 -365
- package/apps/lib/hooks/useHtmlDir.ts +0 -31
- 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 -300
- 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 -1217
- 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/scroller.ts +0 -26
- 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 -738
- 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 -1521
- package/docs/components/data-views/migration.md +0 -81
- 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 -284
- package/docs/components/form-renderer.md +0 -396
- 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 -483
- 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 -60
- 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 -1523
- 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 -726
- 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,396 +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
|
-
| `FormRenderer.NotchAction` | A pill in the drawer's notch. You own the label, so it translates. |
|
|
62
|
-
|
|
63
|
-
### `FormRenderer.Section`
|
|
64
|
-
|
|
65
|
-
Props `title`, `color`, `icon`, `action`, `variant`. It groups fields in a Glare `SectionBlock`:
|
|
66
|
-
`color` is one of `Blue`, `Yellow`, `Green`, `Red`, `Orange`, `Purple`, `Pink`, `Gray`; `action`
|
|
67
|
-
puts buttons on the title row; `variant="Table"` switches to the full-bleed table shell (what
|
|
68
|
-
`FormBuilder.Table` uses internally).
|
|
69
|
-
|
|
70
|
-
It holds no form state, which is why it lives here and not on `FormBuilder` — the same component
|
|
71
|
-
groups editable fields on a form and read-only `FormRenderer.Row` cells on a detail page.
|
|
72
|
-
|
|
73
|
-
Because it reads no context, it also works **outside** `<FormRenderer>` — e.g. wrapping fields in a
|
|
74
|
-
bare `<FormBuilder>` that you are laying out yourself. It is the one compound part that does.
|
|
75
|
-
|
|
76
|
-
> Not to be confused with `FieldSection`, the per-field row layout (label · control) that every
|
|
77
|
-
> field draws for itself. That one stays inside FormBuilder.
|
|
78
|
-
|
|
79
|
-
## Installation
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
npx torch-glare@latest init
|
|
83
|
-
npx torch-glare@latest add FormRenderer
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
`add` also pulls in `FormBuilder`, which FormRenderer renders through.
|
|
87
|
-
|
|
88
|
-
## Imports
|
|
89
|
-
|
|
90
|
-
```tsx
|
|
91
|
-
import { FormRenderer, FormDrawer } from "@/components/FormRenderer";
|
|
92
|
-
import { FormBuilder } from "@/components/FormBuilder";
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
## Props
|
|
96
|
-
|
|
97
|
-
| Prop | Type | Notes |
|
|
98
|
-
| -------------------------------------------------------------- | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
99
|
-
| `children` | `ReactNode` | The form body — `FormRenderer.Section` / field / `FormRenderer.Stepper` JSX. |
|
|
100
|
-
| `onSubmit?` / `onInvalid?` | fns | Submit / validation-fail callbacks. Optional — a detail-tabs view has no form, so omit them there. |
|
|
101
|
-
| `resolver` | `Resolver` | Any react-hook-form resolver, e.g. `zodResolver(schema)`. |
|
|
102
|
-
| `defaultValues` / `values` | `DefaultValues` / `T` | Initial values; `values` re-syncs on change (edit). |
|
|
103
|
-
| `loading` / `resetOnSuccess` | `boolean` | Forwarded to `FormBuilder`. |
|
|
104
|
-
| `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. |
|
|
105
|
-
| `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. |
|
|
106
|
-
| `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. |
|
|
107
|
-
| `display` | `'page' \| 'drawer'` | `'drawer'` wraps the form in `FormDrawer`. |
|
|
108
|
-
| `header` | `{ title; label?; variant? }` | Absolute title header + action bar (page display); `actions` render in it. |
|
|
109
|
-
| `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. |
|
|
110
|
-
| `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. |
|
|
111
|
-
| `id` | `string` | `id` on the underlying `<form>`. Optional — FormRenderer generates and wires one otherwise. |
|
|
112
|
-
| `open` / `onOpenChange` / `title` / `badge` / `onOpenInNewTab` | — | Drawer control (when `display="drawer"`). `title` / `badge` are strings that override `header.title` / `header.label`. |
|
|
113
|
-
| `embedded` | `boolean` | Render without the rounded body card, for a host that already draws one. Defaults to `true` in a drawer. |
|
|
114
|
-
| `activeTab` / `onTabChange` | `string` / `(tab) => void` | Make the [detail-tabs](#detail-tabs-sidebar) rail controlled, so the tab can live in the URL (`?tab=audit`) and survive a reload. Omit both for the uncontrolled default. Inert in form mode. |
|
|
115
|
-
| `activeStep` / `onStepChange` | `number` / `(index) => void` | External control of a `FormRenderer.Stepper`'s step, for a wizard owned by something other than form validity. In controlled mode internal advancement is suppressed and a click is *reported*, not applied. Omit both and the stepper behaves exactly as before. |
|
|
116
|
-
| `drawer` | `{ side?; nested?; framed?; hideHeader?; bareBody?; description?; wrapperClassName?; className? }` | Drawer layout, forwarded to `FormDrawer` — see [Drawer layout](#drawer-layout). One object rather than eight flat props, since none of it means anything on a page. |
|
|
117
|
-
|
|
118
|
-
## Drawer
|
|
119
|
-
|
|
120
|
-
```tsx
|
|
121
|
-
// drawer — pass the Save via `actions`; it renders in the drawer header
|
|
122
|
-
<FormRenderer
|
|
123
|
-
display="drawer"
|
|
124
|
-
open={open}
|
|
125
|
-
onOpenChange={setOpen}
|
|
126
|
-
title="New item"
|
|
127
|
-
badge="New"
|
|
128
|
-
onSubmit={save}
|
|
129
|
-
resolver={r}
|
|
130
|
-
defaultValues={d}
|
|
131
|
-
actions={<FormBuilder.Submit>Save</FormBuilder.Submit>}
|
|
132
|
-
>
|
|
133
|
-
{fields}
|
|
134
|
-
</FormRenderer>
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
### Drawer layout
|
|
138
|
-
|
|
139
|
-
Everything about how the drawer is *shaped* goes in one `drawer` object, because none of it means
|
|
140
|
-
anything on a page:
|
|
141
|
-
|
|
142
|
-
| Key | Type | Default | What it does |
|
|
143
|
-
| ----------------- | ----------------------------- | --------------- | -------------------------------------------------------------------------------------------------- |
|
|
144
|
-
| `side` | `'inline-end' \| 'bottom'` | `'inline-end'` | Which edge it slides from. `'bottom'` is a sheet and drops the notch — there is no inline edge to hang it from. The default follows document direction. |
|
|
145
|
-
| `nested` | `boolean` | `false` | **Required** when this drawer opens inside another one, or the two roots fight over the overlay and the scroll lock. Throws without a parent Drawer. |
|
|
146
|
-
| `framed` | `boolean` | `true` | The dark tray frame and the panel's border / inset shadow. |
|
|
147
|
-
| `hideHeader` | `boolean` | `false` | Skip the header bar, for a child that draws its own. Also drops the body's top padding. |
|
|
148
|
-
| `bareBody` | `boolean` | `false` | Skip the padded scroll wrapper, for a child that already scrolls and offsets for its own header. |
|
|
149
|
-
| `description` | `string` | — | Screen-reader-only description. vaul warns when a drawer has none. |
|
|
150
|
-
| `wrapperClassName`| `string` | per `side` | Lands on the positioner — width, height, insets. Replaces the default sizing. |
|
|
151
|
-
| `className` | `string` | — | Lands on the tray. |
|
|
152
|
-
|
|
153
|
-
```tsx
|
|
154
|
-
// A bottom sheet, opened from inside another drawer.
|
|
155
|
-
<FormRenderer
|
|
156
|
-
display="drawer"
|
|
157
|
-
open={open}
|
|
158
|
-
onOpenChange={setOpen}
|
|
159
|
-
title="Quick add"
|
|
160
|
-
drawer={{ side: "bottom", nested: true, description: "Add a line item" }}
|
|
161
|
-
onSubmit={save}
|
|
162
|
-
actions={<FormBuilder.Submit>Save</FormBuilder.Submit>}
|
|
163
|
-
>
|
|
164
|
-
{fields}
|
|
165
|
-
</FormRenderer>
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
### `FormRenderer.NotchAction`
|
|
169
|
-
|
|
170
|
-
Buttons in the drawer's notch, authored by you. `onOpenInNewTab` still works, but it hardcodes an
|
|
171
|
-
English label and allows only one action — write `NotchAction` children instead and you own both.
|
|
172
|
-
They render nothing where you write them; the renderer lifts them into the notch.
|
|
173
|
-
|
|
174
|
-
```tsx
|
|
175
|
-
<FormRenderer display="drawer" open={open} onOpenChange={setOpen} title={t("invoice")}>
|
|
176
|
-
<FormRenderer.NotchAction onClick={openFullPage}>
|
|
177
|
-
{t("openInNewTab")}
|
|
178
|
-
<i className="ri-arrow-right-up-line text-[12px]" />
|
|
179
|
-
</FormRenderer.NotchAction>
|
|
180
|
-
<FormRenderer.NotchAction color="Blue" onClick={print}>
|
|
181
|
-
{t("print")}
|
|
182
|
-
</FormRenderer.NotchAction>
|
|
183
|
-
|
|
184
|
-
{fields}
|
|
185
|
-
</FormRenderer>
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
`color` matches `DrawerNotchPill` and defaults to `"Yellow"`. Ignored on a page-display form, and a
|
|
189
|
-
`side: "bottom"` sheet has no notch to put them in.
|
|
190
|
-
|
|
191
|
-
## Stepper
|
|
192
|
-
|
|
193
|
-
Drop a `FormRenderer.Stepper` in as the child. The Save lives in the header `actions` and
|
|
194
|
-
submits every step's registered fields at once (steps stay mounted, so the whole form is live).
|
|
195
|
-
|
|
196
|
-
For a stepper, FormRenderer **automatically prepends chevron Back/Next nav + a divider** before
|
|
197
|
-
your Submit, so the action bar reads `[◀] [▶] │ Save`. Back is disabled on the first step; Next
|
|
198
|
-
validates the current step, then advances (disabled on the last step). A step that passes
|
|
199
|
-
validation **stays checked** in the rail — even after you navigate back — while a live validation
|
|
200
|
-
error overrides it to red. You still pass just the Submit; the nav is wired for you:
|
|
201
|
-
|
|
202
|
-
The rail **stays put while the fields scroll**. It is navigation, so it pins below the header rather
|
|
203
|
-
than scrolling out of view with the form; a rail taller than the form body scrolls to its end first,
|
|
204
|
-
as any sticky element does.
|
|
205
|
-
|
|
206
|
-
```tsx
|
|
207
|
-
<FormRenderer
|
|
208
|
-
onSubmit={save}
|
|
209
|
-
resolver={r}
|
|
210
|
-
defaultValues={d}
|
|
211
|
-
header={{ title: "New item", variant: "new" }}
|
|
212
|
-
actions={<FormBuilder.Submit>Save</FormBuilder.Submit>}
|
|
213
|
-
>
|
|
214
|
-
<FormRenderer.Stepper>
|
|
215
|
-
<FormRenderer.Step title="Basics">
|
|
216
|
-
<FormBuilder.Text name="name" label="Name" required />
|
|
217
|
-
</FormRenderer.Step>
|
|
218
|
-
</FormRenderer.Stepper>
|
|
219
|
-
</FormRenderer>
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
## Detail tabs (sidebar)
|
|
223
|
-
|
|
224
|
-
Give FormRenderer `FormRenderer.Sidebar` + `FormRenderer.Tab` children (instead of fields) and it
|
|
225
|
-
switches to a **display-only detail page**: a left **sidebar** where each item swaps in its matching
|
|
226
|
-
tab panel — no `<form>`, no submit. The sidebar sits **where a stepper's rail would**, and only the
|
|
227
|
-
active panel shows (built on the same Radix Tabs primitive shadcn uses, so it's keyboard-accessible).
|
|
228
|
-
Pair it with `header` (`variant="detail"` → a "View" badge) + `actions` (Print / Approve / …).
|
|
229
|
-
|
|
230
|
-
Each `Tab` holds read-only `FormRenderer.Section` blocks; `FormRenderer.Grid` + `FormRenderer.Row` lay
|
|
231
|
-
out the label/value display cells (the display counterpart of form fields).
|
|
232
|
-
|
|
233
|
-
```tsx
|
|
234
|
-
<FormRenderer
|
|
235
|
-
header={{ title: "Order DE-344", variant: "detail" }}
|
|
236
|
-
actions={<Button variant="BorderStyle">Print</Button>}
|
|
237
|
-
>
|
|
238
|
-
{/* The rail — one Item per tab, tied to a Tab by `value`. */}
|
|
239
|
-
<FormRenderer.Sidebar>
|
|
240
|
-
<FormRenderer.Sidebar.Item value="overview" icon={<i className="ri-layout-grid-line" />}>
|
|
241
|
-
Overview
|
|
242
|
-
</FormRenderer.Sidebar.Item>
|
|
243
|
-
<FormRenderer.Sidebar.Item value="items" icon={<i className="ri-table-line" />}>
|
|
244
|
-
Items Table
|
|
245
|
-
</FormRenderer.Sidebar.Item>
|
|
246
|
-
</FormRenderer.Sidebar>
|
|
247
|
-
|
|
248
|
-
{/* One panel per tab — read-only Section blocks. */}
|
|
249
|
-
<FormRenderer.Tab value="overview">
|
|
250
|
-
<FormRenderer.Section title="Main Information" color="Blue">
|
|
251
|
-
<FormRenderer.Grid>
|
|
252
|
-
<FormRenderer.Row label="PO Number" value="PO-000123" />
|
|
253
|
-
<FormRenderer.Row label="Status" value={<Badge label="Submitted" color="yellow" />} />
|
|
254
|
-
</FormRenderer.Grid>
|
|
255
|
-
</FormRenderer.Section>
|
|
256
|
-
</FormRenderer.Tab>
|
|
257
|
-
|
|
258
|
-
<FormRenderer.Tab value="items">…</FormRenderer.Tab>
|
|
259
|
-
</FormRenderer>
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
| Component | Props | Renders |
|
|
263
|
-
| -------------- | -------------------------- | ------------------------------------------------------------------ |
|
|
264
|
-
| `Sidebar` | `children` | The tab rail (a Radix `Tabs.List`), fixed at the stepper's place. |
|
|
265
|
-
| `Sidebar.Item` | `value`, `icon?`, children | A rail nav row (a `Tabs.Trigger`); the active one is a black pill. |
|
|
266
|
-
| `Tab` | `value`, children | A content panel (a `Tabs.Content`) shown when its tab is active. |
|
|
267
|
-
| `Grid` | `columns?` (1–3), children | A padded grid of display `Row`s (default 2 columns). |
|
|
268
|
-
| `Row` | `label`, `value` | A read-only label/value display cell. |
|
|
269
|
-
|
|
270
|
-
The first `Tab` is active by default. Only the active panel is visible; the rail stays fixed while the
|
|
271
|
-
content column scrolls.
|
|
272
|
-
|
|
273
|
-
## Summary panel
|
|
274
|
-
|
|
275
|
-
Pass a hoisted `useForm` as `form` and a `FormSummary` as `summary` — FormRenderer binds
|
|
276
|
-
the form to that instance and lays the panel beside the form (page) or in the drawer tray
|
|
277
|
-
(drawer), so it recomputes live as fields change.
|
|
278
|
-
|
|
279
|
-
```tsx
|
|
280
|
-
const form = useForm<Invoice>({ resolver, defaultValues })
|
|
281
|
-
|
|
282
|
-
<FormRenderer
|
|
283
|
-
form={form}
|
|
284
|
-
onSubmit={save}
|
|
285
|
-
header={{ title: 'Invoice', variant: 'new' }}
|
|
286
|
-
actions={<FormBuilder.Submit>Save invoice</FormBuilder.Submit>}
|
|
287
|
-
summary={
|
|
288
|
-
<FormSummary form={form} title="Invoice" subtitle="Summary">
|
|
289
|
-
<FormSummary.Group title="Total">
|
|
290
|
-
<FormSummary.Row label="Overall Total" emphasized compute={overallTotal} />
|
|
291
|
-
</FormSummary.Group>
|
|
292
|
-
</FormSummary>
|
|
293
|
-
}
|
|
294
|
-
>
|
|
295
|
-
{fields}
|
|
296
|
-
</FormRenderer>
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
Works with `display="drawer"` too — the summary moves into the drawer's tray.
|
|
300
|
-
|
|
301
|
-
## `FormDrawer` — the drawer wrapper
|
|
302
|
-
|
|
303
|
-
`FormRenderer` uses `FormDrawer` internally for `display: 'drawer'`. It's also exported
|
|
304
|
-
so you can put a hand-composed `FormBuilder` in a drawer directly. Since the header sits
|
|
305
|
-
outside the `<form>`, wire the Save button to the form via `id` / `form={id}`:
|
|
306
|
-
|
|
307
|
-
```tsx
|
|
308
|
-
<FormDrawer
|
|
309
|
-
open={open}
|
|
310
|
-
onOpenChange={setOpen}
|
|
311
|
-
title="New item"
|
|
312
|
-
badge="New"
|
|
313
|
-
actions={
|
|
314
|
-
<Button type="submit" form="item-form" is_loading={saving}>
|
|
315
|
-
Save
|
|
316
|
-
</Button>
|
|
317
|
-
}
|
|
318
|
-
>
|
|
319
|
-
<FormBuilder
|
|
320
|
-
id="item-form"
|
|
321
|
-
onSubmit={save}
|
|
322
|
-
resolver={r}
|
|
323
|
-
defaultValues={d}
|
|
324
|
-
fieldDirection="vertical"
|
|
325
|
-
>
|
|
326
|
-
…fields…
|
|
327
|
-
</FormBuilder>
|
|
328
|
-
</FormDrawer>
|
|
329
|
-
```
|
|
330
|
-
|
|
331
|
-
`FormDrawer` props: `open`, `onOpenChange`, `title`, `badge`, `variant`, `actions`,
|
|
332
|
-
`onOpenInNewTab`, `notchActions`, `children`, `summary`, plus the layout flags listed under
|
|
333
|
-
[Drawer layout](#drawer-layout) — `side`, `nested`, `framed`, `hideHeader`, `bareBody`,
|
|
334
|
-
`description`, `wrapperClassName`, `className`. It owns no form state.
|
|
335
|
-
|
|
336
|
-
`notchActions` is the notch's button slot. Going through `FormRenderer` you rarely set it directly —
|
|
337
|
-
write `FormRenderer.NotchAction` children and they are lifted into it for you. Using `FormDrawer` on
|
|
338
|
-
its own, pass the buttons here. When both `notchActions` and `onOpenInNewTab` are given, the former
|
|
339
|
-
wins; `onOpenInNewTab` remains only for callers happy with its built-in English label.
|
|
340
|
-
|
|
341
|
-
### The title
|
|
342
|
-
|
|
343
|
-
The drawer renders the **same floating header as the page form** — a [HeaderBar](./header-bar.md)
|
|
344
|
-
title pill on the left, a dark action pill on the right — so a form's title looks identical in
|
|
345
|
-
either display. `title` is the plain (uppercased) text, `badge` the colored emphasis pill, and
|
|
346
|
-
`variant` (`new` / `edit` / `detail`) picks the badge colors; `badge` defaults from it
|
|
347
|
-
(New / Edit / View).
|
|
348
|
-
|
|
349
|
-
```tsx
|
|
350
|
-
<FormDrawer title="Sales Invoice" badge="New" variant="new" … />
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
Driving it through `FormRenderer`, the `header` prop feeds both displays — including
|
|
354
|
-
`header.variant`, which the drawer previously ignored:
|
|
355
|
-
|
|
356
|
-
```tsx
|
|
357
|
-
<FormRenderer display="drawer" header={{ title: "Sales Invoice", variant: "edit" }} … />
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
`title` and `badge` are **plain strings** (they were `ReactNode` before this shared-header
|
|
361
|
-
change) because they render through `HeaderBar`'s uppercase text treatment.
|
|
362
|
-
|
|
363
|
-
### A summary beside the form
|
|
364
|
-
|
|
365
|
-
`summary` renders a conclusion panel — typically a [FormSummary](./form-summary.md) — _beside_
|
|
366
|
-
the form rather than inside its scrollable body. `FormDrawer` puts the form in a
|
|
367
|
-
[`DrawerPanel`](./drawer.md#drawerpanel) (the light surface) and the summary next to it with a
|
|
368
|
-
6px gutter; the tray paints nothing, so the summary keeps its own dark background and full
|
|
369
|
-
height, scrolling internally when it outruns the drawer.
|
|
370
|
-
|
|
371
|
-
Hoist the form so both read the same instance:
|
|
372
|
-
|
|
373
|
-
```tsx
|
|
374
|
-
const form = useForm({ resolver, defaultValues })
|
|
375
|
-
|
|
376
|
-
<FormDrawer
|
|
377
|
-
open={open} onOpenChange={setOpen} title="New item" badge="New"
|
|
378
|
-
summary={
|
|
379
|
-
<FormSummary form={form} title="Item" subtitle="Summary">
|
|
380
|
-
<FormSummary.Group title="Pricing">…rows…</FormSummary.Group>
|
|
381
|
-
</FormSummary>
|
|
382
|
-
}
|
|
383
|
-
>
|
|
384
|
-
<FormBuilder form={form} id="item-form" onSubmit={save} fieldDirection="vertical">
|
|
385
|
-
…fields…
|
|
386
|
-
</FormBuilder>
|
|
387
|
-
</FormDrawer>
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
> `childrenOutside` is the deprecated former name for `FormDrawer`'s `summary`. It still
|
|
391
|
-
> works — it long predates the FormBuilder/FormRenderer split and is unrelated to it (that
|
|
392
|
-
> move ships no aliases; see the
|
|
393
|
-
> [migration note](../migration/form-builder-2.5.2.md)).
|
|
394
|
-
|
|
395
|
-
`FormRenderer` forwards `summary` straight into the drawer tray, so you rarely need
|
|
396
|
-
`FormDrawer` directly — reach for it only when you want the drawer without a form.
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: FormSummary
|
|
3
|
-
description: A read-only calculation panel displayed beside a form. Each row declares a compute(values) that runs against the live form values, so totals recalculate as the user types.
|
|
4
|
-
component: true
|
|
5
|
-
group: Forms
|
|
6
|
-
keywords: [form-summary, summary, totals, calculation, invoice, panel, react-hook-form, useWatch]
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# FormSummary
|
|
10
|
-
|
|
11
|
-
A read-only **calculation panel** that sits **beside a form** — the invoice-summary
|
|
12
|
-
look: grouped rows of computed totals, right-aligned, in Glare's dark `SystemStyle`
|
|
13
|
-
fields.
|
|
14
|
-
|
|
15
|
-
Each `FormSummary.Row` declares a **`compute(values)`** that runs against the **live**
|
|
16
|
-
form values, so every total recalculates as the user types.
|
|
17
|
-
|
|
18
|
-
The panel renders **outside** the form, beside it. Both read the same form, so
|
|
19
|
-
**hoist `useForm`** and hand the instance to each.
|
|
20
|
-
|
|
21
|
-
> **Normally you do not lay this out by hand.** Pass the panel to
|
|
22
|
-
> [`FormRenderer`](./form-renderer.md)'s `summary` prop and it places it for you — beside the form
|
|
23
|
-
> on a page, in the tray in a drawer. The manual version below is what `summary` does, and is what
|
|
24
|
-
> you want only when you are composing a bare `<FormBuilder>` yourself.
|
|
25
|
-
|
|
26
|
-
```tsx
|
|
27
|
-
const form = useForm({ resolver: zodResolver(schema), defaultValues })
|
|
28
|
-
|
|
29
|
-
<div className="flex gap-4">
|
|
30
|
-
<FormBuilder form={form} onSubmit={save} className="min-w-0 flex-1">
|
|
31
|
-
<FormRenderer.Section title="Line items">…fields…</FormRenderer.Section>
|
|
32
|
-
</FormBuilder>
|
|
33
|
-
|
|
34
|
-
<FormSummary form={form} title="Invoice" subtitle="Summary">
|
|
35
|
-
<FormSummary.Group title="Total">
|
|
36
|
-
<FormSummary.Row label="Total Discount" compute={totalDiscount} />
|
|
37
|
-
<FormSummary.Row label="Overall Total" emphasized compute={overallTotal} />
|
|
38
|
-
<FormSummary.Row label="Overall Total" currency="IQD" tone="success"
|
|
39
|
-
compute={v => overallTotal(v) * v.iqdRate} decimals={0} />
|
|
40
|
-
<FormSummary.Row label="Overall Total" currency="USD" tone="info" compute={overallTotal} />
|
|
41
|
-
</FormSummary.Group>
|
|
42
|
-
</FormSummary>
|
|
43
|
-
</div>
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
`FormBuilder` stays purely an input renderer — it knows nothing about the panel, and
|
|
47
|
-
**you** own the side-by-side layout. Passing `form` to `FormBuilder` makes it use that
|
|
48
|
-
instance instead of creating its own.
|
|
49
|
-
|
|
50
|
-
### Height
|
|
51
|
-
|
|
52
|
-
The panel is `h-full` and fills whatever height its parent gives it, scrolling its groups
|
|
53
|
-
(header pinned) once they outrun it. That means **the parent has to have a height** — the
|
|
54
|
-
usual mistake is `items-start` on the flex row, which collapses the panel to its content
|
|
55
|
-
instead. Leave the row at its default `items-stretch`, as above.
|
|
56
|
-
|
|
57
|
-
To make the panel own the viewport rather than grow with the form, bound the row:
|
|
58
|
-
|
|
59
|
-
```tsx
|
|
60
|
-
<div className="flex h-[calc(100vh-2rem)] gap-4">
|
|
61
|
-
<FormBuilder … className="min-w-0 flex-1 overflow-y-auto" />
|
|
62
|
-
<FormSummary … />
|
|
63
|
-
</div>
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
> Hoisting the form means a remount `key` no longer resets it. Call `form.reset(defaults)`
|
|
67
|
-
> instead (e.g. when opening a drawer).
|
|
68
|
-
|
|
69
|
-
## Installation
|
|
70
|
-
|
|
71
|
-
```bash
|
|
72
|
-
npx torch-glare@latest init
|
|
73
|
-
npx torch-glare@latest add FormSummary
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
## Imports
|
|
77
|
-
|
|
78
|
-
```tsx
|
|
79
|
-
import { useForm } from 'react-hook-form'
|
|
80
|
-
|
|
81
|
-
import { FormBuilder } from '@/components/FormBuilder'
|
|
82
|
-
import { FormRenderer } from '@/components/FormRenderer'
|
|
83
|
-
import { FormSummary } from '@/components/FormSummary'
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
## `FormSummary` props
|
|
87
|
-
|
|
88
|
-
| Prop | Type | Notes |
|
|
89
|
-
|---|---|---|
|
|
90
|
-
| `title` | `ReactNode` | Panel title, e.g. `"Invoice"`. |
|
|
91
|
-
| `subtitle` | `ReactNode` | Muted text beside the title, e.g. `"Summary"`. |
|
|
92
|
-
| `form` | `UseFormReturn` | The form to read values from. The panel always renders outside the `<form>`, so pass the same hoisted instance you gave `FormRenderer` / `FormBuilder`. |
|
|
93
|
-
| `width` | `number \| string` | Panel width; default `228`. |
|
|
94
|
-
| `children` | `ReactNode` | `FormSummary.Group` children. |
|
|
95
|
-
|
|
96
|
-
## `FormSummary.Group` props
|
|
97
|
-
|
|
98
|
-
| Prop | Type | Notes |
|
|
99
|
-
|---|---|---|
|
|
100
|
-
| `title` | `ReactNode` | The group heading (Customer / Total / Tax / …). Groups are separated by a divider. |
|
|
101
|
-
| `collapsible` | `boolean` | When titled, the heading is a [ConclusionHeader](./conclusion-header.md) that opens/closes **this group's** rows; default `true`. |
|
|
102
|
-
| `defaultOpen` | `boolean` | Initial open state when collapsible; default `true`. |
|
|
103
|
-
|
|
104
|
-
The main panel title is a plain header — collapsing happens **per group**, not on the whole panel.
|
|
105
|
-
|
|
106
|
-
## `FormSummary.Row` props
|
|
107
|
-
|
|
108
|
-
| Prop | Type | Notes |
|
|
109
|
-
|---|---|---|
|
|
110
|
-
| `label` | `ReactNode` | Row label, above the value. |
|
|
111
|
-
| `compute` | `(values) => number \| string` | **The calculation** — receives the live form values. |
|
|
112
|
-
| `value` | `number \| string` | Static value, when there's nothing to compute. |
|
|
113
|
-
| `currency` | `ReactNode` | Currency code, e.g. `"IQD"` — rendered **inside** the field's trailing edge. |
|
|
114
|
-
| `tone` | `'neutral' \| 'success' \| 'info'` | Color of the currency code (green / blue). |
|
|
115
|
-
| `emphasized` | `boolean` | The primary result — lighter, emphasized border. |
|
|
116
|
-
| `decimals` | `number` | Decimal places; default `2` (→ `0.00`). |
|
|
117
|
-
| `action` | `ReactNode` | Trailing slot inside the field, e.g. an `ActionButton`. Shares the slot with `currency`. |
|
|
118
|
-
| `format` | `(value) => string` | Override the default number formatting. |
|
|
119
|
-
|
|
120
|
-
## Computing totals
|
|
121
|
-
|
|
122
|
-
`compute` is a plain function of the form values — keep the maths outside the JSX:
|
|
123
|
-
|
|
124
|
-
```tsx
|
|
125
|
-
const subTotal = v => v.items.reduce((s, i) => s + i.qty * i.price, 0)
|
|
126
|
-
const totalDiscount = v => v.items.reduce((s, i) => s + i.discount, 0)
|
|
127
|
-
const taxable = v => Math.max(0, subTotal(v) - totalDiscount(v))
|
|
128
|
-
const totalTax = v => taxable(v) * (v.taxRate / 100)
|
|
129
|
-
const overallTotal = v => taxable(v) + totalTax(v)
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
The panel is **read-only** — it contributes nothing to the submitted values.
|
|
133
|
-
|
|
134
|
-
## Related
|
|
135
|
-
|
|
136
|
-
- [FormRenderer](./form-renderer.md) — its `summary` prop places this panel for you
|
|
137
|
-
- [FormBuilder](./form-builder.md) — the fields the totals read from
|
|
138
|
-
- [ConclusionHeader](./conclusion-header.md) — the header this panel uses
|