shadcn-zod-formkit 1.14.0 → 1.16.0

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.mts CHANGED
@@ -73,13 +73,15 @@ declare enum InputTypes {
73
73
  REPEATER = "repeater",
74
74
  MULTI_SELECT = "multi_select",
75
75
  COMBOBOX = "COMBO_BOX",
76
- SORTABLE_LIST = "sortable_list"
76
+ SORTABLE_LIST = "sortable_list",
77
+ REPEATER_TABS = "repeater_tabs"
77
78
  }
78
79
  declare const inputFieldComp: InputTypes[];
79
80
 
80
81
  interface FieldProps<T = Record<string, any>> {
81
82
  name: keyof T;
82
83
  label: string;
84
+ tabLabelField?: string;
83
85
  childrenPosition?: 'up' | 'down';
84
86
  children?: ReactNode | ((item: any, index: number) => ReactNode);
85
87
  defaultValue?: any;
@@ -193,6 +195,8 @@ interface FormResp<T> {
193
195
  data: T;
194
196
  }
195
197
  interface Props$4<T extends Record<string, any>> {
198
+ showIcon?: boolean;
199
+ showFormHeader?: boolean;
196
200
  formTitle: string;
197
201
  formSubTitle?: string;
198
202
  readOnly?: boolean;
@@ -205,8 +209,10 @@ interface Props$4<T extends Record<string, any>> {
205
209
  withCard?: boolean;
206
210
  submitBtnLabel?: string;
207
211
  submitBtnClass?: string;
212
+ children?: ReactNode;
213
+ childrenHeader?: ReactNode;
208
214
  }
209
- declare const DynamicForm: <T extends Record<string, any>>({ formTitle, formSubTitle, fields, readOnly, record, onSubmit, extraValidations, withErrorsAlert, errorAlertPosition, withCard, submitBtnClass, submitBtnLabel, }: Props$4<T>) => react_jsx_runtime.JSX.Element;
215
+ declare const DynamicForm: <T extends Record<string, any>>({ formTitle, formSubTitle, fields, readOnly, record, onSubmit, extraValidations, children, childrenHeader, showIcon, showFormHeader, withErrorsAlert, errorAlertPosition, withCard, submitBtnClass, submitBtnLabel, }: Props$4<T>) => react_jsx_runtime.JSX.Element;
210
216
 
211
217
  declare const DynamicFormExample: () => react_jsx_runtime.JSX.Element;
212
218
  declare const mockFields: Array<FieldProps | FieldProps[]>;
package/dist/index.d.ts CHANGED
@@ -73,13 +73,15 @@ declare enum InputTypes {
73
73
  REPEATER = "repeater",
74
74
  MULTI_SELECT = "multi_select",
75
75
  COMBOBOX = "COMBO_BOX",
76
- SORTABLE_LIST = "sortable_list"
76
+ SORTABLE_LIST = "sortable_list",
77
+ REPEATER_TABS = "repeater_tabs"
77
78
  }
78
79
  declare const inputFieldComp: InputTypes[];
79
80
 
80
81
  interface FieldProps<T = Record<string, any>> {
81
82
  name: keyof T;
82
83
  label: string;
84
+ tabLabelField?: string;
83
85
  childrenPosition?: 'up' | 'down';
84
86
  children?: ReactNode | ((item: any, index: number) => ReactNode);
85
87
  defaultValue?: any;
@@ -193,6 +195,8 @@ interface FormResp<T> {
193
195
  data: T;
194
196
  }
195
197
  interface Props$4<T extends Record<string, any>> {
198
+ showIcon?: boolean;
199
+ showFormHeader?: boolean;
196
200
  formTitle: string;
197
201
  formSubTitle?: string;
198
202
  readOnly?: boolean;
@@ -205,8 +209,10 @@ interface Props$4<T extends Record<string, any>> {
205
209
  withCard?: boolean;
206
210
  submitBtnLabel?: string;
207
211
  submitBtnClass?: string;
212
+ children?: ReactNode;
213
+ childrenHeader?: ReactNode;
208
214
  }
209
- declare const DynamicForm: <T extends Record<string, any>>({ formTitle, formSubTitle, fields, readOnly, record, onSubmit, extraValidations, withErrorsAlert, errorAlertPosition, withCard, submitBtnClass, submitBtnLabel, }: Props$4<T>) => react_jsx_runtime.JSX.Element;
215
+ declare const DynamicForm: <T extends Record<string, any>>({ formTitle, formSubTitle, fields, readOnly, record, onSubmit, extraValidations, children, childrenHeader, showIcon, showFormHeader, withErrorsAlert, errorAlertPosition, withCard, submitBtnClass, submitBtnLabel, }: Props$4<T>) => react_jsx_runtime.JSX.Element;
210
216
 
211
217
  declare const DynamicFormExample: () => react_jsx_runtime.JSX.Element;
212
218
  declare const mockFields: Array<FieldProps | FieldProps[]>;
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, CheckIcon, XIcon, MinusIcon, GripVerticalIcon, ChevronUpIcon, CalendarIcon, EyeOff, Eye, Pencil, Loader2, Save, Plus, MessageCircleWarning, Info, CircleCheck, CircleX, ChevronsUpDown, Check, Trash2, Upload, GripVertical, SearchIcon, CircleIcon } from 'lucide-react';
1
+ import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, CheckIcon, XIcon, MinusIcon, GripVerticalIcon, ChevronUpIcon, CalendarIcon, EyeOff, Eye, Pencil, Loader2, Save, Plus, MessageCircleWarning, Info, CircleCheck, CircleX, Trash2, ChevronsUpDown, Check, Upload, GripVertical, SearchIcon, CircleIcon } from 'lucide-react';
2
2
  import { InfoCircledIcon } from '@radix-ui/react-icons';
3
3
  import { cva } from 'class-variance-authority';
4
4
  import { twMerge } from 'tailwind-merge';
@@ -26,6 +26,7 @@ import { Toaster as Toaster$1 } from 'sonner';
26
26
  import * as SwitchPrimitive from '@radix-ui/react-switch';
27
27
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
28
28
  import { Command as Command$1 } from 'cmdk';
29
+ import * as TabsPrimitive from '@radix-ui/react-tabs';
29
30
  import * as SliderPrimitive from '@radix-ui/react-slider';
30
31
  import { useSensors, useSensor, PointerSensor, KeyboardSensor, DndContext, closestCenter } from '@dnd-kit/core';
31
32
  import { sortableKeyboardCoordinates, SortableContext, verticalListSortingStrategy, arrayMove, useSortable } from '@dnd-kit/sortable';
@@ -236,9 +237,11 @@ var InputTypes = /* @__PURE__ */ ((InputTypes2) => {
236
237
  InputTypes2["MULTI_SELECT"] = "multi_select";
237
238
  InputTypes2["COMBOBOX"] = "COMBO_BOX";
238
239
  InputTypes2["SORTABLE_LIST"] = "sortable_list";
240
+ InputTypes2["REPEATER_TABS"] = "repeater_tabs";
239
241
  return InputTypes2;
240
242
  })(InputTypes || {});
241
243
  var inputFieldComp = [
244
+ "repeater_tabs" /* REPEATER_TABS */,
242
245
  "sortable_list" /* SORTABLE_LIST */,
243
246
  "COMBO_BOX" /* COMBOBOX */,
244
247
  "multi_select" /* MULTI_SELECT */,
@@ -4583,6 +4586,161 @@ var FieldRepeater = ({ form, input, isSubmitting }) => {
4583
4586
  }
4584
4587
  );
4585
4588
  };
4589
+ function Tabs({
4590
+ className,
4591
+ ...props
4592
+ }) {
4593
+ return /* @__PURE__ */ jsx(
4594
+ TabsPrimitive.Root,
4595
+ {
4596
+ "data-slot": "tabs",
4597
+ className: cn("flex flex-col gap-2", className),
4598
+ ...props
4599
+ }
4600
+ );
4601
+ }
4602
+ function TabsList({
4603
+ className,
4604
+ ...props
4605
+ }) {
4606
+ return /* @__PURE__ */ jsx(
4607
+ TabsPrimitive.List,
4608
+ {
4609
+ "data-slot": "tabs-list",
4610
+ className: cn(
4611
+ "bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
4612
+ className
4613
+ ),
4614
+ ...props
4615
+ }
4616
+ );
4617
+ }
4618
+ function TabsTrigger({
4619
+ className,
4620
+ ...props
4621
+ }) {
4622
+ return /* @__PURE__ */ jsx(
4623
+ TabsPrimitive.Trigger,
4624
+ {
4625
+ "data-slot": "tabs-trigger",
4626
+ className: cn(
4627
+ "data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
4628
+ className
4629
+ ),
4630
+ ...props
4631
+ }
4632
+ );
4633
+ }
4634
+ function TabsContent({
4635
+ className,
4636
+ ...props
4637
+ }) {
4638
+ return /* @__PURE__ */ jsx(
4639
+ TabsPrimitive.Content,
4640
+ {
4641
+ "data-slot": "tabs-content",
4642
+ className: cn("flex-1 outline-none", className),
4643
+ ...props
4644
+ }
4645
+ );
4646
+ }
4647
+ var RepeaterTabsInput = class extends BaseInput {
4648
+ render() {
4649
+ const { input, form, isSubmitting } = this;
4650
+ return /* @__PURE__ */ jsx(FieldRepeaterTabs, { form, input, isSubmitting });
4651
+ }
4652
+ };
4653
+ var FieldRepeaterTabs = ({ form, input, isSubmitting }) => {
4654
+ const { control } = form;
4655
+ const { fields, append, remove } = useFieldArray({
4656
+ control,
4657
+ name: input.name
4658
+ });
4659
+ const [activeTab, setActiveTab] = useState(fields[0]?.id ?? "");
4660
+ const canAdd = !input.maxItems || fields.length < input.maxItems;
4661
+ const canRemove = fields.length > (input.minItems ?? 0);
4662
+ const handleAdd = () => {
4663
+ const newItem = { id: `tab-${Date.now()}` };
4664
+ append(newItem);
4665
+ setActiveTab(newItem.id);
4666
+ };
4667
+ const handleRemove = (index) => {
4668
+ const removedId = fields[index].id;
4669
+ remove(index);
4670
+ if (activeTab === removedId && fields.length > 1) {
4671
+ const nextTab = fields[index - 1] ?? fields[0];
4672
+ if (nextTab) setActiveTab(nextTab.id);
4673
+ }
4674
+ };
4675
+ return /* @__PURE__ */ jsx(
4676
+ FormField,
4677
+ {
4678
+ control,
4679
+ name: input.name,
4680
+ render: () => /* @__PURE__ */ jsxs(FormItem, { className: input.className, children: [
4681
+ input.label && /* @__PURE__ */ jsx(FormLabel, { children: /* @__PURE__ */ jsx("b", { children: input.label }) }),
4682
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx("div", { className: "space-y-3", children: /* @__PURE__ */ jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, className: "w-full", children: [
4683
+ /* @__PURE__ */ jsxs(TabsList, { className: "flex w-full justify-start overflow-x-auto", children: [
4684
+ fields.map((item, index) => /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
4685
+ /* @__PURE__ */ jsx(TabsTrigger, { value: item.id, className: "flex items-center gap-1", children: input.tabLabelField ? form.watch(`${input.name}.${index}.${input.tabLabelField}`) || `Item ${index + 1}` : `Item ${index + 1}` }),
4686
+ canRemove && /* @__PURE__ */ jsx(
4687
+ Button,
4688
+ {
4689
+ type: "button",
4690
+ size: "icon",
4691
+ variant: "ghost",
4692
+ onClick: () => handleRemove(index),
4693
+ children: /* @__PURE__ */ jsx(Trash2, { size: 14 })
4694
+ }
4695
+ )
4696
+ ] }, item.id)),
4697
+ canAdd && /* @__PURE__ */ jsxs(
4698
+ Button,
4699
+ {
4700
+ type: "button",
4701
+ variant: "secondary",
4702
+ size: "sm",
4703
+ onClick: handleAdd,
4704
+ disabled: isSubmitting,
4705
+ className: "ml-2",
4706
+ children: [
4707
+ /* @__PURE__ */ jsx(Plus, { size: 14, className: "mr-1" }),
4708
+ " Agregar"
4709
+ ]
4710
+ }
4711
+ )
4712
+ ] }),
4713
+ fields.map((item, index) => /* @__PURE__ */ jsx(TabsContent, { value: item.id, className: "mt-4", children: input.repeaterFields?.map((fieldGroup, groupIndex) => {
4714
+ const group = Array.isArray(fieldGroup) ? fieldGroup : [fieldGroup];
4715
+ const cols = group.length;
4716
+ return /* @__PURE__ */ jsx("div", { className: `grid gap-3 grid-cols-${cols}`, children: group.map((subField) => /* @__PURE__ */ jsx(
4717
+ FormField,
4718
+ {
4719
+ control,
4720
+ name: `${input.name}.${index}.${subField.name}`,
4721
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs(FormItem, { className: "flex-1", children: [
4722
+ /* @__PURE__ */ jsx(FormLabel, { children: subField.label }),
4723
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
4724
+ Input,
4725
+ {
4726
+ placeholder: subField.placeHolder,
4727
+ disabled: subField.disabled || isSubmitting,
4728
+ ...field
4729
+ }
4730
+ ) }),
4731
+ /* @__PURE__ */ jsx(FormMessage, { children: fieldState.error?.message })
4732
+ ] })
4733
+ },
4734
+ `${input.name}.${index}.${subField.name}`
4735
+ )) }, groupIndex);
4736
+ }) }, item.id))
4737
+ ] }) }) }),
4738
+ input.description && /* @__PURE__ */ jsx(FormDescription, { children: input.description }),
4739
+ /* @__PURE__ */ jsx(FormMessage, {})
4740
+ ] })
4741
+ }
4742
+ );
4743
+ };
4586
4744
  var SelectInput = class extends BaseInput {
4587
4745
  render() {
4588
4746
  const { input, form, isSubmitting } = this;
@@ -5262,6 +5420,7 @@ var inputMap = {
5262
5420
  ["multi_select" /* MULTI_SELECT */]: MultiSelectInput,
5263
5421
  ["COMBO_BOX" /* COMBOBOX */]: ComboboxInput,
5264
5422
  ["sortable_list" /* SORTABLE_LIST */]: SortableListInput,
5423
+ ["repeater_tabs" /* REPEATER_TABS */]: RepeaterTabsInput,
5265
5424
  //ToDos: ============================================================
5266
5425
  ["slider" /* SLIDER */]: SliderInput,
5267
5426
  //ToDo: // PENDIENTE ... VISUALMENTE NO SE VE BIEN.!!!
@@ -5424,6 +5583,10 @@ var DynamicForm = ({
5424
5583
  record = {},
5425
5584
  onSubmit,
5426
5585
  extraValidations,
5586
+ children,
5587
+ childrenHeader,
5588
+ showIcon = true,
5589
+ showFormHeader = true,
5427
5590
  withErrorsAlert = true,
5428
5591
  errorAlertPosition = "up",
5429
5592
  withCard = false,
@@ -5453,12 +5616,18 @@ var DynamicForm = ({
5453
5616
  }
5454
5617
  };
5455
5618
  const formContent = /* @__PURE__ */ jsxs("div", { children: [
5456
- /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center gap-2 p-2 border-b", children: [
5457
- /* @__PURE__ */ jsx(Pencil, { className: "h-5 w-5" }),
5458
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
5459
- /* @__PURE__ */ jsx("p", { children: formTitle }),
5460
- formSubTitle && /* @__PURE__ */ jsx(CardDescription, { children: formSubTitle })
5461
- ] })
5619
+ showFormHeader && /* @__PURE__ */ jsxs(CardTitle, { className: "flex flex-row items-center gap-2 p-2 border-b", children: [
5620
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-row items-center gap-2 w-full", children: [
5621
+ showIcon && /* @__PURE__ */ jsx(Pencil, { className: "h-5 w-5" }),
5622
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
5623
+ /* @__PURE__ */ jsxs(CardTitle, { className: "text-xl", children: [
5624
+ formTitle,
5625
+ " "
5626
+ ] }),
5627
+ formSubTitle && /* @__PURE__ */ jsx(CardDescription, { children: formSubTitle })
5628
+ ] })
5629
+ ] }),
5630
+ childrenHeader && /* @__PURE__ */ jsx("div", { className: "flex flex-row items-center gap-2 w-full h-full", children: childrenHeader })
5462
5631
  ] }),
