@trackunit/react-form-components 0.0.305 → 0.0.309

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
@@ -4,17 +4,17 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var i18nLibraryTranslation = require('@trackunit/i18n-library-translation');
7
+ var reactComponents = require('@trackunit/react-components');
7
8
  var React = require('react');
9
+ var reactUse = require('react-use');
8
10
  var uuid = require('uuid');
9
- var reactComponents = require('@trackunit/react-components');
10
11
  var cssClassVarianceUtilities = require('@trackunit/css-class-variance-utilities');
12
+ var dateFns = require('date-fns');
13
+ var parsePhoneNumberFromString = require('libphonenumber-js');
11
14
  var ReactSelect = require('react-select');
12
15
  var ReactAsyncCreatableSelect = require('react-select/async-creatable');
13
16
  var ReactCreatableSelect = require('react-select/creatable');
14
17
  var ReactAsyncSelect = require('react-select/async');
15
- var reactUse = require('react-use');
16
- var dateFns = require('date-fns');
17
- var parsePhoneNumberFromString = require('libphonenumber-js');
18
18
 
19
19
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
20
20
 
@@ -38,11 +38,11 @@ function _interopNamespace(e) {
38
38
 
39
39
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
40
40
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
41
+ var parsePhoneNumberFromString__default = /*#__PURE__*/_interopDefaultLegacy(parsePhoneNumberFromString);
41
42
  var ReactSelect__default = /*#__PURE__*/_interopDefaultLegacy(ReactSelect);
42
43
  var ReactAsyncCreatableSelect__default = /*#__PURE__*/_interopDefaultLegacy(ReactAsyncCreatableSelect);
43
44
  var ReactCreatableSelect__default = /*#__PURE__*/_interopDefaultLegacy(ReactCreatableSelect);
44
45
  var ReactAsyncSelect__default = /*#__PURE__*/_interopDefaultLegacy(ReactAsyncSelect);
45
- var parsePhoneNumberFromString__default = /*#__PURE__*/_interopDefaultLegacy(parsePhoneNumberFromString);
46
46
 
47
47
  var defaultTranslations = {
48
48
  "clearIndicator.icon.tooltip.clearAll": "Clear all",
@@ -99,6 +99,65 @@ const setupLibraryTranslations = () => {
99
99
  i18nLibraryTranslation.registerTranslations(translations);
100
100
  };
101
101
 
102
+ const cvaActionButton = cssClassVarianceUtilities.cvaMerge(["drop-shadow-none", "rounded-md"], {
103
+ variants: {
104
+ size: {
105
+ small: ["w-6", "h-6"],
106
+ medium: ["w-8", "h-8"],
107
+ },
108
+ },
109
+ defaultVariants: {
110
+ size: "medium",
111
+ },
112
+ });
113
+ const cvaActionContainer = cssClassVarianceUtilities.cvaMerge(["flex", "items-center", "m-1"]);
114
+
115
+ /**
116
+ * The ActionButton component is a wrapper over IconButton to perform an action when the onClick event is triggered.
117
+ *
118
+ * @param {ActionButtonProps} props - The props for the ActionButton component
119
+ * @returns {JSX.Element} ActionButton component
120
+ */
121
+ const ActionButton = ({ type, value, dataTestId, iconSize, disabled, key, className }) => {
122
+ const [, copyToClipboard] = reactUse.useCopyToClipboard();
123
+ const elementKey = React.useMemo(() => key !== null && key !== void 0 ? key : `ActionButton-${uuid.v4()}`, [key]);
124
+ const getIconName = () => {
125
+ switch (type) {
126
+ case "PHONE_NUMBER":
127
+ return "PhoneArrowUpRight";
128
+ case "WEB_ADDRESS":
129
+ return "ArrowTopRightOnSquare";
130
+ case "EMAIL":
131
+ return "Envelope";
132
+ case "COPY":
133
+ default:
134
+ return "ClipboardDocument";
135
+ }
136
+ };
137
+ const ButtonAction = () => {
138
+ var _a, _b;
139
+ switch (type) {
140
+ case "EMAIL":
141
+ return window.open(`mailto:${value}`);
142
+ case "WEB_ADDRESS":
143
+ if (value) {
144
+ return window.open(value, "_blank", "noopener,noreferrer");
145
+ }
146
+ return null;
147
+ case "PHONE_NUMBER":
148
+ return window.open(`tel:${value}`);
149
+ case "COPY":
150
+ return copyToClipboard((_b = (_a = value === null || value === void 0 ? void 0 : value.current) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : "");
151
+ default:
152
+ return null;
153
+ }
154
+ };
155
+ if (ButtonAction === null) {
156
+ return null;
157
+ }
158
+ return (jsxRuntime.jsx("div", { className: cvaActionContainer({ className }), children: jsxRuntime.jsx(reactComponents.IconButton, { className: cvaActionButton({ size: iconSize }), dataTestId: dataTestId || "testIconButtonId", disabled: disabled, icon: jsxRuntime.jsx(reactComponents.Icon, { name: getIconName(), size: "small" }), onClick: ButtonAction, size: "small", variant: "secondary" }) }, elementKey));
159
+ };
160
+
102
161
  /******************************************************************************
103
162
  Copyright (c) Microsoft Corporation.
104
163
 
@@ -136,95 +195,137 @@ function __awaiter(thisArg, _arguments, P, generator) {
136
195
  });
137
196
  }
138
197
 
139
- const cvaLabel = cssClassVarianceUtilities.cvaMerge([
140
- "text-base",
141
- "text-slate-700",
142
- "truncate",
143
- "hover:text-slate-800",
144
- "group-hover:text-slate-800",
145
- "active:text-slate-800",
146
- "group-active:text-slate-800",
147
- ], {
198
+ const cvaInputBase = cssClassVarianceUtilities.cvaMerge([
199
+ "component-baseInput-shadow",
200
+ "component-baseInput-border",
201
+ "component-baseInput-background",
202
+ "border-slate-300",
203
+ "focus-within:ring-2",
204
+ "focus-within:ring-inset",
205
+ "focus-within:ring-primary-500",
206
+ "focus-within:border-slate-400",
207
+ "hover:border-slate-400",
208
+ "hover:bg-slate-50",
209
+ "transition",
210
+ ]);
211
+ const cvaInputBaseDisabled = cssClassVarianceUtilities.cvaMerge(["bg-slate-100", "hover:bg-slate-100", "hover:border-slate-300"]);
212
+ const cvaInputBaseInvalid = cssClassVarianceUtilities.cvaMerge(["border-danger-600", "focus-within:ring-danger-600"]);
213
+ const cvaInput = cssClassVarianceUtilities.cvaMerge(["relative", "flex", "h-10", cvaInputBase()], {
148
214
  variants: {
215
+ size: {
216
+ small: ["h-8"],
217
+ medium: ["h-10"],
218
+ },
219
+ disabled: {
220
+ true: cvaInputBaseDisabled(),
221
+ false: "",
222
+ },
149
223
  invalid: {
150
- true: "text-red-600 hover:text-red-700 active:text-red-700 group-hover:text-red-700 group-active:text-red-700",
224
+ true: cvaInputBaseInvalid(),
151
225
  false: "",
152
226
  },
227
+ },
228
+ });
229
+ const cvaInputField = cssClassVarianceUtilities.cvaMerge([
230
+ "w-full",
231
+ "px-3",
232
+ "border-0",
233
+ "bg-transparent",
234
+ "text-base",
235
+ "text-slate-900",
236
+ "placeholder-slate-400",
237
+ "focus-visible:outline-none",
238
+ ], {
239
+ variants: {
240
+ size: {
241
+ small: ["py-1"],
242
+ medium: ["py-2"],
243
+ },
153
244
  disabled: {
154
- true: "text-slate-400 hover:text-slate-400 group-hover:text-slate-400",
245
+ true: ["text-slate-700"],
155
246
  false: "",
156
247
  },
157
248
  },
158
- defaultVariants: {
159
- invalid: false,
160
- disabled: false,
161
- },
162
249
  });
163
-
164
- /**
165
- * The Label component is used for labels for input fields.
166
- * This component is **not used directly**, but is part of the FormGroup and Field components.
167
- *
168
- * @param {LabelProps} props - The props for the Label component
169
- * @returns {JSX.Element} Label component
170
- */
171
- const Label = ({ id, htmlFor, children, className, dataTestId, disabled, isInvalid, }) => {
172
- return (jsxRuntime.jsx("label", { className: cvaLabel({ invalid: isInvalid, disabled, className }), "data-testid": dataTestId, htmlFor: htmlFor || "", id: id || "", children: children }));
173
- };
174
-
175
- const cvaFormGroup = cssClassVarianceUtilities.cvaMerge(["component-formGroup-gap"], {
250
+ const cvaInputAddon = cssClassVarianceUtilities.cvaMerge([
251
+ "flex",
252
+ "justify-center",
253
+ "items-center",
254
+ "px-3",
255
+ "border-slate-300",
256
+ "text-slate-500",
257
+ "bg-slate-50",
258
+ ]);
259
+ const cvaInputAddonBefore = cssClassVarianceUtilities.cvaMerge([cvaInputAddon(), "border-r", "rounded-l-lg"]);
260
+ const cvaInputAddonAfter = cssClassVarianceUtilities.cvaMerge([cvaInputAddon(), "border-l", "rounded-r-lg"]);
261
+ const cvaInputPrefix = cssClassVarianceUtilities.cvaMerge([
262
+ "flex",
263
+ "justify-center",
264
+ "items-center",
265
+ "text-slate-400",
266
+ "hover:component-search-prefix",
267
+ "component-baseInput-prefix",
268
+ "component-search-borderless",
269
+ "px-3",
270
+ ], {
176
271
  variants: {
177
272
  disabled: {
178
- true: "pointer-events-none",
273
+ true: ["text-slate-500"],
179
274
  false: "",
180
275
  },
181
276
  },
182
277
  });
183
- const cvaFormGroupContainerBefore = cssClassVarianceUtilities.cvaMerge(["flex", "gap-1", "mb-1"]);
184
- const cvaFormGroupContainerAfter = cssClassVarianceUtilities.cvaMerge(["flex", "justify-between", "mt-1", "text-xs", "text-slate-500"], {
278
+ const cvaInputSuffix = cssClassVarianceUtilities.cvaMerge(["flex", "justify-center", "items-center", "text-slate-400", "px-3"], {
185
279
  variants: {
186
- invalid: {
187
- true: "text-danger-500",
280
+ disabled: {
281
+ true: ["text-slate-500"],
188
282
  false: "",
189
283
  },
190
284
  },
191
285
  });
192
- const cvaHelpAddon = cssClassVarianceUtilities.cvaMerge(["ml-auto"]);
193
286
 
194
287
  /**
195
- * The FormGroup component should be used to wrap any Input element that needs a label.
196
- * Besides a label the component supplies an optional Tooltip, HelpText and HelpAddon support.
288
+ * A base input component that can be used for text inputs, password inputs, etc.
289
+ * A reference to the input element is provided as the `ref` prop.
290
+ * Extends props from [React.InputHTMLAttributes](https://reactjs.org/docs/dom-elements.html#input)
197
291
  *
198
- * @param {FormGroupProps} props - The props for the FormGroup component
199
- * @returns {JSX.Element} FormGroup component
292
+ * For specific input types make sure to use the corresponding input component.
293
+ * This is a base used by our other input components such as TextInput, NumberInput, PasswordInput, etc.
200
294
  */
201
- const FormGroup = ({ isInvalid, helpText, helpAddon, tip, className, dataTestId, label, htmlFor, children, tipIconProps, disabled = false, }) => {
202
- return (jsxRuntime.jsxs("div", { className: cvaFormGroup({ disabled, className }), "data-testid": dataTestId, children: [jsxRuntime.jsxs("div", { className: cvaFormGroupContainerBefore(), children: [jsxRuntime.jsx(Label, { className: "component-formGroup-font", dataTestId: dataTestId && `${dataTestId}-label`, htmlFor: htmlFor, id: htmlFor + "-label", children: label }), tip && (jsxRuntime.jsx(reactComponents.Tooltip, { dataTestId: dataTestId && `${dataTestId}-tooltip`, iconProps: tipIconProps, label: tip, placement: "bottom" }))] }), children, jsxRuntime.jsxs("div", { className: cvaFormGroupContainerAfter({ invalid: isInvalid }), children: [helpText && jsxRuntime.jsx("span", { "data-testid": dataTestId && `${dataTestId}-helpText`, children: helpText }), helpAddon && (jsxRuntime.jsx("span", { className: cvaHelpAddon(), "data-testid": dataTestId && `${dataTestId}-helpAddon`, children: helpAddon }))] })] }));
203
- };
295
+ const BaseInput = React__namespace.forwardRef((_a, ref) => {
296
+ var { className, isInvalid, dataTestId, prefix, suffix, addonBefore, addonAfter, actions, fieldSize = "medium", nonInteractive = false, showDefaultActions = false, type, inputClassName, addonBeforeClassName } = _a, rest = __rest(_a, ["className", "isInvalid", "dataTestId", "prefix", "suffix", "addonBefore", "addonAfter", "actions", "fieldSize", "nonInteractive", "showDefaultActions", "type", "inputClassName", "addonBeforeClassName"]);
297
+ const isReadOnlyWithPlaceholder = React.useMemo(() => !!rest.readOnly && !!rest.placeholder && !rest.value, [rest.readOnly, rest.placeholder, rest.value]);
298
+ const renderAsDisabled = rest.disabled || rest.readOnly;
299
+ const innerRef = React__namespace.useRef(null);
300
+ React__namespace.useImperativeHandle(ref, () => innerRef.current, []);
301
+ return (jsxRuntime.jsxs("div", { className: cvaInput({
302
+ disabled: renderAsDisabled,
303
+ invalid: isInvalid,
304
+ size: fieldSize,
305
+ className,
306
+ }), "data-testid": dataTestId && `${dataTestId}-container`, children: [addonBefore && addonBefore !== undefined ? (jsxRuntime.jsx("div", { className: cvaInputAddonBefore({ className: addonBeforeClassName }), "data-testid": dataTestId && `${dataTestId}-addonBefore`, children: addonBefore })) : null, prefix && addonBefore !== prefix ? (jsxRuntime.jsx("div", { className: cvaInputPrefix({
307
+ disabled: renderAsDisabled,
308
+ }), "data-testid": dataTestId && `${dataTestId}-prefix`, children: prefix })) : null, jsxRuntime.jsx("input", Object.assign({ className: cvaInputField({ size: fieldSize, disabled: renderAsDisabled, className: inputClassName }), "data-testid": dataTestId, ref: innerRef, type: isReadOnlyWithPlaceholder ? "text" : type }, rest, { readOnly: rest.readOnly || nonInteractive })), suffix && addonBefore !== suffix ? (jsxRuntime.jsx("div", { className: cvaInputSuffix({
309
+ disabled: renderAsDisabled,
310
+ }), "data-testid": dataTestId && `${dataTestId}-suffix`, children: suffix })) : null, rest.readOnly === true && showDefaultActions ? (jsxRuntime.jsx(ActionButton, { type: "COPY", value: innerRef }, "default-copy-action")) : null, actions && addonBefore !== actions ? actions : null, addonAfter && addonAfter !== undefined && addonBefore !== addonAfter ? (jsxRuntime.jsx("div", { className: cvaInputAddonAfter(), "data-testid": dataTestId && `${dataTestId}-addonAfter`, children: addonAfter })) : null] }));
311
+ });
204
312
 
205
- const cvaSelect = cssClassVarianceUtilities.cvaMerge([
206
- "relative",
207
- "flex",
208
- "shadow-sm",
209
- "rounded-lg",
210
- "border",
211
- "border-slate-300",
212
- "focus-within:ring-2",
213
- "focus-within:ring-inset",
214
- "focus-within:ring-primary-600",
215
- "focus-within:border-slate-400",
216
- "hover:border-slate-400",
217
- "hover:bg-slate-50",
218
- "bg-white",
219
- "transition",
313
+ const cvaLabel = cssClassVarianceUtilities.cvaMerge([
314
+ "text-base",
315
+ "text-slate-700",
316
+ "truncate",
317
+ "hover:text-slate-800",
318
+ "group-hover:text-slate-800",
319
+ "active:text-slate-800",
320
+ "group-active:text-slate-800",
220
321
  ], {
221
322
  variants: {
222
323
  invalid: {
223
- true: "border-red-600 text-red-600 focus-within:ring-red-600 hover:border-red-600",
324
+ true: "text-red-600 hover:text-red-700 active:text-red-700 group-hover:text-red-700 group-active:text-red-700",
224
325
  false: "",
225
326
  },
226
327
  disabled: {
227
- true: "!bg-slate-100",
328
+ true: "text-slate-400 hover:text-slate-400 group-hover:text-slate-400",
228
329
  false: "",
229
330
  },
230
331
  },
@@ -233,94 +334,15 @@ const cvaSelect = cssClassVarianceUtilities.cvaMerge([
233
334
  disabled: false,
234
335
  },
235
336
  });
236
- const cvaSelectIcon = cssClassVarianceUtilities.cvaMerge("mr-2 flex cursor-pointer items-center justify-center text-slate-400 hover:text-slate-500");
237
- const cvaSelectPrefix = cssClassVarianceUtilities.cvaMerge(["flex", "justify-center", "items-center", "text-slate-400", "pl-2"]);
238
- const cvaSelectXIcon = cssClassVarianceUtilities.cvaMerge([
239
- "mr-2 flex cursor-pointer items-center justify-center text-slate-400 hover:text-slate-500",
240
- "ml-1",
241
- ]);
242
- const cvaSelectMenuList = cssClassVarianceUtilities.cvaMerge(["min-w-min", "shadow-md", "rounded-lg", "z-20", "bg-white", "p-1", "border", "border-slate-300", "gap-1", "grid"], {
243
- variants: {
244
- menuIsOpen: {
245
- true: "animate-fade-in-fast",
246
- false: "animate-fade-out-fast",
247
- },
248
- },
249
- });
250
- const cvaSelectDynamicTagContainer = cssClassVarianceUtilities.cvaMerge(["h-full", "flex", "gap-1", "items-center"], {
251
- variants: {
252
- visible: { true: "visible", false: "invisible" },
253
- },
254
- });
255
- const cvaSelectCounter = cssClassVarianceUtilities.cvaMerge(["overflow-hidden", "whitespace-nowrap"]);
256
- const cvaSelectMenu = cssClassVarianceUtilities.cvaMerge(["relative", "p-1", "grid", "gap-1"]);
257
337
 
258
338
  /**
259
- * The SelectContainer component.
339
+ * The CheckIcon component is used by the checkbox to display the checked state.
260
340
  *
261
- * @param {SelectContainerProps} props - The props for the SelectContainer component
262
- * @returns {JSX.Element} SelectContainer component
341
+ * @param {CheckIconProps} props - The props for the CheckIcon component
342
+ * @returns {JSX.Element} CheckIcon component
263
343
  */
264
- const SelectContainer = ({ children, label, hideLabel, id, hasError, error, description, info, dataTestId, isDisabled, }) => {
265
- return (jsxRuntime.jsxs("label", { className: cvaSelect({ invalid: hasError, disabled: isDisabled }), "data-testid": dataTestId, children: [label && !hideLabel && jsxRuntime.jsx(Label, { htmlFor: id, children: label }), children, (hasError || info) && jsxRuntime.jsx(reactComponents.Text, { size: "small", children: hasError ? error : info })] }));
266
- };
267
-
268
- /**
269
- * @param {MultiValue<Option> | SingleValue<Option>} arg option to check type
270
- * @returns {arg is MultiValue<Option> } is Multivalue
271
- */
272
- function isMultiValue(arg) {
273
- return Array.isArray(arg);
274
- }
275
- function isGroupBase(arg) {
276
- return arg.options !== undefined;
277
- }
278
- const isSelectedOption = (option, selected) => {
279
- if (isGroupBase(option)) {
280
- return false;
281
- }
282
- return isMultiValue(selected)
283
- ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
284
- selected.some(v => v.value === option.value)
285
- : // eslint-disable-next-line @typescript-eslint/no-explicit-any
286
- option.value === (selected === null || selected === void 0 ? void 0 : selected.value);
287
- };
288
- const removeSelectedFromGroups = (group, selected) => {
289
- if (isGroupBase(group)) {
290
- return Object.assign(Object.assign({}, group), { options: group.options.filter(option => !isSelectedOption(option, selected)) });
291
- }
292
- return group;
293
- };
294
- /**
295
- * @template IsMulti
296
- * @template Group
297
- * @param {OptionsOrGroups<Option, Group> | undefined} options An array of options to select from
298
- * @param {PropsValue<Option> | undefined} value Selected values
299
- * @returns {OptionsOrGroups<Option, Group>} An array of ordered options with selected on top
300
- */
301
- const getOrderedOptions = (options, value) => {
302
- if (value && options) {
303
- const orderedValues = isMultiValue(value)
304
- ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
305
- [...value].sort((a, b) => a.label.localeCompare(b.label))
306
- : [value];
307
- const selectableOptions = options
308
- .filter(option => !isSelectedOption(option, value))
309
- .map(option => removeSelectedFromGroups(option, value));
310
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
311
- return orderedValues.concat(selectableOptions) || [];
312
- }
313
- return options || [];
314
- };
315
-
316
- /**
317
- * The CheckIcon component is used by the checkbox to display the checked state.
318
- *
319
- * @param {CheckIconProps} props - The props for the CheckIcon component
320
- * @returns {JSX.Element} CheckIcon component
321
- */
322
- const CheckIcon = ({ className, dataTestId }) => {
323
- return (jsxRuntime.jsx("svg", { className: className, "data-testid": dataTestId, fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 10 10", xmlns: "http://www.w3.org/2000/svg", children: jsxRuntime.jsx("path", { d: "m2 5.5 2 2L8.5 3", strokeLinecap: "round", strokeLinejoin: "round" }) }));
344
+ const CheckIcon = ({ className, dataTestId }) => {
345
+ return (jsxRuntime.jsx("svg", { className: className, "data-testid": dataTestId, fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 10 10", xmlns: "http://www.w3.org/2000/svg", children: jsxRuntime.jsx("path", { d: "m2 5.5 2 2L8.5 3", strokeLinecap: "round", strokeLinejoin: "round" }) }));
324
346
  };
325
347
 
326
348
  const cvaCheckbox = cssClassVarianceUtilities.cvaMerge([
@@ -501,662 +523,117 @@ const Checkbox = React__namespace.forwardRef((_a, ref) => {
501
523
  });
502
524
 
503
525
  /**
504
- * A single select menu item is a basic wrapper around Menu item designed to be used as a single value render in Select list
526
+ * A wrapper around BaseInput with a pop-up day picker.
505
527
  *
506
- * @param {SelectMenuItemProps} props - The props for the SingleSelectMenuItem
507
- * @returns {JSX.Element} SingleSelectMenuItem
528
+ * NOTE: If shown with a label, please use the `DateField` component instead.
508
529
  */
509
- const SingleSelectMenuItem = ({ label, icon, onClick, selected, dataTestId, focused, disabled, }) => {
510
- 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 }));
511
- };
530
+ const DateInput = React.forwardRef((_a, ref) => {
531
+ var { min, max, defaultValue, value } = _a, rest = __rest(_a, ["min", "max", "defaultValue", "value"]);
532
+ const formatDateToInputString = (date) => date instanceof Date ? dateFns.format(date, "yyyy-MM-dd") : date;
533
+ // Chrome and Firefox need their default icon to have datepicker functionality.
534
+ const showIcon = !/Chrome/.test(navigator.userAgent) && !/Firefox/.test(navigator.userAgent);
535
+ return (jsxRuntime.jsx(BaseInput, Object.assign({ defaultValue: formatDateToInputString(defaultValue), max: formatDateToInputString(max), min: formatDateToInputString(min), ref: ref, suffix: showIcon && jsxRuntime.jsx(reactComponents.Icon, { dataTestId: "calendar", name: "Calendar", size: "medium", type: "solid" }), type: "date", value: formatDateToInputString(value) }, rest)));
536
+ });
537
+
512
538
  /**
513
- * A multi select menu item is a basic wrapper around Menu item designed to be used as a multi value render in Select list
539
+ * The Label component is used for labels for input fields.
540
+ * This component is **not used directly**, but is part of the FormGroup and Field components.
514
541
  *
515
- * @param {SelectMenuItemProps} props - The props for the MultiSelectMenuItem
516
- * @returns {JSX.Element} multi select menu item
542
+ * @param {LabelProps} props - The props for the Label component
543
+ * @returns {JSX.Element} Label component
517
544
  */
518
- const MultiSelectMenuItem = ({ label, onClick, selected, dataTestId, focused, disabled, }) => {
519
- return (jsxRuntime.jsx(reactComponents.MenuItem, { dataTestId: dataTestId, disabled: disabled, focused: focused, label: label, onClick: e => {
520
- e.stopPropagation();
521
- onClick && onClick(e);
522
- }, prefix: jsxRuntime.jsx(Checkbox, { checked: selected, disabled: disabled, onChange: () => null, onClick: e => {
523
- e.stopPropagation();
524
- }, readOnly: false }), selected: selected }));
545
+ const Label = ({ id, htmlFor, children, className, dataTestId, disabled, isInvalid, }) => {
546
+ return (jsxRuntime.jsx("label", { className: cvaLabel({ invalid: isInvalid, disabled, className }), "data-testid": dataTestId, htmlFor: htmlFor || "", id: id || "", children: children }));
525
547
  };
526
548
 
549
+ const cvaFormGroup = cssClassVarianceUtilities.cvaMerge(["component-formGroup-gap"], {
550
+ variants: {
551
+ disabled: {
552
+ true: "pointer-events-none",
553
+ false: "",
554
+ },
555
+ },
556
+ });
557
+ const cvaFormGroupContainerBefore = cssClassVarianceUtilities.cvaMerge(["flex", "gap-1", "mb-1"]);
558
+ const cvaFormGroupContainerAfter = cssClassVarianceUtilities.cvaMerge(["flex", "justify-between", "mt-1", "text-xs", "text-slate-500"], {
559
+ variants: {
560
+ invalid: {
561
+ true: "text-danger-500",
562
+ false: "",
563
+ },
564
+ },
565
+ });
566
+ const cvaHelpAddon = cssClassVarianceUtilities.cvaMerge(["ml-auto"]);
567
+
527
568
  /**
528
- * Extended Tag component with information about its own width.
529
- * Used in the select component.
569
+ * The FormGroup component should be used to wrap any Input element that needs a label.
570
+ * Besides a label the component supplies an optional Tooltip, HelpText and HelpAddon support.
530
571
  *
531
- * @param {TagProps} props - The props for the tag component
532
- * @returns {JSX.Element} TagWithWidth component
572
+ * @param {FormGroupProps} props - The props for the FormGroup component
573
+ * @returns {JSX.Element} FormGroup component
533
574
  */
534
- const TagWithWidth = (_a) => {
535
- var { onWidthKnown, children } = _a, rest = __rest(_a, ["onWidthKnown", "children"]);
536
- const ref = React__default["default"].useRef(null);
537
- React__default["default"].useLayoutEffect(() => {
538
- var _a;
539
- onWidthKnown && onWidthKnown({ width: ((_a = ref.current) === null || _a === void 0 ? void 0 : _a.offsetWidth) || 0 });
540
- }, [ref, onWidthKnown]);
541
- return (jsxRuntime.jsx(reactComponents.Tag, Object.assign({ ref: ref }, rest, { children: children })));
575
+ const FormGroup = ({ isInvalid, helpText, helpAddon, tip, className, dataTestId, label, htmlFor, children, tipIconProps, disabled = false, }) => {
576
+ return (jsxRuntime.jsxs("div", { className: cvaFormGroup({ disabled, className }), "data-testid": dataTestId, children: [jsxRuntime.jsxs("div", { className: cvaFormGroupContainerBefore(), children: [jsxRuntime.jsx(Label, { className: "component-formGroup-font", dataTestId: dataTestId && `${dataTestId}-label`, htmlFor: htmlFor, id: htmlFor + "-label", children: label }), tip && (jsxRuntime.jsx(reactComponents.Tooltip, { dataTestId: dataTestId && `${dataTestId}-tooltip`, iconProps: tipIconProps, label: tip, placement: "bottom" }))] }), children, jsxRuntime.jsxs("div", { className: cvaFormGroupContainerAfter({ invalid: isInvalid }), children: [helpText && jsxRuntime.jsx("span", { "data-testid": dataTestId && `${dataTestId}-helpText`, children: helpText }), helpAddon && (jsxRuntime.jsx("span", { className: cvaHelpAddon(), "data-testid": dataTestId && `${dataTestId}-helpAddon`, children: helpAddon }))] })] }));
542
577
  };
543
578
 
544
579
  /**
545
- * TagsContainer component to display tags in limited space when children can't fit space it displays counter
580
+ * The date field component is used for entering date values.
546
581
  *
547
- * @param {TagsContainerProps} props - The props for the TagContainer
548
- * @returns {JSX.Element} TagsContainer
582
+ * _**Do use**_ the DateField for date input.
583
+ *
584
+ * _**Do not use**_ this fields for non-serialized dates. Use TextField instead.
549
585
  */
550
- const TagsContainer = ({ items, width = "100%", itemsGap = 5, postFix, disabled }) => {
551
- const [isReady, setIsReady] = React__default["default"].useState(false);
552
- const [counterWidth, setCounterWidth] = React__default["default"].useState(0);
553
- const containerRef = React__default["default"].useRef(null);
554
- const availableWidth = React__default["default"].useRef();
555
- const childrenWidth = React__default["default"].useRef([]);
556
- const itemsCount = items.length;
557
- React__default["default"].useLayoutEffect(() => {
558
- var _a;
559
- availableWidth.current = ((_a = containerRef === null || containerRef === void 0 ? void 0 : containerRef.current) === null || _a === void 0 ? void 0 : _a.offsetWidth) || 0;
560
- }, [containerRef]);
561
- const onWidthKnownHandler = ({ width: reportedWidth }) => {
562
- childrenWidth.current.push({ width: reportedWidth + itemsGap });
563
- if (childrenWidth.current.length === itemsCount) {
564
- setIsReady(true);
565
- }
566
- };
567
- const requiredSpace = childrenWidth.current.reduce((previous, current) => {
568
- return previous + current.width;
569
- }, 0);
570
- let counter = 0;
571
- const availableSpace = ((availableWidth === null || availableWidth === void 0 ? void 0 : availableWidth.current) || 0) - counterWidth;
572
- const renderedElements = items
573
- .concat({ text: "", onClick: () => null, disabled: false }) // reserved element for a potential counter
574
- .map((item, index) => {
575
- const spaceNeeded = childrenWidth.current.slice(0, index + 1).reduce((previous, current) => {
576
- return previous + current.width;
577
- }, 0);
578
- const isLast = index === items.length;
579
- const counterRequired = requiredSpace > availableSpace && counter !== 0;
580
- if (isLast && counterRequired) {
581
- 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));
582
- }
583
- if (isLast) {
584
- return null;
585
- }
586
- const itemCanFit = spaceNeeded <= availableSpace;
587
- if (itemCanFit) {
588
- return (jsxRuntime.jsx(TagWithWidth, { className: "inline-flex shrink-0", color: item.disabled ? "unknown" : "primary", dataTestId: `${item.text}-tag`, disabled: disabled, onClose: e => {
589
- e.stopPropagation();
590
- item.onClick();
591
- }, onWidthKnown: onWidthKnownHandler, children: item.text }, item.text + index));
592
- }
593
- const fromTheItems = item.text !== "";
594
- if (fromTheItems) {
595
- counter = counter + 1;
596
- }
597
- return null;
598
- })
599
- .filter(element => element !== null);
600
- return (jsxRuntime.jsxs("div", { className: cvaSelectDynamicTagContainer({ visible: isReady }), ref: containerRef, style: {
601
- width: `${width}`,
602
- }, children: [renderedElements, postFix] }));
603
- };
586
+ const DateField = React.forwardRef((_a, ref) => {
587
+ var { label, id, tip, helpText, errorMessage, helpAddon, isInvalid, className, defaultValue, dataTestId } = _a, rest = __rest(_a, ["label", "id", "tip", "helpText", "errorMessage", "helpAddon", "isInvalid", "className", "defaultValue", "dataTestId"]);
588
+ const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
589
+ const htmlForId = id ? id : "dateField-" + uuid.v4();
590
+ 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(DateInput, Object.assign({ "aria-labelledby": htmlForId + "-label", defaultValue: defaultValue, id: htmlForId, isInvalid: renderAsInvalid, ref: ref }, rest, { className: className, dataTestId: dataTestId })) }));
591
+ });
592
+
593
+ const cvaDropZone = cssClassVarianceUtilities.cvaMerge([
594
+ "flex",
595
+ "component-baseInput-background",
596
+ "justify-center",
597
+ "text-slate-500",
598
+ "rounded-sm",
599
+ "border-2",
600
+ "border-gray-200",
601
+ "border-dashed",
602
+ "hover:bg-slate-100",
603
+ "hover:border-solid",
604
+ "hover:border-primary-500",
605
+ ], {
606
+ variants: {
607
+ size: {
608
+ small: ["p-2"],
609
+ medium: ["p-4"],
610
+ large: ["p-8"],
611
+ },
612
+ disabled: { true: ["bg-slate-100", "hover:bg-slate-100"], false: "" },
613
+ dragActive: { true: ["border-gray-200", "bg-slate-100"], false: "" },
614
+ dropComplete: {
615
+ true: ["border-solid", "border-primary-500", "bg-slate-100", "hover:border-solid", "hover:border-gray-200"],
616
+ false: "",
617
+ },
618
+ invalid: { true: ["border-danger-600", "text-danger-500"], false: "" },
619
+ },
620
+ });
621
+ const cvaDropZoneLabel = cssClassVarianceUtilities.cvaMerge([
622
+ "h-full",
623
+ "pt-1",
624
+ "pb-1",
625
+ "gap-2",
626
+ "items-center",
627
+ "flex-col",
628
+ "flex",
629
+ "justify-center",
630
+ ]);
604
631
 
605
632
  /**
606
- * A hook to retrieve components override object.
607
- * 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.
633
+ * The Drop Zone can be used to drag and drop files
608
634
  *
609
- * @template IsMulti
610
- * @template Group
611
- * @param {Partial<SelectComponents<Option, IsMulti, Group>> | undefined} componentsProps a custom component prop that you can to override defaults
612
- * @param {boolean} disabled decide to override disabled variant
613
- * @param {boolean} menuIsOpen menu is open state
614
- * @param {React.MutableRefObject<boolean>} refMenuIsEnabled a flag to block menu from open
615
- * @param {string} dataTestId a test id
616
- * @param {number} maxSelectedDisplayCount a number of max display count
617
- * @param {JSX.Element} dropdownIcon an custom dropdown icon
618
- * @returns {Partial<SelectComponents<Option, boolean, GroupBase<Option>>> | undefined} components object to override react-select default components
619
- */
620
- const useCustomComponents = (componentsProps, disabled, menuIsOpen, refMenuIsEnabled, dataTestId, maxSelectedDisplayCount, dropdownIcon) => {
621
- const [t] = useTranslation();
622
- // perhaps it should not be wrap in memo (causing some issues with opening and closing on mobiles)
623
- const customComponents = React__namespace.useMemo(() => {
624
- return Object.assign({ ValueContainer: props => {
625
- if (props.isMulti && Array.isArray(props.children) && props.children.length > 0) {
626
- const PLACEHOLDER_KEY = "placeholder";
627
- const key = props && props.children && props.children[0] ? props.children[0].key : "";
628
- const values = props && props.children ? props.children[0] : [];
629
- const tags = key === PLACEHOLDER_KEY ? [] : values;
630
- const searchInput = props && props.children && props.children[1];
631
- return (jsxRuntime.jsx(ReactSelect.components.ValueContainer, Object.assign({}, props, { isDisabled: props.selectProps.isDisabled, children: maxSelectedDisplayCount === undefined ? (jsxRuntime.jsx(TagsContainer, { disabled: disabled, items: tags
632
- ? tags.map(({ props: tagProps }) => {
633
- return {
634
- text: tagProps.children,
635
- onClick: disabled
636
- ? undefined
637
- : (e) => {
638
- var _a, _b;
639
- refMenuIsEnabled.current = false;
640
- ((_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));
641
- },
642
- disabled: disabled,
643
- };
644
- })
645
- : [], postFix: searchInput, width: "100%" })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [tags &&
646
- tags.slice(0, maxSelectedDisplayCount).map(({ props: tagProps }) => {
647
- var _a, _b;
648
- 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 => {
649
- var _a, _b;
650
- e.stopPropagation();
651
- refMenuIsEnabled.current = false;
652
- ((_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));
653
- }, children: tagProps.children }, (_b = tagProps.children) === null || _b === void 0 ? void 0 : _b.toString()));
654
- }), tags && tags.length > maxSelectedDisplayCount && (jsxRuntime.jsxs(reactComponents.Tag, { color: "neutral", dataTestId: "counter-tag", children: ["+", tags.length - maxSelectedDisplayCount] })), searchInput] })) })));
655
- }
656
- return (jsxRuntime.jsx(ReactSelect.components.ValueContainer, Object.assign({}, props, { isDisabled: props.selectProps.isDisabled, children: props.children })));
657
- }, LoadingIndicator: props => {
658
- return jsxRuntime.jsx(reactComponents.Spinner, { className: "mt-1.5 mr-1", size: "small" });
659
- }, DropdownIndicator: props => {
660
- const icon = props.selectProps.menuIsOpen ? (jsxRuntime.jsx(reactComponents.Icon, { name: "ChevronUp", size: "medium" })) : (jsxRuntime.jsx(reactComponents.Icon, { name: "ChevronDown", size: "medium" }));
661
- return props.selectProps.isLoading ? null : (jsxRuntime.jsx(ReactSelect.components.DropdownIndicator, Object.assign({}, props, { children: jsxRuntime.jsx("div", { className: cvaSelectIcon(), children: dropdownIcon ? dropdownIcon : icon }) })));
662
- }, IndicatorSeparator: () => null, ClearIndicator: props => {
663
- if (disabled) {
664
- return null;
665
- }
666
- 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") }) }) })));
667
- }, Control: props => {
668
- return jsxRuntime.jsx(ReactSelect.components.Control, Object.assign({}, props, { className: props.isDisabled ? "bg-slate-100" : "" }));
669
- }, SingleValue: props => {
670
- 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 }) })));
671
- }, Menu: props => {
672
- return (jsxRuntime.jsx(ReactSelect.components.Menu, Object.assign({}, props, { className: cvaSelectMenuList({ menuIsOpen: props.selectProps.menuIsOpen }) })));
673
- }, MenuList: props => {
674
- return (jsxRuntime.jsx(ReactSelect.components.MenuList, Object.assign({}, props, { innerProps: Object.assign(Object.assign({}, props.innerProps), { onScroll: e => {
675
- const listEl = e.currentTarget;
676
- if (listEl.scrollTop + listEl.clientHeight >= listEl.scrollHeight) {
677
- props.selectProps.onMenuScrollToBottom && props.selectProps.onMenuScrollToBottom(new TouchEvent(""));
678
- }
679
- } }), children: props.children })));
680
- }, Option: props => {
681
- const componentProps = {
682
- label: props.label,
683
- focused: props.isFocused,
684
- selected: props.isSelected,
685
- onClick: props.innerProps.onClick,
686
- };
687
- 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 }))) })));
688
- } }, componentsProps);
689
- // eslint-disable-next-line react-hooks/exhaustive-deps
690
- }, [componentsProps, disabled, maxSelectedDisplayCount]); // do not add dropdownIcon (it will cause issue with opening/closing list for selects with custom icon)
691
- return customComponents;
692
- };
693
-
694
- /**
695
- * @template IsMulti
696
- * @template Group
697
- * @param {React.RefObject<HTMLDivElement>} refContainer react ref to container element
698
- * @param {React.RefObject<HTMLDivElement>} refPrefix react ref to prefix element
699
- * @param {number | undefined} maxSelectedDisplayCount a number of max display count
700
- * @param {StylesConfig<Option, IsMulti, Group> | undefined} styles a optional object to override styles of react-select
701
- * @returns {StylesConfig<Option, boolean>} styles to override in select
702
- */
703
- const useCustomStyles = (refContainer, refPrefix, maxSelectedDisplayCount, styles, disabled) => {
704
- const customStyles = React__namespace.useMemo(() => {
705
- return Object.assign({ control: base => {
706
- return Object.assign(Object.assign({}, base), { border: "0", boxShadow: "0", "&:hover": {
707
- border: "0",
708
- }, marginRight: "2px", backgroundColor: "" });
709
- }, 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: () => ({
710
- width: "0px",
711
- }), menu: base => {
712
- return Object.assign(Object.assign({}, base), { width: "100%", marginTop: "4px", marginBottom: "18px", transition: "all 1s ease-in-out" });
713
- }, 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 => {
714
- 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" });
715
- }, valueContainer: base => {
716
- return Object.assign(Object.assign({}, base), { flexWrap: maxSelectedDisplayCount !== undefined ? "wrap" : "nowrap", gap: "0.25rem" });
717
- }, 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 => {
718
- return Object.assign(Object.assign({}, base), { padding: "0px" });
719
- } }, styles);
720
- // eslint-disable-next-line react-hooks/exhaustive-deps
721
- }, [refContainer, refPrefix]);
722
- return { customStyles };
723
- };
724
-
725
- /**
726
- * A hook used by selects to share the common code
727
- *
728
- * @param {SelectProps} props - The props for the Select component
729
- * @returns {IUseSelect} Select component
730
- */
731
- const useSelect = (_a) => {
732
- var _b;
733
- 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"]);
734
- const refContainer = React__default["default"].useRef(null);
735
- const refPrefix = React__default["default"].useRef(null);
736
- const { customStyles } = useCustomStyles(refContainer, refPrefix, maxSelectedDisplayCount, styles, disabled);
737
- const [menuIsOpen, setMenuIsOpen] = React__default["default"].useState((_b = props.menuIsOpen) !== null && _b !== void 0 ? _b : false);
738
- const refMenuIsEnabled = React__default["default"].useRef(true);
739
- const customComponents = useCustomComponents(components, disabled || false, menuIsOpen, refMenuIsEnabled, dataTestId, maxSelectedDisplayCount, dropdownIcon);
740
- const menuPlacement = "auto";
741
- const openMenuHandler = () => __awaiter(void 0, void 0, void 0, function* () {
742
- onMenuOpen && onMenuOpen();
743
- if (refMenuIsEnabled.current) {
744
- setMenuIsOpen(true);
745
- }
746
- else {
747
- refMenuIsEnabled.current = true;
748
- }
749
- });
750
- const closeMenuHandler = () => {
751
- setMenuIsOpen(false);
752
- onMenuClose && onMenuClose();
753
- };
754
- const orderedOptions = React__default["default"].useMemo(() => {
755
- return disabled
756
- ? getOrderedOptions(options, value).map(option => {
757
- return Object.assign(Object.assign({}, option), { disabled: true });
758
- })
759
- : getOrderedOptions(options, value);
760
- }, [options, value, disabled]);
761
- return {
762
- refContainer,
763
- refPrefix,
764
- customStyles,
765
- menuIsOpen,
766
- customComponents,
767
- menuPlacement,
768
- openMenuHandler,
769
- closeMenuHandler,
770
- orderedOptions,
771
- };
772
- };
773
-
774
- /**
775
- * The CreatableSelect component.
776
- *
777
- * @param {CreateableSelectProps} props - The props for the CreatableSelect component
778
- * @returns {JSX.Element} CreatableSelect component
779
- */
780
- const CreatableSelect = (props) => {
781
- const { id, dataTestId = "select", async, maxMenuHeight = 200, label, error, disabled, isMulti, value, hideLabel, description, info, options, onChange, isLoading, classNamePrefix = "", filterOption, prefix, onInputChange, placeholder, isClearable, } = props;
782
- const hasError = !!error;
783
- const { refPrefix, customStyles, menuIsOpen, customComponents, menuPlacement, openMenuHandler, closeMenuHandler, orderedOptions, } = useSelect(props);
784
- const selectProps = {
785
- value,
786
- menuPlacement,
787
- maxMenuHeight,
788
- onChange,
789
- "aria-label": label,
790
- "data-testid": dataTestId,
791
- components: customComponents,
792
- styles: customStyles,
793
- tabSelectsValue: false,
794
- blurInputOnSelect: !isMulti,
795
- menuPortalTarget: document.body,
796
- isSearchable: disabled ? false : true,
797
- menuShouldBlockScroll: true,
798
- menuShouldScrollIntoView: true,
799
- openMenuOnFocus: disabled ? false : true,
800
- menuIsOpen: disabled ? false : menuIsOpen,
801
- openMenuOnClick: true,
802
- closeMenuOnSelect: false,
803
- isMulti: isMulti,
804
- classNamePrefix,
805
- isLoading,
806
- onInputChange,
807
- placeholder,
808
- isClearable,
809
- id,
810
- };
811
- return (jsxRuntime.jsx(SelectContainer, { dataTestId: dataTestId, description: description, error: error, hasError: hasError, hideLabel: hideLabel, id: id, info: info, isDisabled: disabled, label: label, children: jsxRuntime.jsxs(jsxRuntime.Fragment, { 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({ "aria-label": label, components: customComponents, "data-testid": dataTestId, maxMenuHeight: maxMenuHeight }, props, { onMenuClose: () => {
812
- closeMenuHandler();
813
- }, onMenuOpen: () => {
814
- !disabled && openMenuHandler();
815
- } }))) : (jsxRuntime.jsx(ReactCreatableSelect__default["default"], Object.assign({}, selectProps, { isMulti: isMulti, onMenuClose: () => {
816
- closeMenuHandler();
817
- }, onMenuOpen: () => {
818
- !disabled && openMenuHandler();
819
- }, options: filterOption ? orderedOptions : options })))] }) }));
820
- };
821
-
822
- /**
823
- * Selects are input components used to choose a value from a set.
824
- *
825
- * @param {SelectProps} props - The props for the Select component
826
- * @returns {JSX.Element} Select component
827
- */
828
- const Select = (props) => {
829
- const { className } = props, propsNoClassName = __rest(props, ["className"]);
830
- const { id, dataTestId = "select", prefix, async, maxMenuHeight = 200, label, hasError, disabled, isMulti, value, options, onChange, isLoading, classNamePrefix = dataTestId ? dataTestId : "select", onMenuScrollToBottom, filterOption, onInputChange, isSearchable, isClearable = false, readOnly, openMenuOnClick = !disabled, openMenuOnFocus = !disabled, } = props;
831
- const { refContainer, refPrefix, customStyles, menuIsOpen, customComponents, menuPlacement, openMenuHandler, closeMenuHandler, orderedOptions, } = useSelect(props);
832
- const selectProps = {
833
- value,
834
- menuPlacement,
835
- maxMenuHeight,
836
- onChange,
837
- "aria-label": label,
838
- "data-testid": dataTestId,
839
- components: customComponents,
840
- styles: customStyles,
841
- tabSelectsValue: false,
842
- blurInputOnSelect: !isMulti,
843
- menuPortalTarget: props.menuPortalTarget || document.body,
844
- isSearchable: disabled || readOnly ? false : isSearchable,
845
- menuShouldBlockScroll: true,
846
- menuShouldScrollIntoView: true,
847
- openMenuOnFocus,
848
- menuIsOpen: !readOnly ? menuIsOpen : false,
849
- openMenuOnClick,
850
- closeMenuOnSelect: false,
851
- isMulti,
852
- classNamePrefix,
853
- isLoading,
854
- isClearable,
855
- id,
856
- onMenuScrollToBottom,
857
- onInputChange,
858
- };
859
- 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 })))] }));
860
- };
861
- Select.displayName = "Select";
862
-
863
- /**
864
- * The SelectField component is a Select component wrapped in the FromGroup component.
865
- *
866
- * This means that it can easily be added to any form alongside other Field components.
867
- *
868
- * This is done to make the field compatible with the React-hook-form library.
869
- *
870
- * @param {SelectFieldProps} props - The props for the SelectField component
871
- * @returns {JSX.Element} SelectField component
872
- */
873
- const SelectField = React.forwardRef((_a, ref) => {
874
- var { className, dataTestId, helpText, helpAddon, tip, label, disabled, isInvalid, errorMessage, name, onBlur, options, value, defaultValue, id, onChange } = _a; __rest(_a, ["className", "dataTestId", "helpText", "helpAddon", "tip", "label", "disabled", "isInvalid", "errorMessage", "name", "onBlur", "options", "value", "defaultValue", "id", "onChange"]);
875
- const [innerValue, setInnerValue] = React.useState(value || defaultValue);
876
- const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
877
- const htmlFor = React.useMemo(() => (id ? id : "selectField-" + uuid.v4()), [id]);
878
- const innerRef = React.useRef(null);
879
- React.useImperativeHandle(ref, () => innerRef.current, []);
880
- const handleChange = React.useCallback((newValue) => {
881
- setInnerValue(newValue === null || newValue === void 0 ? void 0 : newValue.value);
882
- }, []);
883
- React.useEffect(() => {
884
- var _a;
885
- if (!innerValue) {
886
- return;
887
- }
888
- const event = new Event("change");
889
- (_a = innerRef.current) === null || _a === void 0 ? void 0 : _a.dispatchEvent(event);
890
- // The event as unknown as ChangeEvent<HTMLInputElement> assertion is needed because
891
- // the event's type is inferred as Event, which doesn't have a target property, whereas ChangeEvent does.
892
- onChange === null || onChange === void 0 ? void 0 : onChange(event);
893
- }, [onChange, innerValue]);
894
- const selectedOption = React.useMemo(() => options.find(option => option.value === value), [options, value]);
895
- const defaultSelectedOption = options.find(option => option.value === defaultValue);
896
- return (jsxRuntime.jsxs(FormGroup, { isInvalid: renderAsInvalid,
897
- htmlFor,
898
- className,
899
- dataTestId,
900
- helpText,
901
- helpAddon,
902
- tip,
903
- label,
904
- disabled, children: [jsxRuntime.jsx("select", { onChange, ref: innerRef, name, value: innerValue, hidden: true, children: options.map(option => {
905
- return (jsxRuntime.jsx("option", { value: option.value, children: option.label }, option.value));
906
- }) }), jsxRuntime.jsx(Select, { id,
907
- isDisabled: disabled,
908
- onBlur,
909
- options,
910
- onChange: handleChange,
911
- value: selectedOption,
912
- defaultValue: defaultSelectedOption })] }));
913
- });
914
-
915
- const cvaActionButton = cssClassVarianceUtilities.cvaMerge(["drop-shadow-none", "rounded-md"], {
916
- variants: {
917
- size: {
918
- small: ["w-6", "h-6"],
919
- medium: ["w-8", "h-8"],
920
- },
921
- },
922
- defaultVariants: {
923
- size: "medium",
924
- },
925
- });
926
- const cvaActionContainer = cssClassVarianceUtilities.cvaMerge(["flex", "items-center", "m-1"]);
927
-
928
- /**
929
- * The ActionButton component is a wrapper over IconButton to perform an action when the onClick event is triggered.
930
- *
931
- * @param {ActionButtonProps} props - The props for the ActionButton component
932
- * @returns {JSX.Element} ActionButton component
933
- */
934
- const ActionButton = ({ type, value, dataTestId, iconSize, disabled, key, className }) => {
935
- const [, copyToClipboard] = reactUse.useCopyToClipboard();
936
- const elementKey = React.useMemo(() => key !== null && key !== void 0 ? key : `ActionButton-${uuid.v4()}`, [key]);
937
- const getIconName = () => {
938
- switch (type) {
939
- case "PHONE_NUMBER":
940
- return "PhoneArrowUpRight";
941
- case "WEB_ADDRESS":
942
- return "ArrowTopRightOnSquare";
943
- case "EMAIL":
944
- return "Envelope";
945
- case "COPY":
946
- default:
947
- return "ClipboardDocument";
948
- }
949
- };
950
- const ButtonAction = () => {
951
- var _a, _b;
952
- switch (type) {
953
- case "EMAIL":
954
- return window.open(`mailto:${value}`);
955
- case "WEB_ADDRESS":
956
- if (value) {
957
- return window.open(value, "_blank", "noopener,noreferrer");
958
- }
959
- return null;
960
- case "PHONE_NUMBER":
961
- return window.open(`tel:${value}`);
962
- case "COPY":
963
- return copyToClipboard((_b = (_a = value === null || value === void 0 ? void 0 : value.current) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : "");
964
- default:
965
- return null;
966
- }
967
- };
968
- if (ButtonAction === null) {
969
- return null;
970
- }
971
- return (jsxRuntime.jsx("div", { className: cvaActionContainer({ className }), children: jsxRuntime.jsx(reactComponents.IconButton, { className: cvaActionButton({ size: iconSize }), dataTestId: dataTestId || "testIconButtonId", disabled: disabled, icon: jsxRuntime.jsx(reactComponents.Icon, { name: getIconName(), size: "small" }), onClick: ButtonAction, size: "small", variant: "secondary" }) }, elementKey));
972
- };
973
-
974
- const cvaInputBase = cssClassVarianceUtilities.cvaMerge([
975
- "component-baseInput-shadow",
976
- "component-baseInput-border",
977
- "component-baseInput-background",
978
- "border-slate-300",
979
- "focus-within:ring-2",
980
- "focus-within:ring-inset",
981
- "focus-within:ring-primary-500",
982
- "focus-within:border-slate-400",
983
- "hover:border-slate-400",
984
- "hover:bg-slate-50",
985
- "transition",
986
- ]);
987
- const cvaInputBaseDisabled = cssClassVarianceUtilities.cvaMerge(["bg-slate-100", "hover:bg-slate-100", "hover:border-slate-300"]);
988
- const cvaInputBaseInvalid = cssClassVarianceUtilities.cvaMerge(["border-danger-600", "focus-within:ring-danger-600"]);
989
- const cvaInput = cssClassVarianceUtilities.cvaMerge(["relative", "flex", "h-10", cvaInputBase()], {
990
- variants: {
991
- size: {
992
- small: ["h-8"],
993
- medium: ["h-10"],
994
- },
995
- disabled: {
996
- true: cvaInputBaseDisabled(),
997
- false: "",
998
- },
999
- invalid: {
1000
- true: cvaInputBaseInvalid(),
1001
- false: "",
1002
- },
1003
- },
1004
- });
1005
- const cvaInputField = cssClassVarianceUtilities.cvaMerge([
1006
- "w-full",
1007
- "px-3",
1008
- "border-0",
1009
- "bg-transparent",
1010
- "text-base",
1011
- "text-slate-900",
1012
- "placeholder-slate-400",
1013
- "focus-visible:outline-none",
1014
- ], {
1015
- variants: {
1016
- size: {
1017
- small: ["py-1"],
1018
- medium: ["py-2"],
1019
- },
1020
- disabled: {
1021
- true: ["text-slate-700"],
1022
- false: "",
1023
- },
1024
- },
1025
- });
1026
- const cvaInputAddon = cssClassVarianceUtilities.cvaMerge([
1027
- "flex",
1028
- "justify-center",
1029
- "items-center",
1030
- "px-3",
1031
- "border-slate-300",
1032
- "text-slate-500",
1033
- "bg-slate-50",
1034
- ]);
1035
- const cvaInputAddonBefore = cssClassVarianceUtilities.cvaMerge([cvaInputAddon(), "border-r", "rounded-l-lg"]);
1036
- const cvaInputAddonAfter = cssClassVarianceUtilities.cvaMerge([cvaInputAddon(), "border-l", "rounded-r-lg"]);
1037
- const cvaInputPrefix = cssClassVarianceUtilities.cvaMerge([
1038
- "flex",
1039
- "justify-center",
1040
- "items-center",
1041
- "text-slate-400",
1042
- "hover:component-search-prefix",
1043
- "component-baseInput-prefix",
1044
- "component-search-borderless",
1045
- "px-3",
1046
- ], {
1047
- variants: {
1048
- disabled: {
1049
- true: ["text-slate-500"],
1050
- false: "",
1051
- },
1052
- },
1053
- });
1054
- const cvaInputSuffix = cssClassVarianceUtilities.cvaMerge(["flex", "justify-center", "items-center", "text-slate-400", "px-3"], {
1055
- variants: {
1056
- disabled: {
1057
- true: ["text-slate-500"],
1058
- false: "",
1059
- },
1060
- },
1061
- });
1062
-
1063
- /**
1064
- * A base input component that can be used for text inputs, password inputs, etc.
1065
- * A reference to the input element is provided as the `ref` prop.
1066
- * Extends props from [React.InputHTMLAttributes](https://reactjs.org/docs/dom-elements.html#input)
1067
- *
1068
- * For specific input types make sure to use the corresponding input component.
1069
- * This is a base used by our other input components such as TextInput, NumberInput, PasswordInput, etc.
1070
- */
1071
- const BaseInput = React__namespace.forwardRef((_a, ref) => {
1072
- var { className, isInvalid, dataTestId, prefix, suffix, addonBefore, addonAfter, actions, fieldSize = "medium", nonInteractive = false, showDefaultActions = false, type, inputClassName, addonBeforeClassName } = _a, rest = __rest(_a, ["className", "isInvalid", "dataTestId", "prefix", "suffix", "addonBefore", "addonAfter", "actions", "fieldSize", "nonInteractive", "showDefaultActions", "type", "inputClassName", "addonBeforeClassName"]);
1073
- const isReadOnlyWithPlaceholder = React.useMemo(() => !!rest.readOnly && !!rest.placeholder && !rest.value, [rest.readOnly, rest.placeholder, rest.value]);
1074
- const renderAsDisabled = rest.disabled || rest.readOnly;
1075
- const innerRef = React__namespace.useRef(null);
1076
- React__namespace.useImperativeHandle(ref, () => innerRef.current, []);
1077
- return (jsxRuntime.jsxs("div", { className: cvaInput({
1078
- disabled: renderAsDisabled,
1079
- invalid: isInvalid,
1080
- size: fieldSize,
1081
- className,
1082
- }), "data-testid": dataTestId && `${dataTestId}-container`, children: [addonBefore && addonBefore !== undefined ? (jsxRuntime.jsx("div", { className: cvaInputAddonBefore({ className: addonBeforeClassName }), "data-testid": dataTestId && `${dataTestId}-addonBefore`, children: addonBefore })) : null, prefix && addonBefore !== prefix ? (jsxRuntime.jsx("div", { className: cvaInputPrefix({
1083
- disabled: renderAsDisabled,
1084
- }), "data-testid": dataTestId && `${dataTestId}-prefix`, children: prefix })) : null, jsxRuntime.jsx("input", Object.assign({ className: cvaInputField({ size: fieldSize, disabled: renderAsDisabled, className: inputClassName }), "data-testid": dataTestId, ref: innerRef, type: isReadOnlyWithPlaceholder ? "text" : type }, rest, { readOnly: rest.readOnly || nonInteractive })), suffix && addonBefore !== suffix ? (jsxRuntime.jsx("div", { className: cvaInputSuffix({
1085
- disabled: renderAsDisabled,
1086
- }), "data-testid": dataTestId && `${dataTestId}-suffix`, children: suffix })) : null, rest.readOnly === true && showDefaultActions ? (jsxRuntime.jsx(ActionButton, { type: "COPY", value: innerRef }, "default-copy-action")) : null, actions && addonBefore !== actions ? actions : null, addonAfter && addonAfter !== undefined && addonBefore !== addonAfter ? (jsxRuntime.jsx("div", { className: cvaInputAddonAfter(), "data-testid": dataTestId && `${dataTestId}-addonAfter`, children: addonAfter })) : null] }));
1087
- });
1088
-
1089
- /**
1090
- * A wrapper around BaseInput with a pop-up day picker.
1091
- *
1092
- * NOTE: If shown with a label, please use the `DateField` component instead.
1093
- */
1094
- const DateInput = React.forwardRef((_a, ref) => {
1095
- var { min, max, defaultValue, value } = _a, rest = __rest(_a, ["min", "max", "defaultValue", "value"]);
1096
- const formatDateToInputString = (date) => date instanceof Date ? dateFns.format(date, "yyyy-MM-dd") : date;
1097
- // Chrome and Firefox need their default icon to have datepicker functionality.
1098
- const showIcon = !/Chrome/.test(navigator.userAgent) && !/Firefox/.test(navigator.userAgent);
1099
- return (jsxRuntime.jsx(BaseInput, Object.assign({ defaultValue: formatDateToInputString(defaultValue), max: formatDateToInputString(max), min: formatDateToInputString(min), ref: ref, suffix: showIcon && jsxRuntime.jsx(reactComponents.Icon, { dataTestId: "calendar", name: "Calendar", size: "medium", type: "solid" }), type: "date", value: formatDateToInputString(value) }, rest)));
1100
- });
1101
-
1102
- /**
1103
- * The date field component is used for entering date values.
1104
- *
1105
- * _**Do use**_ the DateField for date input.
1106
- *
1107
- * _**Do not use**_ this fields for non-serialized dates. Use TextField instead.
1108
- */
1109
- const DateField = React.forwardRef((_a, ref) => {
1110
- var { label, id, tip, helpText, errorMessage, helpAddon, isInvalid, className, defaultValue, dataTestId } = _a, rest = __rest(_a, ["label", "id", "tip", "helpText", "errorMessage", "helpAddon", "isInvalid", "className", "defaultValue", "dataTestId"]);
1111
- const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
1112
- const htmlForId = id ? id : "dateField-" + uuid.v4();
1113
- 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(DateInput, Object.assign({ "aria-labelledby": htmlForId + "-label", defaultValue: defaultValue, id: htmlForId, isInvalid: renderAsInvalid, ref: ref }, rest, { className: className, dataTestId: dataTestId })) }));
1114
- });
1115
-
1116
- const cvaDropZone = cssClassVarianceUtilities.cvaMerge([
1117
- "flex",
1118
- "component-baseInput-background",
1119
- "justify-center",
1120
- "text-slate-500",
1121
- "rounded-sm",
1122
- "border-2",
1123
- "border-gray-200",
1124
- "border-dashed",
1125
- "hover:bg-slate-100",
1126
- "hover:border-solid",
1127
- "hover:border-primary-500",
1128
- ], {
1129
- variants: {
1130
- size: {
1131
- small: ["p-2"],
1132
- medium: ["p-4"],
1133
- large: ["p-8"],
1134
- },
1135
- disabled: { true: ["bg-slate-100", "hover:bg-slate-100"], false: "" },
1136
- dragActive: { true: ["border-gray-200", "bg-slate-100"], false: "" },
1137
- dropComplete: {
1138
- true: ["border-solid", "border-primary-500", "bg-slate-100", "hover:border-solid", "hover:border-gray-200"],
1139
- false: "",
1140
- },
1141
- invalid: { true: ["border-danger-600", "text-danger-500"], false: "" },
1142
- },
1143
- });
1144
- const cvaDropZoneLabel = cssClassVarianceUtilities.cvaMerge([
1145
- "h-full",
1146
- "pt-1",
1147
- "pb-1",
1148
- "gap-2",
1149
- "items-center",
1150
- "flex-col",
1151
- "flex",
1152
- "justify-center",
1153
- ]);
1154
-
1155
- /**
1156
- * The Drop Zone can be used to drag and drop files
1157
- *
1158
- * @param {DropZoneProps} props - The props for the DropZone component
1159
- * @returns {JSX.Element} DropZone component
635
+ * @param {DropZoneProps} props - The props for the DropZone component
636
+ * @returns {JSX.Element} DropZone component
1160
637
  */
