@invana/forms 0.0.7 → 0.0.12

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/dist/index.d.ts CHANGED
@@ -35,7 +35,13 @@ declare const FormDescription: React$1.ForwardRefExoticComponent<React$1.HTMLAtt
35
35
  declare const FormMessage: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLParagraphElement> & React$1.RefAttributes<HTMLParagraphElement>>;
36
36
 
37
37
  type LabelPosition = 'side' | 'top';
38
- type FieldType = 'text' | 'number' | 'boolean' | 'color' | 'select' | 'icon';
38
+ /**
39
+ * Field density. `sm` is the compact look used by dense panels (e.g. the
40
+ * modeller property editor) and is the default for backward compatibility.
41
+ * `md` renders full-size fields for primary, page-level forms.
42
+ */
43
+ type FieldSize = 'sm' | 'md';
44
+ type FieldType = 'text' | 'password' | 'textarea' | 'number' | 'boolean' | 'color' | 'select' | 'icon';
39
45
  type ColorPreset = {
40
46
  label: string;
41
47
  value: string;
@@ -58,6 +64,22 @@ type FieldConfig = {
58
64
  row?: string;
59
65
  presetColors?: ColorPreset[];
60
66
  defaultValue?: string;
67
+ /** Number of visible rows for `textarea` fields. */
68
+ rows?: number;
69
+ /**
70
+ * How many grid columns the field spans on `md+` screens. Defaults to `1`.
71
+ * The grid is two columns by default (see `ObjectField`'s `columns`), so
72
+ * `colSpan: 2` makes a full-width field (textarea, long URI, …). A span
73
+ * larger than the column count simply fills the row. Ignored below `md`,
74
+ * where every field stacks full width.
75
+ */
76
+ colSpan?: number;
77
+ /**
78
+ * Extra classes merged onto the field's grid cell. Escape hatch for
79
+ * per-field layout/spacing tweaks (custom width, ordering, margins, …)
80
+ * without adding a dedicated prop for every case.
81
+ */
82
+ className?: string;
61
83
  };
62
84
  type RowConfig = {
63
85
  id: string;
@@ -69,6 +91,14 @@ interface ObjectFieldProps {
69
91
  fields: FieldConfig[];
70
92
  rowConfig?: RowConfig[];
71
93
  labelPosition?: LabelPosition;
94
+ /** Field density. Defaults to `sm` (compact) for backward compatibility. */
95
+ size?: FieldSize;
96
+ /**
97
+ * Number of columns in the field grid on `md+` screens. Defaults to `2`.
98
+ * Increase it to build wider layouts that fields can span via `colSpan`.
99
+ * Below `md` the grid always collapses to a single column.
100
+ */
101
+ columns?: number;
72
102
  }
73
103
 
74
104
  type AnyValue = any;
@@ -87,10 +117,14 @@ interface BaseFieldProps {
87
117
  step?: number;
88
118
  presetColors?: ColorPreset[];
89
119
  defaultValue?: string;
120
+ rows?: number;
90
121
  className?: string;
91
122
  labelPosition?: LabelPosition;
123
+ size?: FieldSize;
92
124
  }
93
125
  declare const InputField: React$1.FC<BaseFieldProps>;
126
+ declare const PasswordField: React$1.FC<BaseFieldProps>;
127
+ declare const TextareaField: React$1.FC<BaseFieldProps>;
94
128
  declare const SelectField: React$1.FC<BaseFieldProps>;
95
129
  declare const BooleanField: React$1.FC<BaseFieldProps>;
96
130
  declare const ColorField: React$1.FC<BaseFieldProps>;
@@ -98,6 +132,8 @@ declare const NumberField: React$1.FC<BaseFieldProps>;
98
132
  declare const IconField: React$1.FC<BaseFieldProps>;
99
133
  declare const Field: {
100
134
  Input: React$1.FC<BaseFieldProps>;
135
+ Password: React$1.FC<BaseFieldProps>;
136
+ Textarea: React$1.FC<BaseFieldProps>;
101
137
  Boolean: React$1.FC<BaseFieldProps>;
102
138
  Color: React$1.FC<BaseFieldProps>;
103
139
  Number: React$1.FC<BaseFieldProps>;
@@ -108,6 +144,8 @@ declare const ObjectField: React$1.FC<ObjectFieldProps>;
108
144
  interface FormFieldExtensions {
109
145
  ObjectField: typeof ObjectField;
110
146
  Input: typeof InputField;
147
+ Password: typeof PasswordField;
148
+ Textarea: typeof TextareaField;
111
149
  Boolean: typeof BooleanField;
112
150
  Color: typeof ColorField;
113
151
  Number: typeof NumberField;
@@ -147,6 +185,18 @@ declare const IconInput: React$1.FC<IconInputProps>;
147
185
 
148
186
  declare const Input: React$1.ForwardRefExoticComponent<Omit<React$1.DetailedHTMLProps<React$1.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref"> & React$1.RefAttributes<HTMLInputElement>>;
149
187
 
188
+ type PasswordInputProps = Omit<React$1.ComponentProps<"input">, "type"> & {
189
+ /** Controls visibility in a controlled fashion. Omit for self-managed toggle. */
190
+ visible?: boolean;
191
+ onVisibleChange?: (visible: boolean) => void;
192
+ };
193
+ /**
194
+ * Password input with a built-in show/hide toggle. Wraps {@link Input} and
195
+ * overlays an eye / eye-off button that flips the field between `password`
196
+ * and `text`. Visibility is self-managed unless `visible` is supplied.
197
+ */
198
+ declare const PasswordInput: React$1.ForwardRefExoticComponent<Omit<PasswordInputProps, "ref"> & React$1.RefAttributes<HTMLInputElement>>;
199
+
150
200
  declare const Textarea: React$1.ForwardRefExoticComponent<Omit<React$1.DetailedHTMLProps<React$1.TextareaHTMLAttributes<HTMLTextAreaElement>, HTMLTextAreaElement>, "ref"> & React$1.RefAttributes<HTMLTextAreaElement>>;
151
201
 
152
202
  declare const Select: React$1.FC<SelectPrimitive.SelectProps>;
@@ -202,4 +252,4 @@ declare function InputGroupText({ className, ...props }: React$1.ComponentProps<
202
252
  declare function InputGroupInput({ className, ...props }: React$1.ComponentProps<"input">): react_jsx_runtime.JSX.Element;
203
253
  declare function InputGroupTextarea({ className, ...props }: React$1.ComponentProps<"textarea">): react_jsx_runtime.JSX.Element;
204
254
 
205
- export { BooleanField, Checkbox, ColorField, type ColorPreset, ColorSwatches, Field, type FieldConfig, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, type FieldType, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, IconField, IconInput, Input, InputField, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, Label, type LabelPosition, NumberField, ObjectField, type ObjectFieldProps, RadioGroup, RadioGroupItem, type RowConfig, Select, SelectContent, SelectField, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Slider, SliderNumber, Switch, Textarea, useFormField };
255
+ export { BooleanField, Checkbox, ColorField, type ColorPreset, ColorSwatches, Field, type FieldConfig, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, type FieldSize, FieldTitle, type FieldType, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, IconField, IconInput, Input, InputField, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, Label, type LabelPosition, NumberField, ObjectField, type ObjectFieldProps, PasswordField, PasswordInput, type PasswordInputProps, RadioGroup, RadioGroupItem, type RowConfig, Select, SelectContent, SelectField, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Slider, SliderNumber, Switch, Textarea, TextareaField, useFormField };
package/dist/index.js CHANGED
@@ -6,9 +6,9 @@ import { useFormContext, Controller, FormProvider } from 'react-hook-form';
6
6
  import * as LabelPrimitive from '@radix-ui/react-label';
7
7
  import { cva } from 'class-variance-authority';
8
8
  import { jsx, jsxs } from 'react/jsx-runtime';
9
+ import { EyeOff, Eye, ChevronDown, ChevronUp, Check, Circle } from 'lucide-react';
9
10
  import * as SwitchPrimitives from '@radix-ui/react-switch';
10
11
  import * as SelectPrimitive from '@radix-ui/react-select';
11
- import { ChevronDown, ChevronUp, Check, Circle } from 'lucide-react';
12
12
  import * as SliderPrimitive from '@radix-ui/react-slider';
13
13
  import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
14
14
  import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
@@ -126,7 +126,7 @@ var Input = React2.forwardRef(
126
126
  {
127
127
  type,
128
128
  className: cn(
129
- "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
129
+ "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
130
130
  className
131
131
  ),
132
132
  ref,
@@ -136,6 +136,58 @@ var Input = React2.forwardRef(
136
136
  }
137
137
  );
138
138
  Input.displayName = "Input";
139
+ var PasswordInput = React2.forwardRef(
140
+ ({ className, visible, onVisibleChange, disabled, ...props }, ref) => {
141
+ const [internalVisible, setInternalVisible] = React2.useState(false);
142
+ const isControlled = visible !== void 0;
143
+ const show = isControlled ? visible : internalVisible;
144
+ const toggle = () => {
145
+ const next = !show;
146
+ if (!isControlled) setInternalVisible(next);
147
+ onVisibleChange?.(next);
148
+ };
149
+ return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
150
+ /* @__PURE__ */ jsx(
151
+ Input,
152
+ {
153
+ type: show ? "text" : "password",
154
+ className: cn("pr-10", className),
155
+ disabled,
156
+ ref,
157
+ ...props
158
+ }
159
+ ),
160
+ /* @__PURE__ */ jsx(
161
+ "button",
162
+ {
163
+ type: "button",
164
+ onClick: toggle,
165
+ disabled,
166
+ tabIndex: -1,
167
+ "aria-label": show ? "Hide password" : "Show password",
168
+ "aria-pressed": show,
169
+ className: "absolute inset-y-0 right-0 flex items-center justify-center px-3 text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
170
+ children: show ? /* @__PURE__ */ jsx(EyeOff, { className: "size-4", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(Eye, { className: "size-4", "aria-hidden": "true" })
171
+ }
172
+ )
173
+ ] });
174
+ }
175
+ );
176
+ PasswordInput.displayName = "PasswordInput";
177
+ var Textarea = React2.forwardRef(({ className, ...props }, ref) => {
178
+ return /* @__PURE__ */ jsx(
179
+ "textarea",
180
+ {
181
+ className: cn(
182
+ "flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
183
+ className
184
+ ),
185
+ ref,
186
+ ...props
187
+ }
188
+ );
189
+ });
190
+ Textarea.displayName = "Textarea";
139
191
  var Switch = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
140
192
  SwitchPrimitives.Root,
141
193
  {
@@ -409,6 +461,10 @@ var IconInput = ({ value, onChange }) => {
409
461
  )
410
462
  ] });
411
463
  };
464
+ var SIZE = {
465
+ sm: { input: "h-8 text-sm", select: "h-8", label: "text-xs", desc: "text-xs" },
466
+ md: { input: "", select: "", label: "", desc: "" }
467
+ };
412
468
  function itemClasses(labelPosition, className) {
413
469
  return cn(
414
470
  labelPosition === "side" && "grid grid-cols-3 items-center gap-2",
@@ -426,21 +482,74 @@ var InputField = ({
426
482
  value,
427
483
  onChange,
428
484
  labelPosition = "side",
485
+ size = "sm",
429
486
  className
430
487
  }) => /* @__PURE__ */ jsxs(FormItem, { className: itemClasses(labelPosition, className), children: [
431
- label && /* @__PURE__ */ jsx(FormLabel, { className: "text-xs", children: label }),
488
+ label && /* @__PURE__ */ jsx(FormLabel, { className: SIZE[size].label, children: label }),
432
489
  /* @__PURE__ */ jsxs("div", { className: inputWrapper(labelPosition), children: [
433
490
  /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
434
491
  Input,
435
492
  {
436
- className: "h-8 text-sm",
493
+ className: SIZE[size].input,
494
+ placeholder,
495
+ value: value ?? "",
496
+ onChange: (e) => onChange?.(e.target.value)
497
+ }
498
+ ) }),
499
+ description && /* @__PURE__ */ jsx(FormDescription, { className: SIZE[size].desc, children: description }),
500
+ /* @__PURE__ */ jsx(FormMessage, { className: SIZE[size].desc })
501
+ ] })
502
+ ] });
503
+ var PasswordField = ({
504
+ label,
505
+ description,
506
+ placeholder,
507
+ value,
508
+ onChange,
509
+ labelPosition = "side",
510
+ size = "sm",
511
+ className
512
+ }) => /* @__PURE__ */ jsxs(FormItem, { className: itemClasses(labelPosition, className), children: [
513
+ label && /* @__PURE__ */ jsx(FormLabel, { className: SIZE[size].label, children: label }),
514
+ /* @__PURE__ */ jsxs("div", { className: inputWrapper(labelPosition), children: [
515
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
516
+ PasswordInput,
517
+ {
518
+ className: SIZE[size].input,
519
+ placeholder,
520
+ value: value ?? "",
521
+ onChange: (e) => onChange?.(e.target.value)
522
+ }
523
+ ) }),
524
+ description && /* @__PURE__ */ jsx(FormDescription, { className: SIZE[size].desc, children: description }),
525
+ /* @__PURE__ */ jsx(FormMessage, { className: SIZE[size].desc })
526
+ ] })
527
+ ] });
528
+ var TextareaField = ({
529
+ label,
530
+ description,
531
+ placeholder,
532
+ value,
533
+ onChange,
534
+ rows,
535
+ labelPosition = "side",
536
+ size = "sm",
537
+ className
538
+ }) => /* @__PURE__ */ jsxs(FormItem, { className: itemClasses(labelPosition, className), children: [
539
+ label && /* @__PURE__ */ jsx(FormLabel, { className: SIZE[size].label, children: label }),
540
+ /* @__PURE__ */ jsxs("div", { className: inputWrapper(labelPosition), children: [
541
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
542
+ Textarea,
543
+ {
544
+ className: size === "sm" ? "text-sm" : void 0,
545
+ rows,
437
546
  placeholder,
438
547
  value: value ?? "",
439
548
  onChange: (e) => onChange?.(e.target.value)
440
549
  }
441
550
  ) }),
442
- description && /* @__PURE__ */ jsx(FormDescription, { className: "text-xs", children: description }),
443
- /* @__PURE__ */ jsx(FormMessage, { className: "text-xs" })
551
+ description && /* @__PURE__ */ jsx(FormDescription, { className: SIZE[size].desc, children: description }),
552
+ /* @__PURE__ */ jsx(FormMessage, { className: SIZE[size].desc })
444
553
  ] })
