@invana/forms 0.0.31 → 0.0.33

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.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var ui = require('@invana/ui');
4
3
  var React2 = require('react');
4
+ var ui = require('@invana/ui');
5
5
  var reactSlot = require('@radix-ui/react-slot');
6
6
  var reactHookForm = require('react-hook-form');
7
7
  var LabelPrimitive = require('@radix-ui/react-label');
@@ -94,7 +94,7 @@ var FormLabel = React2__namespace.forwardRef(({ className, ...props }, ref) => {
94
94
  Label,
95
95
  {
96
96
  ref,
97
- className: ui.cn(error && "text-destructive", className),
97
+ className: ui.cn(className, error && "text-destructive"),
98
98
  htmlFor: formItemId,
99
99
  ...props
100
100
  }
@@ -153,8 +153,9 @@ var Input = React2__namespace.forwardRef(
153
153
  {
154
154
  type,
155
155
  className: ui.cn(
156
- inputSize === "sm" ? "h-[26px] px-2 py-0" : "h-10 px-3 py-2",
157
- "flex w-full rounded-control border border-input bg-background text-base ring-offset-background file:border-0 file:bg-transparent 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",
156
+ "py-0",
157
+ inputSize === "sm" ? "h-control-sm px-2" : inputSize === "lg" ? "h-control-lg px-3" : "h-control-md px-2.5",
158
+ "flex w-full rounded-control border border-input bg-background text-base ring-offset-background file:border-0 file:bg-transparent 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 aria-invalid:border-destructive",
158
159
  className
159
160
  ),
160
161
  ref,
@@ -164,6 +165,176 @@ var Input = React2__namespace.forwardRef(
164
165
  }
165
166
  );
166
167
  Input.displayName = "Input";
168
+ var Textarea = React2__namespace.forwardRef(({ className, inputSize = "default", ...props }, ref) => {
169
+ return /* @__PURE__ */ jsxRuntime.jsx(
170
+ "textarea",
171
+ {
172
+ className: ui.cn(
173
+ inputSize === "sm" ? "min-h-[52px] px-2 py-1" : "min-h-[80px] px-3 py-2",
174
+ "flex w-full rounded-control border border-input bg-background 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",
175
+ className
176
+ ),
177
+ ref,
178
+ ...props
179
+ }
180
+ );
181
+ });
182
+ Textarea.displayName = "Textarea";
183
+ var InputGroupControl = React2__namespace.createContext({});
184
+ function InputGroup({
185
+ className,
186
+ id,
187
+ "aria-describedby": describedBy,
188
+ "aria-invalid": invalid,
189
+ ...props
190
+ }) {
191
+ const wiring = React2__namespace.useMemo(
192
+ () => ({ id, "aria-describedby": describedBy, "aria-invalid": invalid }),
193
+ [id, describedBy, invalid]
194
+ );
195
+ return /* @__PURE__ */ jsxRuntime.jsx(InputGroupControl.Provider, { value: wiring, children: /* @__PURE__ */ jsxRuntime.jsx(
196
+ "div",
197
+ {
198
+ "data-slot": "input-group",
199
+ role: "group",
200
+ className: ui.cn(
201
+ "group/input-group border-input dark:bg-input/30 shadow-xs relative flex w-full items-center rounded-control border outline-none transition-[color,box-shadow]",
202
+ "h-control-md has-[>textarea]:h-auto",
203
+ // Variants based on alignment.
204
+ "has-[>[data-align=inline-start]]:[&>input]:pl-2",
205
+ "has-[>[data-align=inline-end]]:[&>input]:pr-2",
206
+ "has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3",
207
+ "has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3",
208
+ // Focus state.
209
+ "has-[[data-slot=input-group-control]:focus-visible]:ring-ring has-[[data-slot=input-group-control]:focus-visible]:ring-1",
210
+ // Error state.
211
+ "has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40",
212
+ className
213
+ ),
214
+ ...props
215
+ }
216
+ ) });
217
+ }
218
+ var inputGroupAddonVariants = classVarianceAuthority.cva(
219
+ "text-muted-foreground flex h-auto cursor-text select-none items-center justify-center gap-2 py-1.5 font-medium group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-control [&>svg:not([class*='size-'])]:size-4",
220
+ {
221
+ variants: {
222
+ align: {
223
+ "inline-start": "order-first pl-3 has-[>button]:ml-[-0.45rem] has-[>kbd]:ml-[-0.35rem]",
224
+ "inline-end": "order-last pr-3 has-[>button]:mr-[-0.4rem] has-[>kbd]:mr-[-0.35rem]",
225
+ "block-start": "[.border-b]:pb-3 order-first w-full justify-start px-3 pt-3 group-has-[>input]/input-group:pt-2.5",
226
+ "block-end": "[.border-t]:pt-3 order-last w-full justify-start px-3 pb-3 group-has-[>input]/input-group:pb-2.5"
227
+ }
228
+ },
229
+ defaultVariants: {
230
+ align: "inline-start"
231
+ }
232
+ }
233
+ );
234
+ function InputGroupAddon({
235
+ className,
236
+ align = "inline-start",
237
+ ...props
238
+ }) {
239
+ return /* @__PURE__ */ jsxRuntime.jsx(
240
+ "div",
241
+ {
242
+ role: "group",
243
+ "data-slot": "input-group-addon",
244
+ "data-align": align,
245
+ className: ui.cn(inputGroupAddonVariants({ align }), className),
246
+ onClick: (e) => {
247
+ if (e.target.closest("button")) {
248
+ return;
249
+ }
250
+ e.currentTarget.parentElement?.querySelector("input")?.focus();
251
+ },
252
+ ...props
253
+ }
254
+ );
255
+ }
256
+ var inputGroupButtonVariants = classVarianceAuthority.cva(
257
+ "flex items-center gap-2 shadow-none",
258
+ {
259
+ variants: {
260
+ size: {
261
+ xs: "h-control-xs gap-1 rounded-control px-2 has-[>svg]:px-2 [&>svg:not([class*='size-'])]:size-3.5",
262
+ sm: "h-control-sm gap-1.5 rounded-control px-2.5 has-[>svg]:px-2.5",
263
+ "icon-xs": "size-control-xs rounded-control p-0 has-[>svg]:p-0",
264
+ "icon-sm": "size-control-sm p-0 has-[>svg]:p-0"
265
+ }
266
+ },
267
+ defaultVariants: {
268
+ size: "xs"
269
+ }
270
+ }
271
+ );
272
+ function InputGroupButton({
273
+ className,
274
+ type = "button",
275
+ variant = "ghost",
276
+ size = "xs",
277
+ ...props
278
+ }) {
279
+ return /* @__PURE__ */ jsxRuntime.jsx(
280
+ ui.Button,
281
+ {
282
+ type,
283
+ "data-size": size,
284
+ variant,
285
+ className: ui.cn(inputGroupButtonVariants({ size }), className),
286
+ ...props
287
+ }
288
+ );
289
+ }
290
+ function InputGroupText({ className, ...props }) {
291
+ return /* @__PURE__ */ jsxRuntime.jsx(
292
+ "span",
293
+ {
294
+ className: ui.cn(
295
+ "text-muted-foreground flex items-center gap-2 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none",
296
+ className
297
+ ),
298
+ ...props
299
+ }
300
+ );
301
+ }
302
+ function InputGroupInput({
303
+ className,
304
+ ...props
305
+ }) {
306
+ const wiring = React2__namespace.useContext(InputGroupControl);
307
+ return /* @__PURE__ */ jsxRuntime.jsx(
308
+ Input,
309
+ {
310
+ ...wiring,
311
+ "data-slot": "input-group-control",
312
+ className: ui.cn(
313
+ "flex-1 rounded-none border-0 bg-transparent shadow-none focus-visible:ring-0 dark:bg-transparent",
314
+ className
315
+ ),
316
+ ...props
317
+ }
318
+ );
319
+ }
320
+ function InputGroupTextarea({
321
+ className,
322
+ ...props
323
+ }) {
324
+ const wiring = React2__namespace.useContext(InputGroupControl);
325
+ return /* @__PURE__ */ jsxRuntime.jsx(
326
+ Textarea,
327
+ {
328
+ ...wiring,
329
+ "data-slot": "input-group-control",
330
+ className: ui.cn(
331
+ "flex-1 resize-none rounded-none border-0 bg-transparent py-3 shadow-none focus-visible:ring-0 dark:bg-transparent",
332
+ className
333
+ ),
334
+ ...props
335
+ }
336
+ );
337
+ }
167
338
  var PasswordInput = React2__namespace.forwardRef(
168
339
  ({ className, visible, onVisibleChange, disabled, ...props }, ref) => {
169
340
  const [internalVisible, setInternalVisible] = React2__namespace.useState(false);
@@ -202,21 +373,6 @@ var PasswordInput = React2__namespace.forwardRef(
202
373
  }
203
374
  );
204
375
  PasswordInput.displayName = "PasswordInput";
205
- var Textarea = React2__namespace.forwardRef(({ className, inputSize = "default", ...props }, ref) => {
206
- return /* @__PURE__ */ jsxRuntime.jsx(
207
- "textarea",
208
- {
209
- className: ui.cn(
210
- inputSize === "sm" ? "min-h-[52px] px-2 py-1" : "min-h-[80px] px-3 py-2",
211
- "flex w-full rounded-control border border-input bg-background 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",
212
- className
213
- ),
214
- ref,
215
- ...props
216
- }
217
- );
218
- });
219
- Textarea.displayName = "Textarea";
220
376
  var Switch = React2__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
221
377
  SwitchPrimitives__namespace.Root,
222
378
  {
@@ -290,8 +446,9 @@ var SelectTrigger = React2__namespace.forwardRef(({ className, children, trigger
290
446
  {
291
447
  ref,
292
448
  className: ui.cn(
293
- triggerSize === "sm" ? "h-[26px] px-2 py-0" : "h-9 px-3 py-2",
294
- "flex w-full items-center justify-between whitespace-nowrap rounded-control border border-input bg-transparent shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
449
+ "py-0",
450
+ triggerSize === "sm" ? "h-control-sm px-2" : triggerSize === "lg" ? "h-control-lg px-3" : "h-control-md px-2.5",
451
+ "flex w-full items-center justify-between whitespace-nowrap rounded-control border border-input bg-transparent shadow-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
295
452
  className
296
453
  ),
297
454
  ...props,
@@ -333,7 +490,7 @@ var SelectContent = React2__namespace.forwardRef(({ className, children, positio
333
490
  {
334
491
  ref,
335
492
  className: ui.cn(
336
- "relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
493
+ "relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-surface border bg-popover text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
337
494
  position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
338
495
  className
339
496
  ),
@@ -403,12 +560,15 @@ var ColorSwatches = ({
403
560
  }) => {
404
561
  const [customColor, setCustomColor] = React2__namespace.useState(value || defaultValue);
405
562
  const [isCustom, setIsCustom] = React2__namespace.useState(false);
406
- React2__namespace.useEffect(() => {
407
- if (!value) return;
563
+ const [seen, setSeen] = React2__namespace.useState({
564
+ presetColors
565
+ });
566
+ if (value && (value !== seen.value || presetColors !== seen.presetColors)) {
567
+ setSeen({ value, presetColors });
408
568
  const isPreset = presetColors.some((c) => c.value === value);
409
569
  setIsCustom(!isPreset);
410
570
  if (!isPreset) setCustomColor(value);
411
- }, [value, presetColors]);
571
+ }
412
572
  const select = (newColor, custom = false) => {
413
573
  setIsCustom(custom);
414
574
  if (custom) setCustomColor(newColor);
@@ -485,12 +645,15 @@ var SliderNumber = ({
485
645
  min = 0,
486
646
  max = 100,
487
647
  step = 1,
648
+ disabled,
488
649
  className
489
650
  }) => {
490
651
  const [local, setLocal] = React2__namespace.useState(value);
491
- React2__namespace.useEffect(() => {
652
+ const [seen, setSeen] = React2__namespace.useState(value);
653
+ if (value !== seen) {
654
+ setSeen(value);
492
655
  setLocal(value);
493
- }, [value]);
656
+ }
494
657
  const set = (n) => {
495
658
  setLocal(n);
496
659
  onChange?.(n);
@@ -504,6 +667,7 @@ var SliderNumber = ({
504
667
  min,
505
668
  max,
506
669
  step,
670
+ disabled,
507
671
  className: "flex-1"
508
672
  }
509
673
  ),
@@ -516,14 +680,15 @@ var SliderNumber = ({
516
680
  className: "h-8 w-16",
517
681
  min,
518
682
  max,
519
- step
683
+ step,
684
+ disabled
520
685
  }
521
686
  )
522
687
  ] });
523
688
  };
524
689
  var IconInput = ({ value, onChange }) => {
525
690
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
526
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-control border bg-muted", children: value ? value.slice(0, 2) : "\u2013" }),
691
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex size-control-md shrink-0 items-center justify-center rounded-control border bg-muted", children: value ? value.slice(0, 2) : "\u2013" }),
527
692
  /* @__PURE__ */ jsxRuntime.jsx(
528
693
  Input,
529
694
  {
@@ -531,17 +696,21 @@ var IconInput = ({ value, onChange }) => {
531
696
  value: value ?? "",
532
697
  onChange: (e) => onChange?.(e.target.value),
533
698
  placeholder: "icon name",
534
- className: "h-8"
699
+ className: "h-control-md"
535
700
  }
536
701
  )
537
702
  ] });
538
703
  };
539
704
  var SIZE = {
705
+ // The dense tier — an ask in a conversation, an inspector. Controls are the
706
+ // scale's `sm` (26px), the text stays at the 13px floor; the field label is
707
+ // muted and regular so the values, not the labels, carry the weight.
540
708
  xs: {
541
- input: "h-9",
542
- select: "h-9",
709
+ input: "h-control-sm py-0",
710
+ select: "h-control-sm py-0",
543
711
  textarea: "",
544
712
  label: "text-base",
713
+ fieldLabel: "font-normal text-muted-foreground",
545
714
  desc: "text-base",
546
715
  gap: "gap-x-3 gap-y-2.5",
547
716
  section: "space-y-3",
@@ -554,10 +723,11 @@ var SIZE = {
554
723
  radio: "h-4 w-4"
555
724
  },
556
725
  sm: {
557
- input: "h-9",
558
- select: "h-9",
726
+ input: "h-control-md",
727
+ select: "h-control-md",
559
728
  textarea: "",
560
729
  label: "text-base",
730
+ fieldLabel: "",
561
731
  desc: "text-base",
562
732
  gap: "gap-x-3 gap-y-2",
563
733
  section: "space-y-3",
@@ -570,10 +740,11 @@ var SIZE = {
570
740
  radio: "h-4 w-4"
571
741
  },
572
742
  md: {
573
- input: "",
574
- select: "",
743
+ input: "h-control-lg px-3",
744
+ select: "h-control-lg px-3",
575
745
  textarea: "",
576
746
  label: "text-base",
747
+ fieldLabel: "",
577
748
  desc: "text-base",
578
749
  gap: "gap-4",
579
750
  section: "space-y-4",
@@ -588,7 +759,9 @@ var SIZE = {
588
759
  };
589
760
  function itemClasses(labelPosition, size, className) {
590
761
  return ui.cn(
591
- labelPosition === "side" && ui.cn("grid grid-cols-3 items-center", SIZE[size].sideGap),
762
+ // `space-y-0` undoes FormItem's own stacking, whose margin would push the
763
+ // control below its label in a row.
764
+ labelPosition === "side" && ui.cn("grid grid-cols-3 items-center space-y-0", SIZE[size].sideGap),
592
765
  labelPosition === "top" && SIZE[size].stack,
593
766
  className
594
767
  );
@@ -610,33 +783,57 @@ function FieldLabel({
610
783
  label,
611
784
  badge,
612
785
  size,
786
+ disabled,
613
787
  className
614
788
  }) {
615
789
  if (!label && !badge) return null;
616
- return /* @__PURE__ */ jsxRuntime.jsxs(FormLabel, { className: ui.cn(SIZE[size].label, className), children: [
617
- label,
618
- badge && /* @__PURE__ */ jsxRuntime.jsx(StatusPill, { badge })
619
- ] });
790
+ return /* @__PURE__ */ jsxRuntime.jsxs(
791
+ FormLabel,
792
+ {
793
+ className: ui.cn(SIZE[size].label, SIZE[size].fieldLabel, disabled && "opacity-70", className),
794
+ children: [
795
+ label,
796
+ badge && /* @__PURE__ */ jsxRuntime.jsx(StatusPill, { badge })
797
+ ]
798
+ }
799
+ );
620
800
  }
801
+ var AffixedInput = React2__namespace.forwardRef(({ unit, aside, className, ...props }, ref) => {
802
+ if (!unit && !aside) return /* @__PURE__ */ jsxRuntime.jsx(Input, { ref, className, ...props });
803
+ return /* @__PURE__ */ jsxRuntime.jsxs(InputGroup, { className: ui.cn("bg-background dark:bg-background", className), children: [
804
+ /* @__PURE__ */ jsxRuntime.jsx(InputGroupInput, { ref, className: "h-full", ...props }),
805
+ /* @__PURE__ */ jsxRuntime.jsxs(InputGroupAddon, { align: "inline-end", className: "font-mono font-normal", children: [
806
+ unit && /* @__PURE__ */ jsxRuntime.jsx("span", { children: unit }),
807
+ aside && /* @__PURE__ */ jsxRuntime.jsx("span", { children: aside })
808
+ ] })
809
+ ] });
810
+ });
811
+ AffixedInput.displayName = "AffixedInput";
621
812
  var InputField = ({
622
813
  label,
623
814
  description,
624
815
  placeholder,
625
816
  value,
626
817
  onChange,
818
+ unit,
819
+ aside,
627
820
  labelPosition = "side",
628
821
  size = "sm",
629
822
  labelClassName,
630
823
  badge,
631
- className
824
+ className,
825
+ disabled
632
826
  }) => /* @__PURE__ */ jsxRuntime.jsxs(FormItem, { className: itemClasses(labelPosition, size, className), children: [
633
- /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, className: labelClassName }),
827
+ /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, disabled, className: labelClassName }),
634
828
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: inputWrapper(labelPosition, size), children: [
635
829
  /* @__PURE__ */ jsxRuntime.jsx(FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(
636
- Input,
830
+ AffixedInput,
637
831
  {
638
832
  className: SIZE[size].input,
833
+ unit,
834
+ aside,
639
835
  placeholder,
836
+ disabled,
640
837
  value: value ?? "",
641
838
  onChange: (e) => onChange?.(e.target.value)
642
839
  }
@@ -655,15 +852,17 @@ var PasswordField = ({
655
852
  size = "sm",
656
853
  labelClassName,
657
854
  badge,
658
- className
855
+ className,
856
+ disabled
659
857
  }) => /* @__PURE__ */ jsxRuntime.jsxs(FormItem, { className: itemClasses(labelPosition, size, className), children: [
660
- /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, className: labelClassName }),
858
+ /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, disabled, className: labelClassName }),
661
859
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: inputWrapper(labelPosition, size), children: [
662
860
  /* @__PURE__ */ jsxRuntime.jsx(FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(
663
861
  PasswordInput,
664
862
  {
665
863
  className: SIZE[size].input,
666
864
  placeholder,
865
+ disabled,
667
866
  value: value ?? "",
668
867
  onChange: (e) => onChange?.(e.target.value)
669
868
  }
@@ -683,9 +882,10 @@ var TextareaField = ({
683
882
  size = "sm",
684
883
  labelClassName,
685
884
  badge,
686
- className
885
+ className,
886
+ disabled
687
887
  }) => /* @__PURE__ */ jsxRuntime.jsxs(FormItem, { className: itemClasses(labelPosition, size, className), children: [
688
- /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, className: labelClassName }),
888
+ /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, disabled, className: labelClassName }),
689
889
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: inputWrapper(labelPosition, size), children: [
690
890
  /* @__PURE__ */ jsxRuntime.jsx(FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(
691
891
  Textarea,
@@ -693,6 +893,7 @@ var TextareaField = ({
693
893
  className: SIZE[size].textarea || void 0,
694
894
  rows,
695
895
  placeholder,
896
+ disabled,
696
897
  value: value ?? "",
697
898
  onChange: (e) => onChange?.(e.target.value)
698
899
  }
@@ -712,13 +913,14 @@ var SelectField = ({
712
913
  size = "sm",
713
914
  labelClassName,
714
915
  badge,
715
- className
916
+ className,
917
+ disabled
716
918
  }) => /* @__PURE__ */ jsxRuntime.jsxs(FormItem, { className: itemClasses(labelPosition, size, className), children: [
717
- /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, className: labelClassName }),
919
+ /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, disabled, className: labelClassName }),
718
920
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: inputWrapper(labelPosition, size), children: [
719
- /* @__PURE__ */ jsxRuntime.jsxs(Select, { value: value ?? "", onValueChange: onChange, children: [
921
+ /* @__PURE__ */ jsxRuntime.jsxs(Select, { value: value ?? "", onValueChange: onChange, disabled, children: [
720
922
  /* @__PURE__ */ jsxRuntime.jsx(FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { className: SIZE[size].select, children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder }) }) }),
721
- /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: options.map((o) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: o.value, children: o.label }, o.value)) })
923
+ /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: options.map((o) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: o.value, disabled: o.disabled, children: o.label }, o.value)) })
722
924
  ] }),
723
925
  description && /* @__PURE__ */ jsxRuntime.jsx(FormDescription, { className: SIZE[size].desc, children: description }),
724
926
  /* @__PURE__ */ jsxRuntime.jsx(FormMessage, { className: SIZE[size].desc })
@@ -735,37 +937,53 @@ var BooleanField = ({
735
937
  labelClassName,
736
938
  badge,
737
939
  className,
738
- boxed = false
940
+ boxed = false,
941
+ disabled
739
942
  }) => {
740
943
  const boxClass = boxed ? "rounded-md border p-2" : "";
741
944
  if (control === "checkbox") {
742
- return /* @__PURE__ */ jsxRuntime.jsxs(FormItem, { className: ui.cn("flex items-center gap-2 space-y-0", className), children: [
743
- /* @__PURE__ */ jsxRuntime.jsx(FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(
744
- Checkbox,
745
- {
746
- className: SIZE[size].check,
747
- checked: !!value,
748
- onCheckedChange: onChange
749
- }
750
- ) }),
751
- /* @__PURE__ */ jsxRuntime.jsx(
752
- FieldLabel,
753
- {
754
- label,
755
- badge,
756
- size,
757
- className: ui.cn(
758
- "!mt-0 cursor-pointer font-normal leading-none",
759
- labelClassName
760
- )
761
- }
762
- )
763
- ] });
945
+ return /* @__PURE__ */ jsxRuntime.jsxs(
946
+ FormItem,
947
+ {
948
+ className: ui.cn(
949
+ "flex gap-2 space-y-0",
950
+ description ? "items-start" : "items-center",
951
+ className
952
+ ),
953
+ children: [
954
+ /* @__PURE__ */ jsxRuntime.jsx(FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(
955
+ Checkbox,
956
+ {
957
+ className: SIZE[size].check,
958
+ checked: !!value,
959
+ disabled,
960
+ onCheckedChange: onChange
961
+ }
962
+ ) }),
963
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
964
+ /* @__PURE__ */ jsxRuntime.jsx(
965
+ FieldLabel,
966
+ {
967
+ label,
968
+ badge,
969
+ size,
970
+ disabled,
971
+ className: ui.cn(
972
+ "!mt-0 cursor-pointer font-normal leading-none",
973
+ labelClassName
974
+ )
975
+ }
976
+ ),
977
+ description && /* @__PURE__ */ jsxRuntime.jsx(FormDescription, { className: SIZE[size].desc, children: description })
978
+ ] })
979
+ ]
980
+ }
981
+ );
764
982
  }
765
983
  if (labelPosition === "side") {
766
984
  return /* @__PURE__ */ jsxRuntime.jsxs(FormItem, { className: ui.cn("flex items-center justify-between", boxClass), children: [
767
985
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
768
- /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, className: labelClassName }),
986
+ /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, disabled, className: labelClassName }),
769
987
  description && /* @__PURE__ */ jsxRuntime.jsx(FormDescription, { className: SIZE[size].desc, children: description })
770
988
  ] }),
771
989
  /* @__PURE__ */ jsxRuntime.jsx(FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -773,19 +991,21 @@ var BooleanField = ({
773
991
  {
774
992
  className: SIZE[size].switch || void 0,
775
993
  checked: !!value,
994
+ disabled,
776
995
  onCheckedChange: onChange
777
996
  }
778
997
  ) })
779
998
  ] });
780
999
  }
781
1000
  return /* @__PURE__ */ jsxRuntime.jsxs(FormItem, { className: SIZE[size].stack, children: [
782
- /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, className: labelClassName }),
1001
+ /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, disabled, className: labelClassName }),
783
1002
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cn("flex items-center justify-between", boxClass), children: [
784
1003
  /* @__PURE__ */ jsxRuntime.jsx(FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(
785
1004
  Switch,
786
1005
  {
787
1006
  className: SIZE[size].switch || void 0,
788
1007
  checked: !!value,
1008
+ disabled,
789
1009
  onCheckedChange: onChange
790
1010
  }
791
1011
  ) }),
@@ -804,33 +1024,46 @@ var RadioField = ({
804
1024
  orientation = "vertical",
805
1025
  labelClassName,
806
1026
  badge,
807
- className
1027
+ className,
1028
+ disabled
808
1029
  }) => /* @__PURE__ */ jsxRuntime.jsxs(FormItem, { className: itemClasses(labelPosition, size, className), children: [
809
- /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, className: labelClassName }),
1030
+ /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, disabled, className: labelClassName }),
810
1031
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: inputWrapper(labelPosition, size), children: [
811
1032
  /* @__PURE__ */ jsxRuntime.jsx(FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(
812
1033
  RadioGroup,
813
1034
  {
814
1035
  value: value ?? "",
815
1036
  onValueChange: onChange,
1037
+ disabled,
816
1038
  className: orientation === "horizontal" ? "flex flex-row items-center gap-x-4" : ui.cn("flex flex-col", SIZE[size].stack),
817
- children: options.map((o) => /* @__PURE__ */ jsxRuntime.jsxs(
818
- "label",
819
- {
820
- className: "flex cursor-pointer items-center gap-2",
821
- children: [
822
- /* @__PURE__ */ jsxRuntime.jsx(
823
- RadioGroupItem,
824
- {
825
- value: o.value,
826
- className: ui.cn("shrink-0", SIZE[size].radio)
827
- }
1039
+ children: options.map((o) => {
1040
+ const off = disabled || o.disabled;
1041
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1042
+ "label",
1043
+ {
1044
+ className: ui.cn(
1045
+ "flex gap-2",
1046
+ o.description ? "items-start" : "items-center",
1047
+ off ? "cursor-not-allowed" : "cursor-pointer"
828
1048
  ),
829
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: ui.cn("leading-none", SIZE[size].label), children: o.label })
830
- ]
831
- },
832
- o.value
833
- ))
1049
+ children: [
1050
+ /* @__PURE__ */ jsxRuntime.jsx(
1051
+ RadioGroupItem,
1052
+ {
1053
+ value: o.value,
1054
+ disabled: o.disabled,
1055
+ className: ui.cn("shrink-0", SIZE[size].radio)
1056
+ }
1057
+ ),
1058
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: ui.cn("flex flex-col gap-1", off && "opacity-50"), children: [
1059
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ui.cn(o.description ? "leading-4" : "leading-none", SIZE[size].label), children: o.label }),
1060
+ o.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: ui.cn("text-muted-foreground", SIZE[size].desc), children: o.description })
1061
+ ] })
1062
+ ]
1063
+ },
1064
+ o.value
1065
+ );
1066
+ })
834
1067
  }
