shadcn-zod-formkit 1.10.0 → 1.12.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
@@ -71,7 +71,9 @@ declare enum InputTypes {
71
71
  CURRENCY = "currency",
72
72
  KEY_VALUE = "key_value",
73
73
  REPEATER = "repeater",
74
- MULTI_SELECT = "multi_select"
74
+ MULTI_SELECT = "multi_select",
75
+ COMBOBOX = "COMBO_BOX",
76
+ SORTABLE_LIST = "sortable_list"
75
77
  }
76
78
  declare const inputFieldComp: InputTypes[];
77
79
 
package/dist/index.d.ts CHANGED
@@ -71,7 +71,9 @@ declare enum InputTypes {
71
71
  CURRENCY = "currency",
72
72
  KEY_VALUE = "key_value",
73
73
  REPEATER = "repeater",
74
- MULTI_SELECT = "multi_select"
74
+ MULTI_SELECT = "multi_select",
75
+ COMBOBOX = "COMBO_BOX",
76
+ SORTABLE_LIST = "sortable_list"
75
77
  }
76
78
  declare const inputFieldComp: InputTypes[];
77
79
 
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, 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, ChevronsUpDown, Check, Trash2, 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,9 @@ 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 { sortableKeyboardCoordinates, SortableContext, verticalListSortingStrategy, arrayMove, useSortable } from '@dnd-kit/sortable';
30
+ import { CSS } from '@dnd-kit/utilities';
31
+ import { useSensors, useSensor, PointerSensor, KeyboardSensor, DndContext, closestCenter } from '@dnd-kit/core';
29
32
  import * as SliderPrimitive from '@radix-ui/react-slider';
30
33
  import z2 from 'zod';
31
34
  import { zodResolver } from '@hookform/resolvers/zod';
@@ -231,9 +234,13 @@ var InputTypes = /* @__PURE__ */ ((InputTypes2) => {
231
234
  InputTypes2["KEY_VALUE"] = "key_value";
232
235
  InputTypes2["REPEATER"] = "repeater";
233
236
  InputTypes2["MULTI_SELECT"] = "multi_select";
237
+ InputTypes2["COMBOBOX"] = "COMBO_BOX";
238
+ InputTypes2["SORTABLE_LIST"] = "sortable_list";
234
239
  return InputTypes2;
235
240
  })(InputTypes || {});
236
241
  var inputFieldComp = [
242
+ "sortable_list" /* SORTABLE_LIST */,
243
+ "COMBO_BOX" /* COMBOBOX */,
237
244
  "multi_select" /* MULTI_SELECT */,
238
245
  "repeater" /* REPEATER */,
239
246
  "key_value" /* KEY_VALUE */,
@@ -1949,6 +1956,210 @@ var ColorComp = React3__default.forwardRef(
1949
1956
  ] });
1950
1957
  }
1951
1958
  );