445
554
  ] });
446
555
  var SelectField = ({
@@ -451,16 +560,17 @@ var SelectField = ({
451
560
  onChange,
452
561
  placeholder = "Select type",
453
562
  labelPosition = "side",
563
+ size = "sm",
454
564
  className
455
565
  }) => /* @__PURE__ */ jsxs(FormItem, { className: itemClasses(labelPosition, className), children: [
456
- label && /* @__PURE__ */ jsx(FormLabel, { className: "text-xs", children: label }),
566
+ label && /* @__PURE__ */ jsx(FormLabel, { className: SIZE[size].label, children: label }),
457
567
  /* @__PURE__ */ jsxs("div", { className: inputWrapper(labelPosition), children: [
458
568
  /* @__PURE__ */ jsxs(Select, { value: value ?? "", onValueChange: onChange, children: [
459
- /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(SelectTrigger, { className: "h-8", children: /* @__PURE__ */ jsx(SelectValue, { placeholder }) }) }),
569
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(SelectTrigger, { className: SIZE[size].select, children: /* @__PURE__ */ jsx(SelectValue, { placeholder }) }) }),
460
570
  /* @__PURE__ */ jsx(SelectContent, { children: options.map((o) => /* @__PURE__ */ jsx(SelectItem, { value: o.value, children: o.label }, o.value)) })
461
571
  ] }),
462
- description && /* @__PURE__ */ jsx(FormDescription, { className: "text-xs", children: description }),
463
- /* @__PURE__ */ jsx(FormMessage, { className: "text-xs" })
572
+ description && /* @__PURE__ */ jsx(FormDescription, { className: SIZE[size].desc, children: description }),
573
+ /* @__PURE__ */ jsx(FormMessage, { className: SIZE[size].desc })
464
574
  ] })
465
575
  ] });