1161
638
  const DropZone = (_a) => {
1162
639
  var { className, dataTestId, filesSelected, label, size = "large", isInvalid = false, disabled = false } = _a, rest = __rest(_a, ["className", "dataTestId", "filesSelected", "label", "size", "isInvalid", "disabled"]);
@@ -1236,178 +713,634 @@ const EmailInput = React__namespace.forwardRef((_a, ref) => {
1236
713
  });
1237
714
 
1238
715
  /**
1239
- * The EmailField component is used to enter email.
1240
- * EmailField validates that user enters a valid email address.
1241
- *
716
+ * The EmailField component is used to enter email.
717
+ * EmailField validates that user enters a valid email address.
718
+ *
719
+ */
720
+ const EmailField = React.forwardRef((_a, ref) => {
721
+ var { label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, dataTestId, value, onChange, isInvalid = false } = _a, rest = __rest(_a, ["label", "id", "tip", "helpText", "errorMessage", "helpAddon", "className", "defaultValue", "dataTestId", "value", "onChange", "isInvalid"]);
722
+ const htmlForId = id ? id : "emailField-" + uuid.v4();
723
+ // Type guard to check if value is a string
724
+ function isString(inputValue) {
725
+ return typeof inputValue === "string";
726
+ }
727
+ const renderAsInvalid = !!errorMessage || (value && isString(value) && !validateEmailAddress(value)) || isInvalid;
728
+ const handleChange = React.useCallback((event) => {
729
+ if (onChange) {
730
+ onChange(event);
731
+ }
732
+ }, [onChange]);
733
+ 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(EmailInput, Object.assign({ "aria-labelledby": htmlForId + "-label", defaultValue: defaultValue, disabled: renderAsInvalid, id: htmlForId, isInvalid: renderAsInvalid, onChange: handleChange, ref: ref, value: value }, rest, { className: className, dataTestId: dataTestId })) }));
734
+ });
735
+
736
+ /**
737
+ * A thin wrapper around the `BaseInput` component for number input fields.
738
+ *
739
+ * NOTE: If shown with a label, please use the `NumberField` component instead.
740
+ */
741
+ const NumberInput = React.forwardRef((props, ref) => {
742
+ return jsxRuntime.jsx(BaseInput, Object.assign({ ref: ref, type: "number" }, props, { value: props.value }));
743
+ });
744
+
745
+ /**
746
+ * The number field component is used for entering numeric values and includes controls for incrementally increasing or decreasing the value.
747
+ *
748
+ * _**Do use**_ the NumberField when the controls to incrementally increase or decrease makes the task easier for the user.
749
+ *
750
+ * _**Do not use**_ this fields for non-serialized numbers. Use TextField instead.
751
+ */
752
+ const NumberField = React.forwardRef((_a, ref) => {
753
+ var { label, id, tip, helpText, errorMessage, helpAddon, isInvalid, maxLength, className, value, dataTestId } = _a, rest = __rest(_a, ["label", "id", "tip", "helpText", "errorMessage", "helpAddon", "isInvalid", "maxLength", "className", "value", "dataTestId"]);
754
+ const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
755
+ const htmlForId = id ? id : "numberField-" + uuid.v4();
756
+ return (jsxRuntime.jsx(FormGroup, { dataTestId: dataTestId && `${dataTestId}-FormGroup`, helpAddon: helpAddon, helpText: (renderAsInvalid && errorMessage) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, tip: tip, children: jsxRuntime.jsx(NumberInput, Object.assign({ "aria-labelledby": htmlForId + "-label", id: htmlForId, isInvalid: renderAsInvalid, maxLength: maxLength, ref: ref, value: value }, rest, { className: className, dataTestId: dataTestId })) }));
757
+ });
758
+
759
+ const cvaOptionCardLabel = cssClassVarianceUtilities.cvaMerge([
760
+ cvaInputBase(),
761
+ "text-center",
762
+ "component-baseInput-background",
763
+ "aspect-square",
764
+ "flex",
765
+ "flex-col",
766
+ "gap-2",
767
+ "justify-center",
768
+ "items-center",
769
+ "p-responsive-space",
770
+ "w-full",
771
+ "peer-checked:bg-primary-50",
772
+ "peer-checked:border-primary-600",
773
+ "peer-checked:border-2",
774
+ ], {
775
+ variants: {
776
+ disabled: {
777
+ true: [cvaInputBaseDisabled(), "cursor-not-allowed"],
778
+ false: ["cursor-pointer"],
779
+ },
780
+ },
781
+ });
782
+ const cvaOptionCardContent = cssClassVarianceUtilities.cvaMerge(["flex", "flex-col", "items-center"]);
783
+ const cvaOptionCardContainer = cssClassVarianceUtilities.cvaMerge(["contents"]);
784
+
785
+ /**
786
+ * A card version of a radio button that includes an icon, headings and a description.
787
+ */
788
+ const OptionCard = React.forwardRef((_a, ref) => {
789
+ var { icon, heading, subheading, description, disabled, id, value, className, dataTestId } = _a, rest = __rest(_a, ["icon", "heading", "subheading", "description", "disabled", "id", "value", "className", "dataTestId"]);
790
+ const htmlForId = id !== null && id !== void 0 ? id : "option-card-" + uuid.v4();
791
+ return (jsxRuntime.jsxs("div", { className: cvaOptionCardContainer(), "data-testid": dataTestId, children: [jsxRuntime.jsx("input", Object.assign({ className: "peer hidden", id: htmlForId, ref: ref, type: "radio", value: value }, rest)), jsxRuntime.jsxs("label", { className: cvaOptionCardLabel({ className, disabled }), htmlFor: htmlForId, children: [disabled && icon && React.cloneElement(icon, { className: `${icon.props.className} text-secondary-400` }), !disabled && icon, heading && (jsxRuntime.jsx(reactComponents.Heading, { subtle: disabled, variant: "secondary", children: heading })), (subheading || description) && (jsxRuntime.jsxs("div", { className: cvaOptionCardContent(), children: [subheading && (jsxRuntime.jsx(reactComponents.Text, { align: "center", subtle: disabled, type: "span", weight: "thick", children: subheading })), description && (jsxRuntime.jsx(reactComponents.Text, { align: "center", subtle: true, type: "span", children: description }))] }))] })] }));
792
+ });
793
+
794
+ /**
795
+ * A thin wrapper around the `BaseInput` component for password input fields.
796
+ *
797
+ * NOTE: If shown with a label, please use the `PasswordField` component instead.
798
+ */
799
+ const PasswordInput = React.forwardRef((props, ref) => (jsxRuntime.jsx(BaseInput, Object.assign({ ref: ref }, props))));
800
+
801
+ /**
802
+ * Password fields enter a password or other confidential information. Characters are masked as they are typed.
803
+ *
804
+ * _**Do use** when the user has to input a password or something that needs to be obfuscated_
805
+ *
806
+ * _**Do not use** to confirm user actions, such as deleting. Use a checkbox for such flows._
807
+ */
808
+ const PasswordField = React.forwardRef((_a, ref) => {
809
+ var { id, label, tip, helpText, helpAddon, errorMessage, isInvalid, maxLength, onChange, className, value, dataTestId } = _a, rest = __rest(_a, ["id", "label", "tip", "helpText", "helpAddon", "errorMessage", "isInvalid", "maxLength", "onChange", "className", "value", "dataTestId"]);
810
+ const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
811
+ const htmlFor = id ? id : "passwordField-" + uuid.v4();
812
+ const [showPassword, setShowPassword] = React.useState(false);
813
+ const handleChange = React.useCallback((event) => {
814
+ onChange === null || onChange === void 0 ? void 0 : onChange(event);
815
+ }, [onChange]);
816
+ return (jsxRuntime.jsx(FormGroup, { dataTestId: dataTestId && `${dataTestId}-FormGroup`, helpAddon: helpAddon, helpText: (renderAsInvalid && errorMessage) || helpText, htmlFor: htmlFor, isInvalid: renderAsInvalid, label: label, tip: tip, children: jsxRuntime.jsx(PasswordInput, Object.assign({}, rest, { actions: jsxRuntime.jsx(reactComponents.Icon, { className: "absolute top-0 bottom-0 right-2 h-full content-center", color: "neutral", name: showPassword ? "EyeSlash" : "Eye", onClick: () => setShowPassword(prevState => !prevState), size: "small" }), "aria-labelledby": htmlFor + "-label", className: className, dataTestId: dataTestId, disabled: rest.readOnly, id: htmlFor, isInvalid: renderAsInvalid, maxLength: maxLength, onChange: handleChange, ref: ref, type: showPassword ? "text" : "password", value: value })) }));
817
+ });
818
+
819
+ /**
820
+ * @param phoneNumber - a phone number as a string
821
+ * @returns {boolean} true if the phone number starts with a plus sign
822
+ * @example checkIfPhoneNumberHasPlus("123456789") // false
823
+ * checkIfPhoneNumberHasPlus("+123456789") // true
824
+ */
825
+ const checkIfPhoneNumberHasPlus = (phoneNumber) => {
826
+ return phoneNumber.startsWith("+");
827
+ };
828
+ /**
829
+ * @param phoneNumber - a phone number as a string
830
+ * @returns {string|number} the phone number with a plus sign in front of it
831
+ * @example getPhoneNumberWithPlus("123456789") // "+123456789"
832
+ */
833
+ const getPhoneNumberWithPlus = (phoneNumber) => {
834
+ const stringPhoneNumber = phoneNumber.toString();
835
+ return checkIfPhoneNumberHasPlus(stringPhoneNumber) ? stringPhoneNumber : `+${stringPhoneNumber}`;
836
+ };
837
+ /**
838
+ * Generates a flag emoji based on the given country code.
839
+ *
840
+ * @param {string} countryCode - The two-letter country code (ISO 3166-1 alpha-2).
841
+ * @returns {string} - The corresponding flag emoji for the given country code.
842
+ * @example getPhoneNumberWithPlus("DK") // "🇩🇰"
843
+ */
844
+ const countryCodeToFlagEmoji = (countryCode) => {
845
+ let code = countryCode;
846
+ if (countryCode.startsWith("+")) {
847
+ code = getCountryAbbreviation(countryCode.substring(1));
848
+ }
849
+ else if (!isNaN(Number(countryCode))) {
850
+ code = getCountryAbbreviation(countryCode);
851
+ }
852
+ return parsePhoneNumberFromString.isSupportedCountry(code.toUpperCase())
853
+ ? code.toUpperCase().replace(/./g, char => String.fromCodePoint(127397 + char.charCodeAt(0)))
854
+ : "";
855
+ };
856
+ /**
857
+ * Retrieves the ISO 3166-1 alpha-2 country code associated with a given international calling code.
858
+ *
859
+ * @param {string} callCode - The international calling code for a country.
860
+ * @returns {string} The abbreviation for a country or an empty string if no matching country is found.
861
+ * @example getCountryAbbreviation("45") // "DK"
862
+ * @example getCountryAbbreviation("+45") // "DK"
863
+ */
864
+ const getCountryAbbreviation = (callCode) => {
865
+ let code = callCode;
866
+ if (callCode.startsWith("+")) {
867
+ code = callCode.substring(1);
868
+ }
869
+ return parsePhoneNumberFromString.getCountries().find(c => parsePhoneNumberFromString.getCountryCallingCode(c) === code) || "";
870
+ };
871
+
872
+ /**
873
+ * A custom hook for managing phone number input state and validation.
874
+ *
875
+ * @property {Function} getPhoneNumber - A function for get formatted phone number with country code and plus sign
876
+ */
877
+ const usePhoneInput = () => {
878
+ const getPhoneNumber = ({ country, phone }) => {
879
+ if (country) {
880
+ return getPhoneNumberWithPlus(`${country}${phone || ""}`);
881
+ }
882
+ return phone || "";
883
+ };
884
+ return {
885
+ getPhoneNumber,
886
+ };
887
+ };
888
+
889
+ const cvaSelect = cssClassVarianceUtilities.cvaMerge([
890
+ "relative",
891
+ "flex",
892
+ "shadow-sm",
893
+ "rounded-lg",
894
+ "border",
895
+ "border-slate-300",
896
+ "focus-within:ring-2",
897
+ "focus-within:ring-inset",
898
+ "focus-within:ring-primary-600",
899
+ "focus-within:border-slate-400",
900
+ "hover:border-slate-400",
901
+ "hover:bg-slate-50",
902
+ "bg-white",
903
+ "transition",
904
+ ], {
905
+ variants: {
906
+ invalid: {
907
+ true: "border-red-600 text-red-600 focus-within:ring-red-600 hover:border-red-600",
908
+ false: "",
909
+ },
910
+ disabled: {
911
+ true: "!bg-slate-100",
912
+ false: "",
913
+ },
914
+ },
915
+ defaultVariants: {
916
+ invalid: false,
917
+ disabled: false,
918
+ },
919
+ });
920
+ const cvaSelectIcon = cssClassVarianceUtilities.cvaMerge("mr-2 flex cursor-pointer items-center justify-center text-slate-400 hover:text-slate-500");
921
+ const cvaSelectPrefix = cssClassVarianceUtilities.cvaMerge(["flex", "justify-center", "items-center", "text-slate-400", "pl-2"]);
922
+ const cvaSelectXIcon = cssClassVarianceUtilities.cvaMerge([
923
+ "mr-2 flex cursor-pointer items-center justify-center text-slate-400 hover:text-slate-500",
924
+ "ml-1",
925
+ ]);
926
+ const cvaSelectMenuList = cssClassVarianceUtilities.cvaMerge(["min-w-min", "shadow-md", "rounded-lg", "z-20", "bg-white", "p-1", "border", "border-slate-300", "gap-1", "grid"], {
927
+ variants: {
928
+ menuIsOpen: {
929
+ true: "animate-fade-in-fast",
930
+ false: "animate-fade-out-fast",
931
+ },
932
+ },
933
+ });
934
+ const cvaSelectDynamicTagContainer = cssClassVarianceUtilities.cvaMerge(["h-full", "flex", "gap-1", "items-center"], {
935
+ variants: {
936
+ visible: { true: "visible", false: "invisible" },
937
+ },
938
+ });
939
+ const cvaSelectCounter = cssClassVarianceUtilities.cvaMerge(["overflow-hidden", "whitespace-nowrap"]);
940
+ const cvaSelectMenu = cssClassVarianceUtilities.cvaMerge(["relative", "p-1", "grid", "gap-1"]);
941
+
942
+ /**
943
+ * @param {MultiValue<Option> | SingleValue<Option>} arg option to check type
944
+ * @returns {arg is MultiValue<Option> } is Multivalue
945
+ */
946
+ function isMultiValue(arg) {
947
+ return Array.isArray(arg);
948
+ }
949
+ function isGroupBase(arg) {
950
+ return arg.options !== undefined;
951
+ }
952
+ const isSelectedOption = (option, selected) => {
953
+ if (isGroupBase(option)) {
954
+ return false;
955
+ }
956
+ return isMultiValue(selected)
957
+ ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
958
+ selected.some(v => v.value === option.value)
959
+ : // eslint-disable-next-line @typescript-eslint/no-explicit-any
960
+ option.value === (selected === null || selected === void 0 ? void 0 : selected.value);
961
+ };
962
+ const removeSelectedFromGroups = (group, selected) => {
963
+ if (isGroupBase(group)) {
964
+ return Object.assign(Object.assign({}, group), { options: group.options.filter(option => !isSelectedOption(option, selected)) });
965
+ }
966
+ return group;
967
+ };
968
+ /**
969
+ * @template IsMulti
970
+ * @template Group
971
+ * @param {OptionsOrGroups<Option, Group> | undefined} options An array of options to select from
972
+ * @param {PropsValue<Option> | undefined} value Selected values
973
+ * @returns {OptionsOrGroups<Option, Group>} An array of ordered options with selected on top
1242
974
  */
