@trackunit/react-form-components 0.0.330 → 0.0.332
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 +921 -978
- package/index.esm.js +922 -982
- package/package.json +4 -2
- package/src/components/FormGroup/FormGroup.d.ts +1 -0
- package/src/components/PhoneField/PhoneField.d.ts +1 -2
- package/src/components/PhoneFieldWithController/PhoneFieldWithController.d.ts +23 -0
- package/src/components/PhoneInput/PhoneInput.d.ts +2 -40
- package/src/components/PhoneInput/PhoneInputValidationUtils.d.ts +1 -6
- package/src/index.d.ts +3 -0
- package/src/utilities/useGetPhoneValidationRules.d.ts +12 -0
- package/src/utilities/useZodValidators.d.ts +11 -0
package/index.esm.js
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import {
|
|
2
|
+
import { registerTranslations, useNamespaceTranslation } from '@trackunit/i18n-library-translation';
|
|
3
3
|
import { IconButton, Icon, Tooltip, Heading, Text, MenuItem, Tag, Spinner } from '@trackunit/react-components';
|
|
4
4
|
import { useCopyToClipboard } from 'react-use';
|
|
5
5
|
import { cvaMerge } from '@trackunit/css-class-variance-utilities';
|
|
6
6
|
import * as React from 'react';
|
|
7
|
-
import React__default, { useMemo, forwardRef, useCallback, cloneElement, useState,
|
|
7
|
+
import React__default, { useMemo, forwardRef, useCallback, cloneElement, useState, useRef, useEffect, useImperativeHandle } from 'react';
|
|
8
8
|
import { v4 } from 'uuid';
|
|
9
9
|
import { format } from 'date-fns';
|
|
10
|
-
import parsePhoneNumberFromString, { isSupportedCountry, getCountries, getCountryCallingCode,
|
|
10
|
+
import parsePhoneNumberFromString, { isSupportedCountry, getCountries, getCountryCallingCode, AsYouType, parseIncompletePhoneNumber, isValidPhoneNumber } from 'libphonenumber-js';
|
|
11
|
+
import { Controller } from 'react-hook-form';
|
|
11
12
|
import ReactSelect, { components } from 'react-select';
|
|
12
13
|
export { default as ValueType } from 'react-select';
|
|
13
14
|
import ReactAsyncCreatableSelect from 'react-select/async-creatable';
|
|
14
15
|
import ReactCreatableSelect from 'react-select/creatable';
|
|
15
16
|
import ReactAsyncSelect from 'react-select/async';
|
|
16
17
|
import { nonNullable } from '@trackunit/shared-utils';
|
|
18
|
+
import { z } from 'zod';
|
|
17
19
|
|
|
18
20
|
var defaultTranslations = {
|
|
19
21
|
"clearIndicator.icon.tooltip.clearAll": "Clear all",
|
|
@@ -236,7 +238,7 @@ const cvaInputPrefix = cvaMerge([
|
|
|
236
238
|
"hover:component-search-prefix",
|
|
237
239
|
"component-baseInput-prefix",
|
|
238
240
|
"component-search-borderless",
|
|
239
|
-
"
|
|
241
|
+
"pl-3",
|
|
240
242
|
], {
|
|
241
243
|
variants: {
|
|
242
244
|
disabled: {
|
|
@@ -842,1101 +844,944 @@ const getCountryAbbreviation = (callCode) => {
|
|
|
842
844
|
return getCountries().find(c => getCountryCallingCode(c) === code) || "";
|
|
843
845
|
};
|
|
844
846
|
|
|
847
|
+
const DEFAULT_COUNTRY_CODE = undefined;
|
|
845
848
|
/**
|
|
846
|
-
* A
|
|
849
|
+
* A component for inputting phone numbers with an optional action button for initiating a phone call.
|
|
847
850
|
*
|
|
848
|
-
*
|
|
851
|
+
* @param {string} [dataTestId] - The data test ID for the component.
|
|
852
|
+
* @param {string|number} [value] - The value of the input field. The value should include the country code as well.
|
|
853
|
+
* @param {boolean} [disabled=false] - Whether the component is disabled or not.
|
|
854
|
+
* @param {string} [fieldSize="medium"] - The size of the input field.
|
|
855
|
+
* @param {boolean} [disableAction=false] - Whether the action button is disabled or not.
|
|
856
|
+
* @returns {JSX.Element} - The PhoneInput component.
|
|
849
857
|
*/
|
|
850
|
-
const
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
858
|
+
const PhoneInput = forwardRef((_a, ref) => {
|
|
859
|
+
var { dataTestId, isInvalid, disabled = false, value, defaultValue, fieldSize = "medium", disableAction = false, onChange, readOnly, onFocus, onBlur, name } = _a, rest = __rest(_a, ["dataTestId", "isInvalid", "disabled", "value", "defaultValue", "fieldSize", "disableAction", "onChange", "readOnly", "onFocus", "onBlur", "name"]);
|
|
860
|
+
const [innerValue, setInnerValue] = useState(() => {
|
|
861
|
+
var _a;
|
|
862
|
+
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 : "";
|
|
863
|
+
});
|
|
864
|
+
const fieldIsFocused = useRef(false);
|
|
865
|
+
const [countryCode, setCountryCode] = useState(DEFAULT_COUNTRY_CODE);
|
|
866
|
+
const determineCountry = useCallback((newValue) => {
|
|
867
|
+
const asYouType = new AsYouType();
|
|
868
|
+
asYouType.input(newValue);
|
|
869
|
+
setCountryCode(asYouType.getCountry());
|
|
870
|
+
}, []);
|
|
871
|
+
const handleChange = useCallback(event => {
|
|
872
|
+
const newValue = event.target.value;
|
|
873
|
+
const noneFormattedValue = parseIncompletePhoneNumber(newValue);
|
|
874
|
+
event.target.value = noneFormattedValue;
|
|
875
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(event);
|
|
876
|
+
setInnerValue(newValue);
|
|
877
|
+
determineCountry(newValue);
|
|
878
|
+
}, [onChange, determineCountry]);
|
|
879
|
+
const makePretty = useCallback((newValue) => {
|
|
880
|
+
const asYouType = new AsYouType();
|
|
881
|
+
const pretty = asYouType.input(newValue);
|
|
882
|
+
setInnerValue(pretty);
|
|
883
|
+
setCountryCode(asYouType.getCountry());
|
|
884
|
+
}, []);
|
|
885
|
+
useEffect(() => {
|
|
886
|
+
if (!fieldIsFocused.current) {
|
|
887
|
+
makePretty(typeof value === "string" ? value : "");
|
|
854
888
|
}
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
889
|
+
}, [makePretty, value]);
|
|
890
|
+
const handleBlur = useCallback(event => {
|
|
891
|
+
const newValue = event.target.value;
|
|
892
|
+
makePretty(newValue);
|
|
893
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur(event);
|
|
894
|
+
fieldIsFocused.current = false;
|
|
895
|
+
}, [makePretty, onBlur]);
|
|
896
|
+
const handleFocus = useCallback(event => {
|
|
897
|
+
const newValue = event.target.value;
|
|
898
|
+
const noneFormattedValue = parseIncompletePhoneNumber(newValue);
|
|
899
|
+
setInnerValue(noneFormattedValue);
|
|
900
|
+
onFocus === null || onFocus === void 0 ? void 0 : onFocus(event);
|
|
901
|
+
fieldIsFocused.current = true;
|
|
902
|
+
}, [onFocus]);
|
|
903
|
+
return (jsx("div", { className: "grid grid-cols-1 gap-2", "data-testid": dataTestId && `${dataTestId}-container`, children: jsx(BaseInput, Object.assign({ actions: !disableAction && (jsx(ActionButton, { dataTestId: dataTestId && `${dataTestId}-phoneIcon`, disabled: disabled || isInvalid, iconSize: fieldSize, type: "PHONE_NUMBER", value: (value === null || value === void 0 ? void 0 : value.toString()) || "" })), dataTestId: dataTestId && `${dataTestId}-phoneNumberInput`, disabled: disabled, fieldSize: fieldSize, id: "phoneInput-number", isInvalid: isInvalid, name: name, onBlur: handleBlur, onChange: handleChange, onFocus: handleFocus, prefix: (countryCode && countryCodeToFlagEmoji(countryCode)) || undefined, readOnly: readOnly, ref: ref, type: "tel", value: innerValue }, rest)) }));
|
|
904
|
+
});
|
|
905
|
+
|
|
906
|
+
/**
|
|
907
|
+
* The PhoneField component is used to enter phone number.
|
|
908
|
+
* It is a wrapper around the PhoneInput component and the FormGroup component.
|
|
909
|
+
* It is used to render a phone number field with a label, a tip, a help text, a help addon and an error message.
|
|
910
|
+
*
|
|
911
|
+
* @param {string} [label] - The label for the component.
|
|
912
|
+
* @param {string} [tip] - The tip for the component.
|
|
913
|
+
* @param {string} [helpText] - The help text for the component.
|
|
914
|
+
* @param {string} [helpAddon] - The help addon for the component.
|
|
915
|
+
* @param {string} [errorMessage] - The error message for the component.
|
|
916
|
+
* @param {string} [defaultValue] - The default value for the component.
|
|
917
|
+
* @param {boolean} [disabled=false] - Whether the component is disabled or not.
|
|
918
|
+
* @param {string} [fieldSize="medium"] - The size of the input field.
|
|
919
|
+
* @param {boolean} [disableAction=false] - Whether the action button is disabled or not.
|
|
920
|
+
* @returns {JSX.Element} - The PhoneField component.
|
|
921
|
+
*/
|
|
922
|
+
const PhoneField = forwardRef((_a, ref) => {
|
|
923
|
+
var { label, id, tip, helpText, isInvalid, errorMessage, value, helpAddon, className, defaultValue, dataTestId, name, onChange, onBlur } = _a, rest = __rest(_a, ["label", "id", "tip", "helpText", "isInvalid", "errorMessage", "value", "helpAddon", "className", "defaultValue", "dataTestId", "name", "onChange", "onBlur"]);
|
|
924
|
+
const htmlForId = id ? id : "phoneField-" + v4();
|
|
925
|
+
const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
|
|
926
|
+
return (jsx(FormGroup, { className: className, dataTestId: dataTestId && `${dataTestId}-FormGroup`, disabled: rest.disabled, helpAddon: helpAddon, helpText: (renderAsInvalid && errorMessage) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, tip: tip, children: jsx(PhoneInput, Object.assign({ "aria-labelledby": htmlForId + "-label", dataTestId: dataTestId, defaultValue: defaultValue, id: htmlForId, isInvalid: renderAsInvalid, name: name, onBlur: onBlur, onChange: onChange, ref: ref, value: value }, rest)) }));
|
|
927
|
+
});
|
|
928
|
+
|
|
929
|
+
/**
|
|
930
|
+
* The PhoneFieldWithController component is a wrapper for the PhoneField component to connect it to react-hook-form.
|
|
931
|
+
*
|
|
932
|
+
* @returns {JSX.Element} - The PhoneFieldWithController component.
|
|
933
|
+
*/
|
|
934
|
+
const PhoneFieldWithController = forwardRef((_a, ref) => {
|
|
935
|
+
var { control, controllerProps, name, value } = _a, rest = __rest(_a, ["control", "controllerProps", "name", "value"]);
|
|
936
|
+
return (jsx(Controller, Object.assign({ control: control, defaultValue: value, name: name }, controllerProps, { render: ({ field }) => jsx(PhoneField, Object.assign({}, rest, field, { ref: ref })) })));
|
|
937
|
+
});
|
|
938
|
+
|
|
939
|
+
/**
|
|
940
|
+
* Validates a phone number
|
|
941
|
+
*/
|
|
942
|
+
const validatePhoneNumber = (phoneNumber) => {
|
|
943
|
+
if (!phoneNumber) {
|
|
944
|
+
return "REQUIRED";
|
|
945
|
+
}
|
|
946
|
+
const asYouType = new AsYouType();
|
|
947
|
+
asYouType.input(phoneNumber);
|
|
948
|
+
const countryCode = asYouType.getCallingCode();
|
|
949
|
+
const national = asYouType.getNationalNumber();
|
|
950
|
+
if (phoneNumber && isValidPhoneNumber(phoneNumber)) {
|
|
951
|
+
return undefined;
|
|
952
|
+
}
|
|
953
|
+
if (!countryCode && national) {
|
|
954
|
+
return "REQUIRED_COUNTRY";
|
|
955
|
+
}
|
|
956
|
+
if (phoneNumber &&
|
|
957
|
+
(checkIfPhoneNumberHasPlus(phoneNumber) ? isNaN(+phoneNumber.slice(1, phoneNumber.length)) : isNaN(+phoneNumber))) {
|
|
958
|
+
return "NOT_A_NUMBER";
|
|
959
|
+
}
|
|
960
|
+
const safePhoneNumber = getPhoneNumberWithPlus(phoneNumber === null || phoneNumber === void 0 ? void 0 : phoneNumber.trim());
|
|
961
|
+
if (safePhoneNumber.length <= 5) {
|
|
962
|
+
//needs to be handled manually, parsePhoneNumberFromString can't parse it
|
|
963
|
+
return "TOO_SHORT";
|
|
964
|
+
}
|
|
965
|
+
const number = parsePhoneNumberFromString(safePhoneNumber);
|
|
966
|
+
if (!number) {
|
|
967
|
+
return "NOT_A_NUMBER";
|
|
968
|
+
}
|
|
969
|
+
return "INVALID_NUMBER";
|
|
860
970
|
};
|
|
971
|
+
/**
|
|
972
|
+
* Checks if the country code is valid and required
|
|
973
|
+
*/
|
|
974
|
+
const isInvalidCountryCode = (error, required) => (!!required && error === "REQUIRED") || error === "REQUIRED_COUNTRY";
|
|
975
|
+
/**
|
|
976
|
+
* Checks if the phone number is valid and required
|
|
977
|
+
*/
|
|
978
|
+
const isInvalidPhoneNumber = (error, required) => error !== "REQUIRED_COUNTRY" && ((!!error && error !== "REQUIRED") || (!!required && error === "REQUIRED"));
|
|
861
979
|
|
|
862
|
-
const
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
980
|
+
const cvaRadioGroup = cvaMerge(["flex", "gap-2", "flex-col", "items-start"], {
|
|
981
|
+
variants: {
|
|
982
|
+
layout: {
|
|
983
|
+
inline: ["flex", "gap-3", "flex-row", "items-center"],
|
|
984
|
+
},
|
|
985
|
+
},
|
|
986
|
+
});
|
|
987
|
+
const cvaRadioItem = cvaMerge([
|
|
988
|
+
"w-4",
|
|
989
|
+
"h-4",
|
|
990
|
+
"appearance-none",
|
|
991
|
+
"rounded-3xl",
|
|
992
|
+
"bg-white",
|
|
993
|
+
"border-solid",
|
|
867
994
|
"border",
|
|
868
995
|
"border-slate-300",
|
|
869
|
-
"
|
|
870
|
-
"
|
|
871
|
-
"focus-within:ring-primary-600",
|
|
872
|
-
"focus-within:border-slate-400",
|
|
873
|
-
"hover:border-slate-400",
|
|
874
|
-
"hover:bg-slate-50",
|
|
875
|
-
"bg-white",
|
|
996
|
+
"shadow-sm",
|
|
997
|
+
"shrink-0",
|
|
876
998
|
"transition",
|
|
999
|
+
"box-border",
|
|
1000
|
+
"hover:cursor-pointer",
|
|
1001
|
+
"hover:bg-slate-100",
|
|
1002
|
+
"focus:ring-2",
|
|
1003
|
+
"focus:ring-inset",
|
|
1004
|
+
"focus:ring-blue-700",
|
|
877
1005
|
], {
|
|
878
1006
|
variants: {
|
|
1007
|
+
checked: {
|
|
1008
|
+
true: [
|
|
1009
|
+
"border-solid",
|
|
1010
|
+
"border-4",
|
|
1011
|
+
"border-blue-600",
|
|
1012
|
+
"bg-white",
|
|
1013
|
+
"hover:bg-slate-100",
|
|
1014
|
+
"hover:cursor-pointer",
|
|
1015
|
+
"outline-0",
|
|
1016
|
+
"active:bg-slate-200",
|
|
1017
|
+
"active:ring-2",
|
|
1018
|
+
"active:ring-inset",
|
|
1019
|
+
"active:ring-blue-700",
|
|
1020
|
+
"focus:bg-slate-200",
|
|
1021
|
+
"focus:ring-2",
|
|
1022
|
+
"focus:ring-inset",
|
|
1023
|
+
"focus:ring-blue-700",
|
|
1024
|
+
"group-active:ring-2",
|
|
1025
|
+
"group-active:ring-inset",
|
|
1026
|
+
"group-active:ring-blue-700",
|
|
1027
|
+
],
|
|
1028
|
+
false: "",
|
|
1029
|
+
},
|
|
879
1030
|
invalid: {
|
|
880
|
-
true:
|
|
1031
|
+
true: [
|
|
1032
|
+
"border-red-600",
|
|
1033
|
+
"active:ring-red-700",
|
|
1034
|
+
"focus:ring-red-700",
|
|
1035
|
+
"group-focus:ring-2",
|
|
1036
|
+
"group-focus:ring-inset",
|
|
1037
|
+
],
|
|
881
1038
|
false: "",
|
|
882
1039
|
},
|
|
883
1040
|
disabled: {
|
|
884
|
-
true:
|
|
1041
|
+
true: [
|
|
1042
|
+
"bg-slate-400",
|
|
1043
|
+
"border-slate-300",
|
|
1044
|
+
"cursor-not-allowed",
|
|
1045
|
+
"group-hover:bg-slate-400",
|
|
1046
|
+
"group-focus:bg-slate-400",
|
|
1047
|
+
"hover:bg-slate-400",
|
|
1048
|
+
"focus:bg-slate-400",
|
|
1049
|
+
"active:bg-slate-400",
|
|
1050
|
+
"focus:ring-0",
|
|
1051
|
+
"focus:ring-inset",
|
|
1052
|
+
"group-active:ring-0",
|
|
1053
|
+
"group-active:ring-inset",
|
|
1054
|
+
],
|
|
885
1055
|
false: "",
|
|
886
1056
|
},
|
|
887
1057
|
},
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
const cvaSelectIcon = cvaMerge("mr-2 flex cursor-pointer items-center justify-center text-slate-400 hover:text-slate-500");
|
|
894
|
-
const cvaSelectPrefix = cvaMerge(["flex", "justify-center", "items-center", "text-slate-400", "pl-2"]);
|
|
895
|
-
const cvaSelectXIcon = cvaMerge([
|
|
896
|
-
"mr-2 flex cursor-pointer items-center justify-center text-slate-400 hover:text-slate-500",
|
|
897
|
-
"ml-1",
|
|
898
|
-
]);
|
|
899
|
-
const cvaSelectMenuList = cvaMerge(["min-w-min", "shadow-md", "rounded-lg", "z-20", "bg-white", "p-1", "border", "border-slate-300", "gap-1", "grid"], {
|
|
900
|
-
variants: {
|
|
901
|
-
menuIsOpen: {
|
|
902
|
-
true: "animate-fade-in-fast",
|
|
903
|
-
false: "animate-fade-out-fast",
|
|
1058
|
+
compoundVariants: [
|
|
1059
|
+
{
|
|
1060
|
+
checked: true,
|
|
1061
|
+
disabled: true,
|
|
1062
|
+
className: ["bg-white"],
|
|
904
1063
|
},
|
|
905
|
-
|
|
1064
|
+
],
|
|
906
1065
|
});
|
|
907
|
-
const
|
|
1066
|
+
const cvaRadioItemWrapper = cvaMerge(["flex", "gap-2", "items-center"]);
|
|
1067
|
+
const cvaRadioItemLabelContainer = cvaMerge(["gap-y-1", "grid"]);
|
|
1068
|
+
const cvaRadioItemDescription = cvaMerge(["text-sm", "font-normal", "text-slate-500", "text-left", "whitespace-nowrap", "text-ellipsis", "overflow-hidden"], {
|
|
908
1069
|
variants: {
|
|
909
|
-
|
|
1070
|
+
disabled: {
|
|
1071
|
+
true: ["text-slate-400", "hover:text-slate-400", "group-hover:text-slate-400"],
|
|
1072
|
+
false: "",
|
|
1073
|
+
},
|
|
910
1074
|
},
|
|
911
1075
|
});
|
|
912
|
-
|
|
913
|
-
const
|
|
1076
|
+
|
|
1077
|
+
const RadioGroupContext = React.createContext(null);
|
|
914
1078
|
|
|
915
1079
|
/**
|
|
916
|
-
*
|
|
917
|
-
*
|
|
1080
|
+
* Use radio buttons when you have a group of mutually exclusive choices and only one selection from the group is allowed.
|
|
1081
|
+
*
|
|
1082
|
+
* Radio buttons are used for mutually exclusive choices, not for multiple choices. Only one radio button can be selected at a time. When a user chooses a new item, the previous choice is automatically deselected.
|
|
1083
|
+
*
|
|
1084
|
+
* _**Do use** Radio buttons in forms, settings, or selections in a list._
|
|
1085
|
+
*
|
|
1086
|
+
* _**Do not use** Radio buttons if a user can select many option from a list, use checkboxes instead of radio buttons._
|
|
1087
|
+
*
|
|
1088
|
+
* @param {RadioGroupProps} props - The props for the RadioGroup component
|
|
1089
|
+
* @returns {JSX.Element} RadioGroup component
|
|
918
1090
|
*/
|
|
919
|
-
|
|
920
|
-
return
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
}
|
|
929
|
-
return isMultiValue(selected)
|
|
930
|
-
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
931
|
-
selected.some(v => v.value === option.value)
|
|
932
|
-
: // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
933
|
-
option.value === (selected === null || selected === void 0 ? void 0 : selected.value);
|
|
934
|
-
};
|
|
935
|
-
const removeSelectedFromGroups = (group, selected) => {
|
|
936
|
-
if (isGroupBase(group)) {
|
|
937
|
-
return Object.assign(Object.assign({}, group), { options: group.options.filter(option => !isSelectedOption(option, selected)) });
|
|
938
|
-
}
|
|
939
|
-
return group;
|
|
1091
|
+
const RadioGroup = ({ children, id, name, value, disabled, onChange, label, inline, className, dataTestId, isInvalid, }) => {
|
|
1092
|
+
return (jsx(FormGroup, { dataTestId: dataTestId && `${dataTestId}-FormGroup`, label: label, children: jsx("div", { className: cvaRadioGroup({ layout: inline ? "inline" : null, className }), "data-testid": dataTestId, children: jsx(RadioGroupContext.Provider, { value: {
|
|
1093
|
+
id,
|
|
1094
|
+
value,
|
|
1095
|
+
name: name || id,
|
|
1096
|
+
onChange,
|
|
1097
|
+
disabled,
|
|
1098
|
+
isInvalid,
|
|
1099
|
+
}, children: children }) }) }));
|
|
940
1100
|
};
|
|
1101
|
+
RadioGroup.displayName = "RadioGroup";
|
|
1102
|
+
|
|
941
1103
|
/**
|
|
942
|
-
*
|
|
943
|
-
*
|
|
944
|
-
* @param {
|
|
945
|
-
* @
|
|
946
|
-
* @returns {OptionsOrGroups<Option, Group>} An array of ordered options with selected on top
|
|
1104
|
+
* The RadioItem component.
|
|
1105
|
+
*
|
|
1106
|
+
* @param {RadioItemProps} props - The props for the RadioItem component
|
|
1107
|
+
* @returns {JSX.Element} RadioItem component
|
|
947
1108
|
*/
|
|
948
|
-
const
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
.map(option => removeSelectedFromGroups(option, value));
|
|
957
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
958
|
-
return orderedValues.concat(selectableOptions) || [];
|
|
959
|
-
}
|
|
960
|
-
return options || [];
|
|
1109
|
+
const RadioItem = ({ label, value, dataTestId, className, description, }) => {
|
|
1110
|
+
const groupCtx = React.useContext(RadioGroupContext);
|
|
1111
|
+
const isChecked = (groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.value) === value;
|
|
1112
|
+
return (jsxs("label", { className: cvaRadioItemWrapper({ className }), "data-testid": dataTestId && `${dataTestId}-Wrapper`, htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, children: [jsx("input", { checked: isChecked, className: cvaRadioItem({
|
|
1113
|
+
checked: isChecked,
|
|
1114
|
+
disabled: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.disabled,
|
|
1115
|
+
invalid: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.isInvalid,
|
|
1116
|
+
}), "data-testid": dataTestId, id: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, onChange: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.onChange, type: "radio", value: value }), jsxs("div", { className: cvaRadioItemLabelContainer(), children: [jsx(Label, { dataTestId: dataTestId && `${dataTestId}-Label`, disabled: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.disabled, htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, isInvalid: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.isInvalid, children: label }), description && (jsx("label", { className: cvaRadioItemDescription({ disabled: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.disabled }), "data-testid": dataTestId && `${dataTestId}-Description`, htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, children: description }))] })] }));
|
|
961
1117
|
};
|
|
962
1118
|
|
|
1119
|
+
const cvaTimeRange = cvaMerge(["flex", "flex-1", "items-center", "gap-4", "border-transparent", "rounded-md"]);
|
|
1120
|
+
|
|
963
1121
|
/**
|
|
964
|
-
*
|
|
1122
|
+
* TimeRange is used to create a time range entry.
|
|
965
1123
|
*
|
|
966
|
-
* @param {
|
|
967
|
-
* @returns {JSX.Element}
|
|
1124
|
+
* @param {TimeRangeProps} props - The props for the TimeRange component
|
|
1125
|
+
* @returns {JSX.Element} TimeRange component
|
|
968
1126
|
*/
|
|
969
|
-
const
|
|
970
|
-
|
|
1127
|
+
const TimeRange = ({ id, className, dataTestId, children, range, onChange, disabled, isInvalid, }) => {
|
|
1128
|
+
var _a, _b;
|
|
1129
|
+
const [timeRange, setTimeRange] = React__default.useState(range !== null && range !== void 0 ? range : {
|
|
1130
|
+
timeFrom: "",
|
|
1131
|
+
timeTo: "",
|
|
1132
|
+
});
|
|
1133
|
+
const onChangeFrom = (timeFrom) => {
|
|
1134
|
+
setTimeRange(prev => (Object.assign(Object.assign({}, prev), { timeFrom })));
|
|
1135
|
+
};
|
|
1136
|
+
const onChangeTo = (timeTo) => {
|
|
1137
|
+
setTimeRange(prev => (Object.assign(Object.assign({}, prev), { timeTo })));
|
|
1138
|
+
};
|
|
1139
|
+
const onRangeChange = () => onChange(timeRange);
|
|
1140
|
+
return (jsxs("div", { className: cvaTimeRange({ className }), "data-testid": dataTestId, id: id, children: [jsx(BaseInput, { dataTestId: `${dataTestId}-from`, disabled: disabled, isInvalid: isInvalid, onBlur: onRangeChange, onChange: (time) => onChangeFrom(time.currentTarget.value), type: "time", value: (_a = timeRange === null || timeRange === void 0 ? void 0 : timeRange.timeFrom) !== null && _a !== void 0 ? _a : "" }), children !== null && children !== void 0 ? children : jsx("div", { "data-testid": `${dataTestId}-separator`, children: "-" }), jsx(BaseInput, { dataTestId: `${dataTestId}-to`, disabled: disabled, isInvalid: isInvalid, onBlur: onRangeChange, onChange: (time) => onChangeTo(time.currentTarget.value), type: "time", value: (_b = timeRange === null || timeRange === void 0 ? void 0 : timeRange.timeTo) !== null && _b !== void 0 ? _b : "" })] }));
|
|
971
1141
|
};
|
|
1142
|
+
|
|
1143
|
+
const cvaScheduleItem = cvaMerge(["grid", "pb-4", "gap-2", "grid-cols-[60px,200px,60px,2fr]"]);
|
|
1144
|
+
const cvaScheduleItemText = cvaMerge(["flex", "font-bold", "self-center"]);
|
|
1145
|
+
|
|
972
1146
|
/**
|
|
973
|
-
*
|
|
1147
|
+
* Schedule is used to create a time range entries.
|
|
974
1148
|
*
|
|
975
|
-
* @param {
|
|
976
|
-
* @returns {JSX.Element}
|
|
1149
|
+
* @param {ScheduleProps} props - The props for the Schedule component
|
|
1150
|
+
* @returns {JSX.Element} Schedule component
|
|
977
1151
|
*/
|
|
978
|
-
const
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
1152
|
+
const Schedule = ({ className, dataTestId, schedule, onChange, invalidKeys = [] }) => {
|
|
1153
|
+
const onRangeChange = (range, index) => {
|
|
1154
|
+
const newSchedule = schedule.map((day, dayIndex) => (index === dayIndex ? Object.assign(Object.assign({}, day), { range: Object.assign({}, range) }) : day));
|
|
1155
|
+
onChange(newSchedule);
|
|
1156
|
+
};
|
|
1157
|
+
const onActiveChange = (isActive, index) => {
|
|
1158
|
+
const newSchedule = schedule.map((day, dayIndex) => index === dayIndex ? Object.assign(Object.assign({}, day), { range: { timeFrom: "", timeTo: "" }, isActive }) : day);
|
|
1159
|
+
onChange(newSchedule);
|
|
1160
|
+
};
|
|
1161
|
+
const onAllDayChange = (isAllDayChecked, index) => {
|
|
1162
|
+
const newSchedule = schedule.map((day, dayIndex) => index === dayIndex
|
|
1163
|
+
? Object.assign(Object.assign({}, day), { range: { timeFrom: "", timeTo: "" }, isAllDayActive: isAllDayChecked }) : day);
|
|
1164
|
+
onChange(newSchedule);
|
|
1165
|
+
};
|
|
1166
|
+
return (jsx("div", { className: className, "data-testid": dataTestId, children: schedule.map(({ label, range, isActive, key, checkboxLabel, isAllDayActive }, index) => {
|
|
1167
|
+
return (jsxs("div", { className: cvaScheduleItem(), children: [jsx(Checkbox, { checked: isActive, dataTestId: `${dataTestId}-${key}-checkbox`, label: checkboxLabel, onChange: (event) => onActiveChange(Boolean(event.currentTarget.checked), index) }), jsx(Text, { className: cvaScheduleItemText(), size: "medium", subtle: !isActive, children: label }), jsx(Checkbox, { checked: isAllDayActive && isActive, dataTestId: `${dataTestId}-${key}-allday-checkbox`, disabled: !isActive, onChange: (event) => onAllDayChange(Boolean(event.currentTarget.checked), index) }), jsx(TimeRange, { dataTestId: `${dataTestId}-${key}-range`, disabled: !isActive || isAllDayActive, isInvalid: !!invalidKeys.find((invalidKey) => invalidKey === key), onChange: (newRange) => onRangeChange(newRange, index), range: range })] }, key));
|
|
1168
|
+
}) }));
|
|
985
1169
|
};
|
|
986
1170
|
|
|
1171
|
+
const weekDay = {
|
|
1172
|
+
Monday: "monday",
|
|
1173
|
+
Tuesday: "tuesday",
|
|
1174
|
+
Wednesday: "wednesday",
|
|
1175
|
+
Thursday: "thursday",
|
|
1176
|
+
Friday: "friday",
|
|
1177
|
+
Saturday: "saturday",
|
|
1178
|
+
Sunday: "sunday",
|
|
1179
|
+
};
|
|
1180
|
+
var ScheduleVariant;
|
|
1181
|
+
(function (ScheduleVariant) {
|
|
1182
|
+
ScheduleVariant["ALL_DAYS"] = "all";
|
|
1183
|
+
ScheduleVariant["WEEKDAYS"] = "week";
|
|
1184
|
+
ScheduleVariant["CUSTOM"] = "custom";
|
|
1185
|
+
})(ScheduleVariant || (ScheduleVariant = {}));
|
|
987
1186
|
/**
|
|
988
|
-
*
|
|
989
|
-
* Used in the select component.
|
|
1187
|
+
* Parse a string of week range schedule string to human readable schedule range.
|
|
990
1188
|
*
|
|
991
|
-
* @param {
|
|
992
|
-
* @returns {
|
|
1189
|
+
* @param {string} scheduleString String of week schedule
|
|
1190
|
+
* @returns {WeekSchedule} Week schedule range
|
|
993
1191
|
*/
|
|
994
|
-
const
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1192
|
+
const parseSchedule = (scheduleString) => {
|
|
1193
|
+
if (!scheduleString) {
|
|
1194
|
+
return {
|
|
1195
|
+
variant: ScheduleVariant.ALL_DAYS,
|
|
1196
|
+
schedule: [],
|
|
1197
|
+
};
|
|
1198
|
+
}
|
|
1199
|
+
const schedule = scheduleString.split(",").map(daySchedule => {
|
|
1200
|
+
const [day, timeRange] = daySchedule.split("#");
|
|
1201
|
+
const [timeFrom, timeTo] = timeRange.split("-");
|
|
1202
|
+
const isAllDay = timeFrom === "00:00" && timeTo === "24:00";
|
|
1203
|
+
return {
|
|
1204
|
+
day: Number(day),
|
|
1205
|
+
range: isAllDay
|
|
1206
|
+
? undefined
|
|
1207
|
+
: {
|
|
1208
|
+
timeFrom,
|
|
1209
|
+
timeTo,
|
|
1210
|
+
},
|
|
1211
|
+
isAllDay,
|
|
1212
|
+
};
|
|
1213
|
+
});
|
|
1214
|
+
const filteredSchedule = schedule
|
|
1215
|
+
.filter(daySchedule => daySchedule.range !== null && daySchedule.range !== undefined)
|
|
1216
|
+
.map(daySchedule => ({ day: daySchedule.day, range: daySchedule.range, isAllDay: daySchedule.isAllDay }));
|
|
1217
|
+
let variant;
|
|
1218
|
+
switch (schedule.length) {
|
|
1219
|
+
case 7:
|
|
1220
|
+
const areEqual = schedule.every((day, _, collection) => {
|
|
1221
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1222
|
+
return ((_b = (_a = collection === null || collection === void 0 ? void 0 : collection[0]) === null || _a === void 0 ? void 0 : _a.range) === null || _b === void 0 ? void 0 : _b.timeFrom) === ((_c = day === null || day === void 0 ? void 0 : day.range) === null || _c === void 0 ? void 0 : _c.timeFrom) &&
|
|
1223
|
+
((_e = (_d = collection === null || collection === void 0 ? void 0 : collection[0]) === null || _d === void 0 ? void 0 : _d.range) === null || _e === void 0 ? void 0 : _e.timeTo) === ((_f = day === null || day === void 0 ? void 0 : day.range) === null || _f === void 0 ? void 0 : _f.timeTo);
|
|
1224
|
+
});
|
|
1225
|
+
if (areEqual) {
|
|
1226
|
+
variant = ScheduleVariant.ALL_DAYS;
|
|
1227
|
+
}
|
|
1228
|
+
else {
|
|
1229
|
+
variant = ScheduleVariant.CUSTOM;
|
|
1230
|
+
}
|
|
1231
|
+
break;
|
|
1232
|
+
case 5:
|
|
1233
|
+
const days = [1, 2, 3, 4, 5];
|
|
1234
|
+
const hasConsecutiveDays = schedule.every(({ day }, index) => day === days[index]);
|
|
1235
|
+
if (hasConsecutiveDays) {
|
|
1236
|
+
variant = ScheduleVariant.WEEKDAYS;
|
|
1237
|
+
}
|
|
1238
|
+
else {
|
|
1239
|
+
variant = ScheduleVariant.CUSTOM;
|
|
1240
|
+
}
|
|
1241
|
+
break;
|
|
1242
|
+
default:
|
|
1243
|
+
return {
|
|
1244
|
+
variant: ScheduleVariant.CUSTOM,
|
|
1245
|
+
schedule: filteredSchedule,
|
|
1246
|
+
};
|
|
1247
|
+
}
|
|
1248
|
+
return {
|
|
1249
|
+
variant,
|
|
1250
|
+
schedule: filteredSchedule,
|
|
1251
|
+
};
|
|
1002
1252
|
};
|
|
1003
|
-
|
|
1004
1253
|
/**
|
|
1005
|
-
*
|
|
1254
|
+
* Serialize week schedule to string schedule
|
|
1006
1255
|
*
|
|
1007
|
-
* @param {
|
|
1008
|
-
* @returns {
|
|
1256
|
+
* @param {WeekSchedule} weekSchedule Week schedule range
|
|
1257
|
+
* @returns {string} Schedule string
|
|
1009
1258
|
*/
|
|
1010
|
-
const
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
childrenWidth.current.push({ width: reportedWidth + itemsGap });
|
|
1023
|
-
if (childrenWidth.current.length === itemsCount) {
|
|
1024
|
-
setIsReady(true);
|
|
1025
|
-
}
|
|
1026
|
-
};
|
|
1027
|
-
const requiredSpace = childrenWidth.current.reduce((previous, current) => {
|
|
1028
|
-
return previous + current.width;
|
|
1029
|
-
}, 0);
|
|
1030
|
-
let counter = 0;
|
|
1031
|
-
const availableSpace = ((availableWidth === null || availableWidth === void 0 ? void 0 : availableWidth.current) || 0) - counterWidth;
|
|
1032
|
-
const renderedElements = items
|
|
1033
|
-
.concat({ text: "", onClick: () => null, disabled: false }) // reserved element for a potential counter
|
|
1034
|
-
.map((item, index) => {
|
|
1035
|
-
const spaceNeeded = childrenWidth.current.slice(0, index + 1).reduce((previous, current) => {
|
|
1036
|
-
return previous + current.width;
|
|
1037
|
-
}, 0);
|
|
1038
|
-
const isLast = index === items.length;
|
|
1039
|
-
const counterRequired = requiredSpace > availableSpace && counter !== 0;
|
|
1040
|
-
if (isLast && counterRequired) {
|
|
1041
|
-
return (jsx(TagWithWidth, { color: "white", disabled: disabled, onWidthKnown: ({ width: reportedWidth }) => setCounterWidth(reportedWidth), children: jsxs("div", { className: cvaSelectCounter(), "data-testid": "select-counter", children: ["+", counter] }) }, item.text + index));
|
|
1042
|
-
}
|
|
1043
|
-
if (isLast) {
|
|
1044
|
-
return null;
|
|
1045
|
-
}
|
|
1046
|
-
const itemCanFit = spaceNeeded <= availableSpace;
|
|
1047
|
-
if (itemCanFit) {
|
|
1048
|
-
return (jsx(TagWithWidth, { className: "inline-flex shrink-0", color: item.disabled ? "unknown" : "primary", dataTestId: `${item.text}-tag`, disabled: disabled, onClose: e => {
|
|
1049
|
-
e.stopPropagation();
|
|
1050
|
-
item.onClick();
|
|
1051
|
-
}, onWidthKnown: onWidthKnownHandler, children: item.text }, item.text + index));
|
|
1259
|
+
const serializeSchedule = (weekSchedule) => {
|
|
1260
|
+
return weekSchedule.schedule
|
|
1261
|
+
.filter(({ range, day, isAllDay }) => {
|
|
1262
|
+
const hasRange = (range === null || range === void 0 ? void 0 : range.timeFrom) && (range === null || range === void 0 ? void 0 : range.timeTo);
|
|
1263
|
+
switch (weekSchedule.variant) {
|
|
1264
|
+
case ScheduleVariant.WEEKDAYS:
|
|
1265
|
+
return day <= 5 && hasRange;
|
|
1266
|
+
case ScheduleVariant.ALL_DAYS:
|
|
1267
|
+
return day <= 7 && hasRange;
|
|
1268
|
+
case ScheduleVariant.CUSTOM:
|
|
1269
|
+
default:
|
|
1270
|
+
return hasRange || isAllDay;
|
|
1052
1271
|
}
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1272
|
+
})
|
|
1273
|
+
.map(({ day, range, isAllDay }) => {
|
|
1274
|
+
if (isAllDay) {
|
|
1275
|
+
return `${day}#00:00-24:00`;
|
|
1056
1276
|
}
|
|
1057
|
-
return
|
|
1277
|
+
return `${day}#${range.timeFrom}-${range.timeTo}`;
|
|
1058
1278
|
})
|
|
1059
|
-
.
|
|
1060
|
-
return (jsxs("div", { className: cvaSelectDynamicTagContainer({ visible: isReady }), ref: containerRef, style: {
|
|
1061
|
-
width: `${width}`,
|
|
1062
|
-
}, children: [renderedElements, postFix] }));
|
|
1279
|
+
.join(",");
|
|
1063
1280
|
};
|
|
1064
1281
|
|
|
1065
1282
|
/**
|
|
1066
|
-
* A
|
|
1067
|
-
* This complex object includes all the compositional components that are used in react-select. If you wish to overwrite a component, pass in an object with the appropriate namespace.
|
|
1283
|
+
* A thin wrapper around the `BaseInput` component for text input fields.
|
|
1068
1284
|
*
|
|
1069
|
-
*
|
|
1070
|
-
* @template Group
|
|
1071
|
-
* @param {Partial<SelectComponents<Option, IsMulti, Group>> | undefined} componentsProps a custom component prop that you can to override defaults
|
|
1072
|
-
* @param {boolean} disabled decide to override disabled variant
|
|
1073
|
-
* @param {boolean} menuIsOpen menu is open state
|
|
1074
|
-
* @param {React.MutableRefObject<boolean>} refMenuIsEnabled a flag to block menu from open
|
|
1075
|
-
* @param {string} dataTestId a test id
|
|
1076
|
-
* @param {number} maxSelectedDisplayCount a number of max display count
|
|
1077
|
-
* @param {JSX.Element} dropdownIcon an custom dropdown icon
|
|
1078
|
-
* @returns {Partial<SelectComponents<Option, boolean, GroupBase<Option>>> | undefined} components object to override react-select default components
|
|
1079
|
-
*/
|
|
1080
|
-
const useCustomComponents = (componentsProps, disabled, menuIsOpen, refMenuIsEnabled, dataTestId, maxSelectedDisplayCount, dropdownIcon) => {
|
|
1081
|
-
const [t] = useTranslation();
|
|
1082
|
-
// perhaps it should not be wrap in memo (causing some issues with opening and closing on mobiles)
|
|
1083
|
-
const customComponents = React.useMemo(() => {
|
|
1084
|
-
return Object.assign({ ValueContainer: props => {
|
|
1085
|
-
if (props.isMulti && Array.isArray(props.children) && props.children.length > 0) {
|
|
1086
|
-
const PLACEHOLDER_KEY = "placeholder";
|
|
1087
|
-
const key = props && props.children && props.children[0] ? props.children[0].key : "";
|
|
1088
|
-
const values = props && props.children ? props.children[0] : [];
|
|
1089
|
-
const tags = key === PLACEHOLDER_KEY ? [] : values;
|
|
1090
|
-
const searchInput = props && props.children && props.children[1];
|
|
1091
|
-
return (jsx(components.ValueContainer, Object.assign({}, props, { isDisabled: props.selectProps.isDisabled, children: maxSelectedDisplayCount === undefined ? (jsx(TagsContainer, { disabled: disabled, items: tags
|
|
1092
|
-
? tags.map(({ props: tagProps }) => {
|
|
1093
|
-
return {
|
|
1094
|
-
text: tagProps.children,
|
|
1095
|
-
onClick: disabled
|
|
1096
|
-
? undefined
|
|
1097
|
-
: (e) => {
|
|
1098
|
-
var _a, _b;
|
|
1099
|
-
refMenuIsEnabled.current = false;
|
|
1100
|
-
((_a = tagProps === null || tagProps === void 0 ? void 0 : tagProps.removeProps) === null || _a === void 0 ? void 0 : _a.onClick) && ((_b = tagProps === null || tagProps === void 0 ? void 0 : tagProps.removeProps) === null || _b === void 0 ? void 0 : _b.onClick(e));
|
|
1101
|
-
},
|
|
1102
|
-
disabled: disabled,
|
|
1103
|
-
};
|
|
1104
|
-
})
|
|
1105
|
-
: [], postFix: searchInput, width: "100%" })) : (jsxs(Fragment, { children: [tags &&
|
|
1106
|
-
tags.slice(0, maxSelectedDisplayCount).map(({ props: tagProps }) => {
|
|
1107
|
-
var _a, _b;
|
|
1108
|
-
return (jsx(Tag, { className: "inline-flex shrink-0", color: disabled ? "unknown" : "primary", dataTestId: tagProps.children ? `${(_a = tagProps.children) === null || _a === void 0 ? void 0 : _a.toString()}-tag` : undefined, onClose: e => {
|
|
1109
|
-
var _a, _b;
|
|
1110
|
-
e.stopPropagation();
|
|
1111
|
-
refMenuIsEnabled.current = false;
|
|
1112
|
-
((_a = tagProps === null || tagProps === void 0 ? void 0 : tagProps.removeProps) === null || _a === void 0 ? void 0 : _a.onClick) && ((_b = tagProps === null || tagProps === void 0 ? void 0 : tagProps.removeProps) === null || _b === void 0 ? void 0 : _b.onClick(e));
|
|
1113
|
-
}, children: tagProps.children }, (_b = tagProps.children) === null || _b === void 0 ? void 0 : _b.toString()));
|
|
1114
|
-
}), tags && tags.length > maxSelectedDisplayCount && (jsxs(Tag, { color: "neutral", dataTestId: "counter-tag", children: ["+", tags.length - maxSelectedDisplayCount] })), searchInput] })) })));
|
|
1115
|
-
}
|
|
1116
|
-
return (jsx(components.ValueContainer, Object.assign({}, props, { isDisabled: props.selectProps.isDisabled, children: props.children })));
|
|
1117
|
-
}, LoadingIndicator: props => {
|
|
1118
|
-
return jsx(Spinner, { className: "mt-1.5 mr-1", size: "small" });
|
|
1119
|
-
}, DropdownIndicator: props => {
|
|
1120
|
-
const icon = props.selectProps.menuIsOpen ? (jsx(Icon, { name: "ChevronUp", size: "medium" })) : (jsx(Icon, { name: "ChevronDown", size: "medium" }));
|
|
1121
|
-
return props.selectProps.isLoading ? null : (jsx(components.DropdownIndicator, Object.assign({}, props, { children: jsx("div", { className: cvaSelectIcon(), children: dropdownIcon ? dropdownIcon : icon }) })));
|
|
1122
|
-
}, IndicatorSeparator: () => null, ClearIndicator: props => {
|
|
1123
|
-
if (disabled) {
|
|
1124
|
-
return null;
|
|
1125
|
-
}
|
|
1126
|
-
return (jsx(components.ClearIndicator, Object.assign({}, props, { children: jsx("div", { className: cvaSelectXIcon(), "data-testid": dataTestId && `${dataTestId}-XMarkIcon`, onClick: props.clearValue, children: jsx(Icon, { name: "XCircle", size: "medium", title: t("clearIndicator.icon.tooltip.clearAll") }) }) })));
|
|
1127
|
-
}, Control: props => {
|
|
1128
|
-
return jsx(components.Control, Object.assign({}, props, { className: props.isDisabled ? "bg-slate-100" : "" }));
|
|
1129
|
-
}, SingleValue: props => {
|
|
1130
|
-
return (jsx(components.SingleValue, Object.assign({}, props, { className: props.isDisabled ? "text-slate-700" : "", children: jsx("div", { "data-testid": dataTestId + "-singleValue", children: props.children }) })));
|
|
1131
|
-
}, Menu: props => {
|
|
1132
|
-
return (jsx(components.Menu, Object.assign({}, props, { className: cvaSelectMenuList({ menuIsOpen: props.selectProps.menuIsOpen }) })));
|
|
1133
|
-
}, Placeholder: props => {
|
|
1134
|
-
return (jsx(components.Placeholder, Object.assign({}, props, { className: "!text-slate-400", children: props.children })));
|
|
1135
|
-
}, MenuList: props => {
|
|
1136
|
-
return (jsx(components.MenuList, Object.assign({}, props, { innerProps: Object.assign(Object.assign({}, props.innerProps), { onScroll: e => {
|
|
1137
|
-
const listEl = e.currentTarget;
|
|
1138
|
-
if (listEl.scrollTop + listEl.clientHeight >= listEl.scrollHeight) {
|
|
1139
|
-
props.selectProps.onMenuScrollToBottom && props.selectProps.onMenuScrollToBottom(new TouchEvent(""));
|
|
1140
|
-
}
|
|
1141
|
-
} }), children: props.children })));
|
|
1142
|
-
}, Option: props => {
|
|
1143
|
-
const componentProps = {
|
|
1144
|
-
label: props.label,
|
|
1145
|
-
focused: props.isFocused,
|
|
1146
|
-
selected: props.isSelected,
|
|
1147
|
-
onClick: props.innerProps.onClick,
|
|
1148
|
-
};
|
|
1149
|
-
return (jsx(components.Option, Object.assign({}, props, { innerProps: Object.assign(Object.assign({}, props.innerProps), { role: "option", onClick: () => { } }), children: props.isMulti ? (jsx(MultiSelectMenuItem, Object.assign({}, componentProps, { dataTestId: typeof props.label === "string" ? props.label : undefined, disabled: disabled }))) : (jsx(SingleSelectMenuItem, Object.assign({}, componentProps, { dataTestId: typeof props.label === "string" ? props.label : undefined, disabled: disabled || props.isDisabled }))) })));
|
|
1150
|
-
} }, componentsProps);
|
|
1151
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1152
|
-
}, [componentsProps, disabled, maxSelectedDisplayCount]); // do not add dropdownIcon (it will cause issue with opening/closing list for selects with custom icon)
|
|
1153
|
-
return customComponents;
|
|
1154
|
-
};
|
|
1155
|
-
|
|
1156
|
-
/**
|
|
1157
|
-
* @template IsMulti
|
|
1158
|
-
* @template Group
|
|
1159
|
-
* @param {React.RefObject<HTMLDivElement>} refContainer react ref to container element
|
|
1160
|
-
* @param {React.RefObject<HTMLDivElement>} refPrefix react ref to prefix element
|
|
1161
|
-
* @param {number | undefined} maxSelectedDisplayCount a number of max display count
|
|
1162
|
-
* @param {StylesConfig<Option, IsMulti, Group> | undefined} styles a optional object to override styles of react-select
|
|
1163
|
-
* @returns {StylesConfig<Option, boolean>} styles to override in select
|
|
1164
|
-
*/
|
|
1165
|
-
const useCustomStyles = (refContainer, refPrefix, maxSelectedDisplayCount, styles, disabled) => {
|
|
1166
|
-
const customStyles = React.useMemo(() => {
|
|
1167
|
-
return Object.assign({ control: base => {
|
|
1168
|
-
return Object.assign(Object.assign({}, base), { border: "0", boxShadow: "0", "&:hover": {
|
|
1169
|
-
border: "0",
|
|
1170
|
-
}, marginRight: "2px", backgroundColor: "" });
|
|
1171
|
-
}, singleValue: base => (Object.assign({}, base)), multiValue: base => (Object.assign({}, base)), multiValueLabel: base => (Object.assign({}, base)), indicatorsContainer: base => (Object.assign(Object.assign({}, base), (disabled && { display: "none" }))), indicatorSeparator: () => ({
|
|
1172
|
-
width: "0px",
|
|
1173
|
-
}), menu: base => {
|
|
1174
|
-
return Object.assign(Object.assign({}, base), { width: "100%", marginTop: "4px", marginBottom: "18px", transition: "all 1s ease-in-out" });
|
|
1175
|
-
}, input: base => (Object.assign(Object.assign({}, base), { marginLeft: "0px" })), placeholder: base => (Object.assign({}, base)), option: () => ({}), menuPortal: base => (Object.assign(Object.assign({}, base), { width: (refContainer === null || refContainer === void 0 ? void 0 : refContainer.current) ? `${refContainer.current.clientWidth}px` : base.width, transform: (refPrefix === null || refPrefix === void 0 ? void 0 : refPrefix.current) ? `translate(-${refPrefix.current.clientWidth + 2}px)` : "translate(-2px)", backgroundColor: "#ffffff", borderRadius: "var(--border-radius-lg)", zIndex: 20, borderColor: "rgb(var(--color-slate-300))", boxShadow: "var(--tw-ring-inset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)" })), menuList: base => {
|
|
1176
|
-
return Object.assign(Object.assign({}, base), { position: "relative", padding: "var(--spacing-1)", display: "grid", gap: "var(--spacing-1)", width: "100%", borderRadius: "0px", boxShadow: "none", paddingTop: "0px" });
|
|
1177
|
-
}, valueContainer: base => {
|
|
1178
|
-
return Object.assign(Object.assign({}, base), { flexWrap: maxSelectedDisplayCount !== undefined ? "wrap" : "nowrap", gap: "0.25rem" });
|
|
1179
|
-
}, container: base => (Object.assign(Object.assign({}, base), { border: "none", width: "calc(100% - 2px)", paddingLeft: "2px" })), dropdownIndicator: base => (Object.assign(Object.assign({}, base), { padding: "0px" })), clearIndicator: base => {
|
|
1180
|
-
return Object.assign(Object.assign({}, base), { padding: "0px" });
|
|
1181
|
-
} }, styles);
|
|
1182
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1183
|
-
}, [refContainer, refPrefix]);
|
|
1184
|
-
return { customStyles };
|
|
1185
|
-
};
|
|
1186
|
-
|
|
1187
|
-
/**
|
|
1188
|
-
* A hook used by selects to share the common code
|
|
1189
|
-
*
|
|
1190
|
-
* @param {SelectProps} props - The props for the Select component
|
|
1191
|
-
* @returns {IUseSelect} Select component
|
|
1192
|
-
*/
|
|
1193
|
-
const useSelect = (_a) => {
|
|
1194
|
-
var _b;
|
|
1195
|
-
var { id, className, dataTestId = "select", prefix, async, dropdownIcon, maxMenuHeight = 200, label, hasError, disabled, isMulti, components, value, options, onChange, isLoading, classNamePrefix = "", onMenuOpen, onMenuClose, maxSelectedDisplayCount = undefined, isClearable = false, isSearchable = true, onMenuScrollToBottom, styles, filterOption, onInputChange } = _a, props = __rest(_a, ["id", "className", "dataTestId", "prefix", "async", "dropdownIcon", "maxMenuHeight", "label", "hasError", "disabled", "isMulti", "components", "value", "options", "onChange", "isLoading", "classNamePrefix", "onMenuOpen", "onMenuClose", "maxSelectedDisplayCount", "isClearable", "isSearchable", "onMenuScrollToBottom", "styles", "filterOption", "onInputChange"]);
|
|
1196
|
-
const refContainer = React__default.useRef(null);
|
|
1197
|
-
const refPrefix = React__default.useRef(null);
|
|
1198
|
-
const { customStyles } = useCustomStyles(refContainer, refPrefix, maxSelectedDisplayCount, styles, disabled);
|
|
1199
|
-
const [menuIsOpen, setMenuIsOpen] = React__default.useState((_b = props.menuIsOpen) !== null && _b !== void 0 ? _b : false);
|
|
1200
|
-
const refMenuIsEnabled = React__default.useRef(true);
|
|
1201
|
-
const customComponents = useCustomComponents(components, disabled || false, menuIsOpen, refMenuIsEnabled, dataTestId, maxSelectedDisplayCount, dropdownIcon);
|
|
1202
|
-
const menuPlacement = "auto";
|
|
1203
|
-
const openMenuHandler = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1204
|
-
onMenuOpen && onMenuOpen();
|
|
1205
|
-
if (refMenuIsEnabled.current) {
|
|
1206
|
-
setMenuIsOpen(true);
|
|
1207
|
-
}
|
|
1208
|
-
else {
|
|
1209
|
-
refMenuIsEnabled.current = true;
|
|
1210
|
-
}
|
|
1211
|
-
});
|
|
1212
|
-
const closeMenuHandler = () => {
|
|
1213
|
-
setMenuIsOpen(false);
|
|
1214
|
-
onMenuClose && onMenuClose();
|
|
1215
|
-
};
|
|
1216
|
-
const orderedOptions = React__default.useMemo(() => {
|
|
1217
|
-
return disabled
|
|
1218
|
-
? getOrderedOptions(options, value).map(option => {
|
|
1219
|
-
return Object.assign(Object.assign({}, option), { disabled: true });
|
|
1220
|
-
})
|
|
1221
|
-
: getOrderedOptions(options, value);
|
|
1222
|
-
}, [options, value, disabled]);
|
|
1223
|
-
return {
|
|
1224
|
-
refContainer,
|
|
1225
|
-
refPrefix,
|
|
1226
|
-
customStyles,
|
|
1227
|
-
menuIsOpen,
|
|
1228
|
-
customComponents,
|
|
1229
|
-
menuPlacement,
|
|
1230
|
-
openMenuHandler,
|
|
1231
|
-
closeMenuHandler,
|
|
1232
|
-
orderedOptions,
|
|
1233
|
-
};
|
|
1234
|
-
};
|
|
1235
|
-
|
|
1236
|
-
/**
|
|
1237
|
-
* CreatableSelects are input components used to choose a value from a set.
|
|
1238
|
-
*
|
|
1239
|
-
* @param {CreatableSelectProps} props - The props for the CreatableSelect component
|
|
1240
|
-
* @returns {JSX.Element} CreatableSelect component
|
|
1241
|
-
*/
|
|
1242
|
-
const CreatableSelect = (props) => {
|
|
1243
|
-
const { className } = props, propsNoClassName = __rest(props, ["className"]);
|
|
1244
|
-
const { id, dataTestId = "creatableSelect", prefix, async, maxMenuHeight = 200, label, hasError, disabled, isMulti, value, options, onChange, isLoading, classNamePrefix = dataTestId !== null && dataTestId !== void 0 ? dataTestId : "creatableSelect", onMenuScrollToBottom, filterOption, onInputChange, isSearchable, isClearable = false, readOnly, openMenuOnClick = !disabled, openMenuOnFocus = !disabled, allowCreateWhileLoading, onCreateOption, } = propsNoClassName;
|
|
1245
|
-
const { refContainer, refPrefix, customStyles, menuIsOpen, customComponents, menuPlacement, openMenuHandler, closeMenuHandler, orderedOptions, } = useSelect(props);
|
|
1246
|
-
const creatableSelectProps = {
|
|
1247
|
-
value,
|
|
1248
|
-
menuPlacement,
|
|
1249
|
-
maxMenuHeight,
|
|
1250
|
-
onChange,
|
|
1251
|
-
"aria-label": label,
|
|
1252
|
-
"data-testid": dataTestId,
|
|
1253
|
-
components: customComponents,
|
|
1254
|
-
styles: customStyles,
|
|
1255
|
-
tabSelectsValue: false,
|
|
1256
|
-
blurInputOnSelect: !isMulti,
|
|
1257
|
-
menuPortalTarget: props.menuPortalTarget || document.body,
|
|
1258
|
-
isSearchable: disabled || readOnly ? false : isSearchable,
|
|
1259
|
-
menuShouldBlockScroll: true,
|
|
1260
|
-
menuShouldScrollIntoView: true,
|
|
1261
|
-
openMenuOnFocus,
|
|
1262
|
-
menuIsOpen: !readOnly ? menuIsOpen : false,
|
|
1263
|
-
openMenuOnClick,
|
|
1264
|
-
closeMenuOnSelect: false,
|
|
1265
|
-
isMulti,
|
|
1266
|
-
classNamePrefix,
|
|
1267
|
-
isLoading,
|
|
1268
|
-
isClearable,
|
|
1269
|
-
id,
|
|
1270
|
-
onMenuScrollToBottom,
|
|
1271
|
-
onInputChange,
|
|
1272
|
-
allowCreateWhileLoading,
|
|
1273
|
-
onCreateOption,
|
|
1274
|
-
};
|
|
1275
|
-
return (jsxs("div", { className: cvaSelect({ invalid: hasError, disabled: disabled || readOnly, className }), "data-testid": dataTestId, ref: refContainer, children: [prefix !== undefined && (jsx("div", { className: cvaSelectPrefix(), "data-testid": dataTestId && `${dataTestId}-prefix`, ref: refPrefix, children: prefix })), async ? (jsx(ReactAsyncCreatableSelect, Object.assign({}, propsNoClassName, creatableSelectProps, async, { onMenuClose: closeMenuHandler, onMenuOpen: openMenuHandler }))) : (jsx(ReactCreatableSelect, Object.assign({}, propsNoClassName, creatableSelectProps, { hideSelectedOptions: false, isMulti: isMulti, onMenuClose: closeMenuHandler, onMenuOpen: openMenuHandler, options: filterOption ? orderedOptions : options })))] }));
|
|
1276
|
-
};
|
|
1277
|
-
CreatableSelect.displayName = "CreatableSelect";
|
|
1278
|
-
|
|
1279
|
-
/**
|
|
1280
|
-
* Selects are input components used to choose a value from a set.
|
|
1281
|
-
*
|
|
1282
|
-
* @param {SelectProps} props - The props for the Select component
|
|
1283
|
-
* @returns {JSX.Element} Select component
|
|
1284
|
-
*/
|
|
1285
|
-
const Select = (props) => {
|
|
1286
|
-
const { className } = props, propsNoClassName = __rest(props, ["className"]);
|
|
1287
|
-
const { id, dataTestId = "select", prefix, async, maxMenuHeight = 200, label, hasError, disabled, isMulti, value, options, onChange, isLoading, classNamePrefix = dataTestId !== null && dataTestId !== void 0 ? dataTestId : "select", onMenuScrollToBottom, filterOption, onInputChange, isSearchable, isClearable = false, readOnly, openMenuOnClick = !disabled, openMenuOnFocus = !disabled, } = props;
|
|
1288
|
-
const { refContainer, refPrefix, customStyles, menuIsOpen, customComponents, menuPlacement, openMenuHandler, closeMenuHandler, orderedOptions, } = useSelect(props);
|
|
1289
|
-
const selectProps = {
|
|
1290
|
-
value,
|
|
1291
|
-
menuPlacement,
|
|
1292
|
-
maxMenuHeight,
|
|
1293
|
-
onChange,
|
|
1294
|
-
"aria-label": label,
|
|
1295
|
-
"data-testid": dataTestId,
|
|
1296
|
-
components: customComponents,
|
|
1297
|
-
styles: customStyles,
|
|
1298
|
-
tabSelectsValue: false,
|
|
1299
|
-
blurInputOnSelect: !isMulti,
|
|
1300
|
-
menuPortalTarget: props.menuPortalTarget || document.body,
|
|
1301
|
-
isSearchable: disabled || readOnly ? false : isSearchable,
|
|
1302
|
-
menuShouldBlockScroll: true,
|
|
1303
|
-
menuShouldScrollIntoView: true,
|
|
1304
|
-
openMenuOnFocus,
|
|
1305
|
-
menuIsOpen: !readOnly ? menuIsOpen : false,
|
|
1306
|
-
openMenuOnClick,
|
|
1307
|
-
closeMenuOnSelect: false,
|
|
1308
|
-
isMulti,
|
|
1309
|
-
classNamePrefix,
|
|
1310
|
-
isLoading,
|
|
1311
|
-
isClearable,
|
|
1312
|
-
id,
|
|
1313
|
-
onMenuScrollToBottom,
|
|
1314
|
-
onInputChange,
|
|
1315
|
-
};
|
|
1316
|
-
return (jsxs("div", { className: cvaSelect({ invalid: hasError, disabled: disabled || readOnly, className }), "data-testid": dataTestId, ref: refContainer, children: [prefix !== undefined && (jsx("div", { className: cvaSelectPrefix(), "data-testid": dataTestId && `${dataTestId}-prefix`, ref: refPrefix, children: prefix })), async ? (jsx(ReactAsyncSelect, Object.assign({}, propsNoClassName, selectProps, async, { onMenuClose: closeMenuHandler, onMenuOpen: openMenuHandler }))) : (jsx(ReactSelect, Object.assign({}, propsNoClassName, selectProps, { hideSelectedOptions: false, isMulti: isMulti, onMenuClose: closeMenuHandler, onMenuOpen: openMenuHandler, options: filterOption ? orderedOptions : options })))] }));
|
|
1317
|
-
};
|
|
1318
|
-
Select.displayName = "Select";
|
|
1319
|
-
|
|
1320
|
-
const COUNTRY_CODES_NOT_SUPPORTED_BY_BACKEND = ["+53", "+98", "+211", "+247", "+249", "+383", "+850", "+963"];
|
|
1321
|
-
const ADDITIONAL_COUNTRY_CODES_SUPPORTED_BY_BACKEND = [
|
|
1322
|
-
"1242",
|
|
1323
|
-
"1246",
|
|
1324
|
-
"1264",
|
|
1325
|
-
"1268",
|
|
1326
|
-
"1284",
|
|
1327
|
-
"1340",
|
|
1328
|
-
"1345",
|
|
1329
|
-
"1441",
|
|
1330
|
-
"1473",
|
|
1331
|
-
"1649",
|
|
1332
|
-
"1664",
|
|
1333
|
-
"1670",
|
|
1334
|
-
"1671",
|
|
1335
|
-
"1684",
|
|
1336
|
-
"1721",
|
|
1337
|
-
"1758",
|
|
1338
|
-
"1767",
|
|
1339
|
-
"1784",
|
|
1340
|
-
"1809",
|
|
1341
|
-
"1868",
|
|
1342
|
-
"1869",
|
|
1343
|
-
"1876",
|
|
1344
|
-
"379",
|
|
1345
|
-
"5999",
|
|
1346
|
-
"881",
|
|
1347
|
-
"882",
|
|
1348
|
-
"883",
|
|
1349
|
-
];
|
|
1350
|
-
const DUPLICATE_COUNTRY_CODES = [
|
|
1351
|
-
// +1
|
|
1352
|
-
"AG",
|
|
1353
|
-
"AI",
|
|
1354
|
-
"AS",
|
|
1355
|
-
"BB",
|
|
1356
|
-
"BM",
|
|
1357
|
-
"BS",
|
|
1358
|
-
"CA",
|
|
1359
|
-
"DM",
|
|
1360
|
-
"DO",
|
|
1361
|
-
"GD",
|
|
1362
|
-
"GU",
|
|
1363
|
-
"JM",
|
|
1364
|
-
"KN",
|
|
1365
|
-
"KY",
|
|
1366
|
-
"LC",
|
|
1367
|
-
"MP",
|
|
1368
|
-
"MS",
|
|
1369
|
-
"PR",
|
|
1370
|
-
"SX",
|
|
1371
|
-
"TC",
|
|
1372
|
-
"TT",
|
|
1373
|
-
"VC",
|
|
1374
|
-
"VG",
|
|
1375
|
-
"VI",
|
|
1376
|
-
// +7
|
|
1377
|
-
"KZ",
|
|
1378
|
-
// +39
|
|
1379
|
-
"VA",
|
|
1380
|
-
// +44
|
|
1381
|
-
"GG",
|
|
1382
|
-
"IM",
|
|
1383
|
-
"JE",
|
|
1384
|
-
// +47
|
|
1385
|
-
"SJ",
|
|
1386
|
-
// +61
|
|
1387
|
-
"CC",
|
|
1388
|
-
"CX",
|
|
1389
|
-
// 212
|
|
1390
|
-
"EH",
|
|
1391
|
-
// 262
|
|
1392
|
-
"RE",
|
|
1393
|
-
// 290
|
|
1394
|
-
"SH",
|
|
1395
|
-
// 590
|
|
1396
|
-
"BL",
|
|
1397
|
-
"MF",
|
|
1398
|
-
// 599
|
|
1399
|
-
"CW",
|
|
1400
|
-
];
|
|
1401
|
-
const countries = getCountries()
|
|
1402
|
-
.filter(code => !DUPLICATE_COUNTRY_CODES.includes(code))
|
|
1403
|
-
.map(code => {
|
|
1404
|
-
const c = getCountryCallingCode(code);
|
|
1405
|
-
return {
|
|
1406
|
-
label: `+${c} ${countryCodeToFlagEmoji(code)}`,
|
|
1407
|
-
value: `+${c}`,
|
|
1408
|
-
};
|
|
1409
|
-
});
|
|
1410
|
-
const additionalCountries = ADDITIONAL_COUNTRY_CODES_SUPPORTED_BY_BACKEND.map(code => ({
|
|
1411
|
-
label: `+${code}`,
|
|
1412
|
-
value: `+${code}`,
|
|
1413
|
-
}));
|
|
1414
|
-
const countryCodes = [...countries, ...additionalCountries]
|
|
1415
|
-
.filter(code => !COUNTRY_CODES_NOT_SUPPORTED_BY_BACKEND.includes(code.value))
|
|
1416
|
-
.sort((a, b) => Number(a.value) - Number(b.value));
|
|
1417
|
-
|
|
1418
|
-
/**
|
|
1419
|
-
* The CountryCodeSelect component is used to select a country code for a phone number.
|
|
1420
|
-
*
|
|
1421
|
-
* @param {CountryCodeSelectProps} props - The props for the CountryCodeSelect component
|
|
1422
|
-
* @returns {JSX.Element} CountryCodeSelect component
|
|
1423
|
-
*/
|
|
1424
|
-
const CountryCodeSelect = ({ excludedCountries, countryCode, isInvalid, onChange, disabled, readOnly, dataTestId, placeholder, onBlur, isClearable, }) => {
|
|
1425
|
-
const [isCountryCodeMissing, setIsCountryCodeMissing] = useState(false);
|
|
1426
|
-
useEffect(() => {
|
|
1427
|
-
countryCode && setIsCountryCodeMissing(false);
|
|
1428
|
-
}, [countryCode]);
|
|
1429
|
-
const filteredCodes = countryCodes.filter(code => {
|
|
1430
|
-
return !(excludedCountries === null || excludedCountries === void 0 ? void 0 : excludedCountries.some(excludedCode => excludedCode.value === code.value));
|
|
1431
|
-
});
|
|
1432
|
-
return (jsx(Select, { "aria-invalid": isCountryCodeMissing, className: "w-36", closeMenuOnSelect: true, dataTestId: dataTestId, disabled: disabled, hasError: isCountryCodeMissing || isInvalid, isClearable: isClearable, maxMenuHeight: 200, menuIsOpen: readOnly ? false : undefined, onBlur: onBlur, onChange: onChange, options: filteredCodes.map(code => code), placeholder: placeholder, readOnly: readOnly, value: filteredCodes.find(({ value }) => value === `+${countryCode}`) }));
|
|
1433
|
-
};
|
|
1434
|
-
|
|
1435
|
-
/**
|
|
1436
|
-
* A component for inputting phone numbers with an optional action button for initiating a phone call.
|
|
1437
|
-
*
|
|
1438
|
-
* @param {string} [dataTestId] - The data test ID for the component.
|
|
1439
|
-
* @param {string|number} [value] - The value of the input field. The value should include the country code as well.
|
|
1440
|
-
* @param {boolean} [disabled=false] - Whether the component is disabled or not.
|
|
1441
|
-
* @param {string} [fieldSize="medium"] - The size of the input field.
|
|
1442
|
-
* @param {boolean} [disableAction=false] - Whether the action button is disabled or not.
|
|
1443
|
-
* @returns {JSX.Element} - The PhoneInput component.
|
|
1285
|
+
* NOTE: If shown with a label, please use the `TextField` component instead.
|
|
1444
1286
|
*/
|
|
1445
|
-
const
|
|
1446
|
-
var _b, _c;
|
|
1447
|
-
var { dataTestId, isInvalid, disabled = false, value, defaultValue, fieldSize = "medium", disableAction = false, onChange, onBlurCountryCode, readOnly, countryCodePlaceholder, onChangeCountryCode, onBlur, onFieldsBlur, onChangeValue, isCountryCodeClearable } = _a, rest = __rest(_a, ["dataTestId", "isInvalid", "disabled", "value", "defaultValue", "fieldSize", "disableAction", "onChange", "onBlurCountryCode", "readOnly", "countryCodePlaceholder", "onChangeCountryCode", "onBlur", "onFieldsBlur", "onChangeValue", "isCountryCodeClearable"]);
|
|
1448
|
-
const DEFAULT_COUNTRY_CODE = "+45";
|
|
1449
|
-
const { getPhoneNumber } = usePhoneInput();
|
|
1450
|
-
const [placeholder, setPlaceholder] = useState();
|
|
1451
|
-
useEffect(() => {
|
|
1452
|
-
if (readOnly) {
|
|
1453
|
-
setPlaceholder("");
|
|
1454
|
-
}
|
|
1455
|
-
else {
|
|
1456
|
-
const countryCode = countryCodePlaceholder || DEFAULT_COUNTRY_CODE;
|
|
1457
|
-
setPlaceholder(`${countryCode} ${countryCodeToFlagEmoji(countryCode)}`);
|
|
1458
|
-
}
|
|
1459
|
-
}, [countryCodePlaceholder, readOnly]);
|
|
1460
|
-
const safePhoneNumber = getPhoneNumberWithPlus(value || "");
|
|
1461
|
-
const number = parsePhoneNumberFromString(safePhoneNumber, { defaultCountry: "DK" });
|
|
1462
|
-
const valueHasOnlyCountryCode = (number === null || number === void 0 ? void 0 : number.isPossible) === undefined && typeof value === "string" && value[0] === "+" && value.length < 5;
|
|
1463
|
-
const [phone, setPhone] = useState((_b = number === null || number === void 0 ? void 0 : number.nationalNumber.toString()) !== null && _b !== void 0 ? _b : "");
|
|
1464
|
-
const [code, setCode] = useState(valueHasOnlyCountryCode ? value.replace("+", "") : (_c = number === null || number === void 0 ? void 0 : number.countryCallingCode.toString()) !== null && _c !== void 0 ? _c : "");
|
|
1465
|
-
const codeRef = useRef(code); // synchronus reliable source of truth (country code is calling onblur just after onchange, useState is too slow for this)
|
|
1466
|
-
const phoneRef = useRef(phone); // synchronus reliable source of truth
|
|
1467
|
-
const onChangeHandler = React__default.useCallback(({ newPhone, newCode }) => {
|
|
1468
|
-
onChangeValue &&
|
|
1469
|
-
onChangeValue({
|
|
1470
|
-
phone: getPhoneNumber({ country: newCode, phone: newPhone || "" }),
|
|
1471
|
-
countryCode: newCode,
|
|
1472
|
-
national: newPhone,
|
|
1473
|
-
});
|
|
1474
|
-
}, [onChangeValue, getPhoneNumber]);
|
|
1475
|
-
const onPhoneChangeHandler = React__default.useCallback((ph) => {
|
|
1476
|
-
phoneRef.current = ph;
|
|
1477
|
-
setPhone(ph);
|
|
1478
|
-
onChangeHandler({ newPhone: ph, newCode: code });
|
|
1479
|
-
}, [onChangeHandler, code, phoneRef]);
|
|
1480
|
-
const onCodeChangeHandler = React__default.useCallback((codeNumber) => {
|
|
1481
|
-
codeRef.current = codeNumber;
|
|
1482
|
-
setCode(codeNumber);
|
|
1483
|
-
onChangeHandler({ newPhone: phone, newCode: codeNumber });
|
|
1484
|
-
}, [phone, onChangeHandler, codeRef]);
|
|
1485
|
-
const onBlurHandler = React__default.useCallback(() => {
|
|
1486
|
-
onFieldsBlur &&
|
|
1487
|
-
onFieldsBlur({
|
|
1488
|
-
phone: getPhoneNumber({ country: codeRef.current, phone: phoneRef.current }),
|
|
1489
|
-
countryCode: codeRef.current,
|
|
1490
|
-
national: phoneRef.current,
|
|
1491
|
-
});
|
|
1492
|
-
}, [onFieldsBlur, getPhoneNumber]);
|
|
1493
|
-
const hiddenInputRef = useRef(null);
|
|
1494
|
-
const phoneNumber = getPhoneNumber({ country: code, phone });
|
|
1495
|
-
useEffect(() => {
|
|
1496
|
-
const element = hiddenInputRef.current;
|
|
1497
|
-
const event = new Event("change");
|
|
1498
|
-
element === null || element === void 0 ? void 0 : element.dispatchEvent(event);
|
|
1499
|
-
// The event as unknown as ChangeEvent<HTMLInputElement> assertion is needed because
|
|
1500
|
-
// the event's type is inferred as Event, which doesn't have a target property, whereas ChangeEvent does.
|
|
1501
|
-
onChange && onChange(event);
|
|
1502
|
-
}, [phoneNumber, onChange]);
|
|
1503
|
-
return (jsxs("div", { className: "grid-cols-min-fr grid gap-2", "data-testid": dataTestId && `${dataTestId}-container`, children: [jsx("input", { "aria-invalid": isInvalid, "data-testid": dataTestId, hidden: true, id: "phone-input", onChange: onChange, readOnly: readOnly, ref: hiddenInputRef, value: phoneNumber }), jsx(CountryCodeSelect, { countryCode: code, dataTestId: dataTestId && `${dataTestId}-countryCodeSelect`, disabled: disabled, isClearable: isCountryCodeClearable, isInvalid: isInvalid, onBlur: e => {
|
|
1504
|
-
onBlurHandler();
|
|
1505
|
-
}, onChange: e => {
|
|
1506
|
-
var _a;
|
|
1507
|
-
onCodeChangeHandler((_a = e === null || e === void 0 ? void 0 : e.value) !== null && _a !== void 0 ? _a : "");
|
|
1508
|
-
}, placeholder: placeholder, readOnly: readOnly }), jsx(BaseInput, Object.assign({ actions: !disableAction && (jsx(ActionButton, { dataTestId: dataTestId && `${dataTestId}-phoneIcon`, disabled: disabled || isInvalid, iconSize: fieldSize, type: "PHONE_NUMBER", value: phoneNumber })), dataTestId: dataTestId && `${dataTestId}-phoneNumberInput`, disabled: disabled, fieldSize: fieldSize, id: "phoneInput-number", isInvalid: isInvalid, onBlur: () => {
|
|
1509
|
-
onBlurHandler();
|
|
1510
|
-
}, onChange: e => {
|
|
1511
|
-
onPhoneChangeHandler(e.target.value);
|
|
1512
|
-
}, readOnly: readOnly, type: "tel", value: phone }, rest))] }));
|
|
1513
|
-
});
|
|
1287
|
+
const TextInput = forwardRef((props, ref) => (jsx(BaseInput, Object.assign({ ref: ref, type: "text" }, props))));
|
|
1514
1288
|
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
return "NOT_A_NUMBER";
|
|
1541
|
-
}
|
|
1542
|
-
return "INVALID_NUMBER";
|
|
1543
|
-
};
|
|
1544
|
-
/**
|
|
1545
|
-
* Checks if the country code is valid and required
|
|
1546
|
-
*/
|
|
1547
|
-
const isInvalidCountryCode = (error, required) => (!!required && error === "REQUIRED") || error === "REQUIRED_COUNTRY";
|
|
1548
|
-
/**
|
|
1549
|
-
* Checks if the phone number is valid and required
|
|
1550
|
-
*/
|
|
1551
|
-
const isInvalidPhoneNumber = (error, required) => error !== "REQUIRED_COUNTRY" && ((!!error && error !== "REQUIRED") || (!!required && error === "REQUIRED"));
|
|
1289
|
+
const cvaSearch = cvaMerge([
|
|
1290
|
+
"shadow-none",
|
|
1291
|
+
"component-search-borderless",
|
|
1292
|
+
"component-search-background",
|
|
1293
|
+
"hover:component-search-background",
|
|
1294
|
+
"hover:component-search-focus-hover",
|
|
1295
|
+
"focus:component-search-focus-hover",
|
|
1296
|
+
"focus-within:component-search-focus-within",
|
|
1297
|
+
"transition-all",
|
|
1298
|
+
"duration-300",
|
|
1299
|
+
], {
|
|
1300
|
+
variants: {
|
|
1301
|
+
border: { true: ["!component-search-border"], false: "" },
|
|
1302
|
+
widenOnFocus: {
|
|
1303
|
+
true: [
|
|
1304
|
+
"component-search-width",
|
|
1305
|
+
"component-search-widen",
|
|
1306
|
+
"hover:component-search-widen",
|
|
1307
|
+
"focus-within:component-search-widen-focus",
|
|
1308
|
+
"focus-within:w-full",
|
|
1309
|
+
],
|
|
1310
|
+
false: "w-full",
|
|
1311
|
+
},
|
|
1312
|
+
},
|
|
1313
|
+
});
|
|
1552
1314
|
|
|
1553
1315
|
/**
|
|
1554
|
-
* The
|
|
1555
|
-
* It is a wrapper around the PhoneInput component and the FormGroup component.
|
|
1556
|
-
* It is used to render a phone number field with a label, a tip, a help text, a help addon and an error message.
|
|
1316
|
+
* The Search component is used to render a search input field.
|
|
1557
1317
|
*
|
|
1558
|
-
* @param {
|
|
1559
|
-
* @
|
|
1560
|
-
* @param {string} [helpText] - The help text for the component.
|
|
1561
|
-
* @param {string} [helpAddon] - The help addon for the component.
|
|
1562
|
-
* @param {string} [errorMessage] - The error message for the component.
|
|
1563
|
-
* @param {string} [defaultValue] - The default value for the component.
|
|
1564
|
-
* @param {boolean} [disabled=false] - Whether the component is disabled or not.
|
|
1565
|
-
* @param {string} [fieldSize="medium"] - The size of the input field.
|
|
1566
|
-
* @param {boolean} [disableAction=false] - Whether the action button is disabled or not.
|
|
1567
|
-
* @returns {JSX.Element} - The PhoneField component.
|
|
1318
|
+
* @param {SearchProps} props - The props for the Search component
|
|
1319
|
+
* @returns {JSX.Element} Search component
|
|
1568
1320
|
*/
|
|
1569
|
-
const
|
|
1570
|
-
var {
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
const [localError, setLocalError] = useState(undefined);
|
|
1575
|
-
const renderAsInvalid = !isValid || isInvalid || Boolean(errorMessage);
|
|
1576
|
-
const validate = ({ phone, national, countryCode }) => {
|
|
1577
|
-
const areFieldsPopulated = Boolean(national && countryCode);
|
|
1578
|
-
const phoneValidationResult = validatePhoneNumber({ phone, national, countryCode });
|
|
1579
|
-
setIsValid(areFieldsPopulated ? !Boolean(phoneValidationResult) : true);
|
|
1580
|
-
setLocalError(Boolean(phoneValidationResult) ? t(`phoneField.error.${phoneValidationResult}`) : undefined);
|
|
1581
|
-
};
|
|
1582
|
-
const onChangeValueHandler = (phoneNumberValue) => {
|
|
1583
|
-
validate(phoneNumberValue);
|
|
1584
|
-
onChangeValue && onChangeValue(Object.assign(Object.assign({}, phoneNumberValue), { isValid }));
|
|
1585
|
-
};
|
|
1586
|
-
const handleOnFieldBlur = (phoneNumberValue) => {
|
|
1587
|
-
validate(phoneNumberValue);
|
|
1588
|
-
onFieldsBlur && onFieldsBlur(Object.assign(Object.assign({}, phoneNumberValue), { isValid }));
|
|
1589
|
-
};
|
|
1590
|
-
return (jsx(FormGroup, { className: className, dataTestId: dataTestId && `${dataTestId}-FormGroup`, disabled: rest.disabled, helpAddon: helpAddon, helpText: (renderAsInvalid && (errorMessage || localError)) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, tip: tip, children: jsx(PhoneInput, Object.assign({ "aria-labelledby": htmlForId + "-label", dataTestId: dataTestId, defaultValue: defaultValue, id: htmlForId, isInvalid: renderAsInvalid, onChangeValue: onChangeValueHandler, onFieldsBlur: handleOnFieldBlur, ref: ref, value: value }, rest)) }));
|
|
1321
|
+
const Search = forwardRef((_a, ref) => {
|
|
1322
|
+
var { className, placeholder = "Search", value, widenInputOnFocus, showBorderWhenNotInFocus = false, disabled, onKeyUp, onChange, onFocus, onBlur, name, onClear, dataTestId, autoComplete = "on" } = _a, rest = __rest(_a, ["className", "placeholder", "value", "widenInputOnFocus", "showBorderWhenNotInFocus", "disabled", "onKeyUp", "onChange", "onFocus", "onBlur", "name", "onClear", "dataTestId", "autoComplete"]);
|
|
1323
|
+
return (jsx(TextInput, Object.assign({}, rest, { autoComplete: autoComplete, className: cvaSearch({ className, border: showBorderWhenNotInFocus, widenOnFocus: widenInputOnFocus }), dataTestId: dataTestId, disabled: disabled, name: name, onBlur: onBlur, onChange: onChange, onFocus: onFocus, onKeyUp: onKeyUp, placeholder: placeholder, prefix: jsx(Icon, { name: "MagnifyingGlass", size: "medium" }), ref: ref, suffix: onClear ? (jsx("button", { className: "flex", "data-testid": dataTestId && `${dataTestId}_suffix_component`, onClick: () => {
|
|
1324
|
+
onClear();
|
|
1325
|
+
}, children: jsx(Icon, { name: "XMark", size: "small" }) })) : undefined, value: value })));
|
|
1591
1326
|
});
|
|
1592
1327
|
|
|
1593
|
-
const
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
},
|
|
1599
|
-
});
|
|
1600
|
-
const cvaRadioItem = cvaMerge([
|
|
1601
|
-
"w-4",
|
|
1602
|
-
"h-4",
|
|
1603
|
-
"appearance-none",
|
|
1604
|
-
"rounded-3xl",
|
|
1605
|
-
"bg-white",
|
|
1606
|
-
"border-solid",
|
|
1328
|
+
const cvaSelect = cvaMerge([
|
|
1329
|
+
"relative",
|
|
1330
|
+
"flex",
|
|
1331
|
+
"shadow-sm",
|
|
1332
|
+
"rounded-lg",
|
|
1607
1333
|
"border",
|
|
1608
1334
|
"border-slate-300",
|
|
1609
|
-
"
|
|
1610
|
-
"
|
|
1335
|
+
"focus-within:ring-2",
|
|
1336
|
+
"focus-within:ring-inset",
|
|
1337
|
+
"focus-within:ring-primary-600",
|
|
1338
|
+
"focus-within:border-slate-400",
|
|
1339
|
+
"hover:border-slate-400",
|
|
1340
|
+
"hover:bg-slate-50",
|
|
1341
|
+
"bg-white",
|
|
1611
1342
|
"transition",
|
|
1612
|
-
"box-border",
|
|
1613
|
-
"hover:cursor-pointer",
|
|
1614
|
-
"hover:bg-slate-100",
|
|
1615
|
-
"focus:ring-2",
|
|
1616
|
-
"focus:ring-inset",
|
|
1617
|
-
"focus:ring-blue-700",
|
|
1618
1343
|
], {
|
|
1619
1344
|
variants: {
|
|
1620
|
-
checked: {
|
|
1621
|
-
true: [
|
|
1622
|
-
"border-solid",
|
|
1623
|
-
"border-4",
|
|
1624
|
-
"border-blue-600",
|
|
1625
|
-
"bg-white",
|
|
1626
|
-
"hover:bg-slate-100",
|
|
1627
|
-
"hover:cursor-pointer",
|
|
1628
|
-
"outline-0",
|
|
1629
|
-
"active:bg-slate-200",
|
|
1630
|
-
"active:ring-2",
|
|
1631
|
-
"active:ring-inset",
|
|
1632
|
-
"active:ring-blue-700",
|
|
1633
|
-
"focus:bg-slate-200",
|
|
1634
|
-
"focus:ring-2",
|
|
1635
|
-
"focus:ring-inset",
|
|
1636
|
-
"focus:ring-blue-700",
|
|
1637
|
-
"group-active:ring-2",
|
|
1638
|
-
"group-active:ring-inset",
|
|
1639
|
-
"group-active:ring-blue-700",
|
|
1640
|
-
],
|
|
1641
|
-
false: "",
|
|
1642
|
-
},
|
|
1643
1345
|
invalid: {
|
|
1644
|
-
true:
|
|
1645
|
-
"border-red-600",
|
|
1646
|
-
"active:ring-red-700",
|
|
1647
|
-
"focus:ring-red-700",
|
|
1648
|
-
"group-focus:ring-2",
|
|
1649
|
-
"group-focus:ring-inset",
|
|
1650
|
-
],
|
|
1346
|
+
true: "border-red-600 text-red-600 focus-within:ring-red-600 hover:border-red-600",
|
|
1651
1347
|
false: "",
|
|
1652
1348
|
},
|
|
1653
1349
|
disabled: {
|
|
1654
|
-
true:
|
|
1655
|
-
"bg-slate-400",
|
|
1656
|
-
"border-slate-300",
|
|
1657
|
-
"cursor-not-allowed",
|
|
1658
|
-
"group-hover:bg-slate-400",
|
|
1659
|
-
"group-focus:bg-slate-400",
|
|
1660
|
-
"hover:bg-slate-400",
|
|
1661
|
-
"focus:bg-slate-400",
|
|
1662
|
-
"active:bg-slate-400",
|
|
1663
|
-
"focus:ring-0",
|
|
1664
|
-
"focus:ring-inset",
|
|
1665
|
-
"group-active:ring-0",
|
|
1666
|
-
"group-active:ring-inset",
|
|
1667
|
-
],
|
|
1350
|
+
true: "!bg-slate-100",
|
|
1668
1351
|
false: "",
|
|
1669
1352
|
},
|
|
1670
1353
|
},
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
className: ["bg-white"],
|
|
1676
|
-
},
|
|
1677
|
-
],
|
|
1354
|
+
defaultVariants: {
|
|
1355
|
+
invalid: false,
|
|
1356
|
+
disabled: false,
|
|
1357
|
+
},
|
|
1678
1358
|
});
|
|
1679
|
-
const
|
|
1680
|
-
const
|
|
1681
|
-
const
|
|
1359
|
+
const cvaSelectIcon = cvaMerge("mr-2 flex cursor-pointer items-center justify-center text-slate-400 hover:text-slate-500");
|
|
1360
|
+
const cvaSelectPrefix = cvaMerge(["flex", "justify-center", "items-center", "text-slate-400", "pl-2"]);
|
|
1361
|
+
const cvaSelectXIcon = cvaMerge([
|
|
1362
|
+
"mr-2 flex cursor-pointer items-center justify-center text-slate-400 hover:text-slate-500",
|
|
1363
|
+
"ml-1",
|
|
1364
|
+
]);
|
|
1365
|
+
const cvaSelectMenuList = cvaMerge(["min-w-min", "shadow-md", "rounded-lg", "z-20", "bg-white", "p-1", "border", "border-slate-300", "gap-1", "grid"], {
|
|
1682
1366
|
variants: {
|
|
1683
|
-
|
|
1684
|
-
true:
|
|
1685
|
-
false: "",
|
|
1367
|
+
menuIsOpen: {
|
|
1368
|
+
true: "animate-fade-in-fast",
|
|
1369
|
+
false: "animate-fade-out-fast",
|
|
1686
1370
|
},
|
|
1687
1371
|
},
|
|
1688
1372
|
});
|
|
1689
|
-
|
|
1690
|
-
|
|
1373
|
+
const cvaSelectDynamicTagContainer = cvaMerge(["h-full", "flex", "gap-1", "items-center"], {
|
|
1374
|
+
variants: {
|
|
1375
|
+
visible: { true: "visible", false: "invisible" },
|
|
1376
|
+
},
|
|
1377
|
+
});
|
|
1378
|
+
const cvaSelectCounter = cvaMerge(["overflow-hidden", "whitespace-nowrap"]);
|
|
1379
|
+
const cvaSelectMenu = cvaMerge(["relative", "p-1", "grid", "gap-1"]);
|
|
1691
1380
|
|
|
1692
1381
|
/**
|
|
1693
|
-
*
|
|
1694
|
-
*
|
|
1695
|
-
* Radio buttons are used for mutually exclusive choices, not for multiple choices. Only one radio button can be selected at a time. When a user chooses a new item, the previous choice is automatically deselected.
|
|
1696
|
-
*
|
|
1697
|
-
* _**Do use** Radio buttons in forms, settings, or selections in a list._
|
|
1698
|
-
*
|
|
1699
|
-
* _**Do not use** Radio buttons if a user can select many option from a list, use checkboxes instead of radio buttons._
|
|
1700
|
-
*
|
|
1701
|
-
* @param {RadioGroupProps} props - The props for the RadioGroup component
|
|
1702
|
-
* @returns {JSX.Element} RadioGroup component
|
|
1382
|
+
* @param {MultiValue<Option> | SingleValue<Option>} arg option to check type
|
|
1383
|
+
* @returns {arg is MultiValue<Option> } is Multivalue
|
|
1703
1384
|
*/
|
|
1704
|
-
|
|
1705
|
-
return (
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1385
|
+
function isMultiValue(arg) {
|
|
1386
|
+
return Array.isArray(arg);
|
|
1387
|
+
}
|
|
1388
|
+
function isGroupBase(arg) {
|
|
1389
|
+
return arg.options !== undefined;
|
|
1390
|
+
}
|
|
1391
|
+
const isSelectedOption = (option, selected) => {
|
|
1392
|
+
if (isGroupBase(option)) {
|
|
1393
|
+
return false;
|
|
1394
|
+
}
|
|
1395
|
+
return isMultiValue(selected)
|
|
1396
|
+
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1397
|
+
selected.some(v => v.value === option.value)
|
|
1398
|
+
: // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1399
|
+
option.value === (selected === null || selected === void 0 ? void 0 : selected.value);
|
|
1400
|
+
};
|
|
1401
|
+
const removeSelectedFromGroups = (group, selected) => {
|
|
1402
|
+
if (isGroupBase(group)) {
|
|
1403
|
+
return Object.assign(Object.assign({}, group), { options: group.options.filter(option => !isSelectedOption(option, selected)) });
|
|
1404
|
+
}
|
|
1405
|
+
return group;
|
|
1406
|
+
};
|
|
1407
|
+
/**
|
|
1408
|
+
* @template IsMulti
|
|
1409
|
+
* @template Group
|
|
1410
|
+
* @param {OptionsOrGroups<Option, Group> | undefined} options An array of options to select from
|
|
1411
|
+
* @param {PropsValue<Option> | undefined} value Selected values
|
|
1412
|
+
* @returns {OptionsOrGroups<Option, Group>} An array of ordered options with selected on top
|
|
1413
|
+
*/
|
|
1414
|
+
const getOrderedOptions = (options, value) => {
|
|
1415
|
+
if (value && options) {
|
|
1416
|
+
const orderedValues = isMultiValue(value)
|
|
1417
|
+
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1418
|
+
[...value].sort((a, b) => a.label.localeCompare(b.label))
|
|
1419
|
+
: [value];
|
|
1420
|
+
const selectableOptions = options
|
|
1421
|
+
.filter(option => !isSelectedOption(option, value))
|
|
1422
|
+
.map(option => removeSelectedFromGroups(option, value));
|
|
1423
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1424
|
+
return orderedValues.concat(selectableOptions) || [];
|
|
1425
|
+
}
|
|
1426
|
+
return options || [];
|
|
1713
1427
|
};
|
|
1714
|
-
RadioGroup.displayName = "RadioGroup";
|
|
1715
1428
|
|
|
1716
1429
|
/**
|
|
1717
|
-
*
|
|
1430
|
+
* A single select menu item is a basic wrapper around Menu item designed to be used as a single value render in Select list
|
|
1718
1431
|
*
|
|
1719
|
-
* @param {
|
|
1720
|
-
* @returns {JSX.Element}
|
|
1432
|
+
* @param {SelectMenuItemProps} props - The props for the SingleSelectMenuItem
|
|
1433
|
+
* @returns {JSX.Element} SingleSelectMenuItem
|
|
1721
1434
|
*/
|
|
1722
|
-
const
|
|
1723
|
-
|
|
1724
|
-
const isChecked = (groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.value) === value;
|
|
1725
|
-
return (jsxs("label", { className: cvaRadioItemWrapper({ className }), "data-testid": dataTestId && `${dataTestId}-Wrapper`, htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, children: [jsx("input", { checked: isChecked, className: cvaRadioItem({
|
|
1726
|
-
checked: isChecked,
|
|
1727
|
-
disabled: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.disabled,
|
|
1728
|
-
invalid: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.isInvalid,
|
|
1729
|
-
}), "data-testid": dataTestId, id: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, onChange: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.onChange, type: "radio", value: value }), jsxs("div", { className: cvaRadioItemLabelContainer(), children: [jsx(Label, { dataTestId: dataTestId && `${dataTestId}-Label`, disabled: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.disabled, htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, isInvalid: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.isInvalid, children: label }), description && (jsx("label", { className: cvaRadioItemDescription({ disabled: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.disabled }), "data-testid": dataTestId && `${dataTestId}-Description`, htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, children: description }))] })] }));
|
|
1435
|
+
const SingleSelectMenuItem = ({ label, icon, onClick, selected, dataTestId, focused, disabled, }) => {
|
|
1436
|
+
return (jsx(MenuItem, { dataTestId: dataTestId, disabled: disabled, focused: focused, label: label, onClick: onClick, prefix: icon, selected: selected, suffix: selected ? jsx(Icon, { name: "Check", size: "small" }) : undefined }));
|
|
1730
1437
|
};
|
|
1731
|
-
|
|
1732
|
-
const cvaTimeRange = cvaMerge(["flex", "flex-1", "items-center", "gap-4", "border-transparent", "rounded-md"]);
|
|
1733
|
-
|
|
1734
1438
|
/**
|
|
1735
|
-
*
|
|
1439
|
+
* A multi select menu item is a basic wrapper around Menu item designed to be used as a multi value render in Select list
|
|
1736
1440
|
*
|
|
1737
|
-
* @param {
|
|
1738
|
-
* @returns {JSX.Element}
|
|
1441
|
+
* @param {SelectMenuItemProps} props - The props for the MultiSelectMenuItem
|
|
1442
|
+
* @returns {JSX.Element} multi select menu item
|
|
1739
1443
|
*/
|
|
1740
|
-
const
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
setTimeRange(prev => (Object.assign(Object.assign({}, prev), { timeFrom })));
|
|
1748
|
-
};
|
|
1749
|
-
const onChangeTo = (timeTo) => {
|
|
1750
|
-
setTimeRange(prev => (Object.assign(Object.assign({}, prev), { timeTo })));
|
|
1751
|
-
};
|
|
1752
|
-
const onRangeChange = () => onChange(timeRange);
|
|
1753
|
-
return (jsxs("div", { className: cvaTimeRange({ className }), "data-testid": dataTestId, id: id, children: [jsx(BaseInput, { dataTestId: `${dataTestId}-from`, disabled: disabled, isInvalid: isInvalid, onBlur: onRangeChange, onChange: (time) => onChangeFrom(time.currentTarget.value), type: "time", value: (_a = timeRange === null || timeRange === void 0 ? void 0 : timeRange.timeFrom) !== null && _a !== void 0 ? _a : "" }), children !== null && children !== void 0 ? children : jsx("div", { "data-testid": `${dataTestId}-separator`, children: "-" }), jsx(BaseInput, { dataTestId: `${dataTestId}-to`, disabled: disabled, isInvalid: isInvalid, onBlur: onRangeChange, onChange: (time) => onChangeTo(time.currentTarget.value), type: "time", value: (_b = timeRange === null || timeRange === void 0 ? void 0 : timeRange.timeTo) !== null && _b !== void 0 ? _b : "" })] }));
|
|
1444
|
+
const MultiSelectMenuItem = ({ label, onClick, selected, dataTestId, focused, disabled, }) => {
|
|
1445
|
+
return (jsx(MenuItem, { dataTestId: dataTestId, disabled: disabled, focused: focused, label: label, onClick: e => {
|
|
1446
|
+
e.stopPropagation();
|
|
1447
|
+
onClick && onClick(e);
|
|
1448
|
+
}, prefix: jsx(Checkbox, { checked: selected, disabled: disabled, onChange: () => null, onClick: e => {
|
|
1449
|
+
e.stopPropagation();
|
|
1450
|
+
}, readOnly: false }), selected: selected }));
|
|
1754
1451
|
};
|
|
1755
1452
|
|
|
1756
|
-
|
|
1757
|
-
|
|
1453
|
+
/**
|
|
1454
|
+
* Extended Tag component with information about its own width.
|
|
1455
|
+
* Used in the select component.
|
|
1456
|
+
*
|
|
1457
|
+
* @param {TagProps} props - The props for the tag component
|
|
1458
|
+
* @returns {JSX.Element} TagWithWidth component
|
|
1459
|
+
*/
|
|
1460
|
+
const TagWithWidth = (_a) => {
|
|
1461
|
+
var { onWidthKnown, children } = _a, rest = __rest(_a, ["onWidthKnown", "children"]);
|
|
1462
|
+
const ref = React__default.useRef(null);
|
|
1463
|
+
React__default.useLayoutEffect(() => {
|
|
1464
|
+
var _a;
|
|
1465
|
+
onWidthKnown && onWidthKnown({ width: ((_a = ref.current) === null || _a === void 0 ? void 0 : _a.offsetWidth) || 0 });
|
|
1466
|
+
}, [ref, onWidthKnown]);
|
|
1467
|
+
return (jsx(Tag, Object.assign({ ref: ref }, rest, { children: children })));
|
|
1468
|
+
};
|
|
1758
1469
|
|
|
1759
1470
|
/**
|
|
1760
|
-
*
|
|
1471
|
+
* TagsContainer component to display tags in limited space when children can't fit space it displays counter
|
|
1761
1472
|
*
|
|
1762
|
-
* @param {
|
|
1763
|
-
* @returns {JSX.Element}
|
|
1473
|
+
* @param {TagsContainerProps} props - The props for the TagContainer
|
|
1474
|
+
* @returns {JSX.Element} TagsContainer
|
|
1764
1475
|
*/
|
|
1765
|
-
const
|
|
1766
|
-
const
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
const
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1476
|
+
const TagsContainer = ({ items, width = "100%", itemsGap = 5, postFix, disabled }) => {
|
|
1477
|
+
const [isReady, setIsReady] = React__default.useState(false);
|
|
1478
|
+
const [counterWidth, setCounterWidth] = React__default.useState(0);
|
|
1479
|
+
const containerRef = React__default.useRef(null);
|
|
1480
|
+
const availableWidth = React__default.useRef();
|
|
1481
|
+
const childrenWidth = React__default.useRef([]);
|
|
1482
|
+
const itemsCount = items.length;
|
|
1483
|
+
React__default.useLayoutEffect(() => {
|
|
1484
|
+
var _a;
|
|
1485
|
+
availableWidth.current = ((_a = containerRef === null || containerRef === void 0 ? void 0 : containerRef.current) === null || _a === void 0 ? void 0 : _a.offsetWidth) || 0;
|
|
1486
|
+
}, [containerRef]);
|
|
1487
|
+
const onWidthKnownHandler = ({ width: reportedWidth }) => {
|
|
1488
|
+
childrenWidth.current.push({ width: reportedWidth + itemsGap });
|
|
1489
|
+
if (childrenWidth.current.length === itemsCount) {
|
|
1490
|
+
setIsReady(true);
|
|
1491
|
+
}
|
|
1778
1492
|
};
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1493
|
+
const requiredSpace = childrenWidth.current.reduce((previous, current) => {
|
|
1494
|
+
return previous + current.width;
|
|
1495
|
+
}, 0);
|
|
1496
|
+
let counter = 0;
|
|
1497
|
+
const availableSpace = ((availableWidth === null || availableWidth === void 0 ? void 0 : availableWidth.current) || 0) - counterWidth;
|
|
1498
|
+
const renderedElements = items
|
|
1499
|
+
.concat({ text: "", onClick: () => null, disabled: false }) // reserved element for a potential counter
|
|
1500
|
+
.map((item, index) => {
|
|
1501
|
+
const spaceNeeded = childrenWidth.current.slice(0, index + 1).reduce((previous, current) => {
|
|
1502
|
+
return previous + current.width;
|
|
1503
|
+
}, 0);
|
|
1504
|
+
const isLast = index === items.length;
|
|
1505
|
+
const counterRequired = requiredSpace > availableSpace && counter !== 0;
|
|
1506
|
+
if (isLast && counterRequired) {
|
|
1507
|
+
return (jsx(TagWithWidth, { color: "white", disabled: disabled, onWidthKnown: ({ width: reportedWidth }) => setCounterWidth(reportedWidth), children: jsxs("div", { className: cvaSelectCounter(), "data-testid": "select-counter", children: ["+", counter] }) }, item.text + index));
|
|
1508
|
+
}
|
|
1509
|
+
if (isLast) {
|
|
1510
|
+
return null;
|
|
1511
|
+
}
|
|
1512
|
+
const itemCanFit = spaceNeeded <= availableSpace;
|
|
1513
|
+
if (itemCanFit) {
|
|
1514
|
+
return (jsx(TagWithWidth, { className: "inline-flex shrink-0", color: item.disabled ? "unknown" : "primary", dataTestId: `${item.text}-tag`, disabled: disabled, onClose: e => {
|
|
1515
|
+
e.stopPropagation();
|
|
1516
|
+
item.onClick();
|
|
1517
|
+
}, onWidthKnown: onWidthKnownHandler, children: item.text }, item.text + index));
|
|
1518
|
+
}
|
|
1519
|
+
const fromTheItems = item.text !== "";
|
|
1520
|
+
if (fromTheItems) {
|
|
1521
|
+
counter = counter + 1;
|
|
1522
|
+
}
|
|
1523
|
+
return null;
|
|
1524
|
+
})
|
|
1525
|
+
.filter(element => element !== null);
|
|
1526
|
+
return (jsxs("div", { className: cvaSelectDynamicTagContainer({ visible: isReady }), ref: containerRef, style: {
|
|
1527
|
+
width: `${width}`,
|
|
1528
|
+
}, children: [renderedElements, postFix] }));
|
|
1782
1529
|
};
|
|
1783
1530
|
|
|
1784
|
-
const weekDay = {
|
|
1785
|
-
Monday: "monday",
|
|
1786
|
-
Tuesday: "tuesday",
|
|
1787
|
-
Wednesday: "wednesday",
|
|
1788
|
-
Thursday: "thursday",
|
|
1789
|
-
Friday: "friday",
|
|
1790
|
-
Saturday: "saturday",
|
|
1791
|
-
Sunday: "sunday",
|
|
1792
|
-
};
|
|
1793
|
-
var ScheduleVariant;
|
|
1794
|
-
(function (ScheduleVariant) {
|
|
1795
|
-
ScheduleVariant["ALL_DAYS"] = "all";
|
|
1796
|
-
ScheduleVariant["WEEKDAYS"] = "week";
|
|
1797
|
-
ScheduleVariant["CUSTOM"] = "custom";
|
|
1798
|
-
})(ScheduleVariant || (ScheduleVariant = {}));
|
|
1799
1531
|
/**
|
|
1800
|
-
*
|
|
1532
|
+
* A hook to retrieve components override object.
|
|
1533
|
+
* This complex object includes all the compositional components that are used in react-select. If you wish to overwrite a component, pass in an object with the appropriate namespace.
|
|
1801
1534
|
*
|
|
1802
|
-
* @
|
|
1803
|
-
* @
|
|
1535
|
+
* @template IsMulti
|
|
1536
|
+
* @template Group
|
|
1537
|
+
* @param {Partial<SelectComponents<Option, IsMulti, Group>> | undefined} componentsProps a custom component prop that you can to override defaults
|
|
1538
|
+
* @param {boolean} disabled decide to override disabled variant
|
|
1539
|
+
* @param {boolean} menuIsOpen menu is open state
|
|
1540
|
+
* @param {React.MutableRefObject<boolean>} refMenuIsEnabled a flag to block menu from open
|
|
1541
|
+
* @param {string} dataTestId a test id
|
|
1542
|
+
* @param {number} maxSelectedDisplayCount a number of max display count
|
|
1543
|
+
* @param {JSX.Element} dropdownIcon an custom dropdown icon
|
|
1544
|
+
* @returns {Partial<SelectComponents<Option, boolean, GroupBase<Option>>> | undefined} components object to override react-select default components
|
|
1804
1545
|
*/
|
|
1805
|
-
const
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1546
|
+
const useCustomComponents = (componentsProps, disabled, menuIsOpen, refMenuIsEnabled, dataTestId, maxSelectedDisplayCount, dropdownIcon) => {
|
|
1547
|
+
const [t] = useTranslation();
|
|
1548
|
+
// perhaps it should not be wrap in memo (causing some issues with opening and closing on mobiles)
|
|
1549
|
+
const customComponents = React.useMemo(() => {
|
|
1550
|
+
return Object.assign({ ValueContainer: props => {
|
|
1551
|
+
if (props.isMulti && Array.isArray(props.children) && props.children.length > 0) {
|
|
1552
|
+
const PLACEHOLDER_KEY = "placeholder";
|
|
1553
|
+
const key = props && props.children && props.children[0] ? props.children[0].key : "";
|
|
1554
|
+
const values = props && props.children ? props.children[0] : [];
|
|
1555
|
+
const tags = key === PLACEHOLDER_KEY ? [] : values;
|
|
1556
|
+
const searchInput = props && props.children && props.children[1];
|
|
1557
|
+
return (jsx(components.ValueContainer, Object.assign({}, props, { isDisabled: props.selectProps.isDisabled, children: maxSelectedDisplayCount === undefined ? (jsx(TagsContainer, { disabled: disabled, items: tags
|
|
1558
|
+
? tags.map(({ props: tagProps }) => {
|
|
1559
|
+
return {
|
|
1560
|
+
text: tagProps.children,
|
|
1561
|
+
onClick: disabled
|
|
1562
|
+
? undefined
|
|
1563
|
+
: (e) => {
|
|
1564
|
+
var _a, _b;
|
|
1565
|
+
refMenuIsEnabled.current = false;
|
|
1566
|
+
((_a = tagProps === null || tagProps === void 0 ? void 0 : tagProps.removeProps) === null || _a === void 0 ? void 0 : _a.onClick) && ((_b = tagProps === null || tagProps === void 0 ? void 0 : tagProps.removeProps) === null || _b === void 0 ? void 0 : _b.onClick(e));
|
|
1567
|
+
},
|
|
1568
|
+
disabled: disabled,
|
|
1569
|
+
};
|
|
1570
|
+
})
|
|
1571
|
+
: [], postFix: searchInput, width: "100%" })) : (jsxs(Fragment, { children: [tags &&
|
|
1572
|
+
tags.slice(0, maxSelectedDisplayCount).map(({ props: tagProps }) => {
|
|
1573
|
+
var _a, _b;
|
|
1574
|
+
return (jsx(Tag, { className: "inline-flex shrink-0", color: disabled ? "unknown" : "primary", dataTestId: tagProps.children ? `${(_a = tagProps.children) === null || _a === void 0 ? void 0 : _a.toString()}-tag` : undefined, onClose: e => {
|
|
1575
|
+
var _a, _b;
|
|
1576
|
+
e.stopPropagation();
|
|
1577
|
+
refMenuIsEnabled.current = false;
|
|
1578
|
+
((_a = tagProps === null || tagProps === void 0 ? void 0 : tagProps.removeProps) === null || _a === void 0 ? void 0 : _a.onClick) && ((_b = tagProps === null || tagProps === void 0 ? void 0 : tagProps.removeProps) === null || _b === void 0 ? void 0 : _b.onClick(e));
|
|
1579
|
+
}, children: tagProps.children }, (_b = tagProps.children) === null || _b === void 0 ? void 0 : _b.toString()));
|
|
1580
|
+
}), tags && tags.length > maxSelectedDisplayCount && (jsxs(Tag, { color: "neutral", dataTestId: "counter-tag", children: ["+", tags.length - maxSelectedDisplayCount] })), searchInput] })) })));
|
|
1581
|
+
}
|
|
1582
|
+
return (jsx(components.ValueContainer, Object.assign({}, props, { isDisabled: props.selectProps.isDisabled, children: props.children })));
|
|
1583
|
+
}, LoadingIndicator: props => {
|
|
1584
|
+
return jsx(Spinner, { className: "mt-1.5 mr-1", size: "small" });
|
|
1585
|
+
}, DropdownIndicator: props => {
|
|
1586
|
+
const icon = props.selectProps.menuIsOpen ? (jsx(Icon, { name: "ChevronUp", size: "medium" })) : (jsx(Icon, { name: "ChevronDown", size: "medium" }));
|
|
1587
|
+
return props.selectProps.isLoading ? null : (jsx(components.DropdownIndicator, Object.assign({}, props, { children: jsx("div", { className: cvaSelectIcon(), children: dropdownIcon ? dropdownIcon : icon }) })));
|
|
1588
|
+
}, IndicatorSeparator: () => null, ClearIndicator: props => {
|
|
1589
|
+
if (disabled) {
|
|
1590
|
+
return null;
|
|
1591
|
+
}
|
|
1592
|
+
return (jsx(components.ClearIndicator, Object.assign({}, props, { children: jsx("div", { className: cvaSelectXIcon(), "data-testid": dataTestId && `${dataTestId}-XMarkIcon`, onClick: props.clearValue, children: jsx(Icon, { name: "XCircle", size: "medium", title: t("clearIndicator.icon.tooltip.clearAll") }) }) })));
|
|
1593
|
+
}, Control: props => {
|
|
1594
|
+
return jsx(components.Control, Object.assign({}, props, { className: props.isDisabled ? "bg-slate-100" : "" }));
|
|
1595
|
+
}, SingleValue: props => {
|
|
1596
|
+
return (jsx(components.SingleValue, Object.assign({}, props, { className: props.isDisabled ? "text-slate-700" : "", children: jsx("div", { "data-testid": dataTestId + "-singleValue", children: props.children }) })));
|
|
1597
|
+
}, Menu: props => {
|
|
1598
|
+
return (jsx(components.Menu, Object.assign({}, props, { className: cvaSelectMenuList({ menuIsOpen: props.selectProps.menuIsOpen }) })));
|
|
1599
|
+
}, Placeholder: props => {
|
|
1600
|
+
return (jsx(components.Placeholder, Object.assign({}, props, { className: "!text-slate-400", children: props.children })));
|
|
1601
|
+
}, MenuList: props => {
|
|
1602
|
+
return (jsx(components.MenuList, Object.assign({}, props, { innerProps: Object.assign(Object.assign({}, props.innerProps), { onScroll: e => {
|
|
1603
|
+
const listEl = e.currentTarget;
|
|
1604
|
+
if (listEl.scrollTop + listEl.clientHeight >= listEl.scrollHeight) {
|
|
1605
|
+
props.selectProps.onMenuScrollToBottom && props.selectProps.onMenuScrollToBottom(new TouchEvent(""));
|
|
1606
|
+
}
|
|
1607
|
+
} }), children: props.children })));
|
|
1608
|
+
}, Option: props => {
|
|
1609
|
+
const componentProps = {
|
|
1610
|
+
label: props.label,
|
|
1611
|
+
focused: props.isFocused,
|
|
1612
|
+
selected: props.isSelected,
|
|
1613
|
+
onClick: props.innerProps.onClick,
|
|
1614
|
+
};
|
|
1615
|
+
return (jsx(components.Option, Object.assign({}, props, { innerProps: Object.assign(Object.assign({}, props.innerProps), { role: "option", onClick: () => { } }), children: props.isMulti ? (jsx(MultiSelectMenuItem, Object.assign({}, componentProps, { dataTestId: typeof props.label === "string" ? props.label : undefined, disabled: disabled }))) : (jsx(SingleSelectMenuItem, Object.assign({}, componentProps, { dataTestId: typeof props.label === "string" ? props.label : undefined, disabled: disabled || props.isDisabled }))) })));
|
|
1616
|
+
} }, componentsProps);
|
|
1617
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1618
|
+
}, [componentsProps, disabled, maxSelectedDisplayCount]); // do not add dropdownIcon (it will cause issue with opening/closing list for selects with custom icon)
|
|
1619
|
+
return customComponents;
|
|
1865
1620
|
};
|
|
1621
|
+
|
|
1866
1622
|
/**
|
|
1867
|
-
*
|
|
1623
|
+
* @template IsMulti
|
|
1624
|
+
* @template Group
|
|
1625
|
+
* @param {React.RefObject<HTMLDivElement>} refContainer react ref to container element
|
|
1626
|
+
* @param {React.RefObject<HTMLDivElement>} refPrefix react ref to prefix element
|
|
1627
|
+
* @param {number | undefined} maxSelectedDisplayCount a number of max display count
|
|
1628
|
+
* @param {StylesConfig<Option, IsMulti, Group> | undefined} styles a optional object to override styles of react-select
|
|
1629
|
+
* @returns {StylesConfig<Option, boolean>} styles to override in select
|
|
1630
|
+
*/
|
|
1631
|
+
const useCustomStyles = (refContainer, refPrefix, maxSelectedDisplayCount, styles, disabled) => {
|
|
1632
|
+
const customStyles = React.useMemo(() => {
|
|
1633
|
+
return Object.assign({ control: base => {
|
|
1634
|
+
return Object.assign(Object.assign({}, base), { border: "0", boxShadow: "0", "&:hover": {
|
|
1635
|
+
border: "0",
|
|
1636
|
+
}, marginRight: "2px", backgroundColor: "" });
|
|
1637
|
+
}, singleValue: base => (Object.assign({}, base)), multiValue: base => (Object.assign({}, base)), multiValueLabel: base => (Object.assign({}, base)), indicatorsContainer: base => (Object.assign(Object.assign({}, base), (disabled && { display: "none" }))), indicatorSeparator: () => ({
|
|
1638
|
+
width: "0px",
|
|
1639
|
+
}), menu: base => {
|
|
1640
|
+
return Object.assign(Object.assign({}, base), { width: "100%", marginTop: "4px", marginBottom: "18px", transition: "all 1s ease-in-out" });
|
|
1641
|
+
}, input: base => (Object.assign(Object.assign({}, base), { marginLeft: "0px" })), placeholder: base => (Object.assign({}, base)), option: () => ({}), menuPortal: base => (Object.assign(Object.assign({}, base), { width: (refContainer === null || refContainer === void 0 ? void 0 : refContainer.current) ? `${refContainer.current.clientWidth}px` : base.width, transform: (refPrefix === null || refPrefix === void 0 ? void 0 : refPrefix.current) ? `translate(-${refPrefix.current.clientWidth + 2}px)` : "translate(-2px)", backgroundColor: "#ffffff", borderRadius: "var(--border-radius-lg)", zIndex: 20, borderColor: "rgb(var(--color-slate-300))", boxShadow: "var(--tw-ring-inset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)" })), menuList: base => {
|
|
1642
|
+
return Object.assign(Object.assign({}, base), { position: "relative", padding: "var(--spacing-1)", display: "grid", gap: "var(--spacing-1)", width: "100%", borderRadius: "0px", boxShadow: "none", paddingTop: "0px" });
|
|
1643
|
+
}, valueContainer: base => {
|
|
1644
|
+
return Object.assign(Object.assign({}, base), { flexWrap: maxSelectedDisplayCount !== undefined ? "wrap" : "nowrap", gap: "0.25rem" });
|
|
1645
|
+
}, container: base => (Object.assign(Object.assign({}, base), { border: "none", width: "calc(100% - 2px)", paddingLeft: "2px" })), dropdownIndicator: base => (Object.assign(Object.assign({}, base), { padding: "0px" })), clearIndicator: base => {
|
|
1646
|
+
return Object.assign(Object.assign({}, base), { padding: "0px" });
|
|
1647
|
+
} }, styles);
|
|
1648
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1649
|
+
}, [refContainer, refPrefix]);
|
|
1650
|
+
return { customStyles };
|
|
1651
|
+
};
|
|
1652
|
+
|
|
1653
|
+
/**
|
|
1654
|
+
* A hook used by selects to share the common code
|
|
1868
1655
|
*
|
|
1869
|
-
* @param {
|
|
1870
|
-
* @returns {
|
|
1656
|
+
* @param {SelectProps} props - The props for the Select component
|
|
1657
|
+
* @returns {IUseSelect} Select component
|
|
1871
1658
|
*/
|
|
1872
|
-
const
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1659
|
+
const useSelect = (_a) => {
|
|
1660
|
+
var _b;
|
|
1661
|
+
var { id, className, dataTestId = "select", prefix, async, dropdownIcon, maxMenuHeight = 200, label, hasError, disabled, isMulti, components, value, options, onChange, isLoading, classNamePrefix = "", onMenuOpen, onMenuClose, maxSelectedDisplayCount = undefined, isClearable = false, isSearchable = true, onMenuScrollToBottom, styles, filterOption, onInputChange } = _a, props = __rest(_a, ["id", "className", "dataTestId", "prefix", "async", "dropdownIcon", "maxMenuHeight", "label", "hasError", "disabled", "isMulti", "components", "value", "options", "onChange", "isLoading", "classNamePrefix", "onMenuOpen", "onMenuClose", "maxSelectedDisplayCount", "isClearable", "isSearchable", "onMenuScrollToBottom", "styles", "filterOption", "onInputChange"]);
|
|
1662
|
+
const refContainer = React__default.useRef(null);
|
|
1663
|
+
const refPrefix = React__default.useRef(null);
|
|
1664
|
+
const { customStyles } = useCustomStyles(refContainer, refPrefix, maxSelectedDisplayCount, styles, disabled);
|
|
1665
|
+
const [menuIsOpen, setMenuIsOpen] = React__default.useState((_b = props.menuIsOpen) !== null && _b !== void 0 ? _b : false);
|
|
1666
|
+
const refMenuIsEnabled = React__default.useRef(true);
|
|
1667
|
+
const customComponents = useCustomComponents(components, disabled || false, menuIsOpen, refMenuIsEnabled, dataTestId, maxSelectedDisplayCount, dropdownIcon);
|
|
1668
|
+
const menuPlacement = "auto";
|
|
1669
|
+
const openMenuHandler = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1670
|
+
onMenuOpen && onMenuOpen();
|
|
1671
|
+
if (refMenuIsEnabled.current) {
|
|
1672
|
+
setMenuIsOpen(true);
|
|
1884
1673
|
}
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
if (isAllDay) {
|
|
1888
|
-
return `${day}#00:00-24:00`;
|
|
1674
|
+
else {
|
|
1675
|
+
refMenuIsEnabled.current = true;
|
|
1889
1676
|
}
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1677
|
+
});
|
|
1678
|
+
const closeMenuHandler = () => {
|
|
1679
|
+
setMenuIsOpen(false);
|
|
1680
|
+
onMenuClose && onMenuClose();
|
|
1681
|
+
};
|
|
1682
|
+
const orderedOptions = React__default.useMemo(() => {
|
|
1683
|
+
return disabled
|
|
1684
|
+
? getOrderedOptions(options, value).map(option => {
|
|
1685
|
+
return Object.assign(Object.assign({}, option), { disabled: true });
|
|
1686
|
+
})
|
|
1687
|
+
: getOrderedOptions(options, value);
|
|
1688
|
+
}, [options, value, disabled]);
|
|
1689
|
+
return {
|
|
1690
|
+
refContainer,
|
|
1691
|
+
refPrefix,
|
|
1692
|
+
customStyles,
|
|
1693
|
+
menuIsOpen,
|
|
1694
|
+
customComponents,
|
|
1695
|
+
menuPlacement,
|
|
1696
|
+
openMenuHandler,
|
|
1697
|
+
closeMenuHandler,
|
|
1698
|
+
orderedOptions,
|
|
1699
|
+
};
|
|
1893
1700
|
};
|
|
1894
1701
|
|
|
1895
1702
|
/**
|
|
1896
|
-
*
|
|
1703
|
+
* CreatableSelects are input components used to choose a value from a set.
|
|
1897
1704
|
*
|
|
1898
|
-
*
|
|
1705
|
+
* @param {CreatableSelectProps} props - The props for the CreatableSelect component
|
|
1706
|
+
* @returns {JSX.Element} CreatableSelect component
|
|
1899
1707
|
*/
|
|
1900
|
-
const
|
|
1901
|
-
|
|
1902
|
-
const
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1708
|
+
const CreatableSelect = (props) => {
|
|
1709
|
+
const { className } = props, propsNoClassName = __rest(props, ["className"]);
|
|
1710
|
+
const { id, dataTestId = "creatableSelect", prefix, async, maxMenuHeight = 200, label, hasError, disabled, isMulti, value, options, onChange, isLoading, classNamePrefix = dataTestId !== null && dataTestId !== void 0 ? dataTestId : "creatableSelect", onMenuScrollToBottom, filterOption, onInputChange, isSearchable, isClearable = false, readOnly, openMenuOnClick = !disabled, openMenuOnFocus = !disabled, allowCreateWhileLoading, onCreateOption, } = propsNoClassName;
|
|
1711
|
+
const { refContainer, refPrefix, customStyles, menuIsOpen, customComponents, menuPlacement, openMenuHandler, closeMenuHandler, orderedOptions, } = useSelect(props);
|
|
1712
|
+
const creatableSelectProps = {
|
|
1713
|
+
value,
|
|
1714
|
+
menuPlacement,
|
|
1715
|
+
maxMenuHeight,
|
|
1716
|
+
onChange,
|
|
1717
|
+
"aria-label": label,
|
|
1718
|
+
"data-testid": dataTestId,
|
|
1719
|
+
components: customComponents,
|
|
1720
|
+
styles: customStyles,
|
|
1721
|
+
tabSelectsValue: false,
|
|
1722
|
+
blurInputOnSelect: !isMulti,
|
|
1723
|
+
menuPortalTarget: props.menuPortalTarget || document.body,
|
|
1724
|
+
isSearchable: disabled || readOnly ? false : isSearchable,
|
|
1725
|
+
menuShouldBlockScroll: true,
|
|
1726
|
+
menuShouldScrollIntoView: true,
|
|
1727
|
+
openMenuOnFocus,
|
|
1728
|
+
menuIsOpen: !readOnly ? menuIsOpen : false,
|
|
1729
|
+
openMenuOnClick,
|
|
1730
|
+
closeMenuOnSelect: false,
|
|
1731
|
+
isMulti,
|
|
1732
|
+
classNamePrefix,
|
|
1733
|
+
isLoading,
|
|
1734
|
+
isClearable,
|
|
1735
|
+
id,
|
|
1736
|
+
onMenuScrollToBottom,
|
|
1737
|
+
onInputChange,
|
|
1738
|
+
allowCreateWhileLoading,
|
|
1739
|
+
onCreateOption,
|
|
1740
|
+
};
|
|
1741
|
+
return (jsxs("div", { className: cvaSelect({ invalid: hasError, disabled: disabled || readOnly, className }), "data-testid": dataTestId, ref: refContainer, children: [prefix !== undefined && (jsx("div", { className: cvaSelectPrefix(), "data-testid": dataTestId && `${dataTestId}-prefix`, ref: refPrefix, children: prefix })), async ? (jsx(ReactAsyncCreatableSelect, Object.assign({}, propsNoClassName, creatableSelectProps, async, { onMenuClose: closeMenuHandler, onMenuOpen: openMenuHandler }))) : (jsx(ReactCreatableSelect, Object.assign({}, propsNoClassName, creatableSelectProps, { hideSelectedOptions: false, isMulti: isMulti, onMenuClose: closeMenuHandler, onMenuOpen: openMenuHandler, options: filterOption ? orderedOptions : options })))] }));
|
|
1742
|
+
};
|
|
1743
|
+
CreatableSelect.displayName = "CreatableSelect";
|
|
1927
1744
|
|
|
1928
1745
|
/**
|
|
1929
|
-
*
|
|
1746
|
+
* Selects are input components used to choose a value from a set.
|
|
1930
1747
|
*
|
|
1931
|
-
* @param {
|
|
1932
|
-
* @returns {JSX.Element}
|
|
1748
|
+
* @param {SelectProps} props - The props for the Select component
|
|
1749
|
+
* @returns {JSX.Element} Select component
|
|
1933
1750
|
*/
|
|
1934
|
-
const
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1751
|
+
const Select = (props) => {
|
|
1752
|
+
const { className } = props, propsNoClassName = __rest(props, ["className"]);
|
|
1753
|
+
const { id, dataTestId = "select", prefix, async, maxMenuHeight = 200, label, hasError, disabled, isMulti, value, options, onChange, isLoading, classNamePrefix = dataTestId !== null && dataTestId !== void 0 ? dataTestId : "select", onMenuScrollToBottom, filterOption, onInputChange, isSearchable, isClearable = false, readOnly, openMenuOnClick = !disabled, openMenuOnFocus = !disabled, } = props;
|
|
1754
|
+
const { refContainer, refPrefix, customStyles, menuIsOpen, customComponents, menuPlacement, openMenuHandler, closeMenuHandler, orderedOptions, } = useSelect(props);
|
|
1755
|
+
const selectProps = {
|
|
1756
|
+
value,
|
|
1757
|
+
menuPlacement,
|
|
1758
|
+
maxMenuHeight,
|
|
1759
|
+
onChange,
|
|
1760
|
+
"aria-label": label,
|
|
1761
|
+
"data-testid": dataTestId,
|
|
1762
|
+
components: customComponents,
|
|
1763
|
+
styles: customStyles,
|
|
1764
|
+
tabSelectsValue: false,
|
|
1765
|
+
blurInputOnSelect: !isMulti,
|
|
1766
|
+
menuPortalTarget: props.menuPortalTarget || document.body,
|
|
1767
|
+
isSearchable: disabled || readOnly ? false : isSearchable,
|
|
1768
|
+
menuShouldBlockScroll: true,
|
|
1769
|
+
menuShouldScrollIntoView: true,
|
|
1770
|
+
openMenuOnFocus,
|
|
1771
|
+
menuIsOpen: !readOnly ? menuIsOpen : false,
|
|
1772
|
+
openMenuOnClick,
|
|
1773
|
+
closeMenuOnSelect: false,
|
|
1774
|
+
isMulti,
|
|
1775
|
+
classNamePrefix,
|
|
1776
|
+
isLoading,
|
|
1777
|
+
isClearable,
|
|
1778
|
+
id,
|
|
1779
|
+
onMenuScrollToBottom,
|
|
1780
|
+
onInputChange,
|
|
1781
|
+
};
|
|
1782
|
+
return (jsxs("div", { className: cvaSelect({ invalid: hasError, disabled: disabled || readOnly, className }), "data-testid": dataTestId, ref: refContainer, children: [prefix !== undefined && (jsx("div", { className: cvaSelectPrefix(), "data-testid": dataTestId && `${dataTestId}-prefix`, ref: refPrefix, children: prefix })), async ? (jsx(ReactAsyncSelect, Object.assign({}, propsNoClassName, selectProps, async, { onMenuClose: closeMenuHandler, onMenuOpen: openMenuHandler }))) : (jsx(ReactSelect, Object.assign({}, propsNoClassName, selectProps, { hideSelectedOptions: false, isMulti: isMulti, onMenuClose: closeMenuHandler, onMenuOpen: openMenuHandler, options: filterOption ? orderedOptions : options })))] }));
|
|
1783
|
+
};
|
|
1784
|
+
Select.displayName = "Select";
|
|
1940
1785
|
|
|
1941
1786
|
const FormFieldSelectAdapter = forwardRef((_a, ref) => {
|
|
1942
1787
|
var { className, dataTestId, helpText, helpAddon, tip, label, disabled, isInvalid, errorMessage, name, onBlur, options, value, defaultValue, id, onChange, children } = _a, rest = __rest(_a, ["className", "dataTestId", "helpText", "helpAddon", "tip", "label", "disabled", "isInvalid", "errorMessage", "name", "onBlur", "options", "value", "defaultValue", "id", "onChange", "children"]);
|
|
@@ -2272,6 +2117,101 @@ const UrlField = forwardRef((_a, ref) => {
|
|
|
2272
2117
|
return (jsx(FormGroup, { dataTestId: dataTestId && `${dataTestId}-FormGroup`, disabled: rest.disabled, helpAddon: helpAddon, helpText: renderAsInvalid ? errorMessage : helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, tip: tip, children: jsx(UrlInput, Object.assign({ "aria-labelledby": htmlForId + "-label", disabled: rest.disabled, id: htmlForId, isInvalid: renderAsInvalid, ref: ref, value: value || defaultValue }, rest, { className: className, dataTestId: dataTestId })) }));
|
|
2273
2118
|
});
|
|
2274
2119
|
|
|
2120
|
+
/**
|
|
2121
|
+
* A custom hook for managing phone number input state and validation.
|
|
2122
|
+
*
|
|
2123
|
+
* @property {Function} getPhoneNumber - A function for get formatted phone number with country code and plus sign
|
|
2124
|
+
*/
|
|
2125
|
+
const usePhoneInput = () => {
|
|
2126
|
+
const getPhoneNumber = ({ country, phone }) => {
|
|
2127
|
+
if (country) {
|
|
2128
|
+
return getPhoneNumberWithPlus(`${country}${phone || ""}`);
|
|
2129
|
+
}
|
|
2130
|
+
return phone || "";
|
|
2131
|
+
};
|
|
2132
|
+
return {
|
|
2133
|
+
getPhoneNumber,
|
|
2134
|
+
};
|
|
2135
|
+
};
|
|
2136
|
+
|
|
2137
|
+
/**
|
|
2138
|
+
* Provides Zod validation schemas with custom validators.
|
|
2139
|
+
*
|
|
2140
|
+
* @returns {object} An object containing various Zod validators.
|
|
2141
|
+
* @example
|
|
2142
|
+
* const { ZodPhoneValidator } = useZodValidators();
|
|
2143
|
+
*/
|
|
2144
|
+
const useZodValidators = () => {
|
|
2145
|
+
const [t] = useTranslation();
|
|
2146
|
+
const ZodPhoneValidator = z.string().superRefine((phoneNumber, ctx) => {
|
|
2147
|
+
if (!phoneNumber) {
|
|
2148
|
+
return undefined;
|
|
2149
|
+
}
|
|
2150
|
+
const phoneValidationResult = validatePhoneNumber(phoneNumber);
|
|
2151
|
+
if (phoneValidationResult === "REQUIRED") {
|
|
2152
|
+
ctx.addIssue({
|
|
2153
|
+
code: z.ZodIssueCode.custom,
|
|
2154
|
+
message: t("phoneField.error.REQUIRED"),
|
|
2155
|
+
});
|
|
2156
|
+
}
|
|
2157
|
+
if (phoneValidationResult === "REQUIRED_COUNTRY") {
|
|
2158
|
+
ctx.addIssue({
|
|
2159
|
+
code: z.ZodIssueCode.custom,
|
|
2160
|
+
message: t("phoneField.error.REQUIRED_COUNTRY"),
|
|
2161
|
+
});
|
|
2162
|
+
}
|
|
2163
|
+
if (phoneValidationResult === "INVALID_NUMBER" || phoneValidationResult === "INVALID_LENGTH") {
|
|
2164
|
+
ctx.addIssue({
|
|
2165
|
+
code: z.ZodIssueCode.custom,
|
|
2166
|
+
message: t("phoneField.error.INVALID_NUMBER"),
|
|
2167
|
+
});
|
|
2168
|
+
}
|
|
2169
|
+
if (phoneValidationResult === "NOT_A_NUMBER") {
|
|
2170
|
+
ctx.addIssue({
|
|
2171
|
+
code: z.ZodIssueCode.custom,
|
|
2172
|
+
message: t("phoneField.error.NOT_A_NUMBER"),
|
|
2173
|
+
});
|
|
2174
|
+
}
|
|
2175
|
+
if (phoneValidationResult === "TOO_LONG") {
|
|
2176
|
+
ctx.addIssue({
|
|
2177
|
+
code: z.ZodIssueCode.custom,
|
|
2178
|
+
message: t("phoneField.error.TOO_LONG"),
|
|
2179
|
+
});
|
|
2180
|
+
}
|
|
2181
|
+
if (phoneValidationResult === "TOO_SHORT") {
|
|
2182
|
+
ctx.addIssue({
|
|
2183
|
+
code: z.ZodIssueCode.custom,
|
|
2184
|
+
message: t("phoneField.error.TOO_SHORT"),
|
|
2185
|
+
});
|
|
2186
|
+
}
|
|
2187
|
+
});
|
|
2188
|
+
return useMemo(() => ({ ZodPhoneValidator }), [ZodPhoneValidator]);
|
|
2189
|
+
};
|
|
2190
|
+
|
|
2191
|
+
/**
|
|
2192
|
+
* Custom hook to get phone number validation rules.
|
|
2193
|
+
*
|
|
2194
|
+
* @returns {object} An object containing the `getPhoneNumberValidationRules` method.
|
|
2195
|
+
* @example
|
|
2196
|
+
* const { getPhoneNumberValidationRules } = useGetPhoneValidationRules();
|
|
2197
|
+
* const validationRules = getPhoneNumberValidationRules(false);
|
|
2198
|
+
*/
|
|
2199
|
+
const useGetPhoneValidationRules = () => {
|
|
2200
|
+
const [t] = useTranslation();
|
|
2201
|
+
const getPhoneNumberValidationRules = useCallback((skipValidation = false) => {
|
|
2202
|
+
const defaultRules = {};
|
|
2203
|
+
const pattern = {
|
|
2204
|
+
validate: (value) => {
|
|
2205
|
+
const validationResult = t(`phoneField.error.${validatePhoneNumber(value)}`);
|
|
2206
|
+
return !validationResult || value === "" || value === undefined || value === null || validationResult;
|
|
2207
|
+
},
|
|
2208
|
+
};
|
|
2209
|
+
return !skipValidation
|
|
2210
|
+
? Object.assign(Object.assign({}, pattern), defaultRules) : defaultRules;
|
|
2211
|
+
}, [t]);
|
|
2212
|
+
return { getPhoneNumberValidationRules };
|
|
2213
|
+
};
|
|
2214
|
+
|
|
2275
2215
|
/*
|
|
2276
2216
|
* ----------------------------
|
|
2277
2217
|
* | SETUP TRANSLATIONS START |
|
|
@@ -2281,4 +2221,4 @@ const UrlField = forwardRef((_a, ref) => {
|
|
|
2281
2221
|
*/
|
|
2282
2222
|
setupLibraryTranslations();
|
|
2283
2223
|
|
|
2284
|
-
export { ActionButton, BaseInput, Checkbox, CreatableSelect, CreatableSelectField, DateField, DateInput, DropZone, EMAIL_REGEX, EmailField, EmailInput, FormFieldSelectAdapter, FormGroup, Label, MultiSelectMenuItem, NumberField, NumberInput, OptionCard, PasswordField, PasswordInput, PhoneField, PhoneInput, RadioGroup, RadioItem, Schedule, ScheduleVariant, Search, Select, SelectField, SingleSelectMenuItem, TextArea, TextAreaField, TextField, TextInput, TimeRange, TimeRangeField, Toggle, UploadField, UploadInput, UrlField, UrlInput, checkIfPhoneNumberHasPlus, countryCodeToFlagEmoji, cvaInput, cvaInputAddon, cvaInputAddonAfter, cvaInputAddonBefore, cvaInputBase, cvaInputBaseDisabled, cvaInputBaseInvalid, cvaInputField, cvaInputPrefix, cvaInputSuffix, cvaSelect, cvaSelectCounter, cvaSelectDynamicTagContainer, cvaSelectIcon, cvaSelectMenu, cvaSelectMenuList, cvaSelectPrefix, cvaSelectXIcon, getCountryAbbreviation, getOrderedOptions, getPhoneNumberWithPlus, isInvalidCountryCode, isInvalidPhoneNumber, isMultiValue, parseSchedule, serializeSchedule, useCustomComponents, usePhoneInput, validateEmailAddress, validatePhoneNumber, weekDay };
|
|
2224
|
+
export { ActionButton, BaseInput, Checkbox, CreatableSelect, CreatableSelectField, DateField, DateInput, DropZone, EMAIL_REGEX, EmailField, EmailInput, FormFieldSelectAdapter, FormGroup, Label, MultiSelectMenuItem, NumberField, NumberInput, OptionCard, PasswordField, PasswordInput, PhoneField, PhoneFieldWithController, PhoneInput, RadioGroup, RadioItem, Schedule, ScheduleVariant, Search, Select, SelectField, SingleSelectMenuItem, TextArea, TextAreaField, TextField, TextInput, TimeRange, TimeRangeField, Toggle, UploadField, UploadInput, UrlField, UrlInput, checkIfPhoneNumberHasPlus, countryCodeToFlagEmoji, cvaInput, cvaInputAddon, cvaInputAddonAfter, cvaInputAddonBefore, cvaInputBase, cvaInputBaseDisabled, cvaInputBaseInvalid, cvaInputField, cvaInputPrefix, cvaInputSuffix, cvaSelect, cvaSelectCounter, cvaSelectDynamicTagContainer, cvaSelectIcon, cvaSelectMenu, cvaSelectMenuList, cvaSelectPrefix, cvaSelectXIcon, getCountryAbbreviation, getOrderedOptions, getPhoneNumberWithPlus, isInvalidCountryCode, isInvalidPhoneNumber, isMultiValue, parseSchedule, serializeSchedule, useCustomComponents, useGetPhoneValidationRules, usePhoneInput, useZodValidators, validateEmailAddress, validatePhoneNumber, weekDay };
|