466
576
  var BooleanField = ({
@@ -468,22 +578,23 @@ var BooleanField = ({
468
578
  description,
469
579
  value,
470
580
  onChange,
471
- labelPosition = "side"
581
+ labelPosition = "side",
582
+ size = "sm"
472
583
  }) => {
473
584
  if (labelPosition === "side") {
474
585
  return /* @__PURE__ */ jsxs(FormItem, { className: "flex items-center justify-between rounded-md border p-2", children: [
475
586
  /* @__PURE__ */ jsxs("div", { children: [
476
- label && /* @__PURE__ */ jsx(FormLabel, { className: "text-xs", children: label }),
477
- description && /* @__PURE__ */ jsx(FormDescription, { className: "text-xs", children: description })
587
+ label && /* @__PURE__ */ jsx(FormLabel, { className: SIZE[size].label, children: label }),
588
+ description && /* @__PURE__ */ jsx(FormDescription, { className: SIZE[size].desc, children: description })
478
589
  ] }),
479
590
  /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(Switch, { checked: !!value, onCheckedChange: onChange }) })
480
591
  ] });
481
592
  }
482
593
  return /* @__PURE__ */ jsxs(FormItem, { className: "space-y-2", children: [
483
- label && /* @__PURE__ */ jsx(FormLabel, { className: "text-xs", children: label }),
594
+ label && /* @__PURE__ */ jsx(FormLabel, { className: SIZE[size].label, children: label }),
484
595
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between rounded-md border p-2", children: [
485
596
  /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(Switch, { checked: !!value, onCheckedChange: onChange }) }),
486
- description && /* @__PURE__ */ jsx(FormDescription, { className: "ml-2 text-xs", children: description })
597
+ description && /* @__PURE__ */ jsx(FormDescription, { className: cn("ml-2", SIZE[size].desc), children: description })
487
598
  ] })