1243
- const EmailField = React.forwardRef((_a, ref) => {
1244
- var { label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, dataTestId, value, onChange, isInvalid = false } = _a, rest = __rest(_a, ["label", "id", "tip", "helpText", "errorMessage", "helpAddon", "className", "defaultValue", "dataTestId", "value", "onChange", "isInvalid"]);
1245
- const htmlForId = id ? id : "emailField-" + uuid.v4();
1246
- // Type guard to check if value is a string
1247
- function isString(inputValue) {
1248
- return typeof inputValue === "string";
975
+ const getOrderedOptions = (options, value) => {
976
+ if (value && options) {
977
+ const orderedValues = isMultiValue(value)
978
+ ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
979
+ [...value].sort((a, b) => a.label.localeCompare(b.label))
980
+ : [value];
981
+ const selectableOptions = options
982
+ .filter(option => !isSelectedOption(option, value))
983
+ .map(option => removeSelectedFromGroups(option, value));
984
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
985
+ return orderedValues.concat(selectableOptions) || [];
1249
986
  }
1250
- const renderAsInvalid = !!errorMessage || (value && isString(value) && !validateEmailAddress(value)) || isInvalid;
1251
- const handleChange = React.useCallback((event) => {
1252
- if (onChange) {
1253
- onChange(event);
1254
- }
1255
- }, [onChange]);
1256
- 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(EmailInput, Object.assign({ "aria-labelledby": htmlForId + "-label", defaultValue: defaultValue, disabled: renderAsInvalid, id: htmlForId, isInvalid: renderAsInvalid, onChange: handleChange, ref: ref, value: value }, rest, { className: className, dataTestId: dataTestId })) }));
1257
- });
987
+ return options || [];
988
+ };
1258
989
 