835
1068
  ) }),
836
1069
  description && /* @__PURE__ */ jsxRuntime.jsx(FormDescription, { className: SIZE[size].desc, children: description }),
@@ -848,12 +1081,13 @@ var CheckboxGroupField = ({
848
1081
  orientation = "vertical",
849
1082
  labelClassName,
850
1083
  badge,
851
- className
1084
+ className,
1085
+ disabled
852
1086
  }) => {
853
1087
  const selected = Array.isArray(value) ? value : [];
854
1088
  const toggle = (v, checked) => onChange?.(checked ? [...selected, v] : selected.filter((x) => x !== v));
855
1089
  return /* @__PURE__ */ jsxRuntime.jsxs(FormItem, { className: itemClasses(labelPosition, size, className), children: [
856
- /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, className: labelClassName }),
1090
+ /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, disabled, className: labelClassName }),
857
1091
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: inputWrapper(labelPosition, size), children: [
858
1092
  /* @__PURE__ */ jsxRuntime.jsx(
859
1093
  "div",
@@ -869,6 +1103,7 @@ var CheckboxGroupField = ({
869
1103
  {
870
1104
  className: ui.cn("shrink-0", SIZE[size].check),
871
1105
  checked: selected.includes(o.value),
1106
+ disabled: disabled || o.disabled,
872
1107
  onCheckedChange: (c) => toggle(o.value, c === true)
873
1108
  }
874
1109
  ),
@@ -895,9 +1130,10 @@ var ColorField = ({
895
1130
  size = "sm",
896
1131
  labelClassName,
897
1132
  badge,
898
- className
1133
+ className,
1134
+ disabled
899
1135
  }) => /* @__PURE__ */ jsxRuntime.jsxs(FormItem, { className: itemClasses(labelPosition, size, className), children: [
900
- /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, className: labelClassName }),
1136
+ /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, disabled, className: labelClassName }),
901
1137
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: inputWrapper(labelPosition, size), children: [
902
1138
  /* @__PURE__ */ jsxRuntime.jsx(FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(
903
1139
  ColorSwatches,
@@ -920,22 +1156,40 @@ var NumberField = ({
920
1156
  min,
921
1157
  max,
922
1158
  step,
1159
+ unit,
1160
+ aside,
923
1161
  labelPosition = "side",
924
1162
  size = "sm",
925
1163
  labelClassName,
926
1164
  badge,
927
- className
1165
+ className,
1166
+ disabled
928
1167
  }) => /* @__PURE__ */ jsxRuntime.jsxs(FormItem, { className: itemClasses(labelPosition, size, className), children: [
929
- /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, className: labelClassName }),
1168
+ /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, disabled, className: labelClassName }),
930
1169
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: inputWrapper(labelPosition, size), children: [
931
- /* @__PURE__ */ jsxRuntime.jsx(FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(
1170
+ /* @__PURE__ */ jsxRuntime.jsx(FormControl, { children: min != null && max != null ? /* @__PURE__ */ jsxRuntime.jsx(
932
1171
  SliderNumber,
933
1172
  {
934
1173
  value: typeof value === "number" ? value : 0,
935
1174
  onChange,
936
1175
  min,
937
1176
  max,
938
- step
1177
+ step,
1178
+ disabled
1179
+ }
1180
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1181
+ AffixedInput,
1182
+ {
1183
+ type: "number",
1184
+ className: SIZE[size].input,
1185
+ unit,
1186
+ aside,
1187
+ min,
1188
+ max,
1189
+ step,
1190
+ disabled,
1191
+ value: typeof value === "number" ? value : "",
1192
+ onChange: (e) => onChange?.(e.target.value === "" ? void 0 : Number(e.target.value))
939
1193
  }
940
1194
  ) }),
941
1195
  description && /* @__PURE__ */ jsxRuntime.jsx(FormDescription, { className: SIZE[size].desc, children: description }),
@@ -951,27 +1205,16 @@ var IconField = ({
951
1205
  size = "sm",
952
1206
  labelClassName,
953
1207
  badge,
954
- className
1208
+ className,
1209
+ disabled
955
1210
  }) => /* @__PURE__ */ jsxRuntime.jsxs(FormItem, { className: itemClasses(labelPosition, size, className), children: [
956
- /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, className: labelClassName }),
1211
+ /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label, badge, size, disabled, className: labelClassName }),
957
1212
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: inputWrapper(labelPosition, size), children: [
958
1213
  /* @__PURE__ */ jsxRuntime.jsx(FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(IconInput, { value, onChange }) }),
959
1214
  description && /* @__PURE__ */ jsxRuntime.jsx(FormDescription, { className: SIZE[size].desc, children: description }),
960
1215
  /* @__PURE__ */ jsxRuntime.jsx(FormMessage, { className: SIZE[size].desc })
961
1216
  ] })
962
1217
  ] });
