torch-glare 2.4.3 → 2.4.4
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/apps/lib/components/FormBuilder/form-builder.tsx +7 -8
- package/apps/lib/components/FormRenderer/detail.tsx +207 -0
- package/apps/lib/components/FormRenderer/form-renderer.tsx +46 -3
- package/apps/lib/components/FormRenderer/index.ts +7 -0
- package/apps/lib/components/FormRenderer/types.ts +2 -1
- package/apps/lib/registry.json +1 -1
- package/apps/lib/tsconfig.tsbuildinfo +1 -1
- package/docs/components/form-builder.md +3 -0
- package/docs/components/form-renderer.md +56 -1
- package/docs/how-to/forms-with-form-builder.md +54 -0
- package/package.json +1 -1
|
@@ -226,6 +226,9 @@ automatically.
|
|
|
226
226
|
> [FormRenderer](./form-renderer.md) (pass `fieldDirection="vertical"` to the
|
|
227
227
|
> form), or use `FormRenderer` with `display="drawer"`.
|
|
228
228
|
|
|
229
|
+
> Building a **detail page** with a sidebar of tabs (not a form)? That lives on `FormRenderer`
|
|
230
|
+
> (`FormRenderer.Sidebar` / `.Tab`) — see the FormRenderer docs. `FormBuilder` itself stays form-only.
|
|
231
|
+
|
|
229
232
|
## Calculation panel
|
|
230
233
|
|
|
231
234
|
To show computed totals **beside** the form, render a [FormSummary](./form-summary.md)
|
|
@@ -16,6 +16,10 @@ takes care of the surrounding concerns:
|
|
|
16
16
|
- the **absolute title header** + action bar (page display),
|
|
17
17
|
- **vertical field layout** inside a drawer.
|
|
18
18
|
|
|
19
|
+
FormRenderer has **two modes**: a **form** (author fields as children, as below), or a display-only
|
|
20
|
+
**detail page** — give it `FormRenderer.Sidebar` + `FormRenderer.Tab` children instead of fields and the
|
|
21
|
+
sidebar swaps `FormBuilder.Section` panels (no `<form>`, no submit — see [Detail tabs](#detail-tabs-sidebar)).
|
|
22
|
+
|
|
19
23
|
FormRenderer never manufactures a Submit — **you compose the Save and hand it to `actions`**.
|
|
20
24
|
It renders in the form's header action pill (page) or the drawer header (drawer), and a bare
|
|
21
25
|
`<FormBuilder.Submit>` auto-targets this form (even though the header sits outside the `<form>`).
|
|
@@ -60,7 +64,7 @@ import { FormBuilder } from "@/components/FormBuilder";
|
|
|
60
64
|
| Prop | Type | Notes |
|
|
61
65
|
| -------------------------------------------------------------- | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
62
66
|
| `children` | `ReactNode` | The form body — `FormBuilder.Section` / field / `FormBuilder.Stepper` JSX. |
|
|
63
|
-
| `onSubmit
|
|
67
|
+
| `onSubmit?` / `onInvalid?` | fns | Submit / validation-fail callbacks. Optional — a detail-tabs view has no form, so omit them there. |
|
|
64
68
|
| `resolver` | `Resolver` | Any react-hook-form resolver, e.g. `zodResolver(schema)`. |
|
|
65
69
|
| `defaultValues` / `values` | `DefaultValues` / `T` | Initial values; `values` re-syncs on change (edit). |
|
|
66
70
|
| `loading` / `resetOnSuccess` | `boolean` | Forwarded to `FormBuilder`. |
|
|
@@ -119,6 +123,57 @@ error overrides it to red. You still pass just the Submit; the nav is wired for
|
|
|
119
123
|
</FormRenderer>
|
|
120
124
|
```
|
|
121
125
|
|
|
126
|
+
## Detail tabs (sidebar)
|
|
127
|
+
|
|
128
|
+
Give FormRenderer `FormRenderer.Sidebar` + `FormRenderer.Tab` children (instead of fields) and it
|
|
129
|
+
switches to a **display-only detail page**: a left **sidebar** where each item swaps in its matching
|
|
130
|
+
tab panel — no `<form>`, no submit. The sidebar sits **where a stepper's rail would**, and only the
|
|
131
|
+
active panel shows (built on the same Radix Tabs primitive shadcn uses, so it's keyboard-accessible).
|
|
132
|
+
Pair it with `header` (`variant="detail"` → a "View" badge) + `actions` (Print / Approve / …).
|
|
133
|
+
|
|
134
|
+
Each `Tab` holds read-only `FormBuilder.Section` blocks; `FormRenderer.Grid` + `FormRenderer.Row` lay
|
|
135
|
+
out the label/value display cells (the display counterpart of form fields).
|
|
136
|
+
|
|
137
|
+
```tsx
|
|
138
|
+
<FormRenderer
|
|
139
|
+
header={{ title: "Order DE-344", variant: "detail" }}
|
|
140
|
+
actions={<Button variant="BorderStyle">Print</Button>}
|
|
141
|
+
>
|
|
142
|
+
{/* The rail — one Item per tab, tied to a Tab by `value`. */}
|
|
143
|
+
<FormRenderer.Sidebar>
|
|
144
|
+
<FormRenderer.Sidebar.Item value="overview" icon={<i className="ri-layout-grid-line" />}>
|
|
145
|
+
Overview
|
|
146
|
+
</FormRenderer.Sidebar.Item>
|
|
147
|
+
<FormRenderer.Sidebar.Item value="items" icon={<i className="ri-table-line" />}>
|
|
148
|
+
Items Table
|
|
149
|
+
</FormRenderer.Sidebar.Item>
|
|
150
|
+
</FormRenderer.Sidebar>
|
|
151
|
+
|
|
152
|
+
{/* One panel per tab — read-only Section blocks. */}
|
|
153
|
+
<FormRenderer.Tab value="overview">
|
|
154
|
+
<FormBuilder.Section title="Main Information" color="Blue">
|
|
155
|
+
<FormRenderer.Grid>
|
|
156
|
+
<FormRenderer.Row label="PO Number" value="PO-000123" />
|
|
157
|
+
<FormRenderer.Row label="Status" value={<Badge label="Submitted" color="yellow" />} />
|
|
158
|
+
</FormRenderer.Grid>
|
|
159
|
+
</FormBuilder.Section>
|
|
160
|
+
</FormRenderer.Tab>
|
|
161
|
+
|
|
162
|
+
<FormRenderer.Tab value="items">…</FormRenderer.Tab>
|
|
163
|
+
</FormRenderer>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
| Component | Props | Renders |
|
|
167
|
+
| -------------- | -------------------------- | ------------------------------------------------------------------ |
|
|
168
|
+
| `Sidebar` | `children` | The tab rail (a Radix `Tabs.List`), fixed at the stepper's place. |
|
|
169
|
+
| `Sidebar.Item` | `value`, `icon?`, children | A rail nav row (a `Tabs.Trigger`); the active one is a black pill. |
|
|
170
|
+
| `Tab` | `value`, children | A content panel (a `Tabs.Content`) shown when its tab is active. |
|
|
171
|
+
| `Grid` | `columns?` (1–3), children | A padded grid of display `Row`s (default 2 columns). |
|
|
172
|
+
| `Row` | `label`, `value` | A read-only label/value display cell. |
|
|
173
|
+
|
|
174
|
+
The first `Tab` is active by default. Only the active panel is visible; the rail stays fixed while the
|
|
175
|
+
content column scrolls.
|
|
176
|
+
|
|
122
177
|
## Summary panel
|
|
123
178
|
|
|
124
179
|
Pass a hoisted `useForm` as `form` and a `FormSummary` as `summary` — FormRenderer binds
|
|
@@ -391,6 +391,60 @@ drawer's tray, beside the form:
|
|
|
391
391
|
|
|
392
392
|
---
|
|
393
393
|
|
|
394
|
+
## 8. A detail (view) page — sidebar tabs, not a form
|
|
395
|
+
|
|
396
|
+
Sometimes you want to **display** a record, not edit it. Give `FormRenderer` `FormRenderer.Sidebar`
|
|
397
|
+
|
|
398
|
+
- `FormRenderer.Tab` children (instead of fields) and it switches to a display-only detail page: a
|
|
399
|
+
left **sidebar** where each item swaps in its matching tab panel — no `<form>`, no submit. The
|
|
400
|
+
sidebar sits where a stepper's rail would; only the active panel shows.
|
|
401
|
+
|
|
402
|
+
**Every tab's content is `FormBuilder.Section` blocks.** Inside a Section, use the default
|
|
403
|
+
`FormRenderer.Grid` + `FormRenderer.Row` display cells (the read-only counterpart of form fields), or
|
|
404
|
+
render **your own component** — anything goes inside a Section.
|
|
405
|
+
|
|
406
|
+
```tsx
|
|
407
|
+
<FormRenderer
|
|
408
|
+
header={{ title: "Order DE-344", variant: "detail" }} // "View" badge
|
|
409
|
+
actions={<Button variant="BorderStyle">Print</Button>}
|
|
410
|
+
>
|
|
411
|
+
{/* Rail — each Item's `value` ties to a Tab. */}
|
|
412
|
+
<FormRenderer.Sidebar>
|
|
413
|
+
<FormRenderer.Sidebar.Item value="overview" icon={<i className="ri-layout-grid-line" />}>
|
|
414
|
+
Overview
|
|
415
|
+
</FormRenderer.Sidebar.Item>
|
|
416
|
+
<FormRenderer.Sidebar.Item value="activity" icon={<i className="ri-pulse-line" />}>
|
|
417
|
+
Activity log
|
|
418
|
+
</FormRenderer.Sidebar.Item>
|
|
419
|
+
</FormRenderer.Sidebar>
|
|
420
|
+
|
|
421
|
+
{/* Default display cells */}
|
|
422
|
+
<FormRenderer.Tab value="overview">
|
|
423
|
+
<FormBuilder.Section title="Main Information" color="Blue">
|
|
424
|
+
<FormRenderer.Grid columns={2}>
|
|
425
|
+
<FormRenderer.Row label="PO Number" value={record.poNumber} />
|
|
426
|
+
<FormRenderer.Row label="Status" value={<Badge label="Submitted" color="yellow" />} />
|
|
427
|
+
</FormRenderer.Grid>
|
|
428
|
+
</FormBuilder.Section>
|
|
429
|
+
</FormRenderer.Tab>
|
|
430
|
+
|
|
431
|
+
{/* Or bring your own component — still inside a Section */}
|
|
432
|
+
<FormRenderer.Tab value="activity">
|
|
433
|
+
<FormBuilder.Section title="Activity log" color="Green">
|
|
434
|
+
<YourTimeline items={record.activity} />
|
|
435
|
+
</FormBuilder.Section>
|
|
436
|
+
</FormRenderer.Tab>
|
|
437
|
+
</FormRenderer>
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
`FormRenderer.Grid` takes `columns` (1–3, default 2) and spans the full section width; `FormRenderer.Row`
|
|
441
|
+
takes `label` + `value` (any node). The first `Tab` is active by default.
|
|
442
|
+
|
|
443
|
+
> Generating one? Call the `create-form` tool with `layout="detail"` — it returns this exact wiring
|
|
444
|
+
> with your fields pre-filled as display rows.
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
394
448
|
## Gotchas
|
|
395
449
|
|
|
396
450
|
- **Hoisting `useForm` disables the remount-`key` reset.** Once the form instance lives in
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "torch-glare",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "A copy-in React component library (TypeScript + Radix UI + Tailwind CSS). Its CLI copies component source directly into your project — you own the code.",
|