488
599
  ] });
489
600
  };
@@ -495,9 +606,10 @@ var ColorField = ({
495
606
  presetColors,
496
607
  defaultValue,
497
608
  labelPosition = "side",
609
+ size = "sm",
498
610
  className
499
611
  }) => /* @__PURE__ */ jsxs(FormItem, { className: itemClasses(labelPosition, className), children: [
500
- label && /* @__PURE__ */ jsx(FormLabel, { className: "text-xs", children: label }),
612
+ label && /* @__PURE__ */ jsx(FormLabel, { className: SIZE[size].label, children: label }),
501
613
  /* @__PURE__ */ jsxs("div", { className: inputWrapper(labelPosition), children: [
502
614
  /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
503
615
  ColorSwatches,
@@ -508,8 +620,8 @@ var ColorField = ({
508
620
  defaultValue
509
621
  }
510
622
  ) }),
511
- description && /* @__PURE__ */ jsx(FormDescription, { className: "text-xs", children: description }),
512
- /* @__PURE__ */ jsx(FormMessage, { className: "text-xs" })
623
+ description && /* @__PURE__ */ jsx(FormDescription, { className: SIZE[size].desc, children: description }),
624
+ /* @__PURE__ */ jsx(FormMessage, { className: SIZE[size].desc })
513
625
  ] })
514
626
  ] });