963
- var Field = {
964
- Input: InputField,
965
- Password: PasswordField,
966
- Textarea: TextareaField,
967
- Boolean: BooleanField,
968
- Radio: RadioField,
969
- CheckboxGroup: CheckboxGroupField,
970
- Color: ColorField,
971
- Number: NumberField,
972
- Select: SelectField,
973
- Icon: IconField
974
- };
975
1218
  function humanize(name) {
976
1219
  return name.replace(/([A-Z])/g, " $1").replace(/^./, (c) => c.toUpperCase()).trim();
977
1220
  }
@@ -982,11 +1225,13 @@ function renderField(field, parentName, control, labelPosition, size) {
982
1225
  control,
983
1226
  name: `${parentName}.${field.name}`,
984
1227
  defaultValue: field.defaultValue,
1228
+ rules: field.rules,
985
1229
  render: ({ field: rhf }) => {
986
1230
  const common = {
987
1231
  label: field.label ?? humanize(field.name),
988
1232
  description: field.description,
989
1233
  options: field.options,
1234
+ disabled: field.disabled,
990
1235
  min: field.min,
991
1236
  max: field.max,
992
1237
  step: field.step,
@@ -998,6 +1243,8 @@ function renderField(field, parentName, control, labelPosition, size) {
998
1243
  boxed: field.boxed,
999
1244
  labelClassName: field.labelClassName,
1000
1245
  badge: field.badge,
1246
+ unit: field.unit,
1247
+ aside: field.aside,
1001
1248
  labelPosition,
1002
1249
  size,
1003
1250
  value: rhf.value,
@@ -1049,8 +1296,21 @@ function renderField(field, parentName, control, labelPosition, size) {
1049
1296
  field.name
1050
1297
  );
1051
1298
  }
1052
- function renderGrid(fields, parentName, control, labelPosition, size, columns, key) {
1299
+ function renderGrid(fields, parentName, control, labelPosition, size, columns, key, fit = "viewport") {
1053
1300
  const customCols = columns !== 2;
1301
+ if (fit === "container") {
1302
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "@container", children: /* @__PURE__ */ jsxRuntime.jsx(
1303
+ "div",
1304
+ {
1305
+ className: ui.cn(
1306
+ "grid grid-cols-1",
1307
+ SIZE[size].gap,
1308
+ columns > 1 && "@min-[280px]:grid-cols-2 @min-[280px]:[&>*:last-child:nth-child(odd)]:col-span-2"
1309
+ ),
1310
+ children: fields.map((f) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: f.className, children: renderField(f, parentName, control, labelPosition, size) }, f.name))
1311
+ }
1312
+ ) }, key);
1313
+ }
1054
1314
  return /* @__PURE__ */ jsxRuntime.jsx(
1055
1315
  "div",
1056
1316
  {
@@ -1079,9 +1339,9 @@ function renderGrid(fields, parentName, control, labelPosition, size, columns, k
1079
1339
  key
1080
1340
  );
1081
1341
  }
1082
- function renderRows(fields, rowConfig, parentName, control, labelPosition, size, columns) {
1342
+ function renderRows(fields, rowConfig, parentName, control, labelPosition, size, columns, fit = "viewport") {
1083
1343
  if (!rowConfig || rowConfig.length === 0) {
1084
- return renderGrid(fields, parentName, control, labelPosition, size, columns);
1344
+ return renderGrid(fields, parentName, control, labelPosition, size, columns, void 0, fit);
1085
1345
  }
1086
1346
  const used = new Set(rowConfig.flatMap((r) => r.fields));
1087
1347
  const unassigned = fields.filter((f) => !used.has(f.name));
@@ -1097,7 +1357,8 @@ function renderRows(fields, rowConfig, parentName, control, labelPosition, size,
1097
1357
  labelPosition,
1098
1358
  size,
1099
1359
  columns,
1100
- row.id
1360
+ row.id,
1361
+ fit
1101
1362
  );
1102
1363
  }),
1103
1364
  unassigned.length > 0 && renderGrid(
@@ -1107,7 +1368,8 @@ function renderRows(fields, rowConfig, parentName, control, labelPosition, size,
1107
1368
  labelPosition,
1108
1369
  size,
1109
1370
  columns,
1110
- "_unassigned"
1371
+ "_unassigned",
1372
+ fit
1111
1373
  )
1112
1374
  ] });