1259
990
  /**
1260
- * A thin wrapper around the `BaseInput` component for number input fields.
991
+ * A single select menu item is a basic wrapper around Menu item designed to be used as a single value render in Select list
1261
992
  *
1262
- * NOTE: If shown with a label, please use the `NumberField` component instead.
993
+ * @param {SelectMenuItemProps} props - The props for the SingleSelectMenuItem
994
+ * @returns {JSX.Element} SingleSelectMenuItem
1263
995
  */
1264
- const NumberInput = React.forwardRef((props, ref) => {
1265
- return jsxRuntime.jsx(BaseInput, Object.assign({ ref: ref, type: "number" }, props, { value: props.value }));
1266
- });
1267
-
996
+ const SingleSelectMenuItem = ({ label, icon, onClick, selected, dataTestId, focused, disabled, }) => {
997
+ 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 }));
998
+ };
1268
999
  /**
1269
- * The number field component is used for entering numeric values and includes controls for incrementally increasing or decreasing the value.
1270
- *
1271
- * _**Do use**_ the NumberField when the controls to incrementally increase or decrease makes the task easier for the user.
1000
+ * A multi select menu item is a basic wrapper around Menu item designed to be used as a multi value render in Select list
1272
1001
  *
1273
- * _**Do not use**_ this fields for non-serialized numbers. Use TextField instead.
1274
- */
1275
- const NumberField = React.forwardRef((_a, ref) => {
1276
- var { label, id, tip, helpText, errorMessage, helpAddon, isInvalid, maxLength, className, value, dataTestId } = _a, rest = __rest(_a, ["label", "id", "tip", "helpText", "errorMessage", "helpAddon", "isInvalid", "maxLength", "className", "value", "dataTestId"]);
1277
- const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
1278
- const htmlForId = id ? id : "numberField-" + uuid.v4();
1279
- return (jsxRuntime.jsx(FormGroup, { dataTestId: dataTestId && `${dataTestId}-FormGroup`, helpAddon: helpAddon, helpText: (renderAsInvalid && errorMessage) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, tip: tip, children: jsxRuntime.jsx(NumberInput, Object.assign({ "aria-labelledby": htmlForId + "-label", id: htmlForId, isInvalid: renderAsInvalid, maxLength: maxLength, ref: ref, value: value }, rest, { className: className, dataTestId: dataTestId })) }));
1280
- });
1281
-
1282
- const cvaOptionCardLabel = cssClassVarianceUtilities.cvaMerge([
1283
- cvaInputBase(),
1284
- "text-center",
1285
- "component-baseInput-background",
1286
- "aspect-square",
1287
- "flex",
1288
- "flex-col",
1289
- "gap-2",
1290
- "justify-center",
1291
- "items-center",
1292
- "p-responsive-space",
1293
- "w-full",
1294
- "peer-checked:bg-primary-50",
1295
- "peer-checked:border-primary-600",
1296
- "peer-checked:border-2",
1297
- ], {
1298
- variants: {
1299
- disabled: {
1300
- true: [cvaInputBaseDisabled(), "cursor-not-allowed"],
1301
- false: ["cursor-pointer"],
1302
- },
1303
- },
1304
- });
1305
- const cvaOptionCardContent = cssClassVarianceUtilities.cvaMerge(["flex", "flex-col", "items-center"]);
1306
- const cvaOptionCardContainer = cssClassVarianceUtilities.cvaMerge(["contents"]);
1307
-
1308
- /**
1309
- * A card version of a radio button that includes an icon, headings and a description.
1002
+ * @param {SelectMenuItemProps} props - The props for the MultiSelectMenuItem
1003
+ * @returns {JSX.Element} multi select menu item
1310
1004
  */