1959
+ function Command({
1960
+ className,
1961
+ ...props
1962
+ }) {
1963
+ return /* @__PURE__ */ jsx(
1964
+ Command$1,
1965
+ {
1966
+ "data-slot": "command",
1967
+ className: cn(
1968
+ "bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md",
1969
+ className
1970
+ ),
1971
+ ...props
1972
+ }
1973
+ );
1974
+ }
1975
+ function CommandInput({
1976
+ className,
1977
+ ...props
1978
+ }) {
1979
+ return /* @__PURE__ */ jsxs(
1980
+ "div",
1981
+ {
1982
+ "data-slot": "command-input-wrapper",
1983
+ className: "flex h-9 items-center gap-2 border-b px-3",
1984
+ children: [
1985
+ /* @__PURE__ */ jsx(SearchIcon, { className: "size-4 shrink-0 opacity-50" }),
1986
+ /* @__PURE__ */ jsx(
1987
+ Command$1.Input,
1988
+ {
1989
+ "data-slot": "command-input",
1990
+ className: cn(
1991
+ "placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
1992
+ className
1993
+ ),
1994
+ ...props
1995
+ }
1996
+ )
1997
+ ]
1998
+ }
1999
+ );
2000
+ }
2001
+ function CommandList({
2002
+ className,
2003
+ ...props
2004
+ }) {
2005
+ return /* @__PURE__ */ jsx(
2006
+ Command$1.List,
2007
+ {
2008
+ "data-slot": "command-list",
2009
+ className: cn(
2010
+ "max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto",
2011
+ className
2012
+ ),
2013
+ ...props
2014
+ }
2015
+ );
2016
+ }
2017
+ function CommandEmpty({
2018
+ ...props
2019
+ }) {
2020
+ return /* @__PURE__ */ jsx(
2021
+ Command$1.Empty,
2022
+ {
2023
+ "data-slot": "command-empty",
2024
+ className: "py-6 text-center text-sm",
2025
+ ...props
2026
+ }
2027
+ );
2028
+ }
2029
+ function CommandGroup({
2030
+ className,
2031
+ ...props
2032
+ }) {
2033
+ return /* @__PURE__ */ jsx(
2034
+ Command$1.Group,
2035
+ {
2036
+ "data-slot": "command-group",
2037
+ className: cn(
2038
+ "text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium",
2039
+ className
2040
+ ),
2041
+ ...props
2042
+ }
2043
+ );
2044
+ }
2045
+ function CommandItem({
2046
+ className,
2047
+ ...props
2048
+ }) {
2049
+ return /* @__PURE__ */ jsx(
2050
+ Command$1.Item,
2051
+ {
2052
+ "data-slot": "command-item",
2053
+ className: cn(
2054
+ "data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
2055
+ className
2056
+ ),
2057
+ ...props
2058
+ }
2059
+ );
2060
+ }
2061
+ var ComboboxInput = class extends BaseInput {
2062
+ render() {
2063
+ const { input, form, isSubmitting } = this;
2064
+ return /* @__PURE__ */ jsx(FieldCombobox, { input, form, isSubmitting });
2065
+ }
2066
+ };
2067
+ var FieldCombobox = ({ form, input, isSubmitting }) => {
2068
+ const [open, setOpen] = React3.useState(false);
2069
+ const [options, setOptions] = React3.useState(
2070
+ () => input.listConfig?.list?.length ? input.listConfig.list : []
2071
+ );
2072
+ const optionValue = input?.listConfig?.optionValue ?? input.optionValue ?? "id";
2073
+ const [value, setValue] = React3.useState(input.value?.toString() ?? "");
2074
+ React3.useEffect(() => {
2075
+ const dependsOn = input.dependsOn;
2076
+ if (!dependsOn || !input.loadOptions) return;
2077
+ const subscription = form.watch(async (values) => {
2078
+ const parentValue = values[dependsOn];
2079
+ if (parentValue) {
2080
+ const loader = input.loadOptions;
2081
+ const newOptions = await loader(parentValue);
2082
+ setOptions(newOptions);
2083
+ form.setValue(input.name, "");
2084
+ setValue("");
2085
+ } else {
2086
+ setOptions([]);
2087
+ }
2088
+ });
2089
+ return () => subscription.unsubscribe?.();
2090
+ }, [form, input.loadOptions, input.dependsOn]);
2091
+ React3.useEffect(() => {
2092
+ const currentValue = form.getValues(input.name);
2093
+ if (!currentValue && input.value) {
2094
+ form.setValue(input.name, input.value);
2095
+ setValue(input.value.toString());
2096
+ }
2097
+ }, [form, input.name, input.value]);
2098
+ const getValue = (item) => (optionValue === "name" ? item.name : item.value?.toString() ?? item.id?.toString()) ?? "";
2099
+ const selectedOption = options.find((o) => getValue(o) === value);
2100
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
2101
+ input.label && /* @__PURE__ */ jsx("label", { className: "font-medium text-sm", children: input.label }),
2102
+ /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
2103
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
2104
+ Button,
2105
+ {
2106
+ disabled: input.disabled || isSubmitting,
2107
+ variant: "outline",
2108
+ role: "combobox",
2109
+ "aria-expanded": open,
2110
+ className: "w-[60%] justify-between bg-black/10 dark:bg-white/25",
2111
+ children: [
2112
+ selectedOption ? selectedOption.name : input.placeHolder ?? "Seleccionar...",
2113
+ /* @__PURE__ */ jsx(ChevronsUpDown, { className: "opacity-50" })
2114
+ ]
2115
+ }
2116
+ ) }),
2117
+ /* @__PURE__ */ jsx(PopoverContent, { className: "w-[60%] p-0", children: /* @__PURE__ */ jsxs(
2118
+ Command,
2119
+ {
2120
+ filter: (value2, search) => {
2121
+ const option = options.find((o) => getValue(o) === value2);
2122
+ return option?.name?.toLowerCase().includes(search.toLowerCase()) ? 1 : 0;
2123
+ },
2124
+ children: [
2125
+ /* @__PURE__ */ jsx(CommandInput, { placeholder: `Buscar ${input.label?.toLowerCase()}...`, className: "h-9" }),
2126
+ /* @__PURE__ */ jsxs(CommandList, { children: [
2127
+ /* @__PURE__ */ jsx(CommandEmpty, { children: "No se encontraron resultados." }),
2128
+ /* @__PURE__ */ jsx(CommandGroup, { children: options.map((item) => /* @__PURE__ */ jsxs(
2129
+ CommandItem,
2130
+ {
2131
+ value: getValue(item),
2132
+ onSelect: (currentValue) => {
2133
+ const newValue = currentValue === value ? "" : currentValue;
2134
+ setValue(newValue);
2135
+ form.setValue(input.name, newValue);
2136
+ input.listConfig?.onOptionChange?.(
2137
+ options.find((o) => getValue(o) === newValue)
2138
+ );
2139
+ setOpen(false);
2140
+ },
2141
+ children: [
2142
+ item.name,
2143
+ /* @__PURE__ */ jsx(
2144
+ Check,
2145
+ {
2146
+ className: cn(
2147
+ "ml-auto",
2148
+ value === getValue(item) ? "opacity-100" : "opacity-0"
2149
+ )
2150
+ }
2151
+ )
2152
+ ]
2153
+ },
2154
+ item.id
2155
+ )) })
2156
+ ] })
2157
+ ]
2158
+ }
2159
+ ) })
2160
+ ] })
2161
+ ] });
2162
+ };
1952
2163
  var CurrencyInput = class extends BaseInput {
1953
2164
  render() {
1954
2165
  const { input, form, isSubmitting } = this;
@@ -3749,6 +3960,105 @@ var FieldDateTimeInput = ({ form, input, isSubmitting }) => {
3749
3960
  input.name
3750
3961
  );
3751
3962
  };
3963
+ var SortableListInput = class extends BaseInput {
3964
+ render() {
3965
+ const { input, form, isSubmitting } = this;
3966
+ return /* @__PURE__ */ jsx(FieldSortableList, { form, input, isSubmitting });
3967
+ }
3968
+ };
3969
+ var FieldSortableList = ({ form, input, isSubmitting }) => {
3970
+ const [items, setItems] = useState((input.listConfig?.list ?? []).filter((item) => "name" in item));
3971
+ const sensors = useSensors(
3972
+ useSensor(PointerSensor),
3973
+ useSensor(KeyboardSensor, {
3974
+ coordinateGetter: sortableKeyboardCoordinates
3975
+ })
3976
+ );
3977
+ const handleDragEnd = (event) => {
3978
+ const { active, over } = event;
3979
+ if (!over || active.id === over.id) return;
3980
+ const oldIndex = items.findIndex((i) => i.id === active.id);
3981
+ const newIndex = items.findIndex((i) => i.id === over.id);
3982
+ const newList = arrayMove(items, oldIndex, newIndex);
3983
+ setItems(newList);
3984
+ form.setValue(input.name, newList);
3985
+ if (input.listConfig?.onOptionChange) {
3986
+ input.listConfig.onOptionChange(newList);
3987
+ }
3988
+ };
3989
+ return /* @__PURE__ */ jsx(
3990
+ FormField,
3991
+ {
3992
+ control: form.control,
3993
+ name: input.name,
3994
+ render: () => /* @__PURE__ */ jsxs(FormItem, { className: cn("space-y-2", input.className), children: [
3995
+ /* @__PURE__ */ jsx(FormLabel, { children: /* @__PURE__ */ jsx("b", { children: input.label }) }),
3996
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx("div", { className: "border rounded-md p-3 bg-white", children: /* @__PURE__ */ jsx(
3997
+ DndContext,
3998
+ {
3999
+ sensors,
4000
+ collisionDetection: closestCenter,
4001
+ onDragEnd: handleDragEnd,
4002
+ children: /* @__PURE__ */ jsx(
4003
+ SortableContext,
4004
+ {
4005
+ items: items.map((i) => i.id),
4006
+ strategy: verticalListSortingStrategy,
4007
+ children: items.map((item) => /* @__PURE__ */ jsx(
4008
+ SortableItem,
4009
+ {
4010
+ id: item.id,
4011
+ name: item.name,
4012
+ disabled: isSubmitting
4013
+ },
4014
+ item.id
4015
+ ))
4016
+ }
4017
+ )
4018
+ }
4019
+ ) }) }),
4020
+ input.description && /* @__PURE__ */ jsx(FormDescription, { children: input.description }),
4021
+ /* @__PURE__ */ jsx(FormMessage, {})
4022
+ ] })
4023
+ },
4024
+ input.name
4025
+ );
4026
+ };
4027
+ function SortableItem({
4028
+ id,
4029
+ name,
4030
+ disabled
4031
+ }) {
4032
+ const {
4033
+ attributes,
4034
+ listeners,
4035
+ setNodeRef,
4036
+ transform,
4037
+ transition,
4038
+ isDragging
4039
+ } = useSortable({ id });
4040
+ const style = {
4041
+ transform: CSS.Transform.toString(transform),
4042
+ transition
4043
+ };
4044
+ return /* @__PURE__ */ jsx(
4045
+ "div",
4046
+ {
4047
+ ref: setNodeRef,
4048
+ style,
4049
+ ...attributes,
4050
+ ...listeners,
4051
+ className: cn(
4052
+ "flex items-center justify-between p-2 border rounded-md mb-1 bg-muted/30 cursor-grab select-none",
4053
+ isDragging && "opacity-60 bg-muted/50"
4054
+ ),
4055
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
4056
+ /* @__PURE__ */ jsx(GripVertical, { className: "w-4 h-4 opacity-70" }),
4057
+ /* @__PURE__ */ jsx("span", { children: name })
4058
+ ] })
4059
+ }
4060
+ );
4061
+ }
3752
4062
  var FileInput = class extends BaseInput {
3753
4063
  render() {
3754
4064
  const { input, form, isSubmitting } = this;
@@ -4010,108 +4320,6 @@ var FieldKeyValueList = ({ form, input, isSubmitting }) => {
4010
4320
  }
4011
4321
  );
4012
4322
  };
