shadcn-zod-formkit 1.2.0 → 1.4.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/README.md +2 -0
- package/dist/index.cjs +245 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.mjs +246 -4
- package/dist/index.mjs.map +1 -1
- package/dist/shadcn-zod-formkit-1.4.0.tgz +0 -0
- package/package.json +1 -1
- package/dist/shadcn-zod-formkit-1.2.0.tgz +0 -0
package/README.md
CHANGED
|
@@ -115,6 +115,8 @@ const mockFields: Array<FieldProps |FieldProps[]> = [
|
|
|
115
115
|
| **Input Time** | `InputTypes.TIME` |
|
|
116
116
|
| **Upload Multi File** | `InputTypes.FILE_MULTI_UPLOAD` |
|
|
117
117
|
| **Button Group** | `InputTypes.BUTTON_GROUP` |
|
|
118
|
+
| **Input Currency** | `InputTypes.CURRENCY` |
|
|
119
|
+
| **Input Key Value** | `InputTypes.KEY_VALUE` |
|
|
118
120
|
|
|
119
121
|
|
|
120
122
|
|
package/dist/index.cjs
CHANGED
|
@@ -263,9 +263,13 @@ var InputTypes = /* @__PURE__ */ ((InputTypes2) => {
|
|
|
263
263
|
InputTypes2["FILE_MULTI_UPLOAD"] = "file_multi_upload";
|
|
264
264
|
InputTypes2["SLIDER"] = "slider";
|
|
265
265
|
InputTypes2["BUTTON_GROUP"] = "button_group";
|
|
266
|
+
InputTypes2["CURRENCY"] = "currency";
|
|
267
|
+
InputTypes2["KEY_VALUE"] = "key_value";
|
|
266
268
|
return InputTypes2;
|
|
267
269
|
})(InputTypes || {});
|
|
268
270
|
var inputFieldComp = [
|
|
271
|
+
"key_value" /* KEY_VALUE */,
|
|
272
|
+
"currency" /* CURRENCY */,
|
|
269
273
|
"button_group" /* BUTTON_GROUP */,
|
|
270
274
|
"slider" /* SLIDER */,
|
|
271
275
|
"file_multi_upload" /* FILE_MULTI_UPLOAD */,
|
|
@@ -1977,6 +1981,124 @@ var ColorComp = React3__namespace.default.forwardRef(
|
|
|
1977
1981
|
] });
|
|
1978
1982
|
}
|
|
1979
1983
|
);
|
|
1984
|
+
var CurrencyInput = class extends BaseInput {
|
|
1985
|
+
render() {
|
|
1986
|
+
const { input, form, isSubmitting } = this;
|
|
1987
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FieldCurrency, { input, form, isSubmitting });
|
|
1988
|
+
}
|
|
1989
|
+
};
|
|
1990
|
+
var FieldCurrency = ({ form, input, isSubmitting }) => {
|
|
1991
|
+
const groupConfig = input.inputGroupConfig;
|
|
1992
|
+
input?.infoTooltip;
|
|
1993
|
+
const autoValidate = groupConfig?.autoValidIcons;
|
|
1994
|
+
const iconValidState = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleCheck, { style: { color: "#00bf3e" } });
|
|
1995
|
+
const iconInvalidState = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleX, { style: { color: "#ff8080" } });
|
|
1996
|
+
const iconLoadingState = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "animate-spin", style: { color: "#1e90ff" } });
|
|
1997
|
+
const [isValid2, setIsValid] = React3.useState(() => {
|
|
1998
|
+
const value = form.getValues(input.name);
|
|
1999
|
+
const fieldState = form.getFieldState(input.name);
|
|
2000
|
+
return !fieldState.error && value !== void 0 && value !== "";
|
|
2001
|
+
});
|
|
2002
|
+
const defaultCurrencyFormat = {
|
|
2003
|
+
style: "currency",
|
|
2004
|
+
currency: "USD",
|
|
2005
|
+
minimumFractionDigits: 2,
|
|
2006
|
+
maximumFractionDigits: 2
|
|
2007
|
+
};
|
|
2008
|
+
const mask = input?.mask;
|
|
2009
|
+
const currencyFormat = input?.currencyFormat ?? defaultCurrencyFormat;
|
|
2010
|
+
const [rawValue, setRawValue] = React3.useState(form.getValues(input.name) ?? "");
|
|
2011
|
+
const formatter = React3.useMemo(() => {
|
|
2012
|
+
return new Intl.NumberFormat("es-DO", currencyFormat);
|
|
2013
|
+
}, [currencyFormat]);
|
|
2014
|
+
const parseValue = (formatted) => {
|
|
2015
|
+
const numeric = parseFloat(formatted.replace(/[^0-9.-]/g, ""));
|
|
2016
|
+
return isNaN(numeric) ? null : numeric;
|
|
2017
|
+
};
|
|
2018
|
+
const formatValue = (value) => {
|
|
2019
|
+
if (!value) return "";
|
|
2020
|
+
const numeric = parseFloat(value.replace(/[^0-9.-]/g, ""));
|
|
2021
|
+
if (isNaN(numeric)) return "";
|
|
2022
|
+
if (typeof mask === "string") {
|
|
2023
|
+
return mask.replace(/0+(?:[.,]0+)?/, formatter.format(numeric).replace(/[^\d.,]/g, ""));
|
|
2024
|
+
}
|
|
2025
|
+
if (mask instanceof RegExp) {
|
|
2026
|
+
const valid = mask.test(value);
|
|
2027
|
+
return valid ? value : rawValue;
|
|
2028
|
+
}
|
|
2029
|
+
return formatter.format(numeric);
|
|
2030
|
+
};
|
|
2031
|
+
const handleKeyDown = (e) => {
|
|
2032
|
+
const allowedKeys = [
|
|
2033
|
+
"Backspace",
|
|
2034
|
+
"Delete",
|
|
2035
|
+
"Tab",
|
|
2036
|
+
"ArrowLeft",
|
|
2037
|
+
"ArrowRight",
|
|
2038
|
+
"Home",
|
|
2039
|
+
"End"
|
|
2040
|
+
];
|
|
2041
|
+
if (allowedKeys.includes(e.key)) return;
|
|
2042
|
+
if (!/^[0-9.]$/.test(e.key)) {
|
|
2043
|
+
e.preventDefault();
|
|
2044
|
+
return;
|
|
2045
|
+
}
|
|
2046
|
+
if (e.key === "." && rawValue.includes(".")) {
|
|
2047
|
+
e.preventDefault();
|
|
2048
|
+
}
|
|
2049
|
+
};
|
|
2050
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2051
|
+
FormField,
|
|
2052
|
+
{
|
|
2053
|
+
control: form.control,
|
|
2054
|
+
name: input.name,
|
|
2055
|
+
render: ({ field, fieldState }) => {
|
|
2056
|
+
const validNow = !fieldState.error && field.value !== void 0 && field.value !== "";
|
|
2057
|
+
if (validNow !== isValid2) setIsValid(validNow);
|
|
2058
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(FormItem, { className: input.className, children: [
|
|
2059
|
+
/* @__PURE__ */ jsxRuntime.jsx(FormLabel, { children: /* @__PURE__ */ jsxRuntime.jsx("b", { children: input.label }) }),
|
|
2060
|
+
/* @__PURE__ */ jsxRuntime.jsx(FormControl, { children: /* @__PURE__ */ jsxRuntime.jsxs(InputGroup, { children: [
|
|
2061
|
+
/* @__PURE__ */ jsxRuntime.jsxs(InputGroupAddon, { children: [
|
|
2062
|
+
/* @__PURE__ */ jsxRuntime.jsx(InputGroupText, { children: "$" }),
|
|
2063
|
+
input.inputGroupConfig?.textLeft && /* @__PURE__ */ jsxRuntime.jsx(InputGroupText, { children: input.inputGroupConfig.textLeft })
|
|
2064
|
+
] }),
|
|
2065
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2066
|
+
InputGroupInput,
|
|
2067
|
+
{
|
|
2068
|
+
...field,
|
|
2069
|
+
disabled: input.disabled || isSubmitting,
|
|
2070
|
+
placeholder: input.placeHolder ?? "0.00",
|
|
2071
|
+
inputMode: "decimal",
|
|
2072
|
+
value: rawValue,
|
|
2073
|
+
onKeyDown: handleKeyDown,
|
|
2074
|
+
onChange: (e) => {
|
|
2075
|
+
const newVal = e.target.value;
|
|
2076
|
+
setRawValue(newVal);
|
|
2077
|
+
const parsed = parseValue(newVal);
|
|
2078
|
+
if (parsed !== null) field.onChange(parsed);
|
|
2079
|
+
},
|
|
2080
|
+
onBlur: (e) => {
|
|
2081
|
+
const formatted = formatValue(e.target.value);
|
|
2082
|
+
setRawValue(formatted);
|
|
2083
|
+
},
|
|
2084
|
+
onFocus: (e) => {
|
|
2085
|
+
const numeric = e.target.value.replace(/[^0-9.-]/g, "");
|
|
2086
|
+
setRawValue(numeric);
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
),
|
|
2090
|
+
/* @__PURE__ */ jsxRuntime.jsxs(InputGroupAddon, { align: "inline-end", children: [
|
|
2091
|
+
/* @__PURE__ */ jsxRuntime.jsx(InputGroupText, { children: currencyFormat.currency }),
|
|
2092
|
+
input.inputGroupConfig?.textRight && /* @__PURE__ */ jsxRuntime.jsx(InputGroupText, { children: input.inputGroupConfig.textRight }),
|
|
2093
|
+
autoValidate && /* @__PURE__ */ jsxRuntime.jsx("div", { children: isSubmitting ? iconLoadingState : isValid2 ? iconValidState : iconInvalidState })
|
|
2094
|
+
] })
|
|
2095
|
+
] }) }),
|
|
2096
|
+
/* @__PURE__ */ jsxRuntime.jsx(FormMessage, {})
|
|
2097
|
+
] });
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
);
|
|
2101
|
+
};
|
|
1980
2102
|
var millisecondsInWeek = 6048e5;
|
|
1981
2103
|
var millisecondsInDay = 864e5;
|
|
1982
2104
|
var constructFromSymbol = Symbol.for("constructDateFrom");
|
|
@@ -3813,6 +3935,113 @@ var FieldFileMultiUpload = ({ input, form, isSubmitting }) => {
|
|
|
3813
3935
|
);
|
|
3814
3936
|
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: formField });
|
|
3815
3937
|
};
|
|
3938
|
+
var KeyValueListInput = class extends BaseInput {
|
|
3939
|
+
render() {
|
|
3940
|
+
const { input, form, isSubmitting } = this;
|
|
3941
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3942
|
+
FieldKeyValueList,
|
|
3943
|
+
{
|
|
3944
|
+
input,
|
|
3945
|
+
form,
|
|
3946
|
+
isSubmitting
|
|
3947
|
+
}
|
|
3948
|
+
);
|
|
3949
|
+
}
|
|
3950
|
+
};
|
|
3951
|
+
var FieldKeyValueList = ({ form, input, isSubmitting }) => {
|
|
3952
|
+
const fieldName = input.name;
|
|
3953
|
+
React3.useEffect(() => {
|
|
3954
|
+
const current = form.getValues(fieldName);
|
|
3955
|
+
if (!Array.isArray(current)) {
|
|
3956
|
+
form.setValue(fieldName, []);
|
|
3957
|
+
}
|
|
3958
|
+
}, [form, fieldName]);
|
|
3959
|
+
const handleAddPair = () => {
|
|
3960
|
+
const current = form.getValues(fieldName) || [];
|
|
3961
|
+
form.setValue(fieldName, [...current, { key: "", value: "" }]);
|
|
3962
|
+
};
|
|
3963
|
+
const handleRemovePair = (index) => {
|
|
3964
|
+
const current = form.getValues(fieldName) || [];
|
|
3965
|
+
const updated = current.filter((_, i) => i !== index);
|
|
3966
|
+
form.setValue(fieldName, updated);
|
|
3967
|
+
};
|
|
3968
|
+
const handleChange = (index, fieldType, newValue) => {
|
|
3969
|
+
const current = form.getValues(fieldName) || [];
|
|
3970
|
+
const updated = current.map(
|
|
3971
|
+
(item, i) => i === index ? { ...item, [fieldType]: newValue } : item
|
|
3972
|
+
);
|
|
3973
|
+
form.setValue(fieldName, updated);
|
|
3974
|
+
};
|
|
3975
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3976
|
+
FormField,
|
|
3977
|
+
{
|
|
3978
|
+
control: form.control,
|
|
3979
|
+
name: fieldName,
|
|
3980
|
+
render: () => {
|
|
3981
|
+
const pairs = form.watch(fieldName) || [];
|
|
3982
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(FormItem, { className: input.className, children: [
|
|
3983
|
+
/* @__PURE__ */ jsxRuntime.jsx(FormLabel, { children: /* @__PURE__ */ jsxRuntime.jsx("b", { children: input.label }) }),
|
|
3984
|
+
/* @__PURE__ */ jsxRuntime.jsx(FormMessage, {}),
|
|
3985
|
+
/* @__PURE__ */ jsxRuntime.jsx(FormControl, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 shadow-lg rounded-xl p-3 bg-white", children: [
|
|
3986
|
+
pairs.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "No pairs have been added yet." }),
|
|
3987
|
+
pairs.map((pair, index) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3988
|
+
"div",
|
|
3989
|
+
{
|
|
3990
|
+
className: "flex gap-2 items-center",
|
|
3991
|
+
children: [
|
|
3992
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3993
|
+
Input,
|
|
3994
|
+
{
|
|
3995
|
+
placeholder: "Key",
|
|
3996
|
+
value: pair.key,
|
|
3997
|
+
disabled: isSubmitting,
|
|
3998
|
+
onChange: (e) => handleChange(index, "key", e.target.value),
|
|
3999
|
+
className: "w-1/2"
|
|
4000
|
+
}
|
|
4001
|
+
),
|
|
4002
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4003
|
+
Input,
|
|
4004
|
+
{
|
|
4005
|
+
placeholder: "Value",
|
|
4006
|
+
value: pair.value,
|
|
4007
|
+
disabled: isSubmitting,
|
|
4008
|
+
onChange: (e) => handleChange(index, "value", e.target.value),
|
|
4009
|
+
className: "w-1/2"
|
|
4010
|
+
}
|
|
4011
|
+
),
|
|
4012
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4013
|
+
Button,
|
|
4014
|
+
{
|
|
4015
|
+
type: "button",
|
|
4016
|
+
variant: "destructive",
|
|
4017
|
+
size: "icon",
|
|
4018
|
+
onClick: () => handleRemovePair(index),
|
|
4019
|
+
disabled: isSubmitting,
|
|
4020
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { size: 18 })
|
|
4021
|
+
}
|
|
4022
|
+
)
|
|
4023
|
+
]
|
|
4024
|
+
},
|
|
4025
|
+
index
|
|
4026
|
+
)),
|
|
4027
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-end mt-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4028
|
+
Button,
|
|
4029
|
+
{
|
|
4030
|
+
type: "button",
|
|
4031
|
+
variant: "outline",
|
|
4032
|
+
size: "sm",
|
|
4033
|
+
onClick: handleAddPair,
|
|
4034
|
+
disabled: isSubmitting,
|
|
4035
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { size: 18, className: "mr-1" })
|
|
4036
|
+
}
|
|
4037
|
+
) })
|
|
4038
|
+
] }) }),
|
|
4039
|
+
input.description && /* @__PURE__ */ jsxRuntime.jsx(FormDescription, { children: input.description })
|
|
4040
|
+
] });
|
|
4041
|
+
}
|
|
4042
|
+
}
|
|
4043
|
+
);
|
|
4044
|
+
};
|
|
3816
4045
|
var TextInputGroup = class extends BaseInput {
|
|
3817
4046
|
render() {
|
|
3818
4047
|
const { input, form, isSubmitting } = this;
|
|
@@ -3835,6 +4064,9 @@ var FieldTextGroup = ({ form, input, isSubmitting }) => {
|
|
|
3835
4064
|
const fieldState = form.getFieldState(input.name);
|
|
3836
4065
|
return !fieldState.error && value !== void 0 && value !== "";
|
|
3837
4066
|
});
|
|
4067
|
+
const [showPassword, setShowPassword] = React3.useState(false);
|
|
4068
|
+
const isPasswordField = input.keyboardType === "password";
|
|
4069
|
+
const showInputGroupAddons = iconsRight.length > 0 || textRight || autoValidate || infoTooltip || isPasswordField;
|
|
3838
4070
|
const formField = /* @__PURE__ */ jsxRuntime.jsx(
|
|
3839
4071
|
FormField,
|
|
3840
4072
|
{
|
|
@@ -3856,16 +4088,25 @@ var FieldTextGroup = ({ form, input, isSubmitting }) => {
|
|
|
3856
4088
|
placeholder: input.placeHolder,
|
|
3857
4089
|
disabled: input.disabled || isSubmitting,
|
|
3858
4090
|
...field,
|
|
3859
|
-
type:
|
|
4091
|
+
type: isPasswordField && !showPassword ? "password" : "text"
|
|
3860
4092
|
}
|
|
3861
4093
|
),
|
|
3862
|
-
|
|
4094
|
+
showInputGroupAddons && /* @__PURE__ */ jsxRuntime.jsxs(InputGroupAddon, { align: "inline-end", children: [
|
|
3863
4095
|
infoTooltip && /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
|
|
3864
4096
|
/* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Info, { size: 20 }) }),
|
|
3865
4097
|
/* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: infoTooltip }) })
|
|
3866
4098
|
] }),
|
|
3867
4099
|
textRight && /* @__PURE__ */ jsxRuntime.jsx(InputGroupText, { children: textRight }),
|
|
3868
4100
|
iconsRight.map((IconComponent, index) => /* @__PURE__ */ jsxRuntime.jsx(IconComponent, { size: 20 }, index)),
|
|
4101
|
+
isPasswordField && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4102
|
+
"button",
|
|
4103
|
+
{
|
|
4104
|
+
type: "button",
|
|
4105
|
+
onClick: () => setShowPassword(!showPassword),
|
|
4106
|
+
className: "p-1",
|
|
4107
|
+
children: showPassword ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeOff, { size: 20 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { size: 20 })
|
|
4108
|
+
}
|
|
4109
|
+
),
|
|
3869
4110
|
autoValidate && /* @__PURE__ */ jsxRuntime.jsx("div", { children: isSubmitting ? iconLoadingState : isValid2 ? iconValidState : iconInvalidState })
|
|
3870
4111
|
] })
|
|
3871
4112
|
] }) }),
|
|
@@ -4501,6 +4742,8 @@ var inputMap = {
|
|
|
4501
4742
|
["time" /* TIME */]: TimeInput,
|
|
4502
4743
|
["file_multi_upload" /* FILE_MULTI_UPLOAD */]: FileMultiUploadInput,
|
|
4503
4744
|
["button_group" /* BUTTON_GROUP */]: ButtonGroupInput,
|
|
4745
|
+
["currency" /* CURRENCY */]: CurrencyInput,
|
|
4746
|
+
["key_value" /* KEY_VALUE */]: KeyValueListInput,
|
|
4504
4747
|
//ToDos: ============================================================
|
|
4505
4748
|
["slider" /* SLIDER */]: SliderInput,
|
|
4506
4749
|
//ToDo: // PENDIENTE ... VISUALMENTE NO SE VE BIEN.!!!
|
|
@@ -4510,7 +4753,6 @@ var inputMap = {
|
|
|
4510
4753
|
// [InputTypes.SWITCH_LIST]: SwitchListInput,
|
|
4511
4754
|
// [InputTypes.RANGE]: TextInput,
|
|
4512
4755
|
// [InputTypes.MULTISELECT]: TextInput,
|
|
4513
|
-
// [InputTypes.CURRENCY]: TextInput,
|
|
4514
4756
|
// [InputTypes.IMAGE_UPLOAD]: TextInput,
|
|
4515
4757
|
// [InputTypes.AUDIO_UPLOAD]: TextInput,
|
|
4516
4758
|
// [InputTypes.VIDEO_UPLOAD]: TextInput,
|