torch-glare 2.5.0 → 2.5.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.
Files changed (79) hide show
  1. package/apps/lib/components/DataViews/filters/filters.tsx +7 -11
  2. package/apps/lib/components/FormBuilder/context.ts +8 -25
  3. package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +1 -1
  4. package/apps/lib/components/FormBuilder/form-builder.tsx +32 -172
  5. package/apps/lib/components/FormBuilder/index.ts +0 -4
  6. package/apps/lib/components/FormBuilder/types.ts +6 -16
  7. package/apps/lib/components/FormRenderer/FormDrawer.tsx +2 -2
  8. package/apps/lib/components/FormRenderer/detail.tsx +6 -6
  9. package/apps/lib/components/FormRenderer/form-renderer.tsx +155 -35
  10. package/apps/lib/components/{FormBuilder → FormRenderer}/header.tsx +12 -25
  11. package/apps/lib/components/FormRenderer/index.ts +4 -0
  12. package/apps/lib/components/FormRenderer/section.tsx +39 -0
  13. package/apps/lib/components/{FormBuilder → FormRenderer}/stepper.tsx +47 -19
  14. package/apps/lib/components/FormRenderer/types.ts +6 -6
  15. package/apps/lib/registry.json +62 -3
  16. package/apps/lib/tsconfig.tsbuildinfo +1 -1
  17. package/dist/bin/index.js +8 -4
  18. package/dist/bin/index.js.map +1 -1
  19. package/dist/src/commands/add.d.ts +3 -2
  20. package/dist/src/commands/add.d.ts.map +1 -1
  21. package/dist/src/commands/add.js +27 -35
  22. package/dist/src/commands/add.js.map +1 -1
  23. package/dist/src/commands/hook.d.ts.map +1 -1
  24. package/dist/src/commands/hook.js +23 -13
  25. package/dist/src/commands/hook.js.map +1 -1
  26. package/dist/src/commands/init.d.ts.map +1 -1
  27. package/dist/src/commands/init.js +6 -2
  28. package/dist/src/commands/init.js.map +1 -1
  29. package/dist/src/commands/layout.d.ts.map +1 -1
  30. package/dist/src/commands/layout.js +23 -13
  31. package/dist/src/commands/layout.js.map +1 -1
  32. package/dist/src/commands/provider.d.ts.map +1 -1
  33. package/dist/src/commands/provider.js +22 -12
  34. package/dist/src/commands/provider.js.map +1 -1
  35. package/dist/src/commands/utils.d.ts.map +1 -1
  36. package/dist/src/commands/utils.js +21 -28
  37. package/dist/src/commands/utils.js.map +1 -1
  38. package/dist/src/shared/copyComponentsRecursively.d.ts +5 -3
  39. package/dist/src/shared/copyComponentsRecursively.d.ts.map +1 -1
  40. package/dist/src/shared/copyComponentsRecursively.js +5 -6
  41. package/dist/src/shared/copyComponentsRecursively.js.map +1 -1
  42. package/dist/src/shared/getDependenciesAndInstallNestedComponents.js +1 -1
  43. package/dist/src/shared/getDependenciesAndInstallNestedComponents.js.map +1 -1
  44. package/dist/src/shared/installDependencies.d.ts +16 -1
  45. package/dist/src/shared/installDependencies.d.ts.map +1 -1
  46. package/dist/src/shared/installDependencies.js +41 -21
  47. package/dist/src/shared/installDependencies.js.map +1 -1
  48. package/dist/src/shared/installFromPlan.d.ts +23 -0
  49. package/dist/src/shared/installFromPlan.d.ts.map +1 -0
  50. package/dist/src/shared/installFromPlan.js +77 -0
  51. package/dist/src/shared/installFromPlan.js.map +1 -0
  52. package/dist/src/shared/resolveEntry.d.ts +21 -0
  53. package/dist/src/shared/resolveEntry.d.ts.map +1 -0
  54. package/dist/src/shared/resolveEntry.js +54 -0
  55. package/dist/src/shared/resolveEntry.js.map +1 -0
  56. package/dist/src/shared/suggestOtherCommand.d.ts +8 -0
  57. package/dist/src/shared/suggestOtherCommand.d.ts.map +1 -0
  58. package/dist/src/shared/suggestOtherCommand.js +34 -0
  59. package/dist/src/shared/suggestOtherCommand.js.map +1 -0
  60. package/dist/src/shared/tailwindInit.d.ts +3 -1
  61. package/dist/src/shared/tailwindInit.d.ts.map +1 -1
  62. package/dist/src/shared/tailwindInit.js +3 -1
  63. package/dist/src/shared/tailwindInit.js.map +1 -1
  64. package/dist/src/shared/wireStylesheet.d.ts +32 -0
  65. package/dist/src/shared/wireStylesheet.d.ts.map +1 -0
  66. package/dist/src/shared/wireStylesheet.js +92 -0
  67. package/dist/src/shared/wireStylesheet.js.map +1 -0
  68. package/dist/src/types/main.d.ts +6 -0
  69. package/dist/src/types/main.d.ts.map +1 -1
  70. package/docs/components/form-builder.md +62 -88
  71. package/docs/components/form-renderer.md +61 -25
  72. package/docs/components/form-summary.md +18 -3
  73. package/docs/components/section-block.md +1 -1
  74. package/docs/how-to/forms-with-form-builder.md +44 -41
  75. package/docs/migration/changelog.md +3 -0
  76. package/docs/migration/form-builder-2.5.2.md +113 -0
  77. package/docs/reference/cli.md +28 -3
  78. package/docs/tutorials/getting-started.md +7 -0
  79. package/package.json +1 -1