515
627
  var NumberField = ({
@@ -521,9 +633,10 @@ var NumberField = ({
521
633
  max,
522
634
  step,
523
635
  labelPosition = "side",
636
+ size = "sm",
524
637
  className
525
638
  }) => /* @__PURE__ */ jsxs(FormItem, { className: itemClasses(labelPosition, className), children: [
526
- label && /* @__PURE__ */ jsx(FormLabel, { className: "text-xs", children: label }),
639
+ label && /* @__PURE__ */ jsx(FormLabel, { className: SIZE[size].label, children: label }),
527
640
  /* @__PURE__ */ jsxs("div", { className: inputWrapper(labelPosition), children: [
528
641
  /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
529
642
  SliderNumber,
@@ -535,8 +648,8 @@ var NumberField = ({
535
648
  step
536
649
  }
537
650
  ) }),
538
- description && /* @__PURE__ */ jsx(FormDescription, { className: "text-xs", children: description }),
539
- /* @__PURE__ */ jsx(FormMessage, { className: "text-xs" })
651
+ description && /* @__PURE__ */ jsx(FormDescription, { className: SIZE[size].desc, children: description }),
652
+ /* @__PURE__ */ jsx(FormMessage, { className: SIZE[size].desc })
540
653
  ] })
541
654
  ] });
