torch-glare 2.4.0 → 2.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/apps/lib/components/ActionButton.tsx +7 -12
- package/apps/lib/components/ActionsGroup.tsx +4 -15
- package/apps/lib/components/AlertDialog.tsx +173 -191
- package/apps/lib/components/Avatar.tsx +13 -16
- package/apps/lib/components/Badge.tsx +1 -3
- package/apps/lib/components/BadgeField.tsx +76 -71
- package/apps/lib/components/Breadcrumb.tsx +49 -85
- package/apps/lib/components/Button.tsx +21 -20
- package/apps/lib/components/ButtonGroup.tsx +31 -41
- package/apps/lib/components/Calendar.tsx +51 -29
- package/apps/lib/components/Card.tsx +40 -24
- package/apps/lib/components/Checkbox.tsx +9 -16
- package/apps/lib/components/ColorPicker.tsx +441 -0
- package/apps/lib/components/ConclusionHeader.tsx +148 -0
- package/apps/lib/components/ContextMenu.tsx +97 -96
- package/apps/lib/components/CountBadge.tsx +4 -6
- package/apps/lib/components/DataTable.tsx +196 -216
- package/apps/lib/components/DataViews/DataViewRadio.tsx +1 -6
- package/apps/lib/components/DataViews/DataViewsConfigPanel.tsx +13 -47
- package/apps/lib/components/DataViews/DataViewsHeader.tsx +1 -3
- package/apps/lib/components/DataViews/DataViewsLayout.tsx +5 -12
- package/apps/lib/components/DataViews/FilterPanel.tsx +155 -149
- package/apps/lib/components/DataViews/HeaderSearch.tsx +1 -5
- package/apps/lib/components/DataViews/InboxView.tsx +22 -68
- package/apps/lib/components/DataViews/InboxViewCard.tsx +68 -77
- package/apps/lib/components/DataViews/KanbanView.tsx +8 -25
- package/apps/lib/components/DataViews/PanelControls.tsx +3 -13
- package/apps/lib/components/DataViews/SettingsPanel.tsx +83 -89
- package/apps/lib/components/DataViews/TableView.tsx +8 -28
- package/apps/lib/components/DataViews/TreeView.tsx +12 -40
- package/apps/lib/components/DataViews/badgeAdapter.ts +32 -28
- package/apps/lib/components/DataViews/fieldRenderers.tsx +106 -141
- package/apps/lib/components/DataViews/filters/DatePickerRangeFilter.tsx +30 -23
- package/apps/lib/components/DataViews/filters/DateRangePopover.tsx +39 -32
- package/apps/lib/components/DataViews/filters/PresetChips.tsx +15 -15
- package/apps/lib/components/DataViews/filters/RangeSliderWithInputs.tsx +69 -58
- package/apps/lib/components/DataViews/index.ts +26 -26
- package/apps/lib/components/DataViews/tree/TreeDrawer.tsx +12 -16
- package/apps/lib/components/DataViews/tree/TreeSidebar.tsx +28 -31
- package/apps/lib/components/DataViews/types.ts +104 -115
- package/apps/lib/components/DatePicker.tsx +200 -196
- package/apps/lib/components/Dialog.tsx +92 -105
- package/apps/lib/components/Divider.tsx +21 -24
- package/apps/lib/components/Drawer.tsx +124 -142
- package/apps/lib/components/DropdownMenu.tsx +131 -171
- package/apps/lib/components/FieldHint.tsx +4 -11
- package/apps/lib/components/Form.tsx +146 -155
- package/apps/lib/components/FormBuilder/DisplayField.tsx +40 -0
- package/apps/lib/components/FormBuilder/context.ts +71 -0
- package/apps/lib/components/FormBuilder/fields/ChoiceFields.tsx +65 -0
- package/apps/lib/components/FormBuilder/fields/ColorField.tsx +76 -0
- package/apps/lib/components/FormBuilder/fields/CustomField.tsx +16 -0
- package/apps/lib/components/FormBuilder/fields/DateField.tsx +34 -0
- package/apps/lib/components/FormBuilder/fields/FieldArray.tsx +79 -0
- package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +174 -0
- package/apps/lib/components/FormBuilder/fields/FileField.tsx +40 -0
- package/apps/lib/components/FormBuilder/fields/OptionListFields.tsx +139 -0
- package/apps/lib/components/FormBuilder/fields/OtpField.tsx +32 -0
- package/apps/lib/components/FormBuilder/fields/PhoneField.tsx +82 -0
- package/apps/lib/components/FormBuilder/fields/RichTextEditorField.tsx +37 -0
- package/apps/lib/components/FormBuilder/fields/SelectField.tsx +101 -0
- package/apps/lib/components/FormBuilder/fields/SignatureField.tsx +175 -0
- package/apps/lib/components/FormBuilder/fields/SliderField.tsx +72 -0
- package/apps/lib/components/FormBuilder/fields/SwitchBoxField.tsx +42 -0
- package/apps/lib/components/FormBuilder/fields/TableField.tsx +312 -0
- package/apps/lib/components/FormBuilder/fields/TextField.tsx +222 -0
- package/apps/lib/components/FormBuilder/fields/TreeSelectField.tsx +49 -0
- package/apps/lib/components/FormBuilder/fields/countries.ts +303 -0
- package/apps/lib/components/FormBuilder/fields/index.ts +25 -0
- package/apps/lib/components/FormBuilder/form-builder.tsx +292 -0
- package/apps/lib/components/FormBuilder/header.tsx +105 -0
- package/apps/lib/components/FormBuilder/index.ts +37 -0
- package/apps/lib/components/FormBuilder/numberFormat.ts +16 -0
- package/apps/lib/components/FormBuilder/stepper.tsx +217 -0
- package/apps/lib/components/FormBuilder/submit.tsx +41 -0
- package/apps/lib/components/FormBuilder/types.ts +264 -0
- package/apps/lib/components/FormBuilder/viewFormat.tsx +137 -0
- package/apps/lib/components/FormRenderer/FormDrawer.tsx +121 -0
- package/apps/lib/components/FormRenderer/form-renderer.tsx +113 -0
- package/apps/lib/components/FormRenderer/index.ts +9 -0
- package/apps/lib/components/FormRenderer/types.ts +79 -0
- package/apps/lib/components/FormStepper.tsx +9 -39
- package/apps/lib/components/FormSummary.tsx +282 -0
- package/apps/lib/components/HeaderBar.tsx +1 -9
- package/apps/lib/components/ImageAttachment.tsx +106 -93
- package/apps/lib/components/InnerLabelField.tsx +20 -16
- package/apps/lib/components/Input.tsx +171 -172
- package/apps/lib/components/InputField.tsx +44 -45
- package/apps/lib/components/InputOTP.tsx +68 -69
- package/apps/lib/components/Label.tsx +61 -58
- package/apps/lib/components/LabelField.tsx +4 -5
- package/apps/lib/components/LabeledCheckBox.tsx +8 -12
- package/apps/lib/components/LabeledRadio.tsx +7 -5
- package/apps/lib/components/LinkButton.tsx +2 -9
- package/apps/lib/components/LoginButton.tsx +4 -9
- package/apps/lib/components/PasswordLevel.tsx +5 -5
- package/apps/lib/components/Popover.tsx +15 -33
- package/apps/lib/components/ProfileMenu.tsx +67 -72
- package/apps/lib/components/Radio.tsx +1 -5
- package/apps/lib/components/RadioCard.tsx +11 -28
- package/apps/lib/components/ScrollArea.tsx +45 -43
- package/apps/lib/components/SearchField.tsx +49 -39
- package/apps/lib/components/SearchableSelect.tsx +16 -16
- package/apps/lib/components/SearchableTable.tsx +108 -118
- package/apps/lib/components/SearchableTree.tsx +469 -0
- package/apps/lib/components/SearchableTreeDialog.tsx +493 -0
- package/apps/lib/components/SectionBlock.tsx +19 -23
- package/apps/lib/components/Select.tsx +80 -186
- package/apps/lib/components/SimpleSelect.tsx +196 -187
- package/apps/lib/components/Skeleton.tsx +9 -12
- package/apps/lib/components/SlideDatePicker.tsx +215 -166
- package/apps/lib/components/SpinLoading.tsx +33 -49
- package/apps/lib/components/Stepper.tsx +13 -56
- package/apps/lib/components/Switch.tsx +8 -10
- package/apps/lib/components/TabFormItem.tsx +3 -12
- package/apps/lib/components/TabSwitch.tsx +7 -34
- package/apps/lib/components/Table.tsx +60 -75
- package/apps/lib/components/{ChartBlockTool.ts → TextEditor/ChartBlockTool.ts} +17 -52
- package/apps/lib/components/TextEditor/RichTextField.tsx +46 -0
- package/apps/lib/components/{TableDnDWrapper.ts → TextEditor/TableDnDWrapper.ts} +15 -48
- package/apps/lib/components/{TextEditor.tsx → TextEditor/TextEditor.tsx} +156 -113
- package/apps/lib/components/TextEditor/TextEditorToolbar.tsx +429 -0
- package/apps/lib/components/TextEditor/editor-tools/AlignmentTune.ts +70 -0
- package/apps/lib/components/TextEditor/editor-tools/ColorInlineTool.ts +50 -0
- package/apps/lib/components/TextEditor/editor-tools/StrikethroughInlineTool.ts +48 -0
- package/apps/lib/components/TextEditor/editor-tools/inlineFormat.ts +98 -0
- package/apps/lib/{types → components/TextEditor}/editorjs.d.ts +19 -0
- package/apps/lib/components/TextEditor/index.ts +7 -0
- package/apps/lib/{utils → components/TextEditor}/markdownParser.ts +2 -7
- package/apps/lib/components/Textarea.tsx +9 -13
- package/apps/lib/components/Timeline.tsx +21 -41
- package/apps/lib/components/Toast.tsx +83 -83
- package/apps/lib/components/Toggle.tsx +112 -114
- package/apps/lib/components/ToggleButton.tsx +1 -1
- package/apps/lib/components/Tooltip.tsx +24 -19
- package/apps/lib/components/TransparentLabel.tsx +61 -62
- package/apps/lib/components/TreeDropDown.tsx +86 -52
- package/apps/lib/components/TreeFolder/TreeFolder.tsx +15 -48
- package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +16 -21
- package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +9 -20
- package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +3 -3
- package/apps/lib/components/TreeFolder/icons.tsx +14 -17
- package/apps/lib/components/TreeFolder/index.ts +15 -8
- package/apps/lib/components/TreeFolder/treeFolderUtils.ts +47 -52
- package/apps/lib/components/TreeFolder/types.ts +32 -32
- package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +117 -123
- package/apps/lib/hooks/useActiveTreeItem.ts +52 -55
- package/apps/lib/hooks/useClickOutside.ts +21 -20
- package/apps/lib/hooks/useDataViewsState.ts +86 -80
- package/apps/lib/hooks/useIsMobile.ts +12 -12
- package/apps/lib/hooks/useResize.ts +54 -65
- package/apps/lib/hooks/useTagSelection.ts +201 -201
- package/apps/lib/layouts/CNLayout.tsx +181 -140
- package/apps/lib/layouts/DataViewCard.tsx +4 -18
- package/apps/lib/layouts/FieldSection.tsx +2 -6
- package/apps/lib/layouts/TreeSubLayout.tsx +24 -38
- package/apps/lib/providers/ThemeProvider.tsx +8 -23
- package/apps/lib/registry.json +997 -0
- package/apps/lib/tsconfig.json +9 -0
- package/apps/lib/tsconfig.tsbuildinfo +1 -0
- package/apps/lib/utils/cn.ts +1 -1
- package/apps/lib/utils/color.ts +175 -0
- package/apps/lib/utils/dataViews/columnUtils.ts +46 -44
- package/apps/lib/utils/dataViews/fieldUtils.ts +70 -71
- package/apps/lib/utils/dataViews/nestedDataUtils.tsx +129 -122
- package/apps/lib/utils/dataViews/pathUtils.ts +74 -67
- package/apps/lib/utils/dataViews/rangeUtils.ts +121 -112
- package/apps/lib/utils/dataViews/treeUtils.ts +204 -211
- package/apps/lib/utils/dateFormat.ts +64 -54
- package/apps/lib/utils/resize.ts +21 -25
- package/apps/lib/utils/types.ts +13 -13
- package/dist/bin/index.js +8 -2
- package/dist/bin/index.js.map +1 -1
- package/dist/src/shared/getAvailableFiles.d.ts.map +1 -1
- package/dist/src/shared/getAvailableFiles.js +6 -1
- package/dist/src/shared/getAvailableFiles.js.map +1 -1
- package/dist/src/shared/loadRegistry.d.ts +7 -0
- package/dist/src/shared/loadRegistry.d.ts.map +1 -0
- package/dist/src/shared/loadRegistry.js +31 -0
- package/dist/src/shared/loadRegistry.js.map +1 -0
- package/dist/src/shared/resolveInstallPlan.d.ts +12 -0
- package/dist/src/shared/resolveInstallPlan.d.ts.map +1 -0
- package/dist/src/shared/resolveInstallPlan.js +39 -0
- package/dist/src/shared/resolveInstallPlan.js.map +1 -0
- package/dist/src/types/main.d.ts +24 -0
- package/dist/src/types/main.d.ts.map +1 -1
- package/docs/README.md +10 -2
- package/docs/components/action-button.md +30 -24
- package/docs/components/actions-group.md +26 -20
- package/docs/components/alert-dialog.md +45 -45
- package/docs/components/avatar.md +6 -2
- package/docs/components/badge-field.md +6 -2
- package/docs/components/badge.md +7 -1
- package/docs/components/breadcrumb.md +15 -40
- package/docs/components/button-group.md +13 -10
- package/docs/components/button.md +58 -33
- package/docs/components/calendar.md +26 -19
- package/docs/components/card.md +23 -18
- package/docs/components/chart-block-tool.md +129 -0
- package/docs/components/checkbox.md +16 -8
- package/docs/components/cn-layout.md +7 -1
- package/docs/components/color-picker.md +101 -0
- package/docs/components/conclusion-header.md +80 -0
- package/docs/components/context-menu.md +18 -25
- package/docs/components/count-badge.md +7 -1
- package/docs/components/data-table.md +45 -33
- package/docs/components/data-views-config-panel.md +15 -11
- package/docs/components/data-views-layout.md +13 -16
- package/docs/components/date-picker.md +30 -23
- package/docs/components/dialog.md +43 -42
- package/docs/components/divider.md +10 -4
- package/docs/components/drawer.md +161 -135
- package/docs/components/dropdown-menu.md +25 -34
- package/docs/components/field-hint.md +37 -25
- package/docs/components/field-section.md +9 -3
- package/docs/components/form-builder.md +270 -0
- package/docs/components/form-renderer.md +228 -0
- package/docs/components/form-stepper.md +6 -0
- package/docs/components/form-summary.md +123 -0
- package/docs/components/form.md +17 -20
- package/docs/components/header-bar.md +6 -0
- package/docs/components/image-attachment.md +43 -45
- package/docs/components/inbox-view.md +16 -5
- package/docs/components/inner-label-field.md +34 -24
- package/docs/components/input-field.md +18 -10
- package/docs/components/input-otp.md +14 -11
- package/docs/components/input.md +22 -16
- package/docs/components/kanban-view.md +15 -5
- package/docs/components/label-field.md +32 -22
- package/docs/components/label.md +43 -32
- package/docs/components/labeled-check-box.md +16 -8
- package/docs/components/labeled-radio.md +18 -11
- package/docs/components/link-button.md +7 -1
- package/docs/components/login-button.md +8 -2
- package/docs/components/password-level.md +37 -24
- package/docs/components/popover.md +26 -23
- package/docs/components/profile-menu.md +38 -27
- package/docs/components/radio-card.md +16 -9
- package/docs/components/radio.md +16 -8
- package/docs/components/scroll-area.md +6 -2
- package/docs/components/search-field.md +14 -6
- package/docs/components/searchable-select.md +19 -14
- package/docs/components/searchable-table.md +18 -13
- package/docs/components/searchable-tree-dialog.md +190 -0
- package/docs/components/searchable-tree.md +200 -0
- package/docs/components/section-block.md +12 -4
- package/docs/components/select.md +23 -18
- package/docs/components/simple-select.md +14 -10
- package/docs/components/skeleton.md +43 -33
- package/docs/components/slide-date-picker.md +37 -29
- package/docs/components/spin-loading.md +32 -23
- package/docs/components/stepper.md +6 -0
- package/docs/components/switch.md +14 -6
- package/docs/components/tab-form-item.md +7 -1
- package/docs/components/tab-switch.md +13 -6
- package/docs/components/table-dnd-wrapper.md +107 -0
- package/docs/components/table-view.md +15 -5
- package/docs/components/table.md +28 -28
- package/docs/components/text-editor.md +37 -13
- package/docs/components/textarea.md +15 -7
- package/docs/components/timeline.md +6 -0
- package/docs/components/toast.md +35 -26
- package/docs/components/toggle-button.md +24 -21
- package/docs/components/toggle.md +23 -15
- package/docs/components/tooltip.md +42 -30
- package/docs/components/transparent-label.md +29 -20
- package/docs/components/tree-drop-down.md +31 -23
- package/docs/components/tree-sub-layout.md +6 -2
- package/docs/components/tree-view.md +16 -5
- package/docs/explanation/architecture.md +54 -0
- package/docs/explanation/design-system.md +52 -0
- package/docs/how-to/data-views-from-backend-response.md +6 -4
- package/docs/how-to/form-and-list-recipes.md +26 -19
- package/docs/how-to/forms-with-form-builder.md +408 -0
- package/docs/how-to/guides.md +177 -197
- package/docs/migration/changelog.md +38 -0
- package/docs/reference/cli.md +87 -0
- package/docs/reference/components.md +11 -12
- package/docs/reference/hooks.md +8 -8
- package/docs/reference/providers.md +22 -22
- package/docs/reference/tailwind-plugins.md +2 -2
- package/docs/reference/theme.md +85 -0
- package/docs/reference/types.md +4 -4
- package/docs/reference/utilities.md +19 -26
- package/docs/tutorials/building-first-form.md +170 -172
- package/docs/tutorials/component-composition.md +34 -50
- package/docs/tutorials/getting-started.md +2 -2
- package/docs/tutorials/theming-basics.md +13 -10
- package/package.json +31 -3
- package/dist/src/commands/block.d.ts +0 -5
- package/dist/src/commands/block.d.ts.map +0 -1
- package/dist/src/commands/block.js +0 -255
- package/dist/src/commands/block.js.map +0 -1
- package/dist/src/shared/configureFonts.d.ts +0 -6
- package/dist/src/shared/configureFonts.d.ts.map +0 -1
- package/dist/src/shared/configureFonts.js +0 -106
- package/dist/src/shared/configureFonts.js.map +0 -1
- package/dist/src/shared/configureGlobalCss.d.ts +0 -6
- package/dist/src/shared/configureGlobalCss.d.ts.map +0 -1
- package/dist/src/shared/configureGlobalCss.js +0 -154
- package/dist/src/shared/configureGlobalCss.js.map +0 -1
- package/dist/src/shared/configureTailwind.d.ts +0 -7
- package/dist/src/shared/configureTailwind.d.ts.map +0 -1
- package/dist/src/shared/configureTailwind.js +0 -163
- package/dist/src/shared/configureTailwind.js.map +0 -1
- package/dist/src/shared/detectFramework.d.ts +0 -23
- package/dist/src/shared/detectFramework.d.ts.map +0 -1
- package/dist/src/shared/detectFramework.js +0 -119
- package/dist/src/shared/detectFramework.js.map +0 -1
- package/dist/src/shared/installBaseUtils.d.ts +0 -5
- package/dist/src/shared/installBaseUtils.d.ts.map +0 -1
- package/dist/src/shared/installBaseUtils.js +0 -79
- package/dist/src/shared/installBaseUtils.js.map +0 -1
- package/dist/src/shared/resolveAliases.d.ts +0 -24
- package/dist/src/shared/resolveAliases.d.ts.map +0 -1
- package/dist/src/shared/resolveAliases.js +0 -98
- package/dist/src/shared/resolveAliases.js.map +0 -1
|
@@ -11,13 +11,22 @@ keywords: [field-hint, alert, validation, message, form, feedback, inline]
|
|
|
11
11
|
|
|
12
12
|
## Installation
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
TORCH Glare is a copy-in library: the CLI copies this component's source into your project
|
|
15
|
+
(you do **not** install it from the npm package). Run `init` once, then `add`:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx torch-glare@latest init
|
|
19
|
+
npx torch-glare@latest add FieldHint
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`add` also copies any components, hooks, and utilities that `FieldHint` depends on.
|
|
15
23
|
|
|
16
24
|
## Import
|
|
17
25
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
26
|
+
Import from your project's local path — the alias configured in `glare.json` (e.g. `@/*`):
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
import { FieldHint } from "@/components/FieldHint";
|
|
21
30
|
```
|
|
22
31
|
|
|
23
32
|
## Quick Examples
|
|
@@ -25,7 +34,7 @@ import type { FieldHintProps } from '@torch-ui/components'
|
|
|
25
34
|
### Basic Usage
|
|
26
35
|
|
|
27
36
|
```typescript
|
|
28
|
-
import { FieldHint } from
|
|
37
|
+
import { FieldHint } from "@/components/FieldHint";
|
|
29
38
|
|
|
30
39
|
function Example() {
|
|
31
40
|
return (
|
|
@@ -40,7 +49,7 @@ function Example() {
|
|
|
40
49
|
### All States
|
|
41
50
|
|
|
42
51
|
```typescript
|
|
43
|
-
import { FieldHint } from
|
|
52
|
+
import { FieldHint } from "@/components/FieldHint";
|
|
44
53
|
|
|
45
54
|
function AllStates() {
|
|
46
55
|
return (
|
|
@@ -72,8 +81,8 @@ function AllStates() {
|
|
|
72
81
|
### With Form Field
|
|
73
82
|
|
|
74
83
|
```typescript
|
|
75
|
-
import { FieldHint } from
|
|
76
|
-
import { InputField } from
|
|
84
|
+
import { FieldHint } from "@/components/FieldHint";
|
|
85
|
+
import { InputField } from "@/components/InputField";
|
|
77
86
|
import { useState } from 'react'
|
|
78
87
|
|
|
79
88
|
function WithFormField() {
|
|
@@ -115,7 +124,7 @@ function WithFormField() {
|
|
|
115
124
|
### Custom Icon
|
|
116
125
|
|
|
117
126
|
```typescript
|
|
118
|
-
import { FieldHint } from
|
|
127
|
+
import { FieldHint } from "@/components/FieldHint";
|
|
119
128
|
|
|
120
129
|
function CustomIcon() {
|
|
121
130
|
return (
|
|
@@ -145,8 +154,9 @@ function CustomIcon() {
|
|
|
145
154
|
### Password Validation
|
|
146
155
|
|
|
147
156
|
```typescript
|
|
148
|
-
import { FieldHint } from
|
|
149
|
-
import { InputField
|
|
157
|
+
import { FieldHint } from "@/components/FieldHint";
|
|
158
|
+
import { InputField } from "@/components/InputField";
|
|
159
|
+
import { PasswordLevel } from "@/components/PasswordLevel";
|
|
150
160
|
import { useState } from 'react'
|
|
151
161
|
|
|
152
162
|
function PasswordValidation() {
|
|
@@ -199,8 +209,9 @@ function PasswordValidation() {
|
|
|
199
209
|
### Form Validation
|
|
200
210
|
|
|
201
211
|
```typescript
|
|
202
|
-
import { FieldHint } from
|
|
203
|
-
import {
|
|
212
|
+
import { FieldHint } from "@/components/FieldHint";
|
|
213
|
+
import { Button } from "@/components/Button";
|
|
214
|
+
import { InputField } from "@/components/InputField";
|
|
204
215
|
import { useState } from 'react'
|
|
205
216
|
|
|
206
217
|
function FormValidation() {
|
|
@@ -289,8 +300,9 @@ function FormValidation() {
|
|
|
289
300
|
### API Response Feedback
|
|
290
301
|
|
|
291
302
|
```typescript
|
|
292
|
-
import { FieldHint } from
|
|
293
|
-
import {
|
|
303
|
+
import { FieldHint } from "@/components/FieldHint";
|
|
304
|
+
import { Button } from "@/components/Button";
|
|
305
|
+
import { InputField } from "@/components/InputField";
|
|
294
306
|
import { useState } from 'react'
|
|
295
307
|
|
|
296
308
|
function APIFeedback() {
|
|
@@ -360,7 +372,7 @@ function APIFeedback() {
|
|
|
360
372
|
### File Upload Feedback
|
|
361
373
|
|
|
362
374
|
```typescript
|
|
363
|
-
import { FieldHint } from
|
|
375
|
+
import { FieldHint } from "@/components/FieldHint";
|
|
364
376
|
import { useState } from 'react'
|
|
365
377
|
|
|
366
378
|
function FileUploadFeedback() {
|
|
@@ -429,7 +441,7 @@ function FileUploadFeedback() {
|
|
|
429
441
|
### Multi-line Message
|
|
430
442
|
|
|
431
443
|
```typescript
|
|
432
|
-
import { FieldHint } from
|
|
444
|
+
import { FieldHint } from "@/components/FieldHint";
|
|
433
445
|
|
|
434
446
|
function MultilineMessage() {
|
|
435
447
|
return (
|
|
@@ -456,7 +468,7 @@ Please save your work before continuing.`}
|
|
|
456
468
|
### Dynamic Theme
|
|
457
469
|
|
|
458
470
|
```typescript
|
|
459
|
-
import { FieldHint } from
|
|
471
|
+
import { FieldHint } from "@/components/FieldHint";
|
|
460
472
|
import { useState } from 'react'
|
|
461
473
|
|
|
462
474
|
function DynamicTheme() {
|
|
@@ -488,8 +500,8 @@ function DynamicTheme() {
|
|
|
488
500
|
### Conditional Rendering
|
|
489
501
|
|
|
490
502
|
```typescript
|
|
491
|
-
import { FieldHint } from
|
|
492
|
-
import { InputField } from
|
|
503
|
+
import { FieldHint } from "@/components/FieldHint";
|
|
504
|
+
import { InputField } from "@/components/InputField";
|
|
493
505
|
import { useState } from 'react'
|
|
494
506
|
|
|
495
507
|
function ConditionalHints() {
|
|
@@ -579,7 +591,7 @@ export const FieldHint: React.FC<FieldHintProps>
|
|
|
579
591
|
### Usage with Types
|
|
580
592
|
|
|
581
593
|
```typescript
|
|
582
|
-
import { FieldHint } from
|
|
594
|
+
import { FieldHint } from "@/components/FieldHint";
|
|
583
595
|
import { useState } from 'react'
|
|
584
596
|
|
|
585
597
|
type ValidationState = {
|
|
@@ -607,7 +619,7 @@ function TypedExample() {
|
|
|
607
619
|
### Validation Hook
|
|
608
620
|
|
|
609
621
|
```typescript
|
|
610
|
-
import { FieldHint } from
|
|
622
|
+
import { FieldHint } from "@/components/FieldHint";
|
|
611
623
|
import { useState, useCallback } from 'react'
|
|
612
624
|
|
|
613
625
|
function useFieldValidation<T>(
|
|
@@ -665,8 +677,8 @@ function ValidatedField() {
|
|
|
665
677
|
### Form Field Wrapper
|
|
666
678
|
|
|
667
679
|
```typescript
|
|
668
|
-
import { FieldHint } from
|
|
669
|
-
import { InputField } from
|
|
680
|
+
import { FieldHint } from "@/components/FieldHint";
|
|
681
|
+
import { InputField } from "@/components/InputField";
|
|
670
682
|
import { ReactNode } from 'react'
|
|
671
683
|
|
|
672
684
|
interface FieldWrapperProps {
|
|
@@ -711,7 +723,7 @@ function FieldWrapper({
|
|
|
711
723
|
|
|
712
724
|
```typescript
|
|
713
725
|
import { render, screen } from '@testing-library/react'
|
|
714
|
-
import { FieldHint } from
|
|
726
|
+
import { FieldHint } from "@/components/FieldHint";
|
|
715
727
|
|
|
716
728
|
describe('FieldHint', () => {
|
|
717
729
|
it('renders label text', () => {
|
|
@@ -12,10 +12,16 @@ A structured form section component that provides consistent layout for form fie
|
|
|
12
12
|
|
|
13
13
|
## Installation
|
|
14
14
|
|
|
15
|
+
TORCH Glare is a copy-in library: the CLI copies this component's source into your project
|
|
16
|
+
(you do **not** install it from the npm package). Run `init` once, then `add`:
|
|
17
|
+
|
|
15
18
|
```bash
|
|
16
|
-
npx torch-
|
|
19
|
+
npx torch-glare@latest init
|
|
20
|
+
npx torch-glare@latest add FieldSection
|
|
17
21
|
```
|
|
18
22
|
|
|
23
|
+
`add` also copies any components, hooks, and utilities that `FieldSection` depends on.
|
|
24
|
+
|
|
19
25
|
## Imports
|
|
20
26
|
|
|
21
27
|
```typescript
|
|
@@ -346,7 +352,7 @@ export function ProfileSettingsForm() {
|
|
|
346
352
|
>
|
|
347
353
|
<div className="w-full flex items-center gap-4">
|
|
348
354
|
<Avatar size="L" src="/default-avatar.jpg" />
|
|
349
|
-
<Button variant="
|
|
355
|
+
<Button variant="BluSecStyle" size="M">
|
|
350
356
|
Upload New Photo
|
|
351
357
|
</Button>
|
|
352
358
|
</div>
|
|
@@ -490,7 +496,7 @@ export function AccountSettings() {
|
|
|
490
496
|
}
|
|
491
497
|
>
|
|
492
498
|
<div className="w-full space-y-2">
|
|
493
|
-
<Button variant="
|
|
499
|
+
<Button variant="RedSecStyle" size="M">
|
|
494
500
|
Delete Account
|
|
495
501
|
</Button>
|
|
496
502
|
</div>
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: FormBuilder
|
|
3
|
+
description: A compound, composition-based form. Author forms as JSX children (FormBuilder.Text, FormBuilder.Select, …) with steps-as-components, a drawer wrapper, edit + read-only view modes, and any react-hook-form resolver.
|
|
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
|
+
stepper,
|
|
15
|
+
drawer,
|
|
16
|
+
fields,
|
|
17
|
+
view-mode,
|
|
18
|
+
]
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
# FormBuilder
|
|
22
|
+
|
|
23
|
+
A **compound, composition-based** form. You author a form as JSX children — each
|
|
24
|
+
field is a `FormBuilder.*` component wired to [react-hook-form](https://react-hook-form.com/)
|
|
25
|
+
for you. Steps are components, the drawer is a wrapper, and the same markup renders
|
|
26
|
+
editable or read-only.
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
<FormBuilder onSubmit={save} resolver={zodResolver(schema)} defaultValues={d}>
|
|
30
|
+
<FormBuilder.Section title="Identity" color="Blue">
|
|
31
|
+
<FormBuilder.Text name="name" label="Name" required />
|
|
32
|
+
<FormBuilder.Currency name="price" label="Price" currencySymbol="$" />
|
|
33
|
+
</FormBuilder.Section>
|
|
34
|
+
<FormBuilder.Submit>Save</FormBuilder.Submit>
|
|
35
|
+
</FormBuilder>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
> Need the same form to render as a page _or_ a drawer, with a title header and an
|
|
39
|
+
> `actions` slot for the Save? Wrap these same children in
|
|
40
|
+
> [FormRenderer](./form-renderer.md).
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
TORCH Glare is a copy-in library: the CLI copies this component's source into your project.
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npx torch-glare@latest init
|
|
48
|
+
npx torch-glare@latest add FormBuilder
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Imports
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
import { FormBuilder } from "@/components/FormBuilder";
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Root props
|
|
58
|
+
|
|
59
|
+
| Prop | Type | Notes |
|
|
60
|
+
| ---------------- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
|
61
|
+
| `onSubmit` | `(values) => void \| Promise<void>` | Called on a valid submit. |
|
|
62
|
+
| `onInvalid` | `(errors) => void` | Called when validation fails. |
|
|
63
|
+
| `resolver` | `Resolver` | Any react-hook-form resolver, e.g. `zodResolver(schema)`. |
|
|
64
|
+
| `defaultValues` | `DefaultValues` | Initial values (create). |
|
|
65
|
+
| `values` | `T` | Controlled values (edit) — the form re-syncs when this changes. |
|
|
66
|
+
| `mode` | `'edit' \| 'view'` | `'view'` renders every field read-only. |
|
|
67
|
+
| `loading` | `boolean` | Submit shows a spinner; inputs disable. |
|
|
68
|
+
| `fieldDirection` | `'horizontal' \| 'vertical'` | Row layout (auto-vertical inside a drawer). |
|
|
69
|
+
| `resetOnSuccess` | `boolean` | Reset to defaults after a successful submit. |
|
|
70
|
+
| `form` | `UseFormReturn` | A hoisted `useForm` to bind to — pass when a `conclusion` panel must read the same values. |
|
|
71
|
+
| `conclusion` | `ReactNode` | A live panel (e.g. `FormSummary`) rendered **outside** the `<form>` as the grid's right column. |
|
|
72
|
+
| `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). |
|
|
73
|
+
| `className` | `string` | Lands on the form's outermost element — e.g. `"min-w-0 flex-1"` to fill the space beside a `conclusion` panel. |
|
|
74
|
+
|
|
75
|
+
**Adaptive layout.** FormBuilder lays out responsively: a `FormBuilder.Stepper` puts its nav rail in
|
|
76
|
+
a **left** column beside the fields (both inside the form surface, under the title header), and a
|
|
77
|
+
`conclusion` renders as its own panel **outside** the form surface, beside it — the same structure
|
|
78
|
+
`FormDrawer` uses in the drawer tray (6px gutter). So a stepper + conclusion reads as three columns
|
|
79
|
+
(nav · fields · conclusion), a conclusion alone as two, and a plain form as one. The fields column
|
|
80
|
+
caps at 1100px and centers. The conclusion is outside the `<form>` and reads values via its own
|
|
81
|
+
`form` prop.
|
|
82
|
+
|
|
83
|
+
## Field components
|
|
84
|
+
|
|
85
|
+
Each is a JSX child taking at least `name`, plus `label`, `placeholder`,
|
|
86
|
+
`description`, `required`, `disabled`, `hidden`, `fullWidth`.
|
|
87
|
+
|
|
88
|
+
| Component | Input | Value |
|
|
89
|
+
| --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
|
|
90
|
+
| `FormBuilder.Text` / `.Email` / `.Password` | `InputField` | `string` |
|
|
91
|
+
| `FormBuilder.Number` | numeric `InputField` | `number` |
|
|
92
|
+
| `FormBuilder.Currency` (`currencySymbol`) | `InputField` + symbol | `number` |
|
|
93
|
+
| `FormBuilder.Textarea` | `Textarea` | `string` |
|
|
94
|
+
| `FormBuilder.Slider` (`min,max,step,range`) | `@radix-ui/react-slider` | `number` / `[number,number]` |
|
|
95
|
+
| `FormBuilder.Color` (`presets`, `alpha`) | `ColorPicker` (full palette: SV area, hue, opacity, eyedropper, HEX/RGB/HSL, presets) | hex `string` (`#rrggbb`, or `#rrggbbaa` when opacity < 100%) |
|
|
96
|
+
| `FormBuilder.Phone` (`defaultCountry`) | `SearchableSelect` + `InputField` | `string` |
|
|
97
|
+
| `FormBuilder.Select` / `.SearchableSelect` (`options`, async props) | `SearchableSelect` | `string` |
|
|
98
|
+
| `FormBuilder.MultiSelect` / `.Tags` (`options`) | `BadgeField` | `string[]` |
|
|
99
|
+
| `FormBuilder.RadioList` (`options`, each with optional `description`) | boxed radio list | `string` |
|
|
100
|
+
| `FormBuilder.CheckboxGroup` (`options`, each with optional `description`) | boxed checkbox list | `string[]` |
|
|
101
|
+
| `FormBuilder.RadioCards` (`options` with `description`) | `RadioCard` | `string` |
|
|
102
|
+
| `FormBuilder.Checkbox` (`subLabel`) | `Checkbox` + inline label | `boolean` |
|
|
103
|
+
| `FormBuilder.SwitchBox` (`subLabel`) | `Switch` in a `#f9f9f9` box | `boolean` |
|
|
104
|
+
| `FormBuilder.Otp` (`length`) | `InputOTP` | `string` |
|
|
105
|
+
| `FormBuilder.Date` | `DatePicker` | `Date` |
|
|
106
|
+
| `FormBuilder.DateRange` | `DatePicker` (range) | `{from,to}` |
|
|
107
|
+
| `FormBuilder.DateMultiple` | `DatePicker` (multiple) | `Date[]` |
|
|
108
|
+
| `FormBuilder.DateTime` | `DatePicker` (timePicker) | `Date` |
|
|
109
|
+
| `FormBuilder.TreeSelect` (`nodes`, `getNodeId`, `getNodeLabel`, …) | `SearchableTree` | node id (`string`) |
|
|
110
|
+
| `FormBuilder.File` / `.Image` (`accept`, `multiple`) | `ImageAttachment` | `File \| File[]` |
|
|
111
|
+
| `FormBuilder.RichText` | `TextEditor` (EditorJS) | `OutputData` |
|
|
112
|
+
| `FormBuilder.Signature` (`penColor`) | canvas pad | PNG data-URL `string` |
|
|
113
|
+
| `FormBuilder.FieldArray` (`children` render fn, `defaultItem`) | RHF `useFieldArray` | `object[]` |
|
|
114
|
+
| `FormBuilder.Table` (`columns`, `selectable`, `reorderable`, `defaultItem`) | editable grid in a `SectionBlock` | `object[]` |
|
|
115
|
+
| `FormBuilder.Custom` (`render`, `formatView`) | your control | anything |
|
|
116
|
+
|
|
117
|
+
`FormBuilder.Password` accepts `strengthMeter` (shows a `PasswordLevel` meter). `FormBuilder.FieldArray`
|
|
118
|
+
renders a repeating list — its `children` is a render fn `(rowName, index, remove) => …` and sub-fields
|
|
119
|
+
are named `${rowName}.field`.
|
|
120
|
+
|
|
121
|
+
`FormBuilder.Table` is the **table-shaped** counterpart of `FieldArray` (value `object[]`): an editable
|
|
122
|
+
grid where each row is a record and each column cell is any `FormBuilder.*` field. It renders **inside a
|
|
123
|
+
`SectionBlock`**, so place it as a **top-level child** of the form (not inside a `FormBuilder.Section`).
|
|
124
|
+
Each column pairs a `header` with a `cell(rowName, index)` renderer — name the cell's field
|
|
125
|
+
`${rowName}.<key>`. The section header carries the actions: a **Add New** button (also repeated as the
|
|
126
|
+
bottom footer) and a **Delete Row** button that's disabled until rows are checkbox-selected. Rows support
|
|
127
|
+
**checkbox selection** (+ select-all), **drag-drop reordering**, and — per column, via `sortKey` — a
|
|
128
|
+
sort toggle in the header. Everything hides in `mode="view"`, where cells render read-only. Cells render
|
|
129
|
+
"bare" (control only) with validation errors shown as a tooltip on the control, so a row stays one line
|
|
130
|
+
tall, and each field passes `onTable` so it's borderless and blends into the grid. Practical cell fields
|
|
131
|
+
are the compact ones — `Text`, `Number`, `Currency`, `Select`, `SearchableSelect`, `Date`, `Phone`,
|
|
132
|
+
`Checkbox`, `SwitchBox`; wide fields (`RichText`, `Signature`, `File`) work but aren't suited to a cell.
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
<FormBuilder.Table
|
|
136
|
+
name="items"
|
|
137
|
+
title="Items"
|
|
138
|
+
color="Green"
|
|
139
|
+
addLabel="Add item"
|
|
140
|
+
defaultItem={{ item: "", category: "hardware", qty: 1, price: 0 }}
|
|
141
|
+
columns={[
|
|
142
|
+
{
|
|
143
|
+
header: "Item",
|
|
144
|
+
width: 200,
|
|
145
|
+
cell: (row) => <FormBuilder.Text name={`${row}.item`} required />,
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
header: "Category",
|
|
149
|
+
cell: (row) => <FormBuilder.Select name={`${row}.category`} options={CATEGORY} required />,
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
header: "Qty",
|
|
153
|
+
width: 110,
|
|
154
|
+
cell: (row) => <FormBuilder.Number name={`${row}.qty`} required />,
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
header: "Price",
|
|
158
|
+
width: 140,
|
|
159
|
+
cell: (row) => <FormBuilder.Currency name={`${row}.price`} currencySymbol="$" required />,
|
|
160
|
+
},
|
|
161
|
+
]}
|
|
162
|
+
/>
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
`FormBuilder.RadioList` (single-select, `string`) and `FormBuilder.CheckboxGroup` (multi-select,
|
|
166
|
+
`string[]`) render their `options` as a boxed, divided list — control on the left, primary
|
|
167
|
+
label, and an optional per-option `description` shown as a secondary label. The whole row is
|
|
168
|
+
clickable. Multi-select is also available as `.MultiSelect` / `.Tags` (a tag-chip picker).
|
|
169
|
+
|
|
170
|
+
`FormBuilder.SwitchBox` (value `boolean`) is a switch wrapped in a `#f9f9f9` field box. It
|
|
171
|
+
renders like any other field — the `label` sits in the normal label column — and the box holds
|
|
172
|
+
an optional inline `subLabel`, a vertical divider, and the switch.
|
|
173
|
+
|
|
174
|
+
`FormBuilder.Section` (props `title`, `color`, `icon`) groups fields in a Glare
|
|
175
|
+
`SectionBlock`. `FormBuilder.Submit` is a loading-aware submit button (hidden in view mode). It
|
|
176
|
+
**auto-associates with the enclosing form** (via context), so it submits even when placed in a
|
|
177
|
+
header / action bar that renders _outside_ the `<form>` — no manual `form={id}` wiring.
|
|
178
|
+
|
|
179
|
+
## Title header + action bar
|
|
180
|
+
|
|
181
|
+
`FormBuilder.Header` renders a **title pill** (Glare `HeaderBar`) on the left and an
|
|
182
|
+
**action bar** (your buttons) on the right, **absolutely positioned** over a
|
|
183
|
+
scrollable form body — the products-services item-edit look. Place it as a direct
|
|
184
|
+
child of `<FormBuilder>`; the root then switches to the scroll-shell layout.
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
<FormBuilder onSubmit={save} resolver={r} defaultValues={d}>
|
|
188
|
+
<FormBuilder.Header title="Item" variant="new">
|
|
189
|
+
<FormBuilder.Submit>Save</FormBuilder.Submit>
|
|
190
|
+
{/* add more actions, e.g. a "Save as draft" Button */}
|
|
191
|
+
</FormBuilder.Header>
|
|
192
|
+
|
|
193
|
+
<FormBuilder.Section title="Identity" color="Blue">
|
|
194
|
+
<FormBuilder.Text name="name" label="Name" required />
|
|
195
|
+
</FormBuilder.Section>
|
|
196
|
+
</FormBuilder>
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
- `title` — plain text (uppercased). `label` — badge text (defaults from `variant`).
|
|
200
|
+
- `variant` — `"new" | "edit" | "detail"` (badge color); defaults from `mode`
|
|
201
|
+
(view → `detail`). `children` are the action buttons; `FormBuilder.Submit` submits
|
|
202
|
+
the form (it auto-associates with it, even though the header sits outside `<form>`)
|
|
203
|
+
and auto-hides in view mode.
|
|
204
|
+
|
|
205
|
+
## Stepper (steps are components)
|
|
206
|
+
|
|
207
|
+
Wrap steps in `FormBuilder.Stepper`; each `FormBuilder.Step` holds a step's fields.
|
|
208
|
+
**Every step's fields are always mounted and registered** — the whole form is live
|
|
209
|
+
regardless of which step is showing; the stepper only toggles _visibility_.
|
|
210
|
+
**Navigation is the step buttons themselves**: click a step to go there. Backward is
|
|
211
|
+
free; clicking forward validates the steps in between and stops at the first one with
|
|
212
|
+
errors (shown with a red indicator). Put the **Submit** in the `FormBuilder.Header` (or the
|
|
213
|
+
`FormRenderer` `actions`) — it submits every step's fields at once, from any step.
|
|
214
|
+
|
|
215
|
+
```tsx
|
|
216
|
+
<FormBuilder onSubmit={save} resolver={r} defaultValues={d}>
|
|
217
|
+
<FormBuilder.Header title="Item" variant="new">
|
|
218
|
+
<FormBuilder.Submit>Save</FormBuilder.Submit>
|
|
219
|
+
</FormBuilder.Header>
|
|
220
|
+
|
|
221
|
+
<FormBuilder.Stepper>
|
|
222
|
+
<FormBuilder.Step title="Basics">
|
|
223
|
+
<FormBuilder.Text name="name" label="Name" required />
|
|
224
|
+
</FormBuilder.Step>
|
|
225
|
+
<FormBuilder.Step title="Details">
|
|
226
|
+
<FormBuilder.Select name="category" label="Category" required options={cats} />
|
|
227
|
+
</FormBuilder.Step>
|
|
228
|
+
</FormBuilder.Stepper>
|
|
229
|
+
</FormBuilder>
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
> **In a drawer?** `FormBuilder` is drawer-unaware — it only displays inputs. To
|
|
233
|
+
> show a form in a drawer, wrap it in `FormDrawer` from
|
|
234
|
+
> [FormRenderer](./form-renderer.md) (pass `fieldDirection="vertical"` to the
|
|
235
|
+
> form), or use `FormRenderer` with `display="drawer"`.
|
|
236
|
+
|
|
237
|
+
## Calculation panel
|
|
238
|
+
|
|
239
|
+
To show computed totals **beside** the form, render a [FormSummary](./form-summary.md)
|
|
240
|
+
next to it (not inside it) and share one hoisted form via the `form` prop:
|
|
241
|
+
|
|
242
|
+
```tsx
|
|
243
|
+
const form = useForm({ resolver: r, defaultValues: d })
|
|
244
|
+
|
|
245
|
+
<div className="flex items-start gap-4">
|
|
246
|
+
<FormBuilder form={form} onSubmit={save} className="min-w-0 flex-1">…fields…</FormBuilder>
|
|
247
|
+
<FormSummary form={form} title="Invoice">…rows…</FormSummary>
|
|
248
|
+
</div>
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
`form` makes FormBuilder use an existing react-hook-form instance instead of creating its
|
|
252
|
+
own — that's what lets something outside the form read the same live values.
|
|
253
|
+
|
|
254
|
+
## Edit & view modes
|
|
255
|
+
|
|
256
|
+
- **Edit**: pass `values` (not just `defaultValues`); the form repopulates when the
|
|
257
|
+
data loads. Use a remount `key` so initial-only inputs (date, rich text) re-seed.
|
|
258
|
+
- **View**: `mode="view"` renders the same children read-only (label + formatted value)
|
|
259
|
+
with no submit — one markup drives both edit and detail views.
|
|
260
|
+
|
|
261
|
+
```tsx
|
|
262
|
+
<FormBuilder mode="view" values={entity} onSubmit={() => {}} defaultValues={d}>
|
|
263
|
+
…the same fields…
|
|
264
|
+
</FormBuilder>
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Validation
|
|
268
|
+
|
|
269
|
+
Resolver-agnostic — pass any react-hook-form `resolver` (`zodResolver`, a plain
|
|
270
|
+
resolver function, etc.). The library never depends on zod.
|