1311
- const OptionCard = React.forwardRef((_a, ref) => {
1312
- var { icon, heading, subheading, description, disabled, id, value, className, dataTestId } = _a, rest = __rest(_a, ["icon", "heading", "subheading", "description", "disabled", "id", "value", "className", "dataTestId"]);
1313
- const htmlForId = id !== null && id !== void 0 ? id : "option-card-" + uuid.v4();
1314
- return (jsxRuntime.jsxs("div", { className: cvaOptionCardContainer(), "data-testid": dataTestId, children: [jsxRuntime.jsx("input", Object.assign({ className: "peer hidden", id: htmlForId, ref: ref, type: "radio", value: value }, rest)), jsxRuntime.jsxs("label", { className: cvaOptionCardLabel({ className, disabled }), htmlFor: htmlForId, children: [disabled && icon && React.cloneElement(icon, { className: `${icon.props.className} text-secondary-400` }), !disabled && icon, heading && (jsxRuntime.jsx(reactComponents.Heading, { subtle: disabled, variant: "secondary", children: heading })), (subheading || description) && (jsxRuntime.jsxs("div", { className: cvaOptionCardContent(), children: [subheading && (jsxRuntime.jsx(reactComponents.Text, { align: "center", subtle: disabled, type: "span", weight: "thick", children: subheading })), description && (jsxRuntime.jsx(reactComponents.Text, { align: "center", subtle: true, type: "span", children: description }))] }))] })] }));
1315
- });
1005
+ const MultiSelectMenuItem = ({ label, onClick, selected, dataTestId, focused, disabled, }) => {
1006
+ return (jsxRuntime.jsx(reactComponents.MenuItem, { dataTestId: dataTestId, disabled: disabled, focused: focused, label: label, onClick: e => {
1007
+ e.stopPropagation();
1008
+ onClick && onClick(e);
1009
+ }, prefix: jsxRuntime.jsx(Checkbox, { checked: selected, disabled: disabled, onChange: () => null, onClick: e => {
1010
+ e.stopPropagation();
1011
+ }, readOnly: false }), selected: selected }));
1012
+ };
1316
1013
 