@@ -100,7 +100,12 @@ function FiltersRoot({
100
100
  </h3>
101
101
  ))}
102
102
  {active && (
103
- <Button size="S" variant="BorderStyle" className="ms-auto" onClick={() => setFilters({})}>
103
+ <Button
104
+ size="S"
105
+ variant="BorderStyle"
106
+ className="ms-auto"
107
+ onClick={() => setFilters({})}
108
+ >
104
109
  {clearLabel}
105
110
  </Button>
106
111
  )}
@@ -117,15 +122,7 @@ function FiltersRoot({
117
122
 
118
123
  {/* `onSubmit` is required by FormBuilder but never reached — there is no submit button and
119
124
  no Enter target. Filters emit as you touch them. */}
120
- {/* `layout="bare"` because this form is embedded, not a page: FormBuilder's default
121
- centres the fields at 1100px behind 48px gutters, which in a 260px rail leaves the
122
- controls less room than their own minimum width and overflows them. */}
123
- <FormBuilder
124
- onSubmit={() => {}}
125
- values={values}
126
- fieldDirection="vertical"
127
- layout="bare"
128
- >
125
+ <FormBuilder onSubmit={() => {}} values={values} fieldDirection="vertical">
129
126
  <Sync fields={fields} />
130
127
  <CellContext.Provider value="bare">
131
128
  {/* Same fold as `Panel.Section`: a 0fr→1fr grid row, and `inert` so a collapsed
@@ -151,7 +148,6 @@ function FiltersRoot({
151
148
  );
152
149
  }
153
150
 
154
-
155
151
  /**
156
152
  * The filter surface, assembled in one place. `Presets` and `Custom` are ours because FormBuilder
157
153
  * has no field for them; everything else you write is a FormBuilder field.
@@ -48,9 +48,14 @@ export const useBare = () => useContext(CellContext) !== false;
48
48
  export const useOnTable = () => useContext(CellContext) === "table";
49
49
 
50
50
  /**
51
- * Step registry — a `FormBuilder.Step` provides this so the fields rendered
52
- * inside it can register their `name`. `FormBuilder.Next` then validates just
53
- * those names before advancing. `null` when not inside a stepper.
51
+ * Step registry — a `FormRenderer.Step` provides this so the fields rendered inside it can
52
+ * register their `name`, and the stepper validates just those names before advancing. `null`
53
+ * when not inside a stepper.
54
+ *
55
+ * The stepper itself lives in `FormRenderer` — it is chrome. This registry stays here because
56
+ * the *fields* are what register into it (see `fields/FieldShell.tsx`), and FormBuilder must
57
+ * stand alone without FormRenderer installed. FormRenderer's `StepSlot` imports it from here;
58
+ * the dependency never points the other way.
54
59
  */
55
60
  export interface StepRegistry {
56
61
  register: (name: string) => void;
@@ -58,25 +63,3 @@ export interface StepRegistry {
58
63
  }
59
64
  export const StepContext = createContext<StepRegistry | null>(null);
60
65
  export const useStepRegistry = () => useContext(StepContext);
61
-
62
- /** Stepper state shared by the nav + Back/Next/Submit buttons. */
63
- export interface StepperContextValue {
64
- currentStep: number;
65
- totalSteps: number;
66
- titles: string[];
67
- isFirstStep: boolean;
68
- isLastStep: boolean;
69
- goToNext: () => void | Promise<void>;
70
- goToPrevious: () => void;
71
- goToStep: (index: number) => void;
72
- /** Field names registered per step, for per-step validation. */
73
- stepFields: Record<number, Set<string>>;
74
- /** Steps that have passed validation — stay checked even after navigating back. */
75
- completedSteps: Set<number>;
76
- }
77
- export const StepperContext = createContext<StepperContextValue | null>(null);
78
- export const useStepper = () => {
79
- const ctx = useContext(StepperContext);
80
- if (!ctx) throw new Error("FormBuilder.Step/Back/Next must be used within FormBuilder.Stepper");
81
- return ctx;
82
- };
@@ -36,7 +36,7 @@ export interface FieldShellProps {
36
36
  /**
37
37
  * Shared wrapper for every `FormBuilder.*` field: the FieldSection row + the RHF
38
38
  * `FormField`/`FormItem`/`FormControl`/`FormMessage` scaffolding. Also registers the
39
- * field name into the enclosing `FormBuilder.Step` (if any) so the stepper can
39
+ * field name into the enclosing `FormRenderer.Step` (if any) so the stepper can
40
40
  * validate per step.
41
41
  */
42
42
  export function FieldShell({
@@ -1,15 +1,11 @@
1
1
  "use client";
2
2
 
3
- import * as React from "react";
4
- import { ReactNode } from "react";
5
3
  import { useForm, type FieldValues } from "react-hook-form";
6
4
 
7
5
  import { cn } from "../../utils/cn";
8
6
  import { Form } from "../Form";
9
- import { SectionBlock, type SectionColor, type SectionVariant } from "../SectionBlock";
10
- import { LoadingContext, DirectionContext, StepperContext, FormIdContext } from "./context";
7
+ import { LoadingContext, DirectionContext, FormIdContext } from "./context";
11
8
  import { markFieldKind } from "./field-kind";
12
- import { Header } from "./header";
13
9
  import type { FormBuilderRootProps } from "./types";
14
10
  import {
15
11
  TextField,
@@ -39,52 +35,8 @@ import {
39
35
  RichTextField,
40
36
  CustomField,
41
37
  } from "./fields";
42
- import {
43
- Stepper,
44
- Step,
45
- Back,
46
- Next,
47
- StepperNav,
48
- StepSlot,
49
- useStepperState,
50
- isStepElement,
51
- isStepperElement,
52
- } from "./stepper";
53
38
  import { SubmitButton } from "./submit";
54
39
 
55
- // ─── Section ─────────────────────────────────────────────────────────────────
56
-
57
- export interface SectionProps {
58
- title?: ReactNode;
59
- color?: SectionColor;
60
- icon?: ReactNode;
61
- /**
62
- * `"Table"` switches to the full-bleed table shell — no body padding, a rule under
63
- * the header, and the card clipped to its radius. `FormBuilder.Table` uses it; pass
64
- * it here only when hand-composing a table inside a section.
65
- */
66
- variant?: SectionVariant;
67
- /** Right-aligned content on the title row — e.g. action buttons. */
68
- action?: ReactNode;
69
- children: ReactNode;
70
- }
71
-
72
- /** `FormBuilder.Section` — a titled Glare SectionBlock grouping fields. */
73
- function Section({ title, color, icon, variant, action, children }: SectionProps) {
74
- return (
75
- <SectionBlock title={title} color={color} icon={icon} variant={variant} action={action}>
76
- {children}
77
- </SectionBlock>
78
- );
79
- }
80
-
81
- function isHeaderElement(node: React.ReactNode): node is React.ReactElement {
82
- return (
83
- React.isValidElement(node) &&
84
- (node.type as { __isFormHeader?: boolean })?.__isFormHeader === true
85
- );
86
- }
87
-
88
40
  // ─── Root ────────────────────────────────────────────────────────────────────
89
41
 
90
42
  function FormBuilderRoot<T extends FieldValues = FieldValues>({
@@ -98,9 +50,7 @@ function FormBuilderRoot<T extends FieldValues = FieldValues>({
98
50
  values,
99
51
  loading = false,
100
52
  fieldDirection,
101
- layout = "page",
102
53
  resetOnSuccess,
103
- conclusion,
104
54
  className,
105
55
  }: FormBuilderRootProps<T>) {
106
56
  // Hooks can't be conditional, so always create one; `formProp` wins when given
@@ -117,116 +67,25 @@ function FormBuilderRoot<T extends FieldValues = FieldValues>({
117
67
  if (resetOnSuccess) form.reset();
118
68
  };
119
69
 
120
- // Split out a FormBuilder.Header (renders absolutely) and detect a Stepper child.
121
- const childArray = React.Children.toArray(children);
122
- const header = childArray.find(isHeaderElement);
123
- const rest = childArray.filter((n) => !isHeaderElement(n));
124
-
125
- const stepperEl = rest.find(isStepperElement);
126
- const stepChildren = stepperEl ? React.Children.toArray(stepperEl.props.children) : [];
127
- const steps = stepChildren.filter(isStepElement);
128
- const stepExtras = stepChildren.filter((n) => !isStepElement(n));
129
- const isStepper = !!stepperEl;
130
-
131
- // Stepper state is lifted HERE so the nav can live in its own grid column, outside the
132
- // `<form>`. Called unconditionally (inert when there are no steps) to keep hooks order stable.
133
- const stepper = useStepperState(steps, form.trigger as Parameters<typeof useStepperState>[1]);
134
-
135
- // The stepper nav is its own grid column beside the fields, inside the scrolling body.
136
- const nav = isStepper ? <StepperNav /> : null;
137
-
138
- // The fields the `<form>` wraps: the stepper's steps (+ any custom footer extras like Back/Next),
139
- // or the plain children. The Submit itself lives outside the form (see FormRenderer).
140
- const fields = isStepper ? (
141
- <>
142
- {steps.map((step, i) => (
143
- <StepSlot key={i} index={i} active={i === stepper.currentStep}>
144
- {step.props.children}
145
- </StepSlot>
146
- ))}
147
- {stepExtras}
148
- </>
149
- ) : (
150
- rest
151
- );
152
-
153
- // The fields column caps at 1100px and centers — as the middle column of the grid, and
154
- // standalone. `layout="bare"` drops the cap and the gutters so an embedded form fills its
155
- // container instead: 48px of padding a side is most of a settings rail.
156
- const fieldsInner = (
157
- <div
158
- className={cn(
159
- "flex w-full flex-col gap-4",
160
- layout === "page" && "mx-auto max-w-[1100px] px-[48px]",
161
- )}
162
- >
163
- {fields}
164
- </div>
165
- );
166
-
167
- const formEl = (
168
- <form id={id} className="w-full min-w-0" onSubmit={form.handleSubmit(handleValid, onInvalid)}>
169
- {fieldsInner}
170
- </form>
171
- );
172
-
173
- // Inside the form surface: the stepper rail beside the fields. Columns never wrap — the
174
- // layout stays side-by-side at every screen size (the fields column shrinks instead).
175
- const bodyInner = nav ? (
176
- <div className="grid w-full grid-cols-[1fr_minmax(0,1100px)_1fr] gap-8">
177
- {nav}
178
- {formEl}
179
- {/* Empty third column — balances the rail's gutter so the middle column is centred. */}
180
- <div />
181
- </div>
182
- ) : (
183
- formEl
184
- );
185
-
186
- const surface = header ? (
187
- // Scroll shell: the absolute header floats over the scrollable body. No fixed height — it
188
- // fills whatever the parent gives it (like the drawer's panel fills its tray) and the body
189
- // scrolls internally.
190
- <div className="relative isolate flex h-full w-full flex-col overflow-hidden rounded-2xl bg-background-presentation-body-primary">
191
- {header}
192
- <div className="relative z-[1] flex min-h-0 w-full flex-1 flex-col overflow-y-auto px-6 py-6 pt-[72px] scrollbar-hide">
193
- {bodyInner}
194
- </div>
195
- </div>
196
- ) : (
197
- bodyInner
198
- );
199
-
200
- // The conclusion (right) lives OUTSIDE the scroll surface — its own panel beside it (mirroring the
201
- // drawer's tray, a 6px gutter). Only the surface's body scrolls; the conclusion stays put.
202
- const body = conclusion ? (
203
- <div className="flex h-full flex-row items-stretch">
204
- <div className="min-h-0 min-w-0 flex-1">{surface}</div>
205
- <div className="ml-[6px] flex min-h-0">{conclusion}</div>
206
- </div>
207
- ) : (
208
- surface
209
- );
210
-
211
- // `className` lands on the OUTERMOST element — the one a parent lays out (e.g. `flex-1 min-h-0`
212
- // to fill a flex column). `h-full` fills a parent that has a definite height.
213
- const outerClassName = cn("h-full w-full @container", className);
214
-
215
- const tree = (
216
- <Form {...form}>
217
- <div className={outerClassName}>{body}</div>
218
- </Form>
219
- );
220
-
70
+ // The `<form>` IS the outermost element — FormBuilder draws no frame of its own. `gap-4` is the
71
+ // spacing between sections, which is field structure; `@container` scopes any container query a
72
+ // field wants to the form's own width. Everything that used to wrap this — the page gutters, the
73
+ // scroll shell, the header, the stepper rail, the summary column — belongs to `FormRenderer`.
74
+ //
75
+ // `className` lands here, so a parent still lays the form out (e.g. `flex-1 min-h-0`).
221
76
  return (
222
77
  <FormIdContext.Provider value={id}>
223
78
  <LoadingContext.Provider value={loading}>
224
79
  <DirectionContext.Provider value={direction}>
225
- {isStepper ? (
226
- <StepperContext.Provider value={stepper}>{tree}</StepperContext.Provider>
227
- ) : (
228
- tree
229
- )}
80
+ <Form {...form}>
81
+ <form
82
+ id={id}
83
+ className={cn("flex w-full min-w-0 flex-col gap-4 @container", className)}
84
+ onSubmit={form.handleSubmit(handleValid, onInvalid)}
85
+ >
86
+ {children}
87
+ </form>
88
+ </Form>
230
89
  </DirectionContext.Provider>
231
90
  </LoadingContext.Provider>
232
91
  </FormIdContext.Provider>
@@ -238,16 +97,24 @@ function FormBuilderRoot<T extends FieldValues = FieldValues>({
238
97
  *
239
98
  * ```tsx
240
99
  * <FormBuilder onSubmit={fn} resolver={r} defaultValues={d}>
241
- * <FormBuilder.Section title="Identity" color="Blue">
242
- * <FormBuilder.Text name="name" label="Name" required />
243
- * </FormBuilder.Section>
244
- * <FormBuilder.Submit>Save</FormBuilder.Submit>
100
+ * <FormBuilder.Text name="name" label="Name" required />
101
+ * <FormBuilder.Select name="category" label="Category" options={CATEGORY} />
245
102
  * </FormBuilder>
246
103
  * ```
247
104
  *
248
- * Steps are components (`FormBuilder.Stepper` + `FormBuilder.Step`). FormBuilder is
249
- * drawer-unaware to show a form in a drawer, wrap it in `FormRenderer`'s `FormDrawer`
250
- * (or use `FormRenderer` with `display: "drawer"`).
105
+ * **FormBuilder is the fields and nothing else** — the `<form>`, its react-hook-form context and
106
+ * the field components. Each field draws its own `FieldSection` row (label, required marker,
107
+ * hint); beyond that FormBuilder draws no frame at all: no titled section cards, no page gutters,
108
+ * no scroll shell, no title header, no stepper rail, no summary column. Rendered bare it fills
109
+ * whatever you put it in, which is what an embedded form — a settings rail, a `DataViews` filter
110
+ * panel — wants.
111
+ *
112
+ * For a real page or drawer form, wrap it in `FormRenderer`, which owns all of that chrome:
113
+ * `display` (page vs drawer), `header`, `actions`, `summary`, `FormRenderer.Section` and the
114
+ * wizard (`FormRenderer.Stepper` + `FormRenderer.Step`).
115
+ *
116
+ * `FormBuilder.Submit` stays here — it is the form's own submit button, wired to the `<form>` by
117
+ * id so it works even when the chrome renders it outside the element.
251
118
  */
252
119
  export const FormBuilder = Object.assign(FormBuilderRoot, {
253
120
  // fields
@@ -284,15 +151,8 @@ export const FormBuilder = Object.assign(FormBuilderRoot, {
284
151
  Image: (props: Parameters<typeof FileField>[0]) => <FileField {...props} image />,
285
152
  RichText: RichTextField,
286
153
  Custom: CustomField,
287
- // layout
288
- Section,
289
- Header,
154
+ // the form's own submit button
290
155
  Submit: SubmitButton,
291
- // stepper
292
- Stepper,
293
- Step,
294
- Back,
295
- Next,
296
156
  });
297
157
 
298
158
  /**
@@ -1,10 +1,6 @@
1
1
  export { FormBuilder } from "./form-builder";
2
- export type { SectionProps } from "./form-builder";
3
2
  export { fieldKindOf, markFieldKind } from "./field-kind";
4
- export { FormHeaderBar } from "./header";
5
- export type { HeaderProps, HeaderVariant, FormHeaderBarProps } from "./header";
6
3
  export { RichTextField } from "../TextEditor/RichTextField";
7
- export type { StepProps } from "./stepper";
8
4
  export type { FieldDirection, CellMode } from "./context";
9
5
  export type {
10
6
  BaseFieldProps,
@@ -228,7 +228,7 @@ export interface TableColumn {
228
228
  * `FormBuilder.Table` — an editable table field (built on RHF `useFieldArray`). Each row is a
229
229
  * record; each column cell is any `FormBuilder.*` field. Supports per-row checkbox selection
230
230
  * (+ select-all + bulk delete), drag-drop reordering, and add/remove rows. Renders inside a
231
- * `SectionBlock`, so place it as a top-level child (not inside a `FormBuilder.Section`).
231
+ * `SectionBlock`, so place it as a top-level child (not inside a `FormRenderer.Section`).
232
232
  */
233
233
  export interface TableFieldProps {
234
234
  name: string;
@@ -278,24 +278,14 @@ export interface FormBuilderRootProps<T extends FieldValues = FieldValues> {
278
278
  loading?: boolean;
279
279
  /** Field row direction. Defaults to horizontal (vertical inside a drawer). */
280
280
  fieldDirection?: FieldDirection;
281
- /**
282
- * How the fields column is framed.
283
- *
284
- * `"page"` (the default) is the full-page form: centred, capped at 1100px, and held off the
285
- * edges by 48px gutters.
286
- *
287
- * `"bare"` drops all three so the fields fill whatever they are placed inside. Use it when the
288
- * form is embedded in something narrow — a 260px settings rail has no room to give up 96px to
289
- * gutters, and its controls would overflow the panel rather than fill it.
290
- */
291
- layout?: "page" | "bare";
292
281
  /** Reset to defaults after a successful submit. */
293
282
  resetOnSuccess?: boolean;
294
283
  /**
295
- * A live panel (e.g. `FormSummary`) rendered **outside** the `<form>`, as the right column of the
296
- * adaptive grid with a stepper it makes a 3-column layout (nav · fields · conclusion), otherwise
297
- * 2 columns (fields · conclusion). It reads the shared values via its own `form` prop.
284
+ * Lands on the `<form>` element itself FormBuilder renders nothing around it. Use it to let
285
+ * the form fill its parent (e.g. `"flex-1 min-h-0"` inside a flex column that has a height).
286
+ *
287
+ * There is no `layout` prop: the fields always fill their container. The page framing that
288
+ * used to live here — the 1100px cap and 48px gutters — belongs to `FormRenderer`.
298
289
  */
299
- conclusion?: ReactNode;
300
290
  className?: string;
301
291
  }
@@ -12,7 +12,7 @@ import {
12
12
  DrawerNotchDivider,
13
13
  DrawerNotchPill,
14
14
  } from "../Drawer";
15
- import { FormHeaderBar, type HeaderVariant } from "../FormBuilder/header";
15
+ import { FormHeaderBar, type HeaderVariant } from "./header";
16
16
 
17
17
  export interface FormDrawerProps {
18
18
  open: boolean;
@@ -108,7 +108,7 @@ export function FormDrawer({
108
108
 
109
109
  {/* pt-[72px] clears the 44px header pill (inset 4px) — same as the page shell. The
110
110
  48px bottom breathing-room goes on an inner wrapper, not the scroll container:
111
- FormBuilder's outer element is `h-full`, which would pin it to the content box and
111
+ FormRenderer's outer element is `h-full`, which would pin it to the content box and
112
112
  swallow the container's own `pb`. On a plain wrapper that `h-full` resolves to the
113
113
  content height, so the padding actually lengthens the scroll. The conclusion panel
114
114
  is a separate sibling, so it keeps its own spacing. */}
@@ -5,11 +5,11 @@ import * as TabsPrimitive from "@radix-ui/react-tabs";
5
5
 
6
6
  import { cn } from "../../utils/cn";
7
7
  import { formBarItemStyles } from "../TabFormItem";
8
- import { FormHeaderBar, type HeaderVariant } from "../FormBuilder/header";
8
+ import { FormHeaderBar, type HeaderVariant } from "./header";
9
9
 
10
10
  /**
11
11
  * Detail-tabs — a display-only view where a left **sidebar** switches the main area between
12
- * **`FormBuilder.Section` panels** (a detail page, not a form). It lives on `FormRenderer`
12
+ * **`FormRenderer.Section` panels** (a detail page, not a form). It lives on `FormRenderer`
13
13
  * (`FormRenderer.Sidebar` / `.Sidebar.Item` / `.Tab`) so `FormBuilder` stays form-only. Built on
14
14
  * the same Radix Tabs primitive shadcn uses: the sidebar is the `Tabs.List`, each `Sidebar.Item` a
15
15
  * `Tabs.Trigger`, each `Tab` a `Tabs.Content` — so the fixed rail and the panels share tab state.
@@ -20,7 +20,7 @@ export interface DetailSidebarProps {
20
20
  }
21
21
 
22
22
  /**
23
- * `FormRenderer.Sidebar` — the tab rail, sitting where a `FormBuilder.Stepper`'s nav would.
23
+ * `FormRenderer.Sidebar` — the tab rail, sitting where a `FormRenderer.Stepper`'s nav would.
24
24
  * Renders **nothing itself**: the FormRenderer root detects it and places its `Sidebar.Item`
25
25
  * children (the tab triggers) into the fixed rail.
26
26
  */
@@ -80,7 +80,7 @@ export interface DetailRowProps {
80
80
 
81
81
  /**
82
82
  * `FormRenderer.Row` — a read-only label/value cell for detail content (the display counterpart of a
83
- * form field). Drop several inside a `FormRenderer.Grid` within a `FormBuilder.Section`.
83
+ * form field). Drop several inside a `FormRenderer.Grid` within a `FormRenderer.Section`.
84
84
  */
85
85
  export function DetailRow({ label, value }: DetailRowProps) {
86
86
  return (
@@ -110,7 +110,7 @@ const GRID_COLS: Record<NonNullable<DetailGridProps["columns"]>, string> = {
110
110
  /**
111
111
  * `FormRenderer.Grid` — arranges `FormRenderer.Row`s in an equal-column grid spanning the **full
112
112
  * section width** (default 2 columns, so cells split in half). Padded so the rows breathe inside a
113
- * `FormBuilder.Section` (clear of the title badge, roomy row + column spacing).
113
+ * `FormRenderer.Section` (clear of the title badge, roomy row + column spacing).
114
114
  */
115
115
  export function DetailGrid({ columns = 2, children }: DetailGridProps) {
116
116
  return (
@@ -121,7 +121,7 @@ export function DetailGrid({ columns = 2, children }: DetailGridProps) {
121
121
  export interface DetailTabProps {
122
122
  /** Ties this panel to the `Sidebar.Item` of the same `value`. */
123
123
  value: string;
124
- /** The panel body — typically `FormBuilder.Section` display blocks. */
124
+ /** The panel body — typically `FormRenderer.Section` display blocks. */
125
125
  children: React.ReactNode;
126
126
  }
127
127