torch-glare 2.4.2 → 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.
Files changed (47) hide show
  1. package/apps/lib/components/FormBuilder/context.ts +2 -5
  2. package/apps/lib/components/FormBuilder/fields/ChoiceFields.tsx +2 -7
  3. package/apps/lib/components/FormBuilder/fields/ColorField.tsx +1 -18
  4. package/apps/lib/components/FormBuilder/fields/CustomField.tsx +1 -6
  5. package/apps/lib/components/FormBuilder/fields/DateField.tsx +1 -3
  6. package/apps/lib/components/FormBuilder/fields/FieldArray.tsx +10 -15
  7. package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +6 -32
  8. package/apps/lib/components/FormBuilder/fields/FileField.tsx +1 -2
  9. package/apps/lib/components/FormBuilder/fields/OptionListFields.tsx +2 -9
  10. package/apps/lib/components/FormBuilder/fields/OtpField.tsx +1 -2
  11. package/apps/lib/components/FormBuilder/fields/PhoneField.tsx +24 -23
  12. package/apps/lib/components/FormBuilder/fields/RichTextEditorField.tsx +1 -7
  13. package/apps/lib/components/FormBuilder/fields/SelectField.tsx +3 -13
  14. package/apps/lib/components/FormBuilder/fields/SignatureField.tsx +1 -19
  15. package/apps/lib/components/FormBuilder/fields/SliderField.tsx +1 -6
  16. package/apps/lib/components/FormBuilder/fields/SwitchBoxField.tsx +1 -2
  17. package/apps/lib/components/FormBuilder/fields/TableField.tsx +22 -26
  18. package/apps/lib/components/FormBuilder/fields/TextField.tsx +5 -14
  19. package/apps/lib/components/FormBuilder/fields/TreeSelectField.tsx +1 -7
  20. package/apps/lib/components/FormBuilder/form-builder.tsx +22 -36
  21. package/apps/lib/components/FormBuilder/header.tsx +2 -6
  22. package/apps/lib/components/FormBuilder/index.ts +1 -5
  23. package/apps/lib/components/FormBuilder/stepper.tsx +88 -15
  24. package/apps/lib/components/FormBuilder/submit.tsx +1 -4
  25. package/apps/lib/components/FormBuilder/types.ts +2 -5
  26. package/apps/lib/components/FormRenderer/FormDrawer.tsx +9 -2
  27. package/apps/lib/components/FormRenderer/detail.tsx +207 -0
  28. package/apps/lib/components/FormRenderer/form-renderer.tsx +55 -14
  29. package/apps/lib/components/FormRenderer/index.ts +7 -5
  30. package/apps/lib/components/FormRenderer/types.ts +2 -3
  31. package/apps/lib/components/Popover.tsx +6 -2
  32. package/apps/lib/components/SearchableSelect.tsx +7 -2
  33. package/apps/lib/layouts/FieldSection.tsx +25 -22
  34. package/apps/lib/registry.json +1 -1
  35. package/apps/lib/tsconfig.tsbuildinfo +1 -1
  36. package/dist/src/shared/tailwindInit.d.ts.map +1 -1
  37. package/dist/src/shared/tailwindInit.js +3 -0
  38. package/dist/src/shared/tailwindInit.js.map +1 -1
  39. package/docs/components/form-builder.md +22 -29
  40. package/docs/components/form-renderer.md +72 -11
  41. package/docs/components/searchable-select.md +50 -46
  42. package/docs/how-to/forms-with-form-builder.md +68 -11
  43. package/docs/reference/tailwind-plugins.md +11 -1
  44. package/docs/tutorials/getting-started.md +9 -0
  45. package/package.json +1 -1
  46. package/apps/lib/components/FormBuilder/DisplayField.tsx +0 -40
  47. package/apps/lib/components/FormBuilder/viewFormat.tsx +0 -137