1317
1014
  /**
1318
- * A thin wrapper around the `BaseInput` component for password input fields.
1015
+ * Extended Tag component with information about its own width.
1016
+ * Used in the select component.
1319
1017
  *
1320
- * NOTE: If shown with a label, please use the `PasswordField` component instead.
1018
+ * @param {TagProps} props - The props for the tag component
1019
+ * @returns {JSX.Element} TagWithWidth component
1321
1020
  */
1322
- const PasswordInput = React.forwardRef((props, ref) => (jsxRuntime.jsx(BaseInput, Object.assign({ ref: ref }, props))));
1021
+ const TagWithWidth = (_a) => {
1022
+ var { onWidthKnown, children } = _a, rest = __rest(_a, ["onWidthKnown", "children"]);
1023
+ const ref = React__default["default"].useRef(null);
1024
+ React__default["default"].useLayoutEffect(() => {
1025
+ var _a;
1026
+ onWidthKnown && onWidthKnown({ width: ((_a = ref.current) === null || _a === void 0 ? void 0 : _a.offsetWidth) || 0 });
1027
+ }, [ref, onWidthKnown]);
1028
+ return (jsxRuntime.jsx(reactComponents.Tag, Object.assign({ ref: ref }, rest, { children: children })));
1029
+ };
1323
1030
 