1113
1375
  }
@@ -1119,7 +1381,9 @@ var ObjectField = ({
1119
1381
  groupConfig,
1120
1382
  labelPosition = "side",
1121
1383
  size = "sm",
1122
- columns = 2
1384
+ columns = 2,
1385
+ fit = "viewport",
1386
+ groupAs = "accordion"
1123
1387
  }) => {
1124
1388
  const grouped = fields.reduce((acc, f) => {
1125
1389
  const key = f.group ?? "_ungrouped";
@@ -1132,60 +1396,70 @@ var ObjectField = ({
1132
1396
  const groupConfigById = new Map(
1133
1397
  (groupConfig ?? []).map((g) => [g.id, g])
1134
1398
  );
1135
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: SIZE[size].outer, children: [
1136
- ungrouped.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: SIZE[size].section, children: renderRows(
1137
- ungrouped,
1138
- rowConfig,
1139
- name,
1140
- control,
1141
- labelPosition,
1142
- size,
1143
- columns
1144
- ) }),
1145
- groupedEntries.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
1146
- ui.Accordion,
1147
- {
1148
- type: "multiple",
1149
- defaultValue: groupedEntries.map(([k]) => k),
1150
- className: "w-full",
1151
- children: groupedEntries.map(([group, gFields]) => {
1152
- const gc = groupConfigById.get(group);
1153
- return /* @__PURE__ */ jsxRuntime.jsxs(ui.AccordionItem, { value: group, className: "border-b", children: [
1154
- /* @__PURE__ */ jsxRuntime.jsx(
1155
- ui.AccordionTrigger,
1156
- {
1157
- className: ui.cn(
1158
- "font-semibold uppercase tracking-wide text-muted-foreground hover:no-underline",
1159
- SIZE[size].trigger
1160
- ),
1161
- children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2", children: [
1162
- gc?.label ?? humanize(group),
1163
- (gc?.showCount ?? true) && /* @__PURE__ */ jsxRuntime.jsx(
1164
- ui.Badge,
1165
- {
1166
- variant: "secondary",
1167
- className: "px-1.5 py-0 text-base font-normal tabular-nums",
1168
- children: gFields.length
1169
- }
1399
+ return (
1400
+ // A container has no width of its own, so one fitted to it takes its
1401
+ // parent's: in a row beside a button it would otherwise shrink to nothing.
1402
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cn(SIZE[size].outer, fit === "container" && "w-full min-w-0"), children: [
1403
+ ungrouped.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: SIZE[size].section, children: renderRows(
1404
+ ungrouped,
1405
+ rowConfig,
1406
+ name,
1407
+ control,
1408
+ labelPosition,
1409
+ size,
1410
+ columns,
1411
+ fit
1412
+ ) }),
1413
+ groupedEntries.length > 0 && groupAs === "section" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: SIZE[size].section, children: groupedEntries.map(([group, gFields]) => /* @__PURE__ */ jsxRuntime.jsxs("section", { className: SIZE[size].stack, children: [
1414
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Eyebrow, { children: groupConfigById.get(group)?.label ?? humanize(group) }),
1415
+ renderRows(gFields, rowConfig, name, control, labelPosition, size, columns, fit)
1416
+ ] }, group)) }),
1417
+ groupedEntries.length > 0 && groupAs === "accordion" && /* @__PURE__ */ jsxRuntime.jsx(
1418
+ ui.Accordion,
1419
+ {
1420
+ type: "multiple",
1421
+ defaultValue: groupedEntries.map(([k]) => k),
1422
+ className: "w-full",
1423
+ children: groupedEntries.map(([group, gFields]) => {
1424
+ const gc = groupConfigById.get(group);
1425
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.AccordionItem, { value: group, className: "border-b", children: [
1426
+ /* @__PURE__ */ jsxRuntime.jsx(
1427
+ ui.AccordionTrigger,
1428
+ {
1429
+ className: ui.cn(
1430
+ "font-semibold uppercase tracking-wide text-muted-foreground hover:no-underline",
1431
+ SIZE[size].trigger
1170
1432
  ),
1171
- gc?.badges?.map((b, i) => /* @__PURE__ */ jsxRuntime.jsx(StatusPill, { badge: b }, i))
1172
- ] })
1173
- }
1174
- ),
1175
- /* @__PURE__ */ jsxRuntime.jsx(ui.AccordionContent, { className: "pb-3 pt-1", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: SIZE[size].section, children: renderRows(
1176
- gFields,
1177
- rowConfig,
1178
- name,
1179
- control,
1180
- labelPosition,
1181
- size,
1182
- columns
1183
- ) }) })
1184
- ] }, group);
1185
- })
1186
- }
1187
- )
1188
- ] });
1433
+ children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2", children: [
1434
+ gc?.label ?? humanize(group),
1435
+ (gc?.showCount ?? true) && /* @__PURE__ */ jsxRuntime.jsx(
1436
+ ui.Badge,
1437
+ {
1438
+ variant: "secondary",
1439
+ className: "px-1.5 py-0 text-base font-normal tabular-nums",
1440
+ children: gFields.length
1441
+ }
1442
+ ),
1443
+ gc?.badges?.map((b, i) => /* @__PURE__ */ jsxRuntime.jsx(StatusPill, { badge: b }, i))
1444
+ ] })
1445
+ }
1446
+ ),
1447
+ /* @__PURE__ */ jsxRuntime.jsx(ui.AccordionContent, { className: "pb-3 pt-1", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: SIZE[size].section, children: renderRows(
1448
+ gFields,
1449
+ rowConfig,
1450
+ name,
1451
+ control,
1452
+ labelPosition,
1453
+ size,
1454
+ columns,
1455
+ fit
1456
+ ) }) })
1457
+ ] }, group);
1458
+ })
1459
+ }
1460
+ )
1461
+ ] })
1462
+ );
1189
1463
  };