4013
- function Command({
4014
- className,
4015
- ...props
4016
- }) {
4017
- return /* @__PURE__ */ jsx(
4018
- Command$1,
4019
- {
4020
- "data-slot": "command",
4021
- className: cn(
4022
- "bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md",
4023
- className
4024
- ),
4025
- ...props
4026
- }
4027
- );
4028
- }
4029
- function CommandInput({
4030
- className,
4031
- ...props
4032
- }) {
4033
- return /* @__PURE__ */ jsxs(
4034
- "div",
4035
- {
4036
- "data-slot": "command-input-wrapper",
4037
- className: "flex h-9 items-center gap-2 border-b px-3",
4038
- children: [
4039
- /* @__PURE__ */ jsx(SearchIcon, { className: "size-4 shrink-0 opacity-50" }),
4040
- /* @__PURE__ */ jsx(
4041
- Command$1.Input,
4042
- {
4043
- "data-slot": "command-input",
4044
- className: cn(
4045
- "placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
4046
- className
4047
- ),
4048
- ...props
4049
- }
4050
- )
4051
- ]
4052
- }
4053
- );
4054
- }
4055
- function CommandList({
4056
- className,
4057
- ...props
4058
- }) {
4059
- return /* @__PURE__ */ jsx(
4060
- Command$1.List,
4061
- {
4062
- "data-slot": "command-list",
4063
- className: cn(
4064
- "max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto",
4065
- className
4066
- ),
4067
- ...props
4068
- }
4069
- );
4070
- }
4071
- function CommandEmpty({
4072
- ...props
4073
- }) {
4074
- return /* @__PURE__ */ jsx(
4075
- Command$1.Empty,
4076
- {
4077
- "data-slot": "command-empty",
4078
- className: "py-6 text-center text-sm",
4079
- ...props
4080
- }
4081
- );
4082
- }
4083
- function CommandGroup({
4084
- className,
4085
- ...props
4086
- }) {
4087
- return /* @__PURE__ */ jsx(
4088
- Command$1.Group,
4089
- {
4090
- "data-slot": "command-group",
4091
- className: cn(
4092
- "text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium",
4093
- className
4094
- ),
4095
- ...props
4096
- }
4097
- );
4098
- }
4099
- function CommandItem({
4100
- className,
4101
- ...props
4102
- }) {
4103
- return /* @__PURE__ */ jsx(
4104
- Command$1.Item,
4105
- {
4106
- "data-slot": "command-item",
4107
- className: cn(
4108
- "data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
4109
- className
4110
- ),
4111
- ...props
4112
- }
4113
- );
4114
- }
4115
4323
  var MultiSelectInput = class extends BaseInput {
4116
4324
  render() {
4117
4325
  const { input, form, isSubmitting } = this;
@@ -5054,6 +5262,8 @@ var inputMap = {
5054
5262
  ["key_value" /* KEY_VALUE */]: KeyValueListInput,
5055
5263
  ["repeater" /* REPEATER */]: RepeaterInput,
5056
5264
  ["multi_select" /* MULTI_SELECT */]: MultiSelectInput,
5265
+ ["COMBO_BOX" /* COMBOBOX */]: ComboboxInput,
5266
+ ["sortable_list" /* SORTABLE_LIST */]: SortableListInput,
5057
5267
  //ToDos: ============================================================
5058
5268
  ["slider" /* SLIDER */]: SliderInput,
5059
5269
  //ToDo: // PENDIENTE ... VISUALMENTE NO SE VE BIEN.!!!
@@ -5204,7 +5414,6 @@ var DynamicForm = ({
5204
5414
  const schema = useMemo(() => getDynamicSchema(fields, extraValidations), [fields, extraValidations]);
5205
5415
  const resolver = zodResolver(schema);
5206
5416
  const initialValues = useMemo(() => getDefaultValues(record), [record]);
5207
- console.log("initialValues", initialValues);
5208
5417
  const form = useForm({
5209
5418
  resolver,
5210
5419
  defaultValues: initialValues