1324
1031
  /**
1325
- * Password fields enter a password or other confidential information. Characters are masked as they are typed.
1326
- *
1327
- * _**Do use** when the user has to input a password or something that needs to be obfuscated_
1032
+ * TagsContainer component to display tags in limited space when children can't fit space it displays counter
1328
1033
  *
1329
- * _**Do not use** to confirm user actions, such as deleting. Use a checkbox for such flows._
1034
+ * @param {TagsContainerProps} props - The props for the TagContainer
1035
+ * @returns {JSX.Element} TagsContainer
1330
1036
  */
1331
- const PasswordField = React.forwardRef((_a, ref) => {
1332
- var { id, label, tip, helpText, helpAddon, errorMessage, isInvalid, maxLength, onChange, className, value, dataTestId } = _a, rest = __rest(_a, ["id", "label", "tip", "helpText", "helpAddon", "errorMessage", "isInvalid", "maxLength", "onChange", "className", "value", "dataTestId"]);
1333
- const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
1334
- const htmlFor = id ? id : "passwordField-" + uuid.v4();
1335
- const [showPassword, setShowPassword] = React.useState(false);
1336
- const handleChange = React.useCallback((event) => {
1337
- onChange === null || onChange === void 0 ? void 0 : onChange(event);
1338
- }, [onChange]);
1339
- return (jsxRuntime.jsx(FormGroup, { dataTestId: dataTestId && `${dataTestId}-FormGroup`, helpAddon: helpAddon, helpText: (renderAsInvalid && errorMessage) || helpText, htmlFor: htmlFor, isInvalid: renderAsInvalid, label: label, tip: tip, children: jsxRuntime.jsx(PasswordInput, Object.assign({}, rest, { actions: jsxRuntime.jsx(reactComponents.Icon, { className: "absolute top-0 bottom-0 right-2 h-full content-center", color: "neutral", name: showPassword ? "EyeSlash" : "Eye", onClick: () => setShowPassword(prevState => !prevState), size: "small" }), "aria-labelledby": htmlFor + "-label", className: className, dataTestId: dataTestId, disabled: rest.readOnly, id: htmlFor, isInvalid: renderAsInvalid, maxLength: maxLength, onChange: handleChange, ref: ref, type: showPassword ? "text" : "password", value: value })) }));
1340
- });
1037
+ const TagsContainer = ({ items, width = "100%", itemsGap = 5, postFix, disabled }) => {
1038
+ const [isReady, setIsReady] = React__default["default"].useState(false);
1039
+ const [counterWidth, setCounterWidth] = React__default["default"].useState(0);
1040
+ const containerRef = React__default["default"].useRef(null);
1041
+ const availableWidth = React__default["default"].useRef();
1042
+ const childrenWidth = React__default["default"].useRef([]);
1043
+ const itemsCount = items.length;
1044
+ React__default["default"].useLayoutEffect(() => {
1045
+ var _a;
1046
+ availableWidth.current = ((_a = containerRef === null || containerRef === void 0 ? void 0 : containerRef.current) === null || _a === void 0 ? void 0 : _a.offsetWidth) || 0;
1047
+ }, [containerRef]);
1048
+ const onWidthKnownHandler = ({ width: reportedWidth }) => {
1049
+ childrenWidth.current.push({ width: reportedWidth + itemsGap });
1050
+ if (childrenWidth.current.length === itemsCount) {
1051
+ setIsReady(true);
1052
+ }
1053
+ };
1054
+ const requiredSpace = childrenWidth.current.reduce((previous, current) => {
1055
+ return previous + current.width;
1056
+ }, 0);
1057
+ let counter = 0;
1058
+ const availableSpace = ((availableWidth === null || availableWidth === void 0 ? void 0 : availableWidth.current) || 0) - counterWidth;
1059
+ const renderedElements = items
1060
+ .concat({ text: "", onClick: () => null, disabled: false }) // reserved element for a potential counter
1061
+ .map((item, index) => {
1062
+ const spaceNeeded = childrenWidth.current.slice(0, index + 1).reduce((previous, current) => {
1063
+ return previous + current.width;
1064
+ }, 0);
1065
+ const isLast = index === items.length;
1066
+ const counterRequired = requiredSpace > availableSpace && counter !== 0;
1067
+ if (isLast && counterRequired) {
1068
+ 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));
1069
+ }
1070
+ if (isLast) {
1071
+ return null;
1072
+ }
1073
+ const itemCanFit = spaceNeeded <= availableSpace;
1074
+ if (itemCanFit) {
1075
+ return (jsxRuntime.jsx(TagWithWidth, { className: "inline-flex shrink-0", color: item.disabled ? "unknown" : "primary", dataTestId: `${item.text}-tag`, disabled: disabled, onClose: e => {
1076
+ e.stopPropagation();
1077
+ item.onClick();
1078
+ }, onWidthKnown: onWidthKnownHandler, children: item.text }, item.text + index));
1079
+ }
1080
+ const fromTheItems = item.text !== "";
1081
+ if (fromTheItems) {
1082
+ counter = counter + 1;
1083
+ }
1084
+ return null;
1085
+ })
1086
+ .filter(element => element !== null);
1087
+ return (jsxRuntime.jsxs("div", { className: cvaSelectDynamicTagContainer({ visible: isReady }), ref: containerRef, style: {
1088
+ width: `${width}`,
1089
+ }, children: [renderedElements, postFix] }));
1090
+ };
1341
1091
 
1342
1092
  /**
1343
- * @param phoneNumber - a phone number as a string
1344
- * @returns {boolean} true if the phone number starts with a plus sign
1345
- * @example checkIfPhoneNumberHasPlus("123456789") // false
1346
- * checkIfPhoneNumberHasPlus("+123456789") // true
1093
+ * A hook to retrieve components override object.
1094
+ * 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.
1095
+ *
1096
+ * @template IsMulti
1097
+ * @template Group
1098
+ * @param {Partial<SelectComponents<Option, IsMulti, Group>> | undefined} componentsProps a custom component prop that you can to override defaults
1099
+ * @param {boolean} disabled decide to override disabled variant
1100
+ * @param {boolean} menuIsOpen menu is open state
1101
+ * @param {React.MutableRefObject<boolean>} refMenuIsEnabled a flag to block menu from open
1102
+ * @param {string} dataTestId a test id
1103
+ * @param {number} maxSelectedDisplayCount a number of max display count
1104
+ * @param {JSX.Element} dropdownIcon an custom dropdown icon
1105
+ * @returns {Partial<SelectComponents<Option, boolean, GroupBase<Option>>> | undefined} components object to override react-select default components
1347
1106
  */
1348
- const checkIfPhoneNumberHasPlus = (phoneNumber) => {
1349
- return phoneNumber.startsWith("+");
1107
+ const useCustomComponents = (componentsProps, disabled, menuIsOpen, refMenuIsEnabled, dataTestId, maxSelectedDisplayCount, dropdownIcon) => {
1108
+ const [t] = useTranslation();
1109
+ // perhaps it should not be wrap in memo (causing some issues with opening and closing on mobiles)
1110
+ const customComponents = React__namespace.useMemo(() => {
1111
+ return Object.assign({ ValueContainer: props => {
1112
+ if (props.isMulti && Array.isArray(props.children) && props.children.length > 0) {
1113
+ const PLACEHOLDER_KEY = "placeholder";
1114
+ const key = props && props.children && props.children[0] ? props.children[0].key : "";
1115
+ const values = props && props.children ? props.children[0] : [];
1116
+ const tags = key === PLACEHOLDER_KEY ? [] : values;
1117
+ const searchInput = props && props.children && props.children[1];
1118
+ return (jsxRuntime.jsx(ReactSelect.components.ValueContainer, Object.assign({}, props, { isDisabled: props.selectProps.isDisabled, children: maxSelectedDisplayCount === undefined ? (jsxRuntime.jsx(TagsContainer, { disabled: disabled, items: tags
1119
+ ? tags.map(({ props: tagProps }) => {
1120
+ return {
1121
+ text: tagProps.children,
1122
+ onClick: disabled
1123
+ ? undefined
1124
+ : (e) => {
1125
+ var _a, _b;
1126
+ refMenuIsEnabled.current = false;
1127
+ ((_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));
1128
+ },
1129
+ disabled: disabled,
1130
+ };
1131
+ })
1132
+ : [], postFix: searchInput, width: "100%" })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [tags &&
1133
+ tags.slice(0, maxSelectedDisplayCount).map(({ props: tagProps }) => {
1134
+ var _a, _b;
1135
+ 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 => {
1136
+ var _a, _b;
1137
+ e.stopPropagation();
1138
+ refMenuIsEnabled.current = false;
1139
+ ((_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));
1140
+ }, children: tagProps.children }, (_b = tagProps.children) === null || _b === void 0 ? void 0 : _b.toString()));
1141
+ }), tags && tags.length > maxSelectedDisplayCount && (jsxRuntime.jsxs(reactComponents.Tag, { color: "neutral", dataTestId: "counter-tag", children: ["+", tags.length - maxSelectedDisplayCount] })), searchInput] })) })));
1142
+ }
1143
+ return (jsxRuntime.jsx(ReactSelect.components.ValueContainer, Object.assign({}, props, { isDisabled: props.selectProps.isDisabled, children: props.children })));
1144
+ }, LoadingIndicator: props => {
1145
+ return jsxRuntime.jsx(reactComponents.Spinner, { className: "mt-1.5 mr-1", size: "small" });
1146
+ }, DropdownIndicator: props => {
1147
+ const icon = props.selectProps.menuIsOpen ? (jsxRuntime.jsx(reactComponents.Icon, { name: "ChevronUp", size: "medium" })) : (jsxRuntime.jsx(reactComponents.Icon, { name: "ChevronDown", size: "medium" }));
1148
+ return props.selectProps.isLoading ? null : (jsxRuntime.jsx(ReactSelect.components.DropdownIndicator, Object.assign({}, props, { children: jsxRuntime.jsx("div", { className: cvaSelectIcon(), children: dropdownIcon ? dropdownIcon : icon }) })));
1149
+ }, IndicatorSeparator: () => null, ClearIndicator: props => {
1150
+ if (disabled) {
1151
+ return null;
1152
+ }
1153
+ 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") }) }) })));
1154
+ }, Control: props => {
1155
+ return jsxRuntime.jsx(ReactSelect.components.Control, Object.assign({}, props, { className: props.isDisabled ? "bg-slate-100" : "" }));
1156
+ }, SingleValue: props => {
1157
+ 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 }) })));
1158
+ }, Menu: props => {
1159
+ return (jsxRuntime.jsx(ReactSelect.components.Menu, Object.assign({}, props, { className: cvaSelectMenuList({ menuIsOpen: props.selectProps.menuIsOpen }) })));
1160
+ }, MenuList: props => {
1161
+ return (jsxRuntime.jsx(ReactSelect.components.MenuList, Object.assign({}, props, { innerProps: Object.assign(Object.assign({}, props.innerProps), { onScroll: e => {
1162
+ const listEl = e.currentTarget;
1163
+ if (listEl.scrollTop + listEl.clientHeight >= listEl.scrollHeight) {
1164
+ props.selectProps.onMenuScrollToBottom && props.selectProps.onMenuScrollToBottom(new TouchEvent(""));
1165
+ }
1166
+ } }), children: props.children })));
1167
+ }, Option: props => {
1168
+ const componentProps = {
1169
+ label: props.label,
1170
+ focused: props.isFocused,
1171
+ selected: props.isSelected,
1172
+ onClick: props.innerProps.onClick,
1173
+ };
1174
+ 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 }))) })));
1175
+ } }, componentsProps);
1176
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1177
+ }, [componentsProps, disabled, maxSelectedDisplayCount]); // do not add dropdownIcon (it will cause issue with opening/closing list for selects with custom icon)
1178
+ return customComponents;
1350
1179
  };
1180
+
1351
1181
  /**
1352
- * @param phoneNumber - a phone number as a string
1353
- * @returns {string|number} the phone number with a plus sign in front of it
1354
- * @example getPhoneNumberWithPlus("123456789") // "+123456789"
1182
+ * @template IsMulti
1183
+ * @template Group
1184
+ * @param {React.RefObject<HTMLDivElement>} refContainer react ref to container element
1185
+ * @param {React.RefObject<HTMLDivElement>} refPrefix react ref to prefix element
1186
+ * @param {number | undefined} maxSelectedDisplayCount a number of max display count
1187
+ * @param {StylesConfig<Option, IsMulti, Group> | undefined} styles a optional object to override styles of react-select
1188
+ * @returns {StylesConfig<Option, boolean>} styles to override in select
1355
1189
  */