1190
1464
  var FormField2 = Object.assign(FormField, {
1191
1465
  ObjectField,
@@ -1268,7 +1542,7 @@ function FieldGroup({ className, ...props }) {
1268
1542
  }
1269
1543
  );
1270
1544
  }
1271
- classVarianceAuthority.cva(
1545
+ var fieldVariants = classVarianceAuthority.cva(
1272
1546
  "group/field data-[invalid=true]:text-destructive flex w-full gap-3",
1273
1547
  {
1274
1548
  variants: {
@@ -1291,6 +1565,22 @@ classVarianceAuthority.cva(
1291
1565
  }
1292
1566
  }
1293
1567
  );
1568
+ function Field({
1569
+ className,
1570
+ orientation = "vertical",
1571
+ ...props
1572
+ }) {
1573
+ return /* @__PURE__ */ jsxRuntime.jsx(
1574
+ "div",
1575
+ {
1576
+ role: "group",
1577
+ "data-slot": "field",
1578
+ "data-orientation": orientation,
1579
+ className: ui.cn(fieldVariants({ orientation }), className),
1580
+ ...props
1581
+ }
1582
+ );
1583
+ }
1294
1584
  function FieldContent({ className, ...props }) {
1295
1585
  return /* @__PURE__ */ jsxRuntime.jsx(
1296
1586
  "div",
@@ -1493,146 +1783,6 @@ var ParamRow = React2__namespace.forwardRef(
1493
1783
  )
1494
1784
  );
1495
1785
  ParamRow.displayName = "ParamRow";
1496
- function InputGroup({ className, ...props }) {
1497
- return /* @__PURE__ */ jsxRuntime.jsx(
1498
- "div",
1499
- {
1500
- "data-slot": "input-group",
1501
- role: "group",
1502
- className: ui.cn(
1503
- "group/input-group border-input dark:bg-input/30 shadow-xs relative flex w-full items-center rounded-control border outline-none transition-[color,box-shadow]",
1504
- "h-9 has-[>textarea]:h-auto",
1505
- // Variants based on alignment.
1506
- "has-[>[data-align=inline-start]]:[&>input]:pl-2",
1507
- "has-[>[data-align=inline-end]]:[&>input]:pr-2",
1508
- "has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3",
1509
- "has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3",
1510
- // Focus state.
1511
- "has-[[data-slot=input-group-control]:focus-visible]:ring-ring has-[[data-slot=input-group-control]:focus-visible]:ring-1",
1512
- // Error state.
1513
- "has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40",
1514
- className
1515
- ),
1516
- ...props
1517
- }
1518
- );
1519
- }
1520
- var inputGroupAddonVariants = classVarianceAuthority.cva(
1521
- "text-muted-foreground flex h-auto cursor-text select-none items-center justify-center gap-2 py-1.5 font-medium group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-control [&>svg:not([class*='size-'])]:size-4",
1522
- {
1523
- variants: {
1524
- align: {
1525
- "inline-start": "order-first pl-3 has-[>button]:ml-[-0.45rem] has-[>kbd]:ml-[-0.35rem]",
1526
- "inline-end": "order-last pr-3 has-[>button]:mr-[-0.4rem] has-[>kbd]:mr-[-0.35rem]",
1527
- "block-start": "[.border-b]:pb-3 order-first w-full justify-start px-3 pt-3 group-has-[>input]/input-group:pt-2.5",
1528
- "block-end": "[.border-t]:pt-3 order-last w-full justify-start px-3 pb-3 group-has-[>input]/input-group:pb-2.5"
1529
- }
1530
- },
1531
- defaultVariants: {
1532
- align: "inline-start"
1533
- }
1534
- }
1535
- );
1536
- function InputGroupAddon({
1537
- className,
1538
- align = "inline-start",
1539
- ...props
1540
- }) {
1541
- return /* @__PURE__ */ jsxRuntime.jsx(
1542
- "div",
1543
- {
1544
- role: "group",
1545
- "data-slot": "input-group-addon",
1546
- "data-align": align,
1547
- className: ui.cn(inputGroupAddonVariants({ align }), className),
1548
- onClick: (e) => {
1549
- if (e.target.closest("button")) {
1550
- return;
1551
- }
1552
- e.currentTarget.parentElement?.querySelector("input")?.focus();
1553
- },
1554
- ...props
1555
- }
1556
- );
1557
- }
1558
- var inputGroupButtonVariants = classVarianceAuthority.cva(
1559
- "flex items-center gap-2 shadow-none",
1560
- {
1561
- variants: {
1562
- size: {
1563
- xs: "h-6 gap-1 rounded-control px-2 has-[>svg]:px-2 [&>svg:not([class*='size-'])]:size-3.5",
1564
- sm: "h-8 gap-1.5 rounded-control px-2.5 has-[>svg]:px-2.5",
1565
- "icon-xs": "size-6 rounded-control p-0 has-[>svg]:p-0",
1566
- "icon-sm": "size-8 p-0 has-[>svg]:p-0"
1567
- }
1568
- },
1569
- defaultVariants: {
1570
- size: "xs"
1571
- }
1572
- }
1573
- );
1574
- function InputGroupButton({
1575
- className,
1576
- type = "button",
1577
- variant = "ghost",
1578
- size = "xs",
1579
- ...props
1580
- }) {
1581
- return /* @__PURE__ */ jsxRuntime.jsx(
1582
- ui.Button,
1583
- {
1584
- type,
1585
- "data-size": size,
1586
- variant,
1587
- className: ui.cn(inputGroupButtonVariants({ size }), className),
1588
- ...props
1589
- }
1590
- );
1591
- }
1592
- function InputGroupText({ className, ...props }) {
1593
- return /* @__PURE__ */ jsxRuntime.jsx(
1594
- "span",
1595
- {
1596
- className: ui.cn(
1597
- "text-muted-foreground flex items-center gap-2 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none",
1598
- className
1599
- ),
1600
- ...props
1601
- }
1602
- );
1603
- }
1604
- function InputGroupInput({
1605
- className,
1606
- ...props
1607
- }) {
1608
- return /* @__PURE__ */ jsxRuntime.jsx(
1609
- Input,
1610
- {
1611
- "data-slot": "input-group-control",
1612
- className: ui.cn(
1613
- "flex-1 rounded-none border-0 bg-transparent shadow-none focus-visible:ring-0 dark:bg-transparent",
1614
- className
1615
- ),
1616
- ...props
1617
- }
1618
- );
1619
- }
1620
- function InputGroupTextarea({
1621
- className,
1622
- ...props
1623
- }) {
1624
- return /* @__PURE__ */ jsxRuntime.jsx(
1625
- Textarea,
1626
- {
1627
- "data-slot": "input-group-control",
1628
- className: ui.cn(
1629
- "flex-1 resize-none rounded-none border-0 bg-transparent py-3 shadow-none focus-visible:ring-0 dark:bg-transparent",
1630
- className
1631
- ),
1632
- ...props
1633
- }
1634
- );
1635
- }
1636
1786
 
1637
1787
  exports.BooleanField = BooleanField;
1638
1788
  exports.Checkbox = Checkbox;