5463
5632
  withErrorsAlert && errorAlertPosition === "up" && /* @__PURE__ */ jsx(FormErrorsAlert, { formState: form.formState, fields }),
5464
5633
  /* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsxs(
@@ -5467,7 +5636,10 @@ var DynamicForm = ({
5467
5636
  onSubmit: form.handleSubmit(handleSubmit),
5468
5637
  className: `flex flex-col gap-2 ${readOnly ? "opacity-70 pointer-events-none select-none" : ""}`,
5469
5638
  children: [
5470
- /* @__PURE__ */ jsx("div", { className: "w-full grid grid-cols-1", children: /* @__PURE__ */ jsx(FormFieldsGrid, { fields, form, readOnly }) }),
5639
+ /* @__PURE__ */ jsxs("div", { className: "w-full grid grid-cols-1", children: [
5640
+ /* @__PURE__ */ jsx(FormFieldsGrid, { fields, form, readOnly }),
5641
+ children && /* @__PURE__ */ jsx("div", { className: "flex flex-row items-center gap-2 w-full h-full", children })
5642
+ ] }),
5471
5643
  !readOnly && /* @__PURE__ */ jsx("div", { className: "flex flex-row gap-2 justify-end items-end", children: /* @__PURE__ */ jsx(Button, { type: "submit", size: "lg", className: submitBtnClass, disabled: isPending, children: isPending ? /* @__PURE__ */ jsxs(Fragment, { children: [
5472
5644
  /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 mr-2 animate-spin" }),
5473
5645
  "Guardando..."