1356
- const getPhoneNumberWithPlus = (phoneNumber) => {
1357
- const stringPhoneNumber = phoneNumber.toString();
1358
- return checkIfPhoneNumberHasPlus(stringPhoneNumber) ? stringPhoneNumber : `+${stringPhoneNumber}`;
1190
+ const useCustomStyles = (refContainer, refPrefix, maxSelectedDisplayCount, styles, disabled) => {
1191
+ const customStyles = React__namespace.useMemo(() => {
1192
+ return Object.assign({ control: base => {
1193
+ return Object.assign(Object.assign({}, base), { border: "0", boxShadow: "0", "&:hover": {
1194
+ border: "0",
1195
+ }, marginRight: "2px", backgroundColor: "" });
1196
+ }, 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: () => ({
1197
+ width: "0px",
1198
+ }), menu: base => {
1199
+ return Object.assign(Object.assign({}, base), { width: "100%", marginTop: "4px", marginBottom: "18px", transition: "all 1s ease-in-out" });
1200
+ }, 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 => {
1201
+ 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" });
1202
+ }, valueContainer: base => {
1203
+ return Object.assign(Object.assign({}, base), { flexWrap: maxSelectedDisplayCount !== undefined ? "wrap" : "nowrap", gap: "0.25rem" });
1204
+ }, 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 => {
1205
+ return Object.assign(Object.assign({}, base), { padding: "0px" });
1206
+ } }, styles);
1207
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1208
+ }, [refContainer, refPrefix]);
1209
+ return { customStyles };
1359
1210
  };
1211
+
1360
1212
  /**
1361
- * Generates a flag emoji based on the given country code.
1213
+ * A hook used by selects to share the common code
1362
1214
  *
1363
- * @param {string} countryCode - The two-letter country code (ISO 3166-1 alpha-2).
1364
- * @returns {string} - The corresponding flag emoji for the given country code.
1365
- * @example getPhoneNumberWithPlus("DK") // "🇩🇰"
1215
+ * @param {SelectProps} props - The props for the Select component
1216
+ * @returns {IUseSelect} Select component
1366
1217
  */
1367
- const countryCodeToFlagEmoji = (countryCode) => {
1368
- let code = countryCode;
1369
- if (countryCode.startsWith("+")) {
1370
- code = getCountryAbbreviation(countryCode.substring(1));
1371
- }
1372
- else if (!isNaN(Number(countryCode))) {
1373
- code = getCountryAbbreviation(countryCode);
1374
- }
1375
- return parsePhoneNumberFromString.isSupportedCountry(code.toUpperCase())
1376
- ? code.toUpperCase().replace(/./g, char => String.fromCodePoint(127397 + char.charCodeAt(0)))
1377
- : "";
1218
+ const useSelect = (_a) => {
1219
+ var _b;
1220
+ 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"]);
1221
+ const refContainer = React__default["default"].useRef(null);
1222
+ const refPrefix = React__default["default"].useRef(null);
1223
+ const { customStyles } = useCustomStyles(refContainer, refPrefix, maxSelectedDisplayCount, styles, disabled);
1224
+ const [menuIsOpen, setMenuIsOpen] = React__default["default"].useState((_b = props.menuIsOpen) !== null && _b !== void 0 ? _b : false);
1225
+ const refMenuIsEnabled = React__default["default"].useRef(true);
1226
+ const customComponents = useCustomComponents(components, disabled || false, menuIsOpen, refMenuIsEnabled, dataTestId, maxSelectedDisplayCount, dropdownIcon);
1227
+ const menuPlacement = "auto";
1228
+ const openMenuHandler = () => __awaiter(void 0, void 0, void 0, function* () {
1229
+ onMenuOpen && onMenuOpen();
1230
+ if (refMenuIsEnabled.current) {
1231
+ setMenuIsOpen(true);
1232
+ }
1233
+ else {
1234
+ refMenuIsEnabled.current = true;
1235
+ }
1236
+ });
1237
+ const closeMenuHandler = () => {
1238
+ setMenuIsOpen(false);
1239
+ onMenuClose && onMenuClose();
1240
+ };
1241
+ const orderedOptions = React__default["default"].useMemo(() => {
1242
+ return disabled
1243
+ ? getOrderedOptions(options, value).map(option => {
1244
+ return Object.assign(Object.assign({}, option), { disabled: true });
1245
+ })
1246
+ : getOrderedOptions(options, value);
1247
+ }, [options, value, disabled]);
1248
+ return {
1249
+ refContainer,
1250
+ refPrefix,
1251
+ customStyles,
1252
+ menuIsOpen,
1253
+ customComponents,
1254
+ menuPlacement,
1255
+ openMenuHandler,
1256
+ closeMenuHandler,
1257
+ orderedOptions,
1258
+ };
1378
1259
  };
1260
+
1379
1261
  /**
1380
- * Retrieves the ISO 3166-1 alpha-2 country code associated with a given international calling code.
1262
+ * CreatableSelects are input components used to choose a value from a set.
1381
1263
  *
1382
- * @param {string} callCode - The international calling code for a country.
1383
- * @returns {string} The abbreviation for a country or an empty string if no matching country is found.
1384
- * @example getCountryAbbreviation("45") // "DK"
1385
- * @example getCountryAbbreviation("+45") // "DK"
1264
+ * @param {CreatableSelectProps} props - The props for the CreatableSelect component
1265
+ * @returns {JSX.Element} CreatableSelect component
1386
1266
  */
1387
- const getCountryAbbreviation = (callCode) => {
1388
- let code = callCode;
1389
- if (callCode.startsWith("+")) {
1390
- code = callCode.substring(1);
1391
- }
1392
- return parsePhoneNumberFromString.getCountries().find(c => parsePhoneNumberFromString.getCountryCallingCode(c) === code) || "";
1267
+ const CreatableSelect = (props) => {
1268
+ const { className } = props, propsNoClassName = __rest(props, ["className"]);
1269
+ 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, allowCreateWhileLoading, onCreateOption, } = propsNoClassName;
1270
+ const { refContainer, refPrefix, customStyles, menuIsOpen, customComponents, menuPlacement, openMenuHandler, closeMenuHandler, orderedOptions, } = useSelect(props);
1271
+ const creatableSelectProps = {
1272
+ value,
1273
+ menuPlacement,
1274
+ maxMenuHeight,
1275
+ onChange,
1276
+ "aria-label": label,
1277
+ "data-testid": dataTestId,
1278
+ components: customComponents,
1279
+ styles: customStyles,
1280
+ tabSelectsValue: false,
1281
+ blurInputOnSelect: !isMulti,
1282
+ menuPortalTarget: props.menuPortalTarget || document.body,
1283
+ isSearchable: disabled || readOnly ? false : isSearchable,
1284
+ menuShouldBlockScroll: true,
1285
+ menuShouldScrollIntoView: true,
1286
+ openMenuOnFocus: true,
1287
+ menuIsOpen: !readOnly ? menuIsOpen : false,
1288
+ openMenuOnClick: true,
1289
+ closeMenuOnSelect: false,
1290
+ isMulti,
1291
+ classNamePrefix,
1292
+ isLoading,
1293
+ isClearable,
1294
+ id,
1295
+ onMenuScrollToBottom,
1296
+ onInputChange,
1297
+ allowCreateWhileLoading,
1298
+ onCreateOption,
1299
+ };
1300
+ 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 })))] }));
1393
1301
  };
1302
+ CreatableSelect.displayName = "CreatableSelect";
1394
1303
 
1395
1304
  /**
1396
- * A custom hook for managing phone number input state and validation.
1305
+ * Selects are input components used to choose a value from a set.
1397
1306
  *
1398
- * @property {Function} getPhoneNumber - A function for get formatted phone number with country code and plus sign
1307
+ * @param {SelectProps} props - The props for the Select component
1308
+ * @returns {JSX.Element} Select component
1399
1309
  */
1400
- const usePhoneInput = () => {
1401
- const getPhoneNumber = ({ country, phone }) => {
1402
- if (country) {
1403
- return getPhoneNumberWithPlus(`${country}${phone || ""}`);
1404
- }
1405
- return phone || "";
1406
- };
1407
- return {
1408
- getPhoneNumber,
1310
+ const Select = (props) => {
1311
+ const { className } = props, propsNoClassName = __rest(props, ["className"]);
1312
+ 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;
1313
+ const { refContainer, refPrefix, customStyles, menuIsOpen, customComponents, menuPlacement, openMenuHandler, closeMenuHandler, orderedOptions, } = useSelect(props);
1314
+ const selectProps = {
1315
+ value,
1316
+ menuPlacement,
1317
+ maxMenuHeight,
1318
+ onChange,
1319
+ "aria-label": label,
1320
+ "data-testid": dataTestId,
1321
+ components: customComponents,
1322
+ styles: customStyles,
1323
+ tabSelectsValue: false,
1324
+ blurInputOnSelect: !isMulti,
1325
+ menuPortalTarget: props.menuPortalTarget || document.body,
1326
+ isSearchable: disabled || readOnly ? false : isSearchable,
1327
+ menuShouldBlockScroll: true,
1328
+ menuShouldScrollIntoView: true,
1329
+ openMenuOnFocus,
1330
+ menuIsOpen: !readOnly ? menuIsOpen : false,
1331
+ openMenuOnClick,
1332
+ closeMenuOnSelect: false,
1333
+ isMulti,
1334
+ classNamePrefix,
1335
+ isLoading,
1336
+ isClearable,
1337
+ id,
1338
+ onMenuScrollToBottom,
1339
+ onInputChange,
1409
1340
  };
1341
+ 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 })))] }));
1410
1342
  };
1343
+ Select.displayName = "Select";
1411
1344
 
1412
1345
  const COUNTRY_CODES_NOT_SUPPORTED_BY_BACKEND = ["+53", "+98", "+211", "+247", "+249", "+383", "+850", "+963"];
1413
1346
  const ADDITIONAL_COUNTRY_CODES_SUPPORTED_BY_BACKEND = [
@@ -2030,6 +1963,71 @@ const Search = React.forwardRef((_a, ref) => {
2030
1963
  }, children: jsxRuntime.jsx(reactComponents.Icon, { name: "XMark", size: "small" }) })) : undefined, value: value })));
2031
1964
  });
2032
1965
 
1966
+ const FormFieldSelectAdapter = React.forwardRef((_a, ref) => {
1967
+ 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"]);
1968
+ const [innerValue, setInnerValue] = React.useState(value || defaultValue);
1969
+ const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
1970
+ const htmlFor = React.useMemo(() => (id ? id : "selectField-" + uuid.v4()), [id]);
1971
+ const innerRef = React.useRef(null);
1972
+ React.useImperativeHandle(ref, () => innerRef.current, []);
1973
+ const handleChange = React.useCallback((newValue) => {
1974
+ setInnerValue(newValue === null || newValue === void 0 ? void 0 : newValue.value);
1975
+ }, []);
1976
+ React.useEffect(() => {
1977
+ var _a;
1978
+ if (!innerValue) {
1979
+ return;
1980
+ }
1981
+ const event = new Event("change");
1982
+ (_a = innerRef.current) === null || _a === void 0 ? void 0 : _a.dispatchEvent(event);
1983
+ onChange === null || onChange === void 0 ? void 0 : onChange(event);
1984
+ }, [onChange, innerValue]);
1985
+ const selectedOption = options.find(option => { var _a; return option.value === ((_a = innerRef === null || innerRef === void 0 ? void 0 : innerRef.current) === null || _a === void 0 ? void 0 : _a.value); });
1986
+ const defaultSelectedOption = options.find(option => option.value === defaultValue);
1987
+ return (jsxRuntime.jsxs(FormGroup, { isInvalid: renderAsInvalid,
1988
+ htmlFor,
1989
+ className,
1990
+ dataTestId,
1991
+ helpText,
1992
+ helpAddon,
1993
+ tip,
1994
+ label,
1995
+ disabled, children: [jsxRuntime.jsx("select", { onChange, ref: innerRef, name, value: innerValue, hidden: true, children: options.map(option => {
1996
+ return (jsxRuntime.jsx("option", { value: option.value, children: option.label }, option.value));
1997
+ }) }), children(Object.assign({ id, isDisabled: disabled, onBlur,
1998
+ options, onChange: handleChange, value: selectedOption, defaultValue: defaultSelectedOption }, rest))] }));
1999
+ });
2000
+
2001
+ /**
2002
+ * The CreatableSelectField component is a CreatableSelect component wrapped in the FromGroup component.
2003
+ *
2004
+ * This means that it can easily be added to any form alongside other Field components.
2005
+ *
2006
+ * This is done to make the field compatible with the React-hook-form library.
2007
+ *
2008
+ * @param {SelectFieldProps & CreatableSelectProps} props - The props for the CreatableSelectField component
2009
+ * @returns {JSX.Element} CreatableSelectField component
2010
+ */
2011
+ const CreatableSelectField = (_a) => {
2012
+ var { allowCreateWhileLoading, onCreateOption } = _a, props = __rest(_a, ["allowCreateWhileLoading", "onCreateOption"]);
2013
+ const creatableSelectOnlyProps = { allowCreateWhileLoading, onCreateOption };
2014
+ return (jsxRuntime.jsx(FormFieldSelectAdapter, Object.assign({}, props, { children: convertedProps => jsxRuntime.jsx(CreatableSelect, Object.assign({}, convertedProps, creatableSelectOnlyProps)) })));
2015
+ };
2016
+
2017
+ /**
2018
+ * The SelectField component is a Select component wrapped in the FromGroup component.
2019
+ *
2020
+ * This means that it can easily be added to any form alongside other Field components.
2021
+ *
2022
+ * This is done to make the field compatible with the React-hook-form library.
2023
+ *
2024
+ * @param {SelectFieldProps} props - The props for the SelectField component
2025
+ * @returns {JSX.Element} SelectField component
2026
+ */
2027
+ const SelectField = (props) => {
2028
+ return jsxRuntime.jsx(FormFieldSelectAdapter, Object.assign({}, props, { children: convertedProps => jsxRuntime.jsx(Select, Object.assign({}, convertedProps)) }));
2029
+ };
2030
+
2033
2031
  const cvaTextArea = cssClassVarianceUtilities.cvaMerge([
2034
2032
  cvaInputBase(),
2035
2033
  "block",
@@ -2309,6 +2307,7 @@ exports.ActionButton = ActionButton;
2309
2307
  exports.BaseInput = BaseInput;
2310
2308
  exports.Checkbox = Checkbox;
2311
2309
  exports.CreatableSelect = CreatableSelect;
2310
+ exports.CreatableSelectField = CreatableSelectField;
2312
2311
  exports.DateField = DateField;
2313
2312
  exports.DateInput = DateInput;
2314
2313
  exports.DropZone = DropZone;