@@ -0,0 +1,207 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import * as TabsPrimitive from "@radix-ui/react-tabs";
5
+
6
+ import { cn } from "../../utils/cn";
7
+ import { formBarItemStyles } from "../TabFormItem";
8
+ import { FormHeaderBar, type HeaderVariant } from "../FormBuilder/header";
9
+
10
+ /**
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`
13
+ * (`FormRenderer.Sidebar` / `.Sidebar.Item` / `.Tab`) so `FormBuilder` stays form-only. Built on
14
+ * the same Radix Tabs primitive shadcn uses: the sidebar is the `Tabs.List`, each `Sidebar.Item` a
15
+ * `Tabs.Trigger`, each `Tab` a `Tabs.Content` — so the fixed rail and the panels share tab state.
16
+ */
17
+
18
+ export interface DetailSidebarProps {
19
+ children: React.ReactNode;
20
+ }
21
+
22
+ /**
23
+ * `FormRenderer.Sidebar` — the tab rail, sitting where a `FormBuilder.Stepper`'s nav would.
24
+ * Renders **nothing itself**: the FormRenderer root detects it and places its `Sidebar.Item`
25
+ * children (the tab triggers) into the fixed rail.
26
+ */
27
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- children are read by the FormRenderer root
28
+ function DetailSidebarRoot(_props: DetailSidebarProps) {
29
+ return null;
30
+ }
31
+ (DetailSidebarRoot as unknown as { __isDetailSidebar: boolean }).__isDetailSidebar = true;
32
+
33
+ export interface DetailSidebarItemProps {
34
+ /** Ties this row to the `FormRenderer.Tab` of the same `value` — clicking it shows that panel. */
35
+ value: string;
36
+ /** Leading icon (e.g. a Remix `<i className="ri-…" />`). */
37
+ icon?: React.ReactNode;
38
+ children: React.ReactNode;
39
+ }
40
+
41
+ /**
42
+ * `FormRenderer.Sidebar.Item` — a rail nav row, rendered as a Radix `Tabs.Trigger` styled with the
43
+ * `TabFormItem` `tree` look. Radix drives the active state (`data-state="active"` → black pill).
44
+ */
45
+ function DetailSidebarItem({ value, icon, children }: DetailSidebarItemProps) {
46
+ return (
47
+ <TabsPrimitive.Trigger
48
+ value={value}
49
+ className={cn(
50
+ formBarItemStyles({ componentType: "tree" }),
51
+ "h-[32px] w-full justify-start gap-2 rounded-[10px] px-[6px] [&_i]:text-[16px]",
52
+ // Radix sets `data-state` on the trigger; the active tab is the filled (black) pill.
53
+ "data-[state=active]:bg-background-presentation-tab-topbar-selected data-[state=active]:text-content-presentation-tab-action-selected",
54
+ "data-[state=active]:hover:bg-background-presentation-tab-topbar-selected data-[state=active]:hover:px-[6px]",
55
+ )}
56
+ >
57
+ {icon}
58
+ <span className="flex-1 truncate text-left typography-body-medium-medium">{children}</span>
59
+ </TabsPrimitive.Trigger>
60
+ );
61
+ }
62
+
63
+ export const DetailSidebar = Object.assign(DetailSidebarRoot, {
64
+ Item: DetailSidebarItem,
65
+ });
66
+
67
+ export function isDetailSidebarElement(
68
+ node: React.ReactNode,
69
+ ): node is React.ReactElement<DetailSidebarProps> {
70
+ return (
71
+ React.isValidElement(node) &&
72
+ (node.type as { __isDetailSidebar?: boolean })?.__isDetailSidebar === true
73
+ );
74
+ }
75
+
76
+ export interface DetailRowProps {
77
+ label: React.ReactNode;
78
+ value: React.ReactNode;
79
+ }
80
+
81
+ /**
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`.
84
+ */
85
+ export function DetailRow({ label, value }: DetailRowProps) {
86
+ return (
87
+ <div className="flex flex-col gap-1">
88
+ <span className="typography-body-small-regular text-content-presentation-global-secondary">
89
+ {label}
90
+ </span>
91
+ <span className="typography-body-medium-medium text-content-presentation-global-primary">
92
+ {value}
93
+ </span>
94
+ </div>
95
+ );
96
+ }
97
+
98
+ export interface DetailGridProps {
99
+ /** Column count (default 2). */
100
+ columns?: 1 | 2 | 3;
101
+ children: React.ReactNode;
102
+ }
103
+
104
+ const GRID_COLS: Record<NonNullable<DetailGridProps["columns"]>, string> = {
105
+ 1: "grid-cols-1",
106
+ 2: "grid-cols-2",
107
+ 3: "grid-cols-3",
108
+ };
109
+
110
+ /**
111
+ * `FormRenderer.Grid` — arranges `FormRenderer.Row`s in an equal-column grid spanning the **full
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).
114
+ */
115
+ export function DetailGrid({ columns = 2, children }: DetailGridProps) {
116
+ return (
117
+ <div className={cn("grid w-full gap-x-12 gap-y-5 py-3", GRID_COLS[columns])}>{children}</div>
118
+ );
119
+ }
120
+
121
+ export interface DetailTabProps {
122
+ /** Ties this panel to the `Sidebar.Item` of the same `value`. */
123
+ value: string;
124
+ /** The panel body — typically `FormBuilder.Section` display blocks. */
125
+ children: React.ReactNode;
126
+ }
127
+
128
+ /**
129
+ * `FormRenderer.Tab` — a content panel shown when its `value` is the active tab. Renders
130
+ * **nothing itself**: the FormRenderer root detects it and mounts it as a Radix `Tabs.Content`
131
+ * (kept mounted, inactive ones hidden).
132
+ */
133
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- read by the FormRenderer root
134
+ export function DetailTab(_props: DetailTabProps) {
135
+ return null;
136
+ }
137
+ (DetailTab as unknown as { __isDetailTab: boolean }).__isDetailTab = true;
138
+
139
+ export function isDetailTabElement(
140
+ node: React.ReactNode,
141
+ ): node is React.ReactElement<DetailTabProps> {
142
+ return (
143
+ React.isValidElement(node) && (node.type as { __isDetailTab?: boolean })?.__isDetailTab === true
144
+ );
145
+ }
146
+
147
+ export interface DetailTabsViewProps {
148
+ header?: { title: string; label?: string; variant?: HeaderVariant };
149
+ /** Header action buttons (Print / Approve / …). */
150
+ actions?: React.ReactNode;
151
+ /** The `FormRenderer.Sidebar` element — its children are the tab triggers. */
152
+ sidebar: React.ReactElement<DetailSidebarProps>;
153
+ /** The `FormRenderer.Tab` elements — the content panels. */
154
+ tabs: React.ReactElement<DetailTabProps>[];
155
+ className?: string;
156
+ }
157
+
158
+ /**
159
+ * The detail-tabs surface: the floating header over a fixed left rail (the sidebar) + a scrolling
160
+ * content column showing the active tab. Radix `Tabs.Root` owns the state (uncontrolled, defaults to
161
+ * the first tab). The rail matches the stepper's rail position; only the content column scrolls.
162
+ */
163
+ export function DetailTabsView({ header, actions, sidebar, tabs, className }: DetailTabsViewProps) {
164
+ const defaultValue = tabs[0]?.props.value;
165
+
166
+ return (
167
+ <TabsPrimitive.Root
168
+ orientation="vertical"
169
+ defaultValue={defaultValue}
170
+ className={cn("h-full w-full @container", className)}
171
+ >
172
+ {/* Scroll shell — mirrors FormBuilder's: the absolute header floats over the body. */}
173
+ <div className="relative isolate flex h-full w-full flex-col overflow-hidden rounded-2xl bg-background-presentation-body-primary">
174
+ {header && (
175
+ <FormHeaderBar title={header.title} label={header.label} variant={header.variant}>
176
+ {actions}
177
+ </FormHeaderBar>
178
+ )}
179
+
180
+ <div className="relative z-[1] flex min-h-0 w-full flex-1 flex-row">
181
+ {/* The fixed rail — the tab list. `pt-[72px]` clears the floating header. */}
182
+ <TabsPrimitive.List asChild>
183
+ <aside className="flex h-full w-[216px] shrink-0 flex-col gap-1 overflow-y-auto border-r border-border-presentation-global-primary bg-black-alpha-5 px-2 pb-6 pt-[72px] scrollbar-hide">
184
+ {sidebar.props.children}
185
+ </aside>
186
+ </TabsPrimitive.List>
187
+
188
+ {/* The only scrolling region — the active tab's Sections. */}
189
+ <div className="flex min-h-0 w-full flex-1 flex-col overflow-y-auto px-6 py-6 pt-[72px] scrollbar-hide">
190
+ <div className="mx-auto flex w-full max-w-[1100px] flex-col gap-4">
191
+ {tabs.map((panel) => (
192
+ <TabsPrimitive.Content
193
+ key={panel.props.value}
194
+ value={panel.props.value}
195
+ forceMount
196
+ className="flex flex-col gap-4 outline-none data-[state=inactive]:hidden"
197
+ >
198
+ {panel.props.children}
199
+ </TabsPrimitive.Content>
200
+ ))}
201
+ </div>
202
+ </div>
203
+ </div>
204
+ </div>
205
+ </TabsPrimitive.Root>
206
+ );
207
+ }
@@ -1,10 +1,20 @@
1
1
  "use client";
