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