@trackunit/react-form-components 0.1.1 → 0.1.3
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/index.cjs.js +281 -57
- package/index.esm.js +282 -59
- package/package.json +1 -1
- package/src/components/EmailInput/EmailInput.d.ts +1 -1
- package/src/components/PhoneInput/PhoneInputValidationUtils.d.ts +4 -0
- package/src/translation.d.ts +2 -2
- package/src/utilities/ColorFieldValidationUtils.d.ts +5 -0
- package/src/utilities/EmailFieldValidationUtils.d.ts +5 -0
- package/src/utilities/NumberFieldValidationUtils.d.ts +6 -0
- package/src/utilities/UrlFieldValidationUtils.d.ts +5 -0
- package/src/utilities/typeUtils.d.ts +12 -0
- package/translation.cjs.js +12 -1
- package/translation.cjs10.js +12 -1
- package/translation.cjs11.js +12 -1
- package/translation.cjs12.js +12 -1
- package/translation.cjs13.js +12 -1
- package/translation.cjs14.js +12 -1
- package/translation.cjs15.js +12 -1
- package/translation.cjs16.js +12 -1
- package/translation.cjs17.js +12 -1
- package/translation.cjs2.js +12 -1
- package/translation.cjs3.js +12 -1
- package/translation.cjs4.js +12 -1
- package/translation.cjs5.js +12 -1
- package/translation.cjs6.js +12 -1
- package/translation.cjs7.js +12 -1
- package/translation.cjs8.js +12 -1
- package/translation.cjs9.js +12 -1
- package/translation.esm.js +12 -1
- package/translation.esm10.js +12 -1
- package/translation.esm11.js +12 -1
- package/translation.esm12.js +12 -1
- package/translation.esm13.js +12 -1
- package/translation.esm14.js +12 -1
- package/translation.esm15.js +12 -1
- package/translation.esm16.js +12 -1
- package/translation.esm17.js +12 -1
- package/translation.esm2.js +12 -1
- package/translation.esm3.js +12 -1
- package/translation.esm4.js +12 -1
- package/translation.esm5.js +12 -1
- package/translation.esm6.js +12 -1
- package/translation.esm7.js +12 -1
- package/translation.esm8.js +12 -1
- package/translation.esm9.js +12 -1
package/index.cjs.js
CHANGED
|
@@ -39,10 +39,19 @@ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
|
39
39
|
|
|
40
40
|
var defaultTranslations = {
|
|
41
41
|
"clearIndicator.icon.tooltip.clearAll": "Clear all",
|
|
42
|
+
"colorField.error.INVALID_HEX_CODE": "Please enter a valid HEX code",
|
|
43
|
+
"colorField.error.REQUIRED": "This field is required",
|
|
42
44
|
"dropzone.input.title": "Drag-and-drop file input",
|
|
43
45
|
"dropzone.label.default": "<clickable>Browse</clickable> or drag files here...",
|
|
46
|
+
"emailField.error.INVALID_EMAIL": "Please enter a valid email address",
|
|
47
|
+
"emailField.error.REQUIRED": "The email address is required",
|
|
44
48
|
"field.notEditable.tooltip": "This field is not editable",
|
|
45
49
|
"field.required.asterisk.tooltip": "This field is required",
|
|
50
|
+
"numberField.error.GREATER_THAN": "Value must be greater than or equal to {{min}}",
|
|
51
|
+
"numberField.error.INVALID_NUMBER": "Please enter a valid number",
|
|
52
|
+
"numberField.error.LESS_THAN": "Value must be less than or equal to {{max}}",
|
|
53
|
+
"numberField.error.NOT_IN_BETWEEN": "Must be between {{min}} and {{max}}",
|
|
54
|
+
"numberField.error.REQUIRED": "This field is required",
|
|
46
55
|
"phoneField.error.INVALID_COUNTRY": "The country code is not valid",
|
|
47
56
|
"phoneField.error.INVALID_LENGTH": "The phone number is not valid",
|
|
48
57
|
"phoneField.error.INVALID_NUMBER": "The phone number is not valid",
|
|
@@ -51,7 +60,9 @@ var defaultTranslations = {
|
|
|
51
60
|
"phoneField.error.REQUIRED_COUNTRY": "The country code is required",
|
|
52
61
|
"phoneField.error.TOO_LONG": "The phone number is too long",
|
|
53
62
|
"phoneField.error.TOO_SHORT": "The phone number is too short",
|
|
54
|
-
"phoneField.error.undefined": ""
|
|
63
|
+
"phoneField.error.undefined": "",
|
|
64
|
+
"urlField.error.INVALID_URL": "Please enter a valid URL",
|
|
65
|
+
"urlField.error.REQUIRED": "The URL is required"
|
|
55
66
|
};
|
|
56
67
|
|
|
57
68
|
/** The translation namespace for this library */
|
|
@@ -630,6 +641,39 @@ const CheckboxField = React.forwardRef(({ label, id, tip, helpText, helpAddon, i
|
|
|
630
641
|
});
|
|
631
642
|
CheckboxField.displayName = "CheckboxField";
|
|
632
643
|
|
|
644
|
+
/**
|
|
645
|
+
*
|
|
646
|
+
* @param inputValue - value to check if it is a string
|
|
647
|
+
* @returns {boolean} - true if value is a string
|
|
648
|
+
*/
|
|
649
|
+
const isString = (inputValue) => {
|
|
650
|
+
return typeof inputValue === "string";
|
|
651
|
+
};
|
|
652
|
+
/**
|
|
653
|
+
*
|
|
654
|
+
* @param inputValue - value to check if it is a number
|
|
655
|
+
* @returns {boolean} - true if value is a number
|
|
656
|
+
*/
|
|
657
|
+
const isNumber = (inputValue) => {
|
|
658
|
+
return typeof inputValue === "number";
|
|
659
|
+
};
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* Validates a url
|
|
663
|
+
*/
|
|
664
|
+
const validateColorCode = (colorCode, required) => {
|
|
665
|
+
if (!colorCode && !required) {
|
|
666
|
+
return undefined;
|
|
667
|
+
}
|
|
668
|
+
if (!colorCode && required) {
|
|
669
|
+
return "REQUIRED";
|
|
670
|
+
}
|
|
671
|
+
if (colorCode && isString(colorCode) && isValidHEXColor(colorCode)) {
|
|
672
|
+
return undefined;
|
|
673
|
+
}
|
|
674
|
+
return "INVALID_HEX_CODE";
|
|
675
|
+
};
|
|
676
|
+
|
|
633
677
|
/**
|
|
634
678
|
* Validates if the given value is a valid hex color.
|
|
635
679
|
*
|
|
@@ -645,25 +689,34 @@ const isValidHEXColor = (value) => {
|
|
|
645
689
|
* ColorField validates that user enters a valid color address.
|
|
646
690
|
*
|
|
647
691
|
*/
|
|
648
|
-
const ColorField = React.forwardRef(({ label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, dataTestId, value: propValue, onChange, isInvalid = false, ...rest }, ref) => {
|
|
692
|
+
const ColorField = React.forwardRef(({ label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, dataTestId, value: propValue, onChange, isInvalid = false, onBlur, ...rest }, ref) => {
|
|
649
693
|
const htmlForId = React.useMemo(() => (id ? id : "colorField-" + uuid.v4()), [id]);
|
|
650
694
|
const innerRef = React.useRef(null);
|
|
651
695
|
React.useImperativeHandle(ref, () => innerRef.current, []);
|
|
696
|
+
const [t] = useTranslation();
|
|
652
697
|
// Internal state for color value
|
|
653
|
-
const [
|
|
698
|
+
const [innerValue, setInnerValue] = React.useState(propValue || defaultValue || "");
|
|
699
|
+
const [renderAsInvalid, setRenderAsInvalid] = React.useState(!!errorMessage || (innerValue && typeof innerValue === "string" && !isValidHEXColor(innerValue)) || isInvalid);
|
|
700
|
+
const errorType = React.useMemo(() => validateColorCode(innerValue, rest.required), [rest.required, innerValue]);
|
|
701
|
+
const error = React.useMemo(() => (errorType ? t(`colorField.error.${errorType}`) : errorMessage), [errorType, errorMessage, t]);
|
|
702
|
+
const handleBlur = React.useCallback(event => {
|
|
703
|
+
const newValue = event.target.value;
|
|
704
|
+
setInnerValue(newValue);
|
|
705
|
+
setRenderAsInvalid(!!errorType);
|
|
706
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur(event);
|
|
707
|
+
}, [errorType, onBlur]);
|
|
654
708
|
const handleChange = React.useCallback((event) => {
|
|
655
709
|
const newValue = event.target.value;
|
|
656
|
-
|
|
710
|
+
setInnerValue(newValue);
|
|
657
711
|
if (onChange) {
|
|
658
712
|
onChange(event);
|
|
659
713
|
}
|
|
660
714
|
}, [onChange]);
|
|
661
|
-
|
|
662
|
-
return (jsxRuntime.jsx(FormGroup, { dataTestId: dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && errorMessage) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: rest.required, tip: tip, children: jsxRuntime.jsxs("div", { className: cvaInput({
|
|
715
|
+
return (jsxRuntime.jsx(FormGroup, { dataTestId: dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && error) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: rest.required, tip: tip, children: jsxRuntime.jsxs("div", { className: cvaInput({
|
|
663
716
|
disabled: false,
|
|
664
717
|
invalid: false,
|
|
665
718
|
className,
|
|
666
|
-
}), "data-testid": dataTestId ? `${dataTestId}-container` : undefined, children: [jsxRuntime.jsx("input", { "aria-labelledby": htmlForId + "-label", className: "ml-2 h-[30px] w-[40px] self-center rounded-full bg-inherit", "data-testid": dataTestId, defaultValue: defaultValue, id: htmlForId, onChange: handleChange, ref: innerRef, type: "color", value:
|
|
719
|
+
}), "data-testid": dataTestId ? `${dataTestId}-container` : undefined, children: [jsxRuntime.jsx("input", { "aria-labelledby": htmlForId + "-label", className: "ml-2 h-[30px] w-[40px] self-center rounded-full bg-inherit", "data-testid": dataTestId, defaultValue: defaultValue, id: htmlForId, onBlur: handleBlur, onChange: handleChange, ref: innerRef, type: "color", value: innerValue }), jsxRuntime.jsx("input", { "aria-labelledby": htmlForId + "-label-text", className: cvaInputField({ disabled: false }), "data-testid": dataTestId ? `${dataTestId}-textField` : undefined, onBlur: handleBlur, onChange: handleChange, type: "text", value: innerValue }), jsxRuntime.jsx(reactComponents.IconButton, { className: "mr-1 self-center", icon: jsxRuntime.jsx(reactComponents.Icon, { name: "Pencil", type: "outline" }), onClick: () => {
|
|
667
720
|
if (innerRef.current) {
|
|
668
721
|
innerRef.current.click();
|
|
669
722
|
}
|
|
@@ -824,6 +877,22 @@ const validateEmailAddress = (email) => {
|
|
|
824
877
|
return EMAIL_REGEX.test(email);
|
|
825
878
|
};
|
|
826
879
|
|
|
880
|
+
/**
|
|
881
|
+
* Validates a email id
|
|
882
|
+
*/
|
|
883
|
+
const validateEmailId = (emailId, required) => {
|
|
884
|
+
if (!emailId && !required) {
|
|
885
|
+
return undefined;
|
|
886
|
+
}
|
|
887
|
+
if (!emailId && required) {
|
|
888
|
+
return "REQUIRED";
|
|
889
|
+
}
|
|
890
|
+
if (emailId && isString(emailId) && validateEmailAddress(emailId)) {
|
|
891
|
+
return undefined;
|
|
892
|
+
}
|
|
893
|
+
return "INVALID_EMAIL";
|
|
894
|
+
};
|
|
895
|
+
|
|
827
896
|
/**
|
|
828
897
|
* A Email Input component is used for input of the type Email.
|
|
829
898
|
*
|
|
@@ -854,22 +923,82 @@ EmailInput.displayName = "EmailInput";
|
|
|
854
923
|
* EmailField validates that user enters a valid email address.
|
|
855
924
|
*
|
|
856
925
|
*/
|
|
857
|
-
const EmailField = React.forwardRef(({ label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, dataTestId, value, disabled, onChange, isInvalid = false, ...rest }, ref) => {
|
|
926
|
+
const EmailField = React.forwardRef(({ label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, dataTestId, value, disabled, onChange, onBlur, isInvalid = false, ...rest }, ref) => {
|
|
858
927
|
const htmlForId = id ? id : "emailField-" + uuid.v4();
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
928
|
+
const [t] = useTranslation();
|
|
929
|
+
const [innerValue, setInnerValue] = React.useState(() => {
|
|
930
|
+
var _a;
|
|
931
|
+
return (_a = ((value === null || value === void 0 ? void 0 : value.toString()) || (defaultValue === null || defaultValue === void 0 ? void 0 : defaultValue.toString()))) !== null && _a !== void 0 ? _a : "";
|
|
932
|
+
});
|
|
933
|
+
const [renderAsInvalid, setRenderAsInvalid] = React.useState(!!errorMessage || (value && isString(value) && !validateEmailAddress(value)) || isInvalid);
|
|
934
|
+
const errorType = React.useMemo(() => validateEmailId(innerValue !== null && innerValue !== void 0 ? innerValue : "", rest.required), [rest.required, innerValue]);
|
|
935
|
+
const error = React.useMemo(() => (errorType ? t(`emailField.error.${errorType}`) : errorMessage), [errorType, errorMessage, t]);
|
|
936
|
+
const handleBlur = React.useCallback(event => {
|
|
937
|
+
const newValue = event.target.value;
|
|
938
|
+
setInnerValue(newValue);
|
|
939
|
+
setRenderAsInvalid(!!errorType);
|
|
940
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur(event);
|
|
941
|
+
}, [errorType, onBlur]);
|
|
864
942
|
const handleChange = React.useCallback((event) => {
|
|
943
|
+
setInnerValue(event.target.value);
|
|
865
944
|
if (onChange) {
|
|
866
945
|
onChange(event);
|
|
867
946
|
}
|
|
868
947
|
}, [onChange]);
|
|
869
|
-
return (jsxRuntime.jsx(FormGroup, { dataTestId: dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid &&
|
|
948
|
+
return (jsxRuntime.jsx(FormGroup, { dataTestId: dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && error) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: rest.required, tip: tip, children: jsxRuntime.jsx(EmailInput, { "aria-labelledby": htmlForId + "-label", defaultValue: defaultValue, disabled: disabled, id: htmlForId, isInvalid: renderAsInvalid, onBlur: handleBlur, onChange: handleChange, ref: ref, value: value, ...rest, className: className, dataTestId: dataTestId }) }));
|
|
870
949
|
});
|
|
871
950
|
EmailField.displayName = "EmailField";
|
|
872
951
|
|
|
952
|
+
const isNumberValid = (number) => {
|
|
953
|
+
if (!isNaN(+number) === false) {
|
|
954
|
+
return false;
|
|
955
|
+
}
|
|
956
|
+
if (typeof number === "number") {
|
|
957
|
+
return true;
|
|
958
|
+
}
|
|
959
|
+
return /^(?=.)([+-]?([0-9]*)(\.([0-9]+))?)$/.test(number);
|
|
960
|
+
};
|
|
961
|
+
/**
|
|
962
|
+
* Validates a number
|
|
963
|
+
*/
|
|
964
|
+
const validateNumber = (number, required = false, min, max) => {
|
|
965
|
+
const parsedNumber = Number(number);
|
|
966
|
+
const minValue = typeof min === "string" ? parseFloat(min) : min;
|
|
967
|
+
const maxValue = typeof max === "string" ? parseFloat(max) : max;
|
|
968
|
+
if (number === undefined) {
|
|
969
|
+
return undefined;
|
|
970
|
+
}
|
|
971
|
+
// if the value is a string eg:'test'
|
|
972
|
+
if (number && !isNaN(+number) === false) {
|
|
973
|
+
return "INVALID_NUMBER";
|
|
974
|
+
}
|
|
975
|
+
// if the value is empty and not required
|
|
976
|
+
if (!Number.isNaN(parsedNumber) && !parsedNumber && !required && !min && !max) {
|
|
977
|
+
return undefined;
|
|
978
|
+
}
|
|
979
|
+
// if the value is empty and required
|
|
980
|
+
if (!Number.isNaN(parsedNumber) && !parsedNumber && required) {
|
|
981
|
+
return "REQUIRED";
|
|
982
|
+
}
|
|
983
|
+
// if the value is not in between min and max
|
|
984
|
+
if (minValue && maxValue && isNumberValid(parsedNumber) && !(parsedNumber >= minValue && parsedNumber <= maxValue)) {
|
|
985
|
+
return "NOT_IN_BETWEEN";
|
|
986
|
+
}
|
|
987
|
+
// if the value is less than min
|
|
988
|
+
if (isNumberValid(parsedNumber) && minValue !== undefined && parsedNumber < minValue) {
|
|
989
|
+
return "GREATER_THAN";
|
|
990
|
+
}
|
|
991
|
+
// if the value is greater than max
|
|
992
|
+
if (isNumberValid(parsedNumber) && maxValue !== undefined && parsedNumber > maxValue) {
|
|
993
|
+
return "LESS_THAN";
|
|
994
|
+
}
|
|
995
|
+
// if the value is a number and is valid
|
|
996
|
+
if (isNumber(parsedNumber) && isNumberValid(parsedNumber)) {
|
|
997
|
+
return undefined;
|
|
998
|
+
}
|
|
999
|
+
return "INVALID_NUMBER";
|
|
1000
|
+
};
|
|
1001
|
+
|
|
873
1002
|
/**
|
|
874
1003
|
* A thin wrapper around the `BaseInput` component for number input fields.
|
|
875
1004
|
*
|
|
@@ -887,10 +1016,39 @@ NumberInput.displayName = "NumberInput";
|
|
|
887
1016
|
*
|
|
888
1017
|
* _**Do not use**_ this fields for non-serialized numbers. Use TextField instead.
|
|
889
1018
|
*/
|
|
890
|
-
const NumberField = React.forwardRef(({ label, id, tip, helpText, errorMessage, helpAddon, isInvalid, maxLength, className, value, dataTestId, ...rest }, ref) => {
|
|
891
|
-
const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
|
|
1019
|
+
const NumberField = React.forwardRef(({ label, id, tip, helpText, errorMessage, helpAddon, isInvalid, maxLength, className, value, dataTestId, defaultValue, onBlur, ...rest }, ref) => {
|
|
892
1020
|
const htmlForId = id ? id : "numberField-" + uuid.v4();
|
|
893
|
-
|
|
1021
|
+
const [t] = useTranslation();
|
|
1022
|
+
const [innerValue, setInnerValue] = React.useState(() => {
|
|
1023
|
+
return Number(value === null || value === void 0 ? void 0 : value.toString()) || Number(defaultValue === null || defaultValue === void 0 ? void 0 : defaultValue.toString());
|
|
1024
|
+
});
|
|
1025
|
+
const [renderAsInvalid, setRenderAsInvalid] = React.useState((isInvalid === undefined ? Boolean(errorMessage) : isInvalid) ||
|
|
1026
|
+
!!validateNumber(value === null || value === void 0 ? void 0 : value.toString(), rest.required, rest.min, rest.max));
|
|
1027
|
+
const errorType = React.useMemo(() => validateNumber(innerValue, rest.required, rest.min, rest.max), [innerValue, rest.max, rest.min, rest.required]);
|
|
1028
|
+
const error = React.useMemo(() => {
|
|
1029
|
+
// for the case when a custom error message is provided
|
|
1030
|
+
if (errorMessage) {
|
|
1031
|
+
setRenderAsInvalid(Boolean(errorMessage));
|
|
1032
|
+
return errorMessage;
|
|
1033
|
+
}
|
|
1034
|
+
else if (errorType) {
|
|
1035
|
+
return t(`numberField.error.${errorType}`, { min: rest.min, max: rest.max });
|
|
1036
|
+
}
|
|
1037
|
+
return errorMessage;
|
|
1038
|
+
}, [errorMessage, errorType, rest.max, rest.min, t]);
|
|
1039
|
+
const handleBlur = React.useCallback(event => {
|
|
1040
|
+
const newValue = event.target.value;
|
|
1041
|
+
setInnerValue(newValue.toString());
|
|
1042
|
+
// for the case when a custom error message is provided
|
|
1043
|
+
if (errorMessage && !validateNumber(newValue, rest.required, rest.min, rest.max)) {
|
|
1044
|
+
setRenderAsInvalid(Boolean(errorMessage));
|
|
1045
|
+
}
|
|
1046
|
+
else {
|
|
1047
|
+
setRenderAsInvalid(!!validateNumber(newValue, rest.required, rest.min, rest.max));
|
|
1048
|
+
}
|
|
1049
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur(event);
|
|
1050
|
+
}, [errorMessage, onBlur, rest.max, rest.min, rest.required]);
|
|
1051
|
+
return (jsxRuntime.jsx(FormGroup, { dataTestId: dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && error) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: rest.required, tip: tip, children: jsxRuntime.jsx(NumberInput, { "aria-labelledby": htmlForId + "-label", id: htmlForId, isInvalid: renderAsInvalid, maxLength: maxLength, onBlur: handleBlur, ref: ref, value: value, ...rest, className: className, dataTestId: dataTestId }) }));
|
|
894
1052
|
});
|
|
895
1053
|
NumberField.displayName = "NumberField";
|
|
896
1054
|
|
|
@@ -1071,39 +1229,6 @@ const PhoneInput = React.forwardRef(({ dataTestId, isInvalid, disabled = false,
|
|
|
1071
1229
|
});
|
|
1072
1230
|
PhoneInput.displayName = "PhoneInput";
|
|
1073
1231
|
|
|
1074
|
-
/**
|
|
1075
|
-
* The PhoneField component is used to enter phone number.
|
|
1076
|
-
* It is a wrapper around the PhoneInput component and the FormGroup component.
|
|
1077
|
-
* It is used to render a phone number field with a label, a tip, a help text, a help addon and an error message.
|
|
1078
|
-
*
|
|
1079
|
-
* @param {string} [label] - The label for the component.
|
|
1080
|
-
* @param {string} [tip] - The tip for the component.
|
|
1081
|
-
* @param {string} [helpText] - The help text for the component.
|
|
1082
|
-
* @param {string} [helpAddon] - The help addon for the component.
|
|
1083
|
-
* @param {string} [errorMessage] - The error message for the component.
|
|
1084
|
-
* @param {string} [defaultValue] - The default value for the component.
|
|
1085
|
-
* @param {boolean} [disabled=false] - Whether the component is disabled or not.
|
|
1086
|
-
* @param {string} [fieldSize="medium"] - The size of the input field.
|
|
1087
|
-
* @param {boolean} [disableAction=false] - Whether the action button is disabled or not.
|
|
1088
|
-
* @returns {JSX.Element} - The PhoneField component.
|
|
1089
|
-
*/
|
|
1090
|
-
const PhoneField = React.forwardRef(({ label, id, tip, helpText, isInvalid, errorMessage, value, helpAddon, className, defaultValue, dataTestId, name, onChange, onBlur, ...rest }, ref) => {
|
|
1091
|
-
const htmlForId = id ? id : "phoneField-" + uuid.v4();
|
|
1092
|
-
const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
|
|
1093
|
-
return (jsxRuntime.jsx(FormGroup, { className: className, dataTestId: dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && errorMessage) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: rest.required, tip: tip, children: jsxRuntime.jsx(PhoneInput, { "aria-labelledby": htmlForId + "-label", dataTestId: dataTestId, defaultValue: defaultValue, id: htmlForId, isInvalid: renderAsInvalid, name: name, onBlur: onBlur, onChange: onChange, ref: ref, value: value, ...rest }) }));
|
|
1094
|
-
});
|
|
1095
|
-
PhoneField.displayName = "PhoneField";
|
|
1096
|
-
|
|
1097
|
-
/**
|
|
1098
|
-
* The PhoneFieldWithController component is a wrapper for the PhoneField component to connect it to react-hook-form.
|
|
1099
|
-
*
|
|
1100
|
-
* @returns {JSX.Element} - The PhoneFieldWithController component.
|
|
1101
|
-
*/
|
|
1102
|
-
const PhoneFieldWithController = React.forwardRef(({ control, controllerProps, name, value, ...rest }, ref) => {
|
|
1103
|
-
return (jsxRuntime.jsx(reactHookForm.Controller, { control: control, defaultValue: value, name: name, ...controllerProps, render: ({ field }) => jsxRuntime.jsx(PhoneField, { ...rest, ...field, ref: ref }) }));
|
|
1104
|
-
});
|
|
1105
|
-
PhoneFieldWithController.displayName = "PhoneFieldWithController";
|
|
1106
|
-
|
|
1107
1232
|
/**
|
|
1108
1233
|
* Validates a phone number
|
|
1109
1234
|
*/
|
|
@@ -1143,6 +1268,79 @@ const isInvalidCountryCode = (error, required) => (!!required && error === "REQU
|
|
|
1143
1268
|
* Checks if the phone number is valid and required
|
|
1144
1269
|
*/
|
|
1145
1270
|
const isInvalidPhoneNumber = (error, required) => error !== "REQUIRED_COUNTRY" && ((!!error && error !== "REQUIRED") || (!!required && error === "REQUIRED"));
|
|
1271
|
+
/**
|
|
1272
|
+
* Checks if the phone number is valid and returns corresponding error message
|
|
1273
|
+
*/
|
|
1274
|
+
const phoneErrorMessage = (phoneNumber, required) => {
|
|
1275
|
+
if ((validatePhoneNumber(phoneNumber) === "REQUIRED" && !required) ||
|
|
1276
|
+
(validatePhoneNumber(phoneNumber) === "REQUIRED" && required && phoneNumber === undefined)) {
|
|
1277
|
+
return undefined;
|
|
1278
|
+
}
|
|
1279
|
+
return validatePhoneNumber(phoneNumber);
|
|
1280
|
+
};
|
|
1281
|
+
|
|
1282
|
+
/**
|
|
1283
|
+
* The PhoneField component is used to enter phone number.
|
|
1284
|
+
* It is a wrapper around the PhoneInput component and the FormGroup component.
|
|
1285
|
+
* It is used to render a phone number field with a label, a tip, a help text, a help addon and an error message.
|
|
1286
|
+
*
|
|
1287
|
+
* @param {string} [label] - The label for the component.
|
|
1288
|
+
* @param {string} [tip] - The tip for the component.
|
|
1289
|
+
* @param {string} [helpText] - The help text for the component.
|
|
1290
|
+
* @param {string} [helpAddon] - The help addon for the component.
|
|
1291
|
+
* @param {string} [errorMessage] - The error message for the component.
|
|
1292
|
+
* @param {string} [defaultValue] - The default value for the component.
|
|
1293
|
+
* @param {boolean} [disabled=false] - Whether the component is disabled or not.
|
|
1294
|
+
* @param {string} [fieldSize="medium"] - The size of the input field.
|
|
1295
|
+
* @param {boolean} [disableAction=false] - Whether the action button is disabled or not.
|
|
1296
|
+
* @returns {JSX.Element} - The PhoneField component.
|
|
1297
|
+
*/
|
|
1298
|
+
const PhoneField = React.forwardRef(({ label, id, tip, helpText, isInvalid, errorMessage, value, helpAddon, className, defaultValue, dataTestId, name, onBlur, ...rest }, ref) => {
|
|
1299
|
+
const htmlForId = id ? id : "phoneField-" + uuid.v4();
|
|
1300
|
+
const [t] = useTranslation();
|
|
1301
|
+
const [innerValue, setInnerValue] = React.useState(() => {
|
|
1302
|
+
var _a;
|
|
1303
|
+
return (_a = ((value === null || value === void 0 ? void 0 : value.toString()) || (defaultValue === null || defaultValue === void 0 ? void 0 : defaultValue.toString()))) !== null && _a !== void 0 ? _a : undefined;
|
|
1304
|
+
});
|
|
1305
|
+
const [renderAsInvalid, setRenderAsInvalid] = React.useState((isInvalid === undefined ? Boolean(errorMessage) : isInvalid) ||
|
|
1306
|
+
!!phoneErrorMessage(value === null || value === void 0 ? void 0 : value.toString(), rest.required));
|
|
1307
|
+
const errorType = React.useMemo(() => phoneErrorMessage(innerValue, rest.required), [innerValue, rest.required]);
|
|
1308
|
+
const error = React.useMemo(() => {
|
|
1309
|
+
// for the case when a custom error message is provided
|
|
1310
|
+
if (errorMessage) {
|
|
1311
|
+
setRenderAsInvalid(Boolean(errorMessage));
|
|
1312
|
+
return errorMessage;
|
|
1313
|
+
}
|
|
1314
|
+
else if (errorType) {
|
|
1315
|
+
return t(`phoneField.error.${errorType}`);
|
|
1316
|
+
}
|
|
1317
|
+
return errorMessage;
|
|
1318
|
+
}, [errorMessage, errorType, t]);
|
|
1319
|
+
const handleBlur = React.useCallback(event => {
|
|
1320
|
+
const newValue = event.target.value;
|
|
1321
|
+
setInnerValue(newValue);
|
|
1322
|
+
// for the case when a custom error message is provided
|
|
1323
|
+
if (errorMessage && !phoneErrorMessage(newValue.toString(), rest.required)) {
|
|
1324
|
+
setRenderAsInvalid(Boolean(errorMessage));
|
|
1325
|
+
}
|
|
1326
|
+
else {
|
|
1327
|
+
setRenderAsInvalid(!!phoneErrorMessage(newValue.toString(), rest.required));
|
|
1328
|
+
}
|
|
1329
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur(event);
|
|
1330
|
+
}, [errorMessage, onBlur, rest.required]);
|
|
1331
|
+
return (jsxRuntime.jsx(FormGroup, { className: className, dataTestId: dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && error) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: rest.required, tip: tip, children: jsxRuntime.jsx(PhoneInput, { "aria-labelledby": htmlForId + "-label", dataTestId: dataTestId, defaultValue: defaultValue, id: htmlForId, isInvalid: renderAsInvalid, name: name, onBlur: handleBlur, ref: ref, value: value, ...rest }) }));
|
|
1332
|
+
});
|
|
1333
|
+
PhoneField.displayName = "PhoneField";
|
|
1334
|
+
|
|
1335
|
+
/**
|
|
1336
|
+
* The PhoneFieldWithController component is a wrapper for the PhoneField component to connect it to react-hook-form.
|
|
1337
|
+
*
|
|
1338
|
+
* @returns {JSX.Element} - The PhoneFieldWithController component.
|
|
1339
|
+
*/
|
|
1340
|
+
const PhoneFieldWithController = React.forwardRef(({ control, controllerProps, name, value, ...rest }, ref) => {
|
|
1341
|
+
return (jsxRuntime.jsx(reactHookForm.Controller, { control: control, defaultValue: value, name: name, ...controllerProps, render: ({ field }) => jsxRuntime.jsx(PhoneField, { ...rest, ...field, ref: ref }) }));
|
|
1342
|
+
});
|
|
1343
|
+
PhoneFieldWithController.displayName = "PhoneFieldWithController";
|
|
1146
1344
|
|
|
1147
1345
|
const cvaRadioGroup = cssClassVarianceUtilities.cvaMerge(["flex", "gap-2", "flex-col", "items-start"], {
|
|
1148
1346
|
variants: {
|
|
@@ -2454,6 +2652,22 @@ const validateUrlAddress = (url) => {
|
|
|
2454
2652
|
return urlPattern.test(url);
|
|
2455
2653
|
};
|
|
2456
2654
|
|
|
2655
|
+
/**
|
|
2656
|
+
* Validates a url
|
|
2657
|
+
*/
|
|
2658
|
+
const validateUrl = (url, required) => {
|
|
2659
|
+
if (!url && !required) {
|
|
2660
|
+
return undefined;
|
|
2661
|
+
}
|
|
2662
|
+
if (!url && required) {
|
|
2663
|
+
return "REQUIRED";
|
|
2664
|
+
}
|
|
2665
|
+
if (url && isString(url) && validateUrlAddress(url)) {
|
|
2666
|
+
return undefined;
|
|
2667
|
+
}
|
|
2668
|
+
return "INVALID_URL";
|
|
2669
|
+
};
|
|
2670
|
+
|
|
2457
2671
|
/**
|
|
2458
2672
|
* A thin wrapper around the `BaseInput` component for URL input fields.
|
|
2459
2673
|
*
|
|
@@ -2471,14 +2685,23 @@ UrlInput.displayName = "UrlField";
|
|
|
2471
2685
|
* UrlField validates that user enters a valid web address.
|
|
2472
2686
|
*
|
|
2473
2687
|
*/
|
|
2474
|
-
const UrlField = React.forwardRef(({ label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, dataTestId, isInvalid = false, value, ...rest }, ref) => {
|
|
2688
|
+
const UrlField = React.forwardRef(({ label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, dataTestId, isInvalid = false, value, onBlur, ...rest }, ref) => {
|
|
2475
2689
|
const htmlForId = id ? id : "urlField-" + uuid.v4();
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2690
|
+
const [t] = useTranslation();
|
|
2691
|
+
const [innerValue, setInnerValue] = React.useState(() => {
|
|
2692
|
+
var _a;
|
|
2693
|
+
return (_a = ((value === null || value === void 0 ? void 0 : value.toString()) || (defaultValue === null || defaultValue === void 0 ? void 0 : defaultValue.toString()))) !== null && _a !== void 0 ? _a : "";
|
|
2694
|
+
});
|
|
2695
|
+
const [renderAsInvalid, setRenderAsInvalid] = React.useState(!!errorMessage || (value && isString(value) && !validateUrlAddress(value)) || isInvalid);
|
|
2696
|
+
const errorType = React.useMemo(() => validateUrl(innerValue !== null && innerValue !== void 0 ? innerValue : "", rest.required), [rest.required, innerValue]);
|
|
2697
|
+
const error = React.useMemo(() => (errorType ? t(`urlField.error.${errorType}`) : errorMessage), [errorType, errorMessage, t]);
|
|
2698
|
+
const handleBlur = React.useCallback(event => {
|
|
2699
|
+
const newValue = event.target.value;
|
|
2700
|
+
setInnerValue(newValue);
|
|
2701
|
+
setRenderAsInvalid(!!validateUrl(newValue, rest.required));
|
|
2702
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur(event);
|
|
2703
|
+
}, [onBlur, rest.required]);
|
|
2704
|
+
return (jsxRuntime.jsx(FormGroup, { dataTestId: dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: renderAsInvalid ? error : helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: rest.required, tip: tip, children: jsxRuntime.jsx(UrlInput, { "aria-labelledby": htmlForId + "-label", id: htmlForId, isInvalid: renderAsInvalid, onBlur: handleBlur, ref: ref, value: value || defaultValue, ...rest, className: className, dataTestId: dataTestId }) }));
|
|
2482
2705
|
});
|
|
2483
2706
|
UrlField.displayName = "UrlField";
|
|
2484
2707
|
|
|
@@ -2667,6 +2890,7 @@ exports.isInvalidPhoneNumber = isInvalidPhoneNumber;
|
|
|
2667
2890
|
exports.isMultiValue = isMultiValue;
|
|
2668
2891
|
exports.isValidHEXColor = isValidHEXColor;
|
|
2669
2892
|
exports.parseSchedule = parseSchedule;
|
|
2893
|
+
exports.phoneErrorMessage = phoneErrorMessage;
|
|
2670
2894
|
exports.serializeSchedule = serializeSchedule;
|
|
2671
2895
|
exports.useCustomComponents = useCustomComponents;
|
|
2672
2896
|
exports.useGetPhoneValidationRules = useGetPhoneValidationRules;
|