2
2
 
3
- import { useId } from "react";
3
+ import { Children, useId } from "react";
4
4
  import { FieldValues } from "react-hook-form";
5
5
 
6
6
  import { FormBuilder } from "../FormBuilder";
7
- import { FormIdContext, LoadingContext, ModeContext } from "../FormBuilder/context";
7
+ import { FormIdContext, LoadingContext } from "../FormBuilder/context";
8
+ import { StepperActions } from "../FormBuilder/stepper";
9
+ import {
10
+ DetailSidebar,
11
+ DetailTab,
12
+ DetailGrid,
13
+ DetailRow,
14
+ DetailTabsView,
15
+ isDetailSidebarElement,
16
+ isDetailTabElement,
17
+ } from "./detail";
8
18
  import { FormDrawer } from "./FormDrawer";
9
19
  import type { FormRendererProps } from "./types";
10
20
 
@@ -16,8 +26,12 @@ import type { FormRendererProps } from "./types";
16
26
  * FormRenderer never manufactures a Submit — you compose it and hand it to `actions`
17
27
  * (`actions={<FormBuilder.Submit>Save</FormBuilder.Submit>}`). It renders in the form's
18
28
  * header action pill (page) or the drawer header (drawer), and auto-targets this form.
29
+ *
30
+ * Give it `FormRenderer.Sidebar` + `FormRenderer.Tab` children instead of fields and it switches to
31
+ * a **detail-tabs** view: a display-only page (no `<form>`) whose sidebar swaps `FormBuilder.Section`
32
+ * panels — the sidebar sits where a stepper's rail would.
19
33
  */