542
655
  var IconField = ({
@@ -545,17 +658,20 @@ var IconField = ({
545
658
  value,
546
659
  onChange,
547
660
  labelPosition = "side",
661
+ size = "sm",
548
662
  className
549
663
  }) => /* @__PURE__ */ jsxs(FormItem, { className: itemClasses(labelPosition, className), children: [
550
- label && /* @__PURE__ */ jsx(FormLabel, { className: "text-xs", children: label }),
664
+ label && /* @__PURE__ */ jsx(FormLabel, { className: SIZE[size].label, children: label }),
551
665
  /* @__PURE__ */ jsxs("div", { className: inputWrapper(labelPosition), children: [
552
666
  /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(IconInput, { value, onChange }) }),
553
- description && /* @__PURE__ */ jsx(FormDescription, { className: "text-xs", children: description }),
554
- /* @__PURE__ */ jsx(FormMessage, { className: "text-xs" })
667
+ description && /* @__PURE__ */ jsx(FormDescription, { className: SIZE[size].desc, children: description }),
668
+ /* @__PURE__ */ jsx(FormMessage, { className: SIZE[size].desc })
555
669
  ] })
556
670
  ] });
557
671
  var Field = {
558
672
  Input: InputField,
673
+ Password: PasswordField,
674
+ Textarea: TextareaField,
559
675
  Boolean: BooleanField,
560
676
  Color: ColorField,
561
677
  Number: NumberField,
@@ -565,12 +681,7 @@ var Field = {
565
681
  function humanize(name) {
566
682
  return name.replace(/([A-Z])/g, " $1").replace(/^./, (c) => c.toUpperCase()).trim();
567
683
  }
568
- function chunk(arr, size) {
569
- const out = [];
570
- for (let i = 0; i < arr.length; i += size) out.push(arr.slice(i, i + size));
571
- return out;
572
- }
573
- function renderField(field, parentName, control, labelPosition) {
684
+ function renderField(field, parentName, control, labelPosition, size) {
574
685
  return /* @__PURE__ */ jsx(
575
686
  FormField,
576
687
  {
@@ -587,11 +698,21 @@ function renderField(field, parentName, control, labelPosition) {
587
698
  step: field.step,
588
699
  presetColors: field.presetColors,
589
700
  defaultValue: field.defaultValue,
701
+ rows: field.rows,
590
702
  labelPosition,
703
+ size,
591
704
  value: rhf.value,
592
705
  onChange: rhf.onChange
593
706
  };
594
707
  switch (field.type) {
708
+ case "password":
709
+ return /* @__PURE__ */ jsx(
710
+ PasswordField,
711
+ {
712
+ ...common,
713
+ placeholder: field.placeholder ?? `Enter ${field.name}`
714
+ }
715
+ );
595
716
  case "boolean":
596
717
  return /* @__PURE__ */ jsx(BooleanField, { ...common });
597
718
  case "color":
@@ -602,6 +723,14 @@ function renderField(field, parentName, control, labelPosition) {
602
723
  return /* @__PURE__ */ jsx(SelectField, { ...common });
603
724
  case "icon":
604
725
  return /* @__PURE__ */ jsx(IconField, { ...common });
726
+ case "textarea":
727
+ return /* @__PURE__ */ jsx(
728
+ TextareaField,
729
+ {
730
+ ...common,
731
+ placeholder: field.placeholder ?? `Enter ${field.name}`
732
+ }
733
+ );
605
734
  case "text":
606
735
  default:
607
736
  return /* @__PURE__ */ jsx(
@@ -617,9 +746,38 @@ function renderField(field, parentName, control, labelPosition) {
617
746
  field.name
618
747
  );
619
748
  }
620
- function renderRows(fields, rowConfig, parentName, control, labelPosition) {
749
+ function renderGrid(fields, parentName, control, labelPosition, size, columns, key) {
750
+ const customCols = columns !== 2;
751
+ return /* @__PURE__ */ jsx(
752
+ "div",
753
+ {
754
+ className: cn(
755
+ "grid grid-cols-1 gap-4",
756
+ customCols ? "md:[grid-template-columns:repeat(var(--ff-cols),minmax(0,1fr))]" : "md:grid-cols-2"
757
+ ),
758
+ style: customCols ? { "--ff-cols": columns } : void 0,
759
+ children: fields.map((f) => {
760
+ const span = f.colSpan && f.colSpan > 1 ? f.colSpan : void 0;
761
+ return /* @__PURE__ */ jsx(
762
+ "div",
763
+ {
764
+ className: cn(
765
+ span && "md:[grid-column:span_var(--ff-span)/span_var(--ff-span)]",
766
+ f.className
767
+ ),
768
+ style: span ? { "--ff-span": span } : void 0,
769
+ children: renderField(f, parentName, control, labelPosition, size)
770
+ },
771
+ f.name
772
+ );
773
+ })
774
+ },
775
+ key
776
+ );
777
+ }
778
+ function renderRows(fields, rowConfig, parentName, control, labelPosition, size, columns) {
621
779
  if (!rowConfig || rowConfig.length === 0) {
622
- return /* @__PURE__ */ jsx("div", { className: "grid gap-4", children: chunk(fields, 2).map((row, i) => /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: row.map((f) => renderField(f, parentName, control, labelPosition)) }, i)) });
780
+ return renderGrid(fields, parentName, control, labelPosition, size, columns);
623
781
  }
624
782
  const used = new Set(rowConfig.flatMap((r) => r.fields));
625
783
  const unassigned = fields.filter((f) => !used.has(f.name));
@@ -627,16 +785,26 @@ function renderRows(fields, rowConfig, parentName, control, labelPosition) {
627
785
  return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
628
786
  rowConfig.map((row) => {
629
787
  const rowFields = row.fields.map((n) => byName.get(n)).filter((f) => !!f);
630
- return chunk(rowFields, 2).map((cnk, idx) => /* @__PURE__ */ jsx(
631
- "div",
632
- {
633
- className: "grid grid-cols-1 gap-4 md:grid-cols-2",
634
- children: cnk.map((f) => renderField(f, parentName, control, labelPosition))
635
- },
636
- `${row.id}-${idx}`
637
- ));
788
+ if (rowFields.length === 0) return null;
789
+ return renderGrid(
790
+ rowFields,
791
+ parentName,
792
+ control,
793
+ labelPosition,
794
+ size,
795
+ columns,
796
+ row.id
797
+ );
638
798
  }),
639
- unassigned.length > 0 && /* @__PURE__ */ jsx("div", { className: "grid gap-4", children: chunk(unassigned, 2).map((row, i) => /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: row.map((f) => renderField(f, parentName, control, labelPosition)) }, `u-${i}`)) })
799
+ unassigned.length > 0 && renderGrid(
800
+ unassigned,
801
+ parentName,
802
+ control,
803
+ labelPosition,
804
+ size,
805
+ columns,
806
+ "_unassigned"
807
+ )
640
808
  ] });
641
809
  }
642
810
  var ObjectField = ({
@@ -644,7 +812,9 @@ var ObjectField = ({
644
812
  name,
645
813
  fields,
646
814
  rowConfig,
647
- labelPosition = "side"
815
+ labelPosition = "side",
816
+ size = "sm",
817
+ columns = 2
648
818
  }) => {
649
819
  const grouped = fields.reduce((acc, f) => {
650
820
  const key = f.group ?? "_ungrouped";
@@ -655,7 +825,15 @@ var ObjectField = ({
655
825
  delete grouped["_ungrouped"];
656
826
  const groupedEntries = Object.entries(grouped);
657
827
  return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
658
- ungrouped.length > 0 && /* @__PURE__ */ jsx("div", { className: "space-y-4", children: renderRows(ungrouped, rowConfig, name, control, labelPosition) }),
828
+ ungrouped.length > 0 && /* @__PURE__ */ jsx("div", { className: "space-y-4", children: renderRows(
829
+ ungrouped,
830
+ rowConfig,
831
+ name,
832
+ control,
833
+ labelPosition,
834
+ size,
835
+ columns
836
+ ) }),
659
837
  groupedEntries.length > 0 && /* @__PURE__ */ jsx(
660
838
  Accordion,
661
839
  {
@@ -667,7 +845,15 @@ var ObjectField = ({
667
845
  humanize(group),
668
846
  " Settings"
669
847
  ] }),
670
- /* @__PURE__ */ jsx(AccordionContent, { className: "px-3 pb-3", children: /* @__PURE__ */ jsx("div", { className: "space-y-4", children: renderRows(gFields, rowConfig, name, control, labelPosition) }) })
848
+ /* @__PURE__ */ jsx(AccordionContent, { className: "px-3 pb-3", children: /* @__PURE__ */ jsx("div", { className: "space-y-4", children: renderRows(
849
+ gFields,
850
+ rowConfig,
851
+ name,
852
+ control,
853
+ labelPosition,
854
+ size,
855
+ columns
856
+ ) }) })
671
857
  ] }, group))
672
858
  }
673
859
  )
@@ -676,26 +862,14 @@ var ObjectField = ({
676
862
  var FormField2 = Object.assign(FormField, {
677
863
  ObjectField,
678
864
  Input: InputField,
865
+ Password: PasswordField,
866
+ Textarea: TextareaField,
679
867
  Boolean: BooleanField,
680
868
  Color: ColorField,
681
869
  Number: NumberField,
682
870
  Select: SelectField,
683
871
  Icon: IconField
684
872
  });
685
- var Textarea = React2.forwardRef(({ className, ...props }, ref) => {
686
- return /* @__PURE__ */ jsx(
687
- "textarea",
688
- {
689
- className: cn(
690
- "flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
691
- className
692
- ),
693
- ref,
694
- ...props
695
- }
696
- );
697
- });
698
- Textarea.displayName = "Textarea";
699
873
  var Checkbox = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
700
874
  CheckboxPrimitive.Root,
701
875
  {
@@ -1074,6 +1248,6 @@ function InputGroupTextarea({
1074
1248
  );
1075
1249
  }
1076
1250
 
1077
- export { BooleanField, Checkbox, ColorField, ColorSwatches, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, Form, FormControl, FormDescription, FormField2 as FormField, FormItem, FormLabel, FormMessage, IconField, IconInput, Input, InputField, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, Label, NumberField, ObjectField, RadioGroup, RadioGroupItem, Select, SelectContent, SelectField, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Slider, SliderNumber, Switch, Textarea, useFormField };
1251
+ export { BooleanField, Checkbox, ColorField, ColorSwatches, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, Form, FormControl, FormDescription, FormField2 as FormField, FormItem, FormLabel, FormMessage, IconField, IconInput, Input, InputField, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, Label, NumberField, ObjectField, PasswordField, PasswordInput, RadioGroup, RadioGroupItem, Select, SelectContent, SelectField, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Slider, SliderNumber, Switch, Textarea, TextareaField, useFormField };
1078
1252
  //# sourceMappingURL=index.js.map
1079
1253
  //# sourceMappingURL=index.js.map