shadcn-zod-formkit 1.9.2 → 1.11.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.cjs CHANGED
@@ -268,9 +268,11 @@ var InputTypes = /* @__PURE__ */ ((InputTypes2) => {
268
268
  InputTypes2["KEY_VALUE"] = "key_value";
269
269
  InputTypes2["REPEATER"] = "repeater";
270
270
  InputTypes2["MULTI_SELECT"] = "multi_select";
271
+ InputTypes2["COMBOBOX"] = "COMBO_BOX";
271
272
  return InputTypes2;
272
273
  })(InputTypes || {});
273
274
  var inputFieldComp = [
275
+ "COMBO_BOX" /* COMBOBOX */,
274
276
  "multi_select" /* MULTI_SELECT */,
275
277
  "repeater" /* REPEATER */,
276
278
  "key_value" /* KEY_VALUE */,
@@ -1986,6 +1988,210 @@ var ColorComp = React3__namespace.default.forwardRef(
1986
1988
  ] });
1987
1989
  }
1988
1990
  );
1991
+ function Command({
1992
+ className,
1993
+ ...props
1994
+ }) {
1995
+ return /* @__PURE__ */ jsxRuntime.jsx(
1996
+ cmdk.Command,
1997
+ {
1998
+ "data-slot": "command",
1999
+ className: cn(
2000
+ "bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md",
2001
+ className
2002
+ ),
2003
+ ...props
2004
+ }
2005
+ );
2006
+ }
2007
+ function CommandInput({
2008
+ className,
2009
+ ...props
2010
+ }) {
2011
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2012
+ "div",
2013
+ {
2014
+ "data-slot": "command-input-wrapper",
2015
+ className: "flex h-9 items-center gap-2 border-b px-3",
2016
+ children: [
2017
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SearchIcon, { className: "size-4 shrink-0 opacity-50" }),
2018
+ /* @__PURE__ */ jsxRuntime.jsx(
2019
+ cmdk.Command.Input,
2020
+ {
2021
+ "data-slot": "command-input",
2022
+ className: cn(
2023
+ "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",
2024
+ className
2025
+ ),
2026
+ ...props
2027
+ }
2028
+ )
2029
+ ]
2030
+ }
2031
+ );
2032
+ }
2033
+ function CommandList({
2034
+ className,
2035
+ ...props
2036
+ }) {
2037
+ return /* @__PURE__ */ jsxRuntime.jsx(
2038
+ cmdk.Command.List,
2039
+ {
2040
+ "data-slot": "command-list",
2041
+ className: cn(
2042
+ "max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto",
2043
+ className
2044
+ ),
2045
+ ...props
2046
+ }
2047
+ );
2048
+ }
2049
+ function CommandEmpty({
2050
+ ...props
2051
+ }) {
2052
+ return /* @__PURE__ */ jsxRuntime.jsx(
2053
+ cmdk.Command.Empty,
2054
+ {
2055
+ "data-slot": "command-empty",
2056
+ className: "py-6 text-center text-sm",
2057
+ ...props
2058
+ }
2059
+ );
2060
+ }
2061
+ function CommandGroup({
2062
+ className,
2063
+ ...props
2064
+ }) {
2065
+ return /* @__PURE__ */ jsxRuntime.jsx(
2066
+ cmdk.Command.Group,
2067
+ {
2068
+ "data-slot": "command-group",
2069
+ className: cn(
2070
+ "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",
2071
+ className
2072
+ ),
2073
+ ...props
2074
+ }
2075
+ );
2076
+ }
2077
+ function CommandItem({
2078
+ className,
2079
+ ...props
2080
+ }) {
2081
+ return /* @__PURE__ */ jsxRuntime.jsx(
2082
+ cmdk.Command.Item,
2083
+ {
2084
+ "data-slot": "command-item",
2085
+ className: cn(
2086
+ "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",
2087
+ className
2088
+ ),
2089
+ ...props
2090
+ }
2091
+ );
2092
+ }
2093
+ var ComboboxInput = class extends BaseInput {
2094
+ render() {
2095
+ const { input, form, isSubmitting } = this;
2096
+ return /* @__PURE__ */ jsxRuntime.jsx(FieldCombobox, { input, form, isSubmitting });
2097
+ }
2098
+ };
2099
+ var FieldCombobox = ({ form, input, isSubmitting }) => {
2100
+ const [open, setOpen] = React3__namespace.useState(false);
2101
+ const [options, setOptions] = React3__namespace.useState(
2102
+ () => input.listConfig?.list?.length ? input.listConfig.list : []
2103
+ );
2104
+ const optionValue = input?.listConfig?.optionValue ?? input.optionValue ?? "id";
2105
+ const [value, setValue] = React3__namespace.useState(input.value?.toString() ?? "");
2106
+ React3__namespace.useEffect(() => {
2107
+ const dependsOn = input.dependsOn;
2108
+ if (!dependsOn || !input.loadOptions) return;
2109
+ const subscription = form.watch(async (values) => {
2110
+ const parentValue = values[dependsOn];
2111
+ if (parentValue) {
2112
+ const loader = input.loadOptions;
2113
+ const newOptions = await loader(parentValue);
2114
+ setOptions(newOptions);
2115
+ form.setValue(input.name, "");
2116
+ setValue("");
2117
+ } else {
2118
+ setOptions([]);
2119
+ }
2120
+ });
2121
+ return () => subscription.unsubscribe?.();
2122
+ }, [form, input.loadOptions, input.dependsOn]);
2123
+ React3__namespace.useEffect(() => {
2124
+ const currentValue = form.getValues(input.name);
2125
+ if (!currentValue && input.value) {
2126
+ form.setValue(input.name, input.value);
2127
+ setValue(input.value.toString());
2128
+ }
2129
+ }, [form, input.name, input.value]);
2130
+ const getValue = (item) => (optionValue === "name" ? item.name : item.value?.toString() ?? item.id?.toString()) ?? "";
2131
+ const selectedOption = options.find((o) => getValue(o) === value);
2132
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
2133
+ input.label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: "font-medium text-sm", children: input.label }),
2134
+ /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: setOpen, children: [
2135
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
2136
+ Button,
2137
+ {
2138
+ disabled: input.disabled || isSubmitting,
2139
+ variant: "outline",
2140
+ role: "combobox",
2141
+ "aria-expanded": open,
2142
+ className: "w-[60%] justify-between bg-black/10 dark:bg-white/25",
2143
+ children: [
2144
+ selectedOption ? selectedOption.name : input.placeHolder ?? "Seleccionar...",
2145
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsUpDown, { className: "opacity-50" })
2146
+ ]
2147
+ }
2148
+ ) }),
2149
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverContent, { className: "w-[60%] p-0", children: /* @__PURE__ */ jsxRuntime.jsxs(
2150
+ Command,
2151
+ {
2152
+ filter: (value2, search) => {
2153
+ const option = options.find((o) => getValue(o) === value2);
2154
+ return option?.name?.toLowerCase().includes(search.toLowerCase()) ? 1 : 0;
2155
+ },
2156
+ children: [
2157
+ /* @__PURE__ */ jsxRuntime.jsx(CommandInput, { placeholder: `Buscar ${input.label?.toLowerCase()}...`, className: "h-9" }),
2158
+ /* @__PURE__ */ jsxRuntime.jsxs(CommandList, { children: [
2159
+ /* @__PURE__ */ jsxRuntime.jsx(CommandEmpty, { children: "No se encontraron resultados." }),
2160
+ /* @__PURE__ */ jsxRuntime.jsx(CommandGroup, { children: options.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
2161
+ CommandItem,
2162
+ {
2163
+ value: getValue(item),
2164
+ onSelect: (currentValue) => {
2165
+ const newValue = currentValue === value ? "" : currentValue;
2166
+ setValue(newValue);
2167
+ form.setValue(input.name, newValue);
2168
+ input.listConfig?.onOptionChange?.(
2169
+ options.find((o) => getValue(o) === newValue)
2170
+ );
2171
+ setOpen(false);
2172
+ },
2173
+ children: [
2174
+ item.name,
2175
+ /* @__PURE__ */ jsxRuntime.jsx(
2176
+ lucideReact.Check,
2177
+ {
2178
+ className: cn(
2179
+ "ml-auto",
2180
+ value === getValue(item) ? "opacity-100" : "opacity-0"
2181
+ )
2182
+ }
2183
+ )
2184
+ ]
2185
+ },
2186
+ item.id
2187
+ )) })
2188
+ ] })
2189
+ ]
2190
+ }
2191
+ ) })
2192
+ ] })
2193
+ ] });
2194
+ };
1989
2195
  var CurrencyInput = class extends BaseInput {
1990
2196
  render() {
1991
2197
  const { input, form, isSubmitting } = this;
@@ -4047,108 +4253,6 @@ var FieldKeyValueList = ({ form, input, isSubmitting }) => {
4047
4253
  }
4048
4254
  );
4049
4255
  };
4050
- function Command({
4051
- className,
4052
- ...props
4053
- }) {
4054
- return /* @__PURE__ */ jsxRuntime.jsx(
4055
- cmdk.Command,
4056
- {
4057
- "data-slot": "command",
4058
- className: cn(
4059
- "bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md",
4060
- className
4061
- ),
4062
- ...props
4063
- }
4064
- );
4065
- }
4066
- function CommandInput({
4067
- className,
4068
- ...props
4069
- }) {
4070
- return /* @__PURE__ */ jsxRuntime.jsxs(
4071
- "div",
4072
- {
4073
- "data-slot": "command-input-wrapper",
4074
- className: "flex h-9 items-center gap-2 border-b px-3",
4075
- children: [
4076
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SearchIcon, { className: "size-4 shrink-0 opacity-50" }),
4077
- /* @__PURE__ */ jsxRuntime.jsx(
4078
- cmdk.Command.Input,
4079
- {
4080
- "data-slot": "command-input",
4081
- className: cn(
4082
- "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",
4083
- className
4084
- ),
4085
- ...props
4086
- }
4087
- )
4088
- ]
4089
- }
4090
- );
4091
- }
4092
- function CommandList({
4093
- className,
4094
- ...props
4095
- }) {
4096
- return /* @__PURE__ */ jsxRuntime.jsx(
4097
- cmdk.Command.List,
4098
- {
4099
- "data-slot": "command-list",
4100
- className: cn(
4101
- "max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto",
4102
- className
4103
- ),
4104
- ...props
4105
- }
4106
- );
4107
- }
4108
- function CommandEmpty({
4109
- ...props
4110
- }) {
4111
- return /* @__PURE__ */ jsxRuntime.jsx(
4112
- cmdk.Command.Empty,
4113
- {
4114
- "data-slot": "command-empty",
4115
- className: "py-6 text-center text-sm",
4116
- ...props
4117
- }
4118
- );
4119
- }
4120
- function CommandGroup({
4121
- className,
4122
- ...props
4123
- }) {
4124
- return /* @__PURE__ */ jsxRuntime.jsx(
4125
- cmdk.Command.Group,
4126
- {
4127
- "data-slot": "command-group",
4128
- className: cn(
4129
- "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",
4130
- className
4131
- ),
4132
- ...props
4133
- }
4134
- );
4135
- }
4136
- function CommandItem({
4137
- className,
4138
- ...props
4139
- }) {
4140
- return /* @__PURE__ */ jsxRuntime.jsx(
4141
- cmdk.Command.Item,
4142
- {
4143
- "data-slot": "command-item",
4144
- className: cn(
4145
- "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",
4146
- className
4147
- ),
4148
- ...props
4149
- }
4150
- );
4151
- }
4152
4256
  var MultiSelectInput = class extends BaseInput {
4153
4257
  render() {
4154
4258
  const { input, form, isSubmitting } = this;
@@ -4524,11 +4628,12 @@ var FieldSelect = ({ form, input, isSubmitting }) => {
4524
4628
  { value: 3, id: 3, name: "MOCK OPTION - PERMISO 3" },
4525
4629
  { value: 4, id: 4, name: "MOCK OPTION - PERMISO 4" }
4526
4630
  ];
4527
- const lista = input?.listConfig?.list?.every((item) => "name" in item) ? input.listConfig.list : mockInputOptions;
4528
- const optionValue = input?.listConfig?.optionValue ?? input.optionValue ?? "id";
4529
- const [value, setValue] = React3.useState(
4530
- input.value?.toString() ?? ""
4631
+ const [lista, setLista] = React3.useState(
4632
+ input?.listConfig?.list?.every((item) => "name" in item) ? input.listConfig.list : mockInputOptions
4531
4633
  );
4634
+ const [loading, setLoading] = React3.useState(false);
4635
+ const [value, setValue] = React3.useState(input.value?.toString() ?? "");
4636
+ const optionValue = input?.listConfig?.optionValue ?? input.optionValue ?? "id";
4532
4637
  React3.useEffect(() => {
4533
4638
  const currentValue = form.getValues(input.name);
4534
4639
  if (!currentValue && input.value) {
@@ -4536,8 +4641,32 @@ var FieldSelect = ({ form, input, isSubmitting }) => {
4536
4641
  setValue(input.value.toString());
4537
4642
  }
4538
4643
  }, [form, input.name, input.value]);
4644
+ React3.useEffect(() => {
4645
+ if (input.dependsOn && input.loadOptions) {
4646
+ const subscription = form.watch(async (values) => {
4647
+ const dependencyValue = values[input.dependsOn];
4648
+ if (dependencyValue) {
4649
+ try {
4650
+ setLoading(true);
4651
+ const newOptions = await input.loadOptions(dependencyValue);
4652
+ setLista(newOptions);
4653
+ } catch (err) {
4654
+ console.error(`Error loading options for ${input.name}:`, err);
4655
+ setLista([]);
4656
+ } finally {
4657
+ setLoading(false);
4658
+ }
4659
+ } else {
4660
+ setLista([]);
4661
+ form.setValue(input.name, "");
4662
+ }
4663
+ });
4664
+ return () => subscription.unsubscribe?.();
4665
+ }
4666
+ }, [form, input.dependsOn, input.loadOptions, input.name]);
4539
4667
  const getValue = (item) => {
4540
- return (optionValue === "name" ? item.name.toString() : item.value.toString() ?? item.id).toString();
4668
+ const val = optionValue === "name" ? item.name : item.value?.toString?.() ?? item.id?.toString();
4669
+ return val?.toString() ?? "";
4541
4670
  };
4542
4671
  return /* @__PURE__ */ jsxRuntime.jsx(
4543
4672
  FormField,
@@ -4555,15 +4684,29 @@ var FieldSelect = ({ form, input, isSubmitting }) => {
4555
4684
  /* @__PURE__ */ jsxRuntime.jsx(FormControl, { children: /* @__PURE__ */ jsxRuntime.jsxs(
4556
4685
  Select,
4557
4686
  {
4558
- disabled: input.disabled || isSubmitting,
4687
+ disabled: input.disabled || isSubmitting || loading,
4559
4688
  onValueChange: (val) => {
4560
4689
  field.onChange(val);
4561
4690
  setValue(val);
4691
+ if (input.listConfig?.onOptionChange) {
4692
+ const selectedItem = lista.find(
4693
+ (item) => getValue(item) === val
4694
+ );
4695
+ input.listConfig.onOptionChange(selectedItem);
4696
+ }
4562
4697
  },
4563
4698
  value: currentValue || void 0,
4564
4699
  children: [
4565
- /* @__PURE__ */ jsxRuntime.jsx(FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { className: "w-[60%] bg-black/10 dark:bg-white/25", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: input.placeHolder }) }) }),
4566
- /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: lista.map((item) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: getValue(item), children: item.name }, item.id)) })
4700
+ /* @__PURE__ */ jsxRuntime.jsx(FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { className: "w-[60%] bg-black/10 dark:bg-white/25", children: /* @__PURE__ */ jsxRuntime.jsx(
4701
+ SelectValue,
4702
+ {
4703
+ placeholder: loading ? "Cargando..." : input.placeHolder ?? "Seleccionar"
4704
+ }
4705
+ ) }) }),
4706
+ /* @__PURE__ */ jsxRuntime.jsxs(SelectContent, { children: [
4707
+ lista.map((item) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: getValue(item), children: item.name }, item.id)),
4708
+ lista.length === 0 && !loading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 text-sm text-muted-foreground", children: "No hay opciones disponibles" })
4709
+ ] })
4567
4710
  ]
4568
4711
  }
4569
4712
  ) })
@@ -5052,6 +5195,7 @@ var inputMap = {
5052
5195
  ["key_value" /* KEY_VALUE */]: KeyValueListInput,
5053
5196
  ["repeater" /* REPEATER */]: RepeaterInput,
5054
5197
  ["multi_select" /* MULTI_SELECT */]: MultiSelectInput,
5198
+ ["COMBO_BOX" /* COMBOBOX */]: ComboboxInput,
5055
5199
  //ToDos: ============================================================
5056
5200
  ["slider" /* SLIDER */]: SliderInput,
5057
5201
  //ToDo: // PENDIENTE ... VISUALMENTE NO SE VE BIEN.!!!