20
- export function FormRenderer<T extends FieldValues = FieldValues>({
34
+ function FormRendererRoot<T extends FieldValues = FieldValues>({
21
35
  children,
22
36
  id,
23
37
  onSubmit,
@@ -25,7 +39,6 @@ export function FormRenderer<T extends FieldValues = FieldValues>({
25
39
  resolver,
26
40
  defaultValues,
27
41
  values,
28
- mode = "edit",
29
42
  loading,
30
43
  resetOnSuccess,
31
44
  fieldDirection,
@@ -52,16 +65,33 @@ export function FormRenderer<T extends FieldValues = FieldValues>({
52
65
  const autoId = useId();
53
66
  const formId = id ?? autoId;
54
67
 
68
+ // Detail-tabs mode: a `FormRenderer.Sidebar` + `FormRenderer.Tab` children mean a display-only
69
+ // detail page (no `<form>`) — the sidebar swaps Section panels via Radix Tabs. Detected here so
70
+ // the form props below are simply unused.
71
+ const childArray = Children.toArray(children);
72
+ const detailSidebar = childArray.find(isDetailSidebarElement);
73
+ const detailTabs = childArray.filter(isDetailTabElement);
74
+ if (detailSidebar && detailTabs.length > 0) {
75
+ return (
76
+ <DetailTabsView
77
+ header={header}
78
+ actions={actions}
79
+ sidebar={detailSidebar}
80
+ tabs={detailTabs}
81
+ className={className}
82
+ />
83
+ );
84
+ }
85
+
55
86
  const inner = (
56
87
  <FormBuilder
57
88
  id={formId}
58
89
  form={form}
59
- onSubmit={onSubmit}
90
+ onSubmit={onSubmit ?? (() => {})}
60
91
  onInvalid={onInvalid}
61
92
  resolver={resolver}
62
93
  defaultValues={defaultValues}
63
94
  values={values}
64
- mode={mode}
65
95
  loading={loading}
66
96
  fieldDirection={effectiveDirection}
67
97
  resetOnSuccess={resetOnSuccess}
@@ -73,7 +103,8 @@ export function FormRenderer<T extends FieldValues = FieldValues>({
73
103
  >
74
104
  {useHeader && (
75
105
  <FormBuilder.Header title={header!.title} label={header!.label} variant={header!.variant}>
76
- {actions}
106
+ {/* A stepper form prepends chevron Back/Next + a divider before the Submit. */}
107
+ {actions && <StepperActions>{actions}</StepperActions>}
77
108
  </FormBuilder.Header>
78
109
  )}
79
110
 
@@ -90,15 +121,13 @@ export function FormRenderer<T extends FieldValues = FieldValues>({
90
121
  badge={badge ?? header?.label}
91
122
  variant={header?.variant}
92
123
  summary={summary}
93
- // The drawer header sits outside the `<form>`, so re-supply the form/loading/mode context
94
- // a bare `FormBuilder.Submit` reads (on the page it gets these from the FormBuilder tree).
124
+ // The drawer header sits outside the `<form>`, so re-supply the form-id and loading
125
+ // context a bare `FormBuilder.Submit` reads (on the page it gets these from the tree).
95
126
  actions={
96
127
  actions ? (
97
- <ModeContext.Provider value={mode}>
98
- <LoadingContext.Provider value={!!loading}>
99
- <FormIdContext.Provider value={formId}>{actions}</FormIdContext.Provider>
100
- </LoadingContext.Provider>
101
- </ModeContext.Provider>
128
+ <LoadingContext.Provider value={!!loading}>
129
+ <FormIdContext.Provider value={formId}>{actions}</FormIdContext.Provider>
130
+ </LoadingContext.Provider>
102
131
  ) : undefined
103
132
  }
104
133
  onOpenInNewTab={onOpenInNewTab}
@@ -111,3 +140,15 @@ export function FormRenderer<T extends FieldValues = FieldValues>({
111
140
  // Page display: FormBuilder already placed `summary` as the grid's conclusion column.
112
141
  return inner;
113
142
  }
143
+
144
+ /**
145
+ * FormRenderer — see {@link FormRendererRoot}. The compound statics drive the display-only
146
+ * **detail-tabs** view: `FormRenderer.Sidebar` (the rail) + `FormRenderer.Sidebar.Item` (a tab) +
147
+ * `FormRenderer.Tab` (a `FormBuilder.Section` panel).
148
+ */
149
+ export const FormRenderer = Object.assign(FormRendererRoot, {
150
+ Sidebar: DetailSidebar,
151
+ Tab: DetailTab,
152
+ Grid: DetailGrid,
153
+ Row: DetailRow,
154
+ });
@@ -1,9 +1,11 @@
1
1
  export { FormRenderer } from "./form-renderer";
2
2
  export { FormDrawer } from "./FormDrawer";
3
3
  export type { FormDrawerProps } from "./FormDrawer";
4
+ export type { FormRendererProps, FormRendererDisplay, FieldDirection } from "./types";
4
5
  export type {
5
- FormRendererProps,
6
- FormRendererMode,
7
- FormRendererDisplay,
8
- FieldDirection,
9
- } from "./types";
6
+ DetailSidebarProps,
7
+ DetailSidebarItemProps,
8
+ DetailTabProps,
9
+ DetailRowProps,
10
+ DetailGridProps,
11
+ } from "./detail";
@@ -15,7 +15,6 @@ import type {
15
15
  * form's header / drawer action bar) where you place the Save.
16
16
  */
17
17
 
18
- export type FormRendererMode = "edit" | "view";
19
18
  export type FormRendererDisplay = "page" | "drawer";
20
19
  export type FieldDirection = "horizontal" | "vertical";
21
20
 
@@ -24,12 +23,12 @@ export interface FormRendererProps<T extends FieldValues = FieldValues> {
24
23
  children: ReactNode;
25
24
 
26
25
  // --- react-hook-form root (forwarded to FormBuilder) ---
27
- onSubmit: (values: T) => void | Promise<void>;
26
+ /** Submit handler. Optional — a display-only detail-tabs view (`FormRenderer.Sidebar`) has no form. */
27
+ onSubmit?: (values: T) => void | Promise<void>;
28
28
  onInvalid?: (errors: FieldErrors<T>) => void;
29
29
  resolver?: Resolver<T>;
30
30
  defaultValues?: DefaultValues<T>;
31
31
  values?: T;
32
- mode?: FormRendererMode;
33
32
  loading?: boolean;
34
33
  resetOnSuccess?: boolean;
35
34
  /** Row layout; defaults to vertical inside a drawer. */
@@ -239,10 +239,14 @@ const popoverStyles = cva(
239
239
  "bg-background-system-body-primary",
240
240
  "shadow-[0px_0px_18px_0px_rgba(0,0,0,0.75)]",
241
241
  ],
242
+ // Adopts the DropdownMenu surface (`menuContentStyles`): backdrop-blurred, borderless
243
+ // rounded-14 panel with a soft ambient shadow — keeping the original background color.
242
244
  PresentationStyle: [
243
- "border-border-presentation-global-primary",
245
+ "border-transparent",
246
+ "rounded-[14px]",
247
+ "backdrop-blur-[21px]",
244
248
  "bg-background-presentation-form-base",
245
- "shadow-[0px_0px_10px_0px_rgba(0,0,0,0.4),0px_4px_4px_0px_rgba(0,0,0,0.2)]",
249
+ "shadow-[0_0_32px_2px_rgba(0,0,0,0.20),0_0_48px_2px_rgba(0,0,0,0.05)]",
246
250
  ],
247
251
  },
248
252
  overlayBlur: {
@@ -24,6 +24,9 @@ export interface SearchableSelectOption {
24
24
  value: string;
25
25
  label: string;
26
26
  icon?: ReactNode;
27
+ /** Text used for client-side filtering. Defaults to `label` — set it to match on a subset
28
+ * (e.g. a country name only, when the label also shows a dial code). */
29
+ searchText?: string;
27
30
  }
28
31
 
29
32
  interface Props {
@@ -38,6 +41,7 @@ interface Props {
38
41
  theme?: Themes;
39
42
  dir?: string;
40
43
  className?: string;
44
+ inputClassName?: string;
41
45
  /** Transparent border/background so the trigger blends into a table cell. */
42
46
  onTable?: boolean;
43
47
 
@@ -107,6 +111,7 @@ export function SearchableSelect({
107
111
  theme,
108
112
  dir,
109
113
  className,
114
+ inputClassName,
110
115
  onTable,
111
116
  filterClientSide = true,
112
117
  onSearchChange,
@@ -155,7 +160,7 @@ export function SearchableSelect({
155
160
  if (!filterClientSide) return options;
156
161
  const q = search.trim().toLowerCase();
157
162
  if (!q) return options;
158
- return options.filter((o) => o.label.toLowerCase().includes(q));
163
+ return options.filter((o) => (o.searchText ?? o.label).toLowerCase().includes(q));
159
164
  }, [options, search, filterClientSide]);
160
165
 
161
166
  const selectedOption = options.find((o) => o.value === value) ?? null;
@@ -201,7 +206,7 @@ export function SearchableSelect({
201
206
  setOpen(true);
202
207
  }}
203
208
  onBlur={() => setSearching(false)}
204
- className={cn("min-w-[100px] flex-1", {
209
+ className={cn("min-w-[100px] flex-1", inputClassName, {
205
210
  "!h-[18px]": size === "XS",
206
211
  "!h-[22px]": size === "S",
207
212
  "!h-[24px]": size === "M",
@@ -31,32 +31,35 @@ export function FieldSection({
31
31
  <section
32
32
  {...props}
33
33
  data-theme={theme}
34
- className={cn(
35
- "grid py-[16px] px-[12px] w-full max-w-[1200px] min-w-[0px] ",
36
- direction === "vertical" && "grid-rows-[auto_1fr] gap-[12px]",
37
- direction === "horizontal" && "grid-cols-[350px_1fr] gap-[24px]",
38
- direction === "flexible" &&
39
- "grid-rows-[auto_1fr] gap-[12px] lg:grid-cols-[350px_1fr] lg:grid-rows-[1fr] lg:gap-[24px]",
40
- className,
41
- )}
34
+ className={cn("w-full max-w-[1200px] min-w-[0px] @container", className)}
42
35
  >
43
- {/* Fixed width section for labels */}
44
- <div className="flex flex-col gap-[12px]">
45
- {label && (
46
- <Label
47
- size={size}
48
- label={label}
49
- requiredLabel={requiredLabel}
50
- labelDirections={"horizontal"}
51
- />
36
+ <div
37
+ className={cn(
38
+ "grid py-[16px] px-[12px] w-full min-w-[0px]",
39
+ direction === "vertical" && "grid-rows-[auto_1fr] gap-[12px]",
40
+ direction === "horizontal" && "grid-cols-[350px_1fr] gap-[24px]",
41
+ direction === "flexible" &&
42
+ "grid-rows-[auto_1fr] gap-[12px] @md:grid-cols-[350px_1fr] @md:grid-rows-[1fr] @md:gap-[24px]",
52
43
  )}
44
+ >
45
+ {/* Fixed width section for labels */}
46
+ <div className="flex flex-col gap-[12px]">
47
+ {label && (
48
+ <Label
49
+ size={size}
50
+ label={label}
51
+ requiredLabel={requiredLabel}
52
+ labelDirections={"horizontal"}
53
+ />
54
+ )}
53
55
 
54
- {secondaryLabel && <Label size={size} secondaryLabel={secondaryLabel} />}
55
- {childrenUnderLabel}
56
- </div>
56
+ {secondaryLabel && <Label size={size} secondaryLabel={secondaryLabel} />}
57
+ {childrenUnderLabel}
58
+ </div>
57
59
 
58
- {/* Flexible section that takes up the remaining space */}
59
- <div className="grid grid-cols-1 place-items-end gap-[12px]">{children}</div>
60
+ {/* Flexible section that takes up the remaining space */}
61
+ <div className="grid grid-cols-1 place-items-end gap-[12px]">{children}</div>
62
+ </div>
60
63
  </section>
61
64
  );
62
65
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.4.2",
2
+ "version": "2.4.4",
3
3
  "generatedBy": "scripts/bin/generateRegistry",
4
4
  "items": [
5
5
  {