@trackunit/react-form-components 1.8.116 → 1.8.119
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 +92 -84
- package/index.esm.js +92 -84
- package/package.json +7 -7
- package/src/components/ActionButton/ActionButton.d.ts +1 -1
- package/src/components/BaseInput/BaseInput.d.ts +1 -1
- package/src/components/BaseInput/components/AddonRenderer.d.ts +1 -1
- package/src/components/BaseInput/components/LockReasonRenderer.d.ts +2 -2
- package/src/components/BaseInput/components/PrefixRenderer.d.ts +1 -1
- package/src/components/BaseInput/components/SuffixRenderer.d.ts +2 -2
- package/src/components/BaseSelect/SelectMenuItem/SelectMenuItem.d.ts +2 -2
- package/src/components/BaseSelect/useCustomComponents.d.ts +2 -2
- package/src/components/BaseSelect/useSelect.d.ts +1 -1
- package/src/components/Checkbox/CheckIcon.d.ts +1 -1
- package/src/components/Checkbox/Checkbox.d.ts +1 -1
- package/src/components/CheckboxField/CheckboxField.d.ts +1 -1
- package/src/components/DateField/DateField.d.ts +1 -1
- package/src/components/DropZone/DropZone.d.ts +1 -1
- package/src/components/EmailField/EmailBaseInput/EmailBaseInput.d.ts +1 -1
- package/src/components/EmailField/EmailField.d.ts +1 -1
- package/src/components/FormGroup/FormGroup.d.ts +1 -1
- package/src/components/Label/Label.d.ts +1 -1
- package/src/components/NumberField/NumberField.d.ts +1 -1
- package/src/components/OptionCard/OptionCard.d.ts +1 -1
- package/src/components/PasswordField/PasswordField.d.ts +1 -1
- package/src/components/PhoneField/PhoneBaseInput/CountryCodeSelect.d.ts +1 -1
- package/src/components/PhoneField/PhoneBaseInput/PhoneBaseInput.d.ts +1 -1
- package/src/components/PhoneField/PhoneField.d.ts +1 -1
- package/src/components/RadioGroup/RadioGroup.d.ts +1 -1
- package/src/components/RadioGroup/RadioItem.d.ts +1 -1
- package/src/components/Schedule/Schedule.d.ts +1 -1
- package/src/components/Search/Search.d.ts +1 -1
- package/src/components/SelectField/FormFieldSelectAdapter.d.ts +1 -1
- package/src/components/TextAreaField/TextArea/TextAreaBaseInput.d.ts +1 -1
- package/src/components/TextAreaField/TextAreaField.d.ts +1 -1
- package/src/components/TextField/TextField.d.ts +1 -1
- package/src/components/TimeRange/TimeRange.d.ts +1 -1
- package/src/components/TimeRangeField/TimeRangeField.d.ts +1 -1
- package/src/components/ToggleSwitchOption/ToggleSwitchOption.d.ts +1 -1
- package/src/components/UploadField/UploadField.d.ts +1 -1
- package/src/components/UrlField/UrlBaseInput/UrlBaseInput.d.ts +1 -1
- package/src/components/UrlField/UrlField.d.ts +1 -1
package/index.esm.js
CHANGED
|
@@ -274,7 +274,7 @@ const cvaInputSuffix = cvaMerge(["flex", "justify-center", "items-center", "text
|
|
|
274
274
|
/**
|
|
275
275
|
* Renders the addon element if provided
|
|
276
276
|
*/
|
|
277
|
-
const AddonRenderer = ({ addon, dataTestId, className, fieldSize, position }) => {
|
|
277
|
+
const AddonRenderer = ({ addon, "data-testid": dataTestId, className, fieldSize, position, }) => {
|
|
278
278
|
if (!addon) {
|
|
279
279
|
return null;
|
|
280
280
|
}
|
|
@@ -315,7 +315,7 @@ const cvaActionContainer = cvaMerge(["flex", "items-center"], {
|
|
|
315
315
|
* @param {ActionButtonProps} props - The props for the ActionButton component
|
|
316
316
|
* @returns {ReactElement} ActionButton component
|
|
317
317
|
*/
|
|
318
|
-
const ActionButton = ({ type, value, dataTestId, size, disabled, className, onClick }) => {
|
|
318
|
+
const ActionButton = ({ type, value, "data-testid": dataTestId, size, disabled, className, onClick, }) => {
|
|
319
319
|
const [, copyToClipboard] = useCopyToClipboard();
|
|
320
320
|
const getIconName = () => {
|
|
321
321
|
switch (type) {
|
|
@@ -354,7 +354,7 @@ const ActionButton = ({ type, value, dataTestId, size, disabled, className, onCl
|
|
|
354
354
|
}
|
|
355
355
|
};
|
|
356
356
|
const adjustedIconSize = size === "large" ? "medium" : size;
|
|
357
|
-
return (jsx("div", { className: cvaActionContainer({ className, size }), children: jsx(IconButton, { className: cvaActionButton({ size: adjustedIconSize }),
|
|
357
|
+
return (jsx("div", { className: cvaActionContainer({ className, size }), children: jsx(IconButton, { className: cvaActionButton({ size: adjustedIconSize }), "data-testid": dataTestId || "testIconButtonId", disabled: disabled, icon: jsx(Icon, { name: getIconName(), size: adjustedIconSize }), onClick: buttonAction, size: "small", variant: "secondary" }) }));
|
|
358
358
|
};
|
|
359
359
|
|
|
360
360
|
const GenericActionsRenderer = ({ genericAction, disabled, fieldSize, innerRef, tooltipLabel, }) => {
|
|
@@ -362,7 +362,7 @@ const GenericActionsRenderer = ({ genericAction, disabled, fieldSize, innerRef,
|
|
|
362
362
|
if (!genericAction) {
|
|
363
363
|
return null;
|
|
364
364
|
}
|
|
365
|
-
return (jsx(Tooltip, { label: tooltipLabel ?? t("baseInput.copyAction.toolTip"), placement: "top", children: jsx(ActionButton, {
|
|
365
|
+
return (jsx(Tooltip, { label: tooltipLabel ?? t("baseInput.copyAction.toolTip"), placement: "top", children: jsx(ActionButton, { "data-testid": "copy-value-button", disabled: disabled, size: fieldSize ?? undefined, type: genericAction === "edit" ? "EDIT" : "COPY", value: innerRef }) }));
|
|
366
366
|
};
|
|
367
367
|
|
|
368
368
|
/**
|
|
@@ -382,7 +382,7 @@ const InputLockReasonTooltip = ({ reasons, kind }) => {
|
|
|
382
382
|
};
|
|
383
383
|
|
|
384
384
|
// Renders a tooltip for lock reasons if the prop is an object
|
|
385
|
-
const LockReasonRenderer = ({ lockReason, dataTestId, }) => {
|
|
385
|
+
const LockReasonRenderer = ({ lockReason, "data-testid": dataTestId, }) => {
|
|
386
386
|
// Only render if lockReason is an object
|
|
387
387
|
if (typeof lockReason !== "object") {
|
|
388
388
|
return null;
|
|
@@ -391,7 +391,7 @@ const LockReasonRenderer = ({ lockReason, dataTestId, }) => {
|
|
|
391
391
|
};
|
|
392
392
|
|
|
393
393
|
// Renders the prefix element or falls back to a default prefix for certain types
|
|
394
|
-
const PrefixRenderer = forwardRef(({ prefix, type, dataTestId, disabled }, ref) => {
|
|
394
|
+
const PrefixRenderer = forwardRef(({ prefix, type, "data-testid": dataTestId, disabled }, ref) => {
|
|
395
395
|
// Default icons for specific input types
|
|
396
396
|
const defaultPrefixMap = {
|
|
397
397
|
email: jsx(Icon, { name: "AtSymbol", size: "small" }),
|
|
@@ -407,7 +407,7 @@ const PrefixRenderer = forwardRef(({ prefix, type, dataTestId, disabled }, ref)
|
|
|
407
407
|
});
|
|
408
408
|
|
|
409
409
|
// Renders the suffix element or shows an icon if invalid/warning
|
|
410
|
-
const SuffixRenderer = ({ suffix, isInvalid, isWarning, dataTestId, disabled, }) => {
|
|
410
|
+
const SuffixRenderer = ({ suffix, isInvalid, isWarning, "data-testid": dataTestId, disabled, }) => {
|
|
411
411
|
// If user provided suffix that's not identical to addonBefore, render it
|
|
412
412
|
if (suffix) {
|
|
413
413
|
return (jsx("div", { className: cvaInputSuffix({
|
|
@@ -433,7 +433,7 @@ const SuffixRenderer = ({ suffix, isInvalid, isWarning, dataTestId, disabled, })
|
|
|
433
433
|
* For specific input types make sure to use the corresponding input component.
|
|
434
434
|
* This is a base used by our other input components such as TextBaseInput, NumberBaseInput, PasswordBaseInput, etc.
|
|
435
435
|
*/
|
|
436
|
-
const BaseInput = ({ className, isInvalid = false, dataTestId, prefix, suffix, addonBefore, addonAfter, actions, fieldSize = "medium", nonInteractive = false, inputClassName, placeholder, isWarning = false, type, genericAction, style, ref, required = false, ...rest }) => {
|
|
436
|
+
const BaseInput = ({ className, isInvalid = false, "data-testid": dataTestId, prefix, suffix, addonBefore, addonAfter, actions, fieldSize = "medium", nonInteractive = false, inputClassName, placeholder, isWarning = false, type, genericAction, style, ref, required = false, ...rest }) => {
|
|
437
437
|
// Derive final flags
|
|
438
438
|
const renderAsDisabled = Boolean(rest.disabled);
|
|
439
439
|
const renderAsReadonly = Boolean(rest.readOnly);
|
|
@@ -472,13 +472,13 @@ const BaseInput = ({ className, isInvalid = false, dataTestId, prefix, suffix, a
|
|
|
472
472
|
isWarning,
|
|
473
473
|
size: fieldSize,
|
|
474
474
|
className,
|
|
475
|
-
}), "data-testid": dataTestId ? `${dataTestId}-container` : undefined, style: style, children: [jsxs("div", { className: cvaAccessoriesContainer({ className: cvaInputItemPlacementManager({ position: "before" }) }), "data-testid": dataTestId ? `${dataTestId}-before-container` : undefined, ref: beforeContainerRef, children: [jsx(AddonRenderer, { addon: addonBefore,
|
|
475
|
+
}), "data-testid": dataTestId ? `${dataTestId}-container` : undefined, style: style, children: [jsxs("div", { className: cvaAccessoriesContainer({ className: cvaInputItemPlacementManager({ position: "before" }) }), "data-testid": dataTestId ? `${dataTestId}-before-container` : undefined, ref: beforeContainerRef, children: [jsx(AddonRenderer, { addon: addonBefore, "data-testid": dataTestId, fieldSize: fieldSize, position: "before" }), jsx(PrefixRenderer, { "data-testid": dataTestId, disabled: renderAsDisabled, prefix: prefix, type: type })] }), jsx("input", { "aria-required": required, className: cvaInputElement({
|
|
476
476
|
size: fieldSize,
|
|
477
477
|
className: cvaInputItemPlacementManager({ position: "span", className: inputClassName }),
|
|
478
478
|
}), "data-testid": dataTestId, placeholder: renderAsDisabled ? undefined : placeholder, ref: innerRef, required: required, style: {
|
|
479
479
|
paddingLeft: `calc(var(--before-width, 0px) + ${themeSpacing[2]})`,
|
|
480
480
|
paddingRight: `calc(var(--after-width, 0px) + ${themeSpacing[2]})`,
|
|
481
|
-
}, type: type, ...rest, disabled: renderAsDisabled, readOnly: renderAsReadonly || nonInteractive }), jsxs("div", { className: cvaAccessoriesContainer({ className: cvaInputItemPlacementManager({ position: "after" }) }), "data-testid": dataTestId ? `${dataTestId}-after-container` : undefined, ref: afterContainerRef, children: [jsx(LockReasonRenderer, {
|
|
481
|
+
}, type: type, ...rest, disabled: renderAsDisabled, readOnly: renderAsReadonly || nonInteractive }), jsxs("div", { className: cvaAccessoriesContainer({ className: cvaInputItemPlacementManager({ position: "after" }) }), "data-testid": dataTestId ? `${dataTestId}-after-container` : undefined, ref: afterContainerRef, children: [jsx(LockReasonRenderer, { "data-testid": dataTestId + "-disabled", lockReason: rest.disabled }), jsx(LockReasonRenderer, { "data-testid": dataTestId + "-readonly", lockReason: Boolean(rest.readOnly) && !Boolean(rest.disabled) ? rest.readOnly : undefined }), jsx(GenericActionsRenderer, { fieldSize: fieldSize, genericAction: genericAction, innerRef: innerRef }), jsx(SuffixRenderer, { "data-testid": dataTestId, disabled: renderAsDisabled, isInvalid: isInvalid, isWarning: isWarning, suffix: suffix }), actions, jsx(AddonRenderer, { addon: addonAfter, "data-testid": dataTestId, fieldSize: fieldSize, position: "after" })] })] }));
|
|
482
482
|
};
|
|
483
483
|
BaseInput.displayName = "BaseInput";
|
|
484
484
|
|
|
@@ -501,7 +501,7 @@ const DateBaseInput = ({ min, max, defaultValue, value, ref, ...rest }) => {
|
|
|
501
501
|
: date;
|
|
502
502
|
// Chrome and Firefox need their default icon to have datepicker functionality.
|
|
503
503
|
const showIcon = !/Chrome/.test(navigator.userAgent) && !/Firefox/.test(navigator.userAgent);
|
|
504
|
-
return (jsx(BaseInput, { defaultValue: formatDateToInputString(defaultValue), max: formatDateToInputString(max), min: formatDateToInputString(min), ref: ref, suffix: showIcon ? jsx(Icon, {
|
|
504
|
+
return (jsx(BaseInput, { defaultValue: formatDateToInputString(defaultValue), max: formatDateToInputString(max), min: formatDateToInputString(min), ref: ref, suffix: showIcon ? jsx(Icon, { "data-testid": "calendar", name: "Calendar", size: "medium", type: "solid" }) : null, type: "date", value: formatDateToInputString(value), ...rest }));
|
|
505
505
|
};
|
|
506
506
|
|
|
507
507
|
/**
|
|
@@ -609,7 +609,7 @@ const DEFAULT_COUNTRY_CODE = undefined;
|
|
|
609
609
|
* @param {string} [fieldSize="medium"] - The size of the input field.
|
|
610
610
|
* @param {boolean} [disableAction=false] - Whether the action button is disabled or not.
|
|
611
611
|
*/
|
|
612
|
-
const PhoneBaseInput = ({ dataTestId, isInvalid, disabled = false, value, defaultValue, fieldSize = "medium", disableAction = false, onChange, readOnly, onFocus, onBlur, name, ref, ...rest }) => {
|
|
612
|
+
const PhoneBaseInput = ({ "data-testid": dataTestId, isInvalid, disabled = false, value, defaultValue, fieldSize = "medium", disableAction = false, onChange, readOnly, onFocus, onBlur, name, ref, ...rest }) => {
|
|
613
613
|
const [innerValue, setInnerValue] = useState(() => {
|
|
614
614
|
return (value?.toString() || defaultValue?.toString()) ?? "";
|
|
615
615
|
});
|
|
@@ -651,7 +651,7 @@ const PhoneBaseInput = ({ dataTestId, isInvalid, disabled = false, value, defaul
|
|
|
651
651
|
onFocus?.(event);
|
|
652
652
|
fieldIsFocused.current = true;
|
|
653
653
|
}, [onFocus]);
|
|
654
|
-
return (jsx("div", { className: "grid grid-cols-1 gap-2", "data-testid": dataTestId ? `${dataTestId}-container` : null, children: jsx(BaseInput, { actions: !disableAction && innerValue && innerValue.length > 0 ? (jsx(ActionButton, {
|
|
654
|
+
return (jsx("div", { className: "grid grid-cols-1 gap-2", "data-testid": dataTestId ? `${dataTestId}-container` : null, children: jsx(BaseInput, { actions: !disableAction && innerValue && innerValue.length > 0 ? (jsx(ActionButton, { "data-testid": dataTestId ? `${dataTestId}-phoneIcon` : undefined, disabled: isInvalid, size: fieldSize ?? undefined, type: "PHONE_NUMBER", value: value?.toString() || "" })) : null, "data-testid": dataTestId ? `${dataTestId}-phoneNumberInput` : undefined, disabled: disabled, fieldSize: fieldSize, id: "phoneInput-number", isInvalid: isInvalid, name: name, onBlur: handleBlur, onChange: handleChange, onFocus: handleFocus, prefix: (countryCode && countryCodeToFlagEmoji(countryCode)) || undefined, readOnly: readOnly, ref: ref, type: "tel", value: innerValue, ...rest }) }));
|
|
655
655
|
};
|
|
656
656
|
|
|
657
657
|
const cvaTextAreaBaseInput = cvaMerge([
|
|
@@ -690,7 +690,7 @@ const cvaTextAreaBaseInput = cvaMerge([
|
|
|
690
690
|
* The TextArea is a base component, and should not be used very often.
|
|
691
691
|
* For most cases the TextAreaField is the correct component.
|
|
692
692
|
*/
|
|
693
|
-
const TextAreaBaseInput = ({ id, name, value, rows, disabled, placeholder, readOnly, tabIndex, onChange, onFocus, onBlur, maxLength, resize = "vertical", defaultValue, required, dataTestId, isInvalid, className, ref, ...rest }) => {
|
|
693
|
+
const TextAreaBaseInput = ({ id, name, value, rows, disabled, placeholder, readOnly, tabIndex, onChange, onFocus, onBlur, maxLength, resize = "vertical", defaultValue, required, "data-testid": dataTestId, isInvalid, className, ref, ...rest }) => {
|
|
694
694
|
return (jsx("textarea", { className: cvaTextAreaBaseInput({ className, resize, invalid: isInvalid, disabled }), defaultValue: defaultValue, disabled: disabled, id: id, maxLength: maxLength, name: name, onBlur: onBlur, onFocus: onFocus, placeholder: placeholder, readOnly: readOnly, ref: ref, required: required, rows: rows, tabIndex: tabIndex, value: value, ...rest, "data-testid": dataTestId, onChange: onChange }));
|
|
695
695
|
};
|
|
696
696
|
|
|
@@ -865,7 +865,7 @@ const cvaLabel = cvaMerge([
|
|
|
865
865
|
* @param {CheckIconProps} props - The props for the CheckIcon component
|
|
866
866
|
* @returns {ReactElement} CheckIcon component
|
|
867
867
|
*/
|
|
868
|
-
const CheckIcon = ({ className, dataTestId }) => {
|
|
868
|
+
const CheckIcon = ({ className, "data-testid": dataTestId }) => {
|
|
869
869
|
return (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: jsx("path", { d: "m2 5.5 2 2L8.5 3", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
870
870
|
};
|
|
871
871
|
|
|
@@ -990,7 +990,7 @@ const IndeterminateIcon = ({ className }) => (jsx("svg", { className: className,
|
|
|
990
990
|
* @augments props from [React.InputHTMLAttributes](https://reactjs.org/docs/dom-elements.html#input)
|
|
991
991
|
* @param {CheckboxProps} props - The props for the Checkbox component
|
|
992
992
|
*/
|
|
993
|
-
const Checkbox = ({ className, dataTestId = "checkbox", onChange, checked = false, disabled = false, isInvalid = false, readOnly, indeterminate = false, suffix, label, tabIndex = 0, stopPropagation, ref, ...rest }) => {
|
|
993
|
+
const Checkbox = ({ className, "data-testid": dataTestId = "checkbox", onChange, checked = false, disabled = false, isInvalid = false, readOnly, indeterminate = false, suffix, label, tabIndex = 0, stopPropagation, ref, ...rest }) => {
|
|
994
994
|
const icon = indeterminate ? (jsx(IndeterminateIcon, { className: cvaCheckboxIcon() })) : (checked && jsx(CheckIcon, { className: cvaCheckboxIcon() }));
|
|
995
995
|
const internalRef = useRef(null);
|
|
996
996
|
const { isTextTruncated: isLabelCutOff, ref: labelRef } = useIsTextTruncated();
|
|
@@ -1029,8 +1029,8 @@ Checkbox.displayName = "Checkbox";
|
|
|
1029
1029
|
* @param {SelectMenuItemProps} props - The props for the SingleSelectMenuItem
|
|
1030
1030
|
* @returns {ReactElement} SingleSelectMenuItem
|
|
1031
1031
|
*/
|
|
1032
|
-
const SingleSelectMenuItem = ({ label, icon, onClick, selected, focused, dataTestId, disabled, optionLabelDescription, optionPrefix, fieldSize, }) => {
|
|
1033
|
-
return (jsx(MenuItem, {
|
|
1032
|
+
const SingleSelectMenuItem = ({ label, icon, onClick, selected, focused, "data-testid": dataTestId, disabled, optionLabelDescription, optionPrefix, fieldSize, }) => {
|
|
1033
|
+
return (jsx(MenuItem, { "data-testid": dataTestId, disabled: disabled, fieldSize: fieldSize, focused: focused, label: label, onClick: onClick, optionLabelDescription: optionLabelDescription, optionPrefix: isValidElement(optionPrefix)
|
|
1034
1034
|
? cloneElement(optionPrefix, {
|
|
1035
1035
|
className: "mr-1 flex items-center",
|
|
1036
1036
|
size: "medium",
|
|
@@ -1043,8 +1043,8 @@ const SingleSelectMenuItem = ({ label, icon, onClick, selected, focused, dataTes
|
|
|
1043
1043
|
* @param {SelectMenuItemProps} props - The props for the MultiSelectMenuItem
|
|
1044
1044
|
* @returns {ReactElement} multi select menu item
|
|
1045
1045
|
*/
|
|
1046
|
-
const MultiSelectMenuItem = ({ label, onClick, selected, focused, dataTestId, disabled, optionLabelDescription, optionPrefix, fieldSize, }) => {
|
|
1047
|
-
return (jsx(MenuItem, {
|
|
1046
|
+
const MultiSelectMenuItem = ({ label, onClick, selected, focused, "data-testid": dataTestId, disabled, optionLabelDescription, optionPrefix, fieldSize, }) => {
|
|
1047
|
+
return (jsx(MenuItem, { "data-testid": dataTestId, disabled: disabled, fieldSize: fieldSize, focused: focused, label: label, onClick: e => {
|
|
1048
1048
|
e.stopPropagation();
|
|
1049
1049
|
onClick && onClick(e);
|
|
1050
1050
|
}, optionLabelDescription: optionLabelDescription, optionPrefix: isValidElement(optionPrefix)
|
|
@@ -1131,7 +1131,7 @@ const TagsContainer = ({ items, width = "100%", itemsGap = 6, postFix, preFix, d
|
|
|
1131
1131
|
...acc,
|
|
1132
1132
|
elements: [
|
|
1133
1133
|
...acc.elements,
|
|
1134
|
-
jsx(TagWithWidth, { className: "inline-flex shrink-0", color: item.disabled ? "neutral" : "white",
|
|
1134
|
+
jsx(TagWithWidth, { className: "inline-flex shrink-0", color: item.disabled ? "neutral" : "white", "data-testid": `${item.text}-tag`, disabled: disabled, icon: item.Icon, onClose: e => {
|
|
1135
1135
|
e.stopPropagation();
|
|
1136
1136
|
item.onClick();
|
|
1137
1137
|
}, onWidthKnown: onWidthKnownHandler, children: item.text }, item.text + index),
|
|
@@ -1165,7 +1165,7 @@ const TagsContainer = ({ items, width = "100%", itemsGap = 6, postFix, preFix, d
|
|
|
1165
1165
|
* @param {ReactNode} prefix a prefix element
|
|
1166
1166
|
* @returns {Partial<SelectComponents<Option, boolean, GroupBase<Option>>> | undefined} components object to override react-select default components
|
|
1167
1167
|
*/
|
|
1168
|
-
const useCustomComponents = ({ componentsProps, disabled, readOnly, setMenuIsEnabled, dataTestId, maxSelectedDisplayCount, prefix, hasError, fieldSize, getOptionLabelDescription, getOptionPrefix, }) => {
|
|
1168
|
+
const useCustomComponents = ({ componentsProps, disabled, readOnly, setMenuIsEnabled, "data-testid": dataTestId, maxSelectedDisplayCount, prefix, hasError, fieldSize, getOptionLabelDescription, getOptionPrefix, }) => {
|
|
1169
1169
|
const [t] = useTranslation();
|
|
1170
1170
|
// perhaps it should not be wrap in memo (causing some issues with opening and closing on mobiles)
|
|
1171
1171
|
const customComponents = useMemo(() => {
|
|
@@ -1200,13 +1200,13 @@ const useCustomComponents = ({ componentsProps, disabled, readOnly, setMenuIsEna
|
|
|
1200
1200
|
})
|
|
1201
1201
|
: [], postFix: searchInput, preFix: placeholderElement ? jsx("span", { className: "absolute", children: placeholderElement }) : null, width: "100%" })) : (jsxs(Fragment, { children: [tags
|
|
1202
1202
|
? tags.slice(0, maxSelectedDisplayCount).map(({ props: tagProps }) => {
|
|
1203
|
-
return (jsx(Tag, { className: "inline-flex shrink-0", color: disabled ? "unknown" : "primary",
|
|
1203
|
+
return (jsx(Tag, { className: "inline-flex shrink-0", color: disabled ? "unknown" : "primary", "data-testid": tagProps.children ? `${tagProps.children.toString()}-tag` : undefined, onClose: e => {
|
|
1204
1204
|
e.stopPropagation();
|
|
1205
1205
|
setMenuIsEnabled(false);
|
|
1206
1206
|
tagProps.removeProps.onClick && tagProps.removeProps.onClick(e);
|
|
1207
1207
|
}, children: tagProps.children }, tagProps.children?.toString()));
|
|
1208
1208
|
})
|
|
1209
|
-
: null, tags && tags.length > maxSelectedDisplayCount ? (jsxs(Tag, { color: "neutral",
|
|
1209
|
+
: null, tags && tags.length > maxSelectedDisplayCount ? (jsxs(Tag, { color: "neutral", "data-testid": "counter-tag", children: ["+", tags.length - maxSelectedDisplayCount] })) : null, searchInput, placeholderElement] })) }));
|
|
1210
1210
|
}
|
|
1211
1211
|
return (jsx(Fragment, { children: jsx(components.ValueContainer, { ...props, isDisabled: props.selectProps.isDisabled, children: props.children }) }));
|
|
1212
1212
|
},
|
|
@@ -1271,7 +1271,7 @@ const useCustomComponents = ({ componentsProps, disabled, readOnly, setMenuIsEna
|
|
|
1271
1271
|
...props.innerProps,
|
|
1272
1272
|
role: "option",
|
|
1273
1273
|
onClick: () => { },
|
|
1274
|
-
}, children: props.isMulti ? (jsx(MultiSelectMenuItem, { ...componentProps,
|
|
1274
|
+
}, children: props.isMulti ? (jsx(MultiSelectMenuItem, { ...componentProps, "data-testid": typeof props.label === "string" ? props.label : undefined, disabled: disabled, fieldSize: fieldSize, optionLabelDescription: getOptionLabelDescription?.(props.data), optionPrefix: getOptionPrefix?.(props.data) })) : (jsx(SingleSelectMenuItem, { ...componentProps, "data-testid": typeof props.label === "string" ? props.label : undefined, disabled: disabled || props.isDisabled, fieldSize: fieldSize, optionLabelDescription: getOptionLabelDescription?.(props.data), optionPrefix: getOptionPrefix?.(props.data) })) }));
|
|
1275
1275
|
},
|
|
1276
1276
|
...componentsProps,
|
|
1277
1277
|
};
|
|
@@ -1400,7 +1400,7 @@ const useCustomStyles = ({ refContainer, maxSelectedDisplayCount, styles, disabl
|
|
|
1400
1400
|
* @param {SelectProps} props - The props for the Select component
|
|
1401
1401
|
* @returns {UseSelectProps} Select component
|
|
1402
1402
|
*/
|
|
1403
|
-
const useSelect = ({ id, className, dataTestId = "select", prefix, async, maxMenuHeight = 200, label, hasError, disabled, isMulti, components, value, options, onChange, isLoading, classNamePrefix = "", onMenuOpen, onMenuClose, maxSelectedDisplayCount = undefined, isClearable = false, isSearchable = true, onMenuScrollToBottom, styles, filterOption, onInputChange, getOptionLabelDescription, getOptionPrefix, fieldSize = "medium", ...props }) => {
|
|
1403
|
+
const useSelect = ({ id, className, "data-testid": dataTestId = "select", prefix, async, maxMenuHeight = 200, label, hasError, disabled, isMulti, components, value, options, onChange, isLoading, classNamePrefix = "", onMenuOpen, onMenuClose, maxSelectedDisplayCount = undefined, isClearable = false, isSearchable = true, onMenuScrollToBottom, styles, filterOption, onInputChange, getOptionLabelDescription, getOptionPrefix, fieldSize = "medium", ...props }) => {
|
|
1404
1404
|
const refContainer = useRef(document.createElement("div"));
|
|
1405
1405
|
const { customStyles } = useCustomStyles({
|
|
1406
1406
|
refContainer,
|
|
@@ -1416,7 +1416,7 @@ const useSelect = ({ id, className, dataTestId = "select", prefix, async, maxMen
|
|
|
1416
1416
|
disabled: Boolean(disabled),
|
|
1417
1417
|
readOnly: Boolean(props.readOnly),
|
|
1418
1418
|
setMenuIsEnabled,
|
|
1419
|
-
dataTestId,
|
|
1419
|
+
"data-testid": dataTestId,
|
|
1420
1420
|
maxSelectedDisplayCount,
|
|
1421
1421
|
prefix,
|
|
1422
1422
|
hasError,
|
|
@@ -1458,7 +1458,7 @@ const ReactSyncSelect = ReactSelect.default || ReactSelect;
|
|
|
1458
1458
|
* @returns {ReactElement} Select component
|
|
1459
1459
|
*/
|
|
1460
1460
|
const BaseSelect = (props) => {
|
|
1461
|
-
const { id, dataTestId = "select", prefix, async, maxMenuHeight = 200, label, hasError, disabled, isMulti, menuPosition = "absolute", value, options, onChange, isLoading, classNamePrefix = "select", onMenuScrollToBottom, onInputChange, isSearchable, isClearable = false, readOnly, fieldSize = "medium", openMenuOnClick = !disabled, openMenuOnFocus = false, hideSelectedOptions = false, } = props;
|
|
1461
|
+
const { id, "data-testid": dataTestId = "select", prefix, async, maxMenuHeight = 200, label, hasError, disabled, isMulti, menuPosition = "absolute", value, options, onChange, isLoading, classNamePrefix = "select", onMenuScrollToBottom, onInputChange, isSearchable, isClearable = false, readOnly, fieldSize = "medium", openMenuOnClick = !disabled, openMenuOnFocus = false, hideSelectedOptions = false, } = props;
|
|
1462
1462
|
const { refContainer, customStyles, menuIsOpen, customComponents, menuPlacement, openMenuHandler, closeMenuHandler } = useSelect(props);
|
|
1463
1463
|
const reactSelectProps = useMemo(() => ({
|
|
1464
1464
|
value,
|
|
@@ -1533,7 +1533,7 @@ BaseSelect.displayName = "BaseSelect";
|
|
|
1533
1533
|
* @returns {ReactElement} CreatableSelect component
|
|
1534
1534
|
*/
|
|
1535
1535
|
const CreatableSelect = (props) => {
|
|
1536
|
-
const { id, dataTestId = "creatableSelect", prefix, async, maxMenuHeight = 200, label, hasError, disabled, isMulti, value, options, onChange, isLoading, classNamePrefix = "creatableSelect", onMenuScrollToBottom, onInputChange, isSearchable, isClearable = false, readOnly, openMenuOnClick = !disabled, openMenuOnFocus = !disabled, allowCreateWhileLoading, onCreateOption, } = props;
|
|
1536
|
+
const { id, "data-testid": dataTestId = "creatableSelect", prefix, async, maxMenuHeight = 200, label, hasError, disabled, isMulti, value, options, onChange, isLoading, classNamePrefix = "creatableSelect", onMenuScrollToBottom, onInputChange, isSearchable, isClearable = false, readOnly, openMenuOnClick = !disabled, openMenuOnFocus = !disabled, allowCreateWhileLoading, onCreateOption, } = props;
|
|
1537
1537
|
const { refContainer, customStyles, menuIsOpen, customComponents, menuPlacement, openMenuHandler, closeMenuHandler } = useSelect(props);
|
|
1538
1538
|
const reactCreatableSelectProps = useMemo(() => ({
|
|
1539
1539
|
value,
|
|
@@ -1602,7 +1602,7 @@ CreatableSelect.displayName = "CreatableSelect";
|
|
|
1602
1602
|
* @param {LabelProps} props - The props for the Label component
|
|
1603
1603
|
* @returns {ReactElement} Label component
|
|
1604
1604
|
*/
|
|
1605
|
-
const Label = ({ id, htmlFor, children, className, dataTestId, disabled, isInvalid, }) => {
|
|
1605
|
+
const Label = ({ id, htmlFor, children, className, "data-testid": dataTestId, disabled, isInvalid, }) => {
|
|
1606
1606
|
return (jsx("label", { className: cvaLabel({ invalid: isInvalid, disabled, className }), "data-testid": dataTestId, htmlFor: htmlFor || "", id: id || "", children: children }));
|
|
1607
1607
|
};
|
|
1608
1608
|
|
|
@@ -1636,13 +1636,13 @@ const cvaHelpAddon = cvaMerge(["ml-auto"]);
|
|
|
1636
1636
|
* @param {FormGroupProps} props - The props for the FormGroup component
|
|
1637
1637
|
* @returns {ReactElement} FormGroup component
|
|
1638
1638
|
*/
|
|
1639
|
-
const FormGroup = ({ isInvalid, isWarning, helpText, helpAddon, tip, className, dataTestId, label, htmlFor, children, required = false, }) => {
|
|
1639
|
+
const FormGroup = ({ isInvalid, isWarning, helpText, helpAddon, tip, className, "data-testid": dataTestId, label, htmlFor, children, required = false, }) => {
|
|
1640
1640
|
const [t] = useTranslation();
|
|
1641
1641
|
const validationStateIcon = useMemo(() => {
|
|
1642
1642
|
const color = isInvalid ? "danger" : isWarning ? "warning" : null;
|
|
1643
1643
|
return color ? jsx(Icon, { color: color, name: "ExclamationTriangle", size: "small" }) : null;
|
|
1644
1644
|
}, [isInvalid, isWarning]);
|
|
1645
|
-
return (jsxs("div", { className: cvaFormGroup({ className }), "data-testid": dataTestId, children: [label ? (jsxs("div", { className: cvaFormGroupContainerBefore(), children: [jsxs(Fragment, { children: [jsx(Label, { className: "component-formGroup-font",
|
|
1645
|
+
return (jsxs("div", { className: cvaFormGroup({ className }), "data-testid": dataTestId, children: [label ? (jsxs("div", { className: cvaFormGroupContainerBefore(), children: [jsxs(Fragment, { children: [jsx(Label, { className: "component-formGroup-font", "data-testid": dataTestId ? `${dataTestId}-label` : undefined, htmlFor: htmlFor, id: htmlFor + "-label", children: label }), required ? (jsx(Tooltip, { "data-testid": "required-asterisk", label: t("field.required.asterisk.tooltip"), children: "*" })) : null] }), tip ? (jsx(Tooltip, { className: "ml-1", "data-testid": dataTestId ? `${dataTestId}-tooltip` : undefined, label: tip, placement: "bottom" })) : null] })) : null, children, helpText || helpAddon ? (jsxs("div", { className: cvaFormGroupContainerAfter({ invalid: isInvalid, isWarning: isWarning }), children: [helpText ? (jsxs("div", { className: "flex gap-1", children: [validationStateIcon, jsx("span", { "data-testid": dataTestId ? `${dataTestId}-helpText` : undefined, children: helpText })] })) : undefined, helpAddon ? (jsx("span", { className: cvaHelpAddon(), "data-testid": dataTestId ? `${dataTestId}-helpAddon` : null, children: helpAddon })) : null] })) : null] }));
|
|
1646
1646
|
};
|
|
1647
1647
|
|
|
1648
1648
|
/**
|
|
@@ -1650,9 +1650,9 @@ const FormGroup = ({ isInvalid, isWarning, helpText, helpAddon, tip, className,
|
|
|
1650
1650
|
*
|
|
1651
1651
|
* _**Do use**_ the CheckboxField for boolean input.
|
|
1652
1652
|
*/
|
|
1653
|
-
const CheckboxField = ({ label, id, tip, helpText, helpAddon, isInvalid, className, checked, dataTestId, checkboxLabel, onChange, ref, ...rest }) => {
|
|
1653
|
+
const CheckboxField = ({ label, id, tip, helpText, helpAddon, isInvalid, className, checked, "data-testid": dataTestId, checkboxLabel, onChange, ref, ...rest }) => {
|
|
1654
1654
|
const htmlForId = id ? id : "checkboxField-" + uuidv4();
|
|
1655
|
-
return (jsx(FormGroup, { className: "flex flex-col gap-1",
|
|
1655
|
+
return (jsx(FormGroup, { className: "flex flex-col gap-1", "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: helpText, htmlFor: htmlForId, label: label, required: rest.required ? !(rest.disabled || rest.readOnly) : false, tip: tip, children: jsx(Checkbox, { checked: checked, className: className, "data-testid": dataTestId, id: htmlForId, label: checkboxLabel, onChange: onChange, ref: ref, ...rest }) }));
|
|
1656
1656
|
};
|
|
1657
1657
|
CheckboxField.displayName = "CheckboxField";
|
|
1658
1658
|
|
|
@@ -1730,7 +1730,7 @@ const isValidHEXColor = (value) => {
|
|
|
1730
1730
|
* ColorField validates that user enters a valid color address.
|
|
1731
1731
|
*
|
|
1732
1732
|
*/
|
|
1733
|
-
const ColorField = forwardRef(({ label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, dataTestId, value: propValue, onChange, isInvalid = false, onBlur, fieldSize = "medium", ...rest }, ref) => {
|
|
1733
|
+
const ColorField = forwardRef(({ label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, "data-testid": dataTestId, value: propValue, onChange, isInvalid = false, onBlur, fieldSize = "medium", ...rest }, ref) => {
|
|
1734
1734
|
const renderAsDisabled = Boolean(rest.disabled);
|
|
1735
1735
|
const renderAsReadonly = Boolean(rest.readOnly);
|
|
1736
1736
|
const htmlForId = useMemo(() => (id ? id : "colorField-" + uuidv4()), [id]);
|
|
@@ -1755,7 +1755,7 @@ const ColorField = forwardRef(({ label, id, tip, helpText, errorMessage, helpAdd
|
|
|
1755
1755
|
setRenderAsInvalid(!!errorType);
|
|
1756
1756
|
onBlur?.(event);
|
|
1757
1757
|
}, [errorType, onBlur]);
|
|
1758
|
-
return (jsx(FormGroup, {
|
|
1758
|
+
return (jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && error) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: rest.required ? !(renderAsDisabled || renderAsReadonly) : false, tip: tip, children: jsxs("div", { className: cvaInput$1({
|
|
1759
1759
|
size: fieldSize,
|
|
1760
1760
|
disabled: renderAsDisabled,
|
|
1761
1761
|
invalid: renderAsInvalid,
|
|
@@ -1774,10 +1774,10 @@ ColorField.displayName = "ColorField";
|
|
|
1774
1774
|
*
|
|
1775
1775
|
* _**Do not use**_ this fields for non-serialized dates. Use TextField instead.
|
|
1776
1776
|
*/
|
|
1777
|
-
const DateField = ({ label, id, tip, helpText, errorMessage, helpAddon, isInvalid, className, defaultValue, dataTestId, ref, ...rest }) => {
|
|
1777
|
+
const DateField = ({ label, id, tip, helpText, errorMessage, helpAddon, isInvalid, className, defaultValue, "data-testid": dataTestId, ref, ...rest }) => {
|
|
1778
1778
|
const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
|
|
1779
1779
|
const htmlForId = id ? id : "dateField-" + uuidv4();
|
|
1780
|
-
return (jsx(FormGroup, {
|
|
1780
|
+
return (jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && errorMessage) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: rest.required ? !(rest.disabled || rest.readOnly) : false, tip: tip, children: jsx(DateBaseInput, { "aria-labelledby": htmlForId + "-label", defaultValue: defaultValue, id: htmlForId, isInvalid: renderAsInvalid, ref: ref, ...rest, className: className, "data-testid": dataTestId }) }));
|
|
1781
1781
|
};
|
|
1782
1782
|
DateField.displayName = "DateField";
|
|
1783
1783
|
|
|
@@ -1845,7 +1845,7 @@ const DropZoneDefaultLabel = () => (jsx(Trans, { components: {
|
|
|
1845
1845
|
* @param {DropZoneProps} props - The props for the DropZone component
|
|
1846
1846
|
* @returns {ReactElement} DropZone component
|
|
1847
1847
|
*/
|
|
1848
|
-
const DropZone = ({ className, dataTestId, filesSelected, label = jsx(DropZoneDefaultLabel, {}), size = "large", isInvalid = false, disabled = false, accept, multiple = false, ...rest }) => {
|
|
1848
|
+
const DropZone = ({ className, "data-testid": dataTestId, filesSelected, label = jsx(DropZoneDefaultLabel, {}), size = "large", isInvalid = false, disabled = false, accept, multiple = false, ...rest }) => {
|
|
1849
1849
|
const [dragActive, setDragActive] = useState(false);
|
|
1850
1850
|
const [fileDropped, setFileDropped] = useState(false);
|
|
1851
1851
|
const [t] = useTranslation();
|
|
@@ -1938,7 +1938,7 @@ const validateEmailId = (emailId, required) => {
|
|
|
1938
1938
|
* A reference to the input element is provided as the `ref` prop.
|
|
1939
1939
|
* For specific input types make sure to use the corresponding input component.
|
|
1940
1940
|
*/
|
|
1941
|
-
const EmailBaseInput = ({ fieldSize = "medium", disabled = false, dataTestId, isInvalid = false, onChange, disableAction = false, ref, ...rest }) => {
|
|
1941
|
+
const EmailBaseInput = ({ fieldSize = "medium", disabled = false, "data-testid": dataTestId, isInvalid = false, onChange, disableAction = false, ref, ...rest }) => {
|
|
1942
1942
|
const [email, setEmail] = useState(rest.value?.toString() || rest.defaultValue?.toString());
|
|
1943
1943
|
const sendEmail = () => {
|
|
1944
1944
|
return window.open(`mailto:${email}`);
|
|
@@ -1949,7 +1949,7 @@ const EmailBaseInput = ({ fieldSize = "medium", disabled = false, dataTestId, is
|
|
|
1949
1949
|
setEmail(newValue);
|
|
1950
1950
|
}, [onChange]);
|
|
1951
1951
|
const renderAsInvalid = (email && !validateEmailAddress(email)) || isInvalid;
|
|
1952
|
-
return (jsx(BaseInput, { actions: email && email.length > 0 ? (jsx(ActionButton, {
|
|
1952
|
+
return (jsx(BaseInput, { actions: email && email.length > 0 ? (jsx(ActionButton, { "data-testid": dataTestId ? `${dataTestId}-emailIcon` : undefined, disabled: disableAction || isInvalid, onClick: sendEmail, size: fieldSize ?? undefined, type: "EMAIL", value: email })) : null, "data-testid": dataTestId, disabled: disabled, fieldSize: fieldSize, isInvalid: renderAsInvalid, onChange: handleChange, placeholder: rest.placeholder || "mail@example.com", ref: ref, type: "email", ...rest }));
|
|
1953
1953
|
};
|
|
1954
1954
|
|
|
1955
1955
|
/**
|
|
@@ -1957,7 +1957,7 @@ const EmailBaseInput = ({ fieldSize = "medium", disabled = false, dataTestId, is
|
|
|
1957
1957
|
* EmailField validates that user enters a valid email address.
|
|
1958
1958
|
*
|
|
1959
1959
|
*/
|
|
1960
|
-
const EmailField = ({ label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, dataTestId, value, onChange, onBlur, isInvalid = false, ref, ...rest }) => {
|
|
1960
|
+
const EmailField = ({ label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, "data-testid": dataTestId, value, onChange, onBlur, isInvalid = false, ref, ...rest }) => {
|
|
1961
1961
|
const htmlForId = id ? id : "emailField-" + uuidv4();
|
|
1962
1962
|
const [t] = useTranslation();
|
|
1963
1963
|
const [innerValue, setInnerValue] = useState(() => {
|
|
@@ -1978,7 +1978,7 @@ const EmailField = ({ label, id, tip, helpText, errorMessage, helpAddon, classNa
|
|
|
1978
1978
|
onChange(event);
|
|
1979
1979
|
}
|
|
1980
1980
|
}, [onChange]);
|
|
1981
|
-
return (jsx(FormGroup, {
|
|
1981
|
+
return (jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && error) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: rest.required ? !(rest.disabled || rest.readOnly) : false, tip: tip, children: jsx(EmailBaseInput, { "aria-labelledby": htmlForId + "-label", defaultValue: defaultValue, id: htmlForId, isInvalid: renderAsInvalid, onBlur: handleBlur, onChange: handleChange, ref: ref, value: value, ...rest, className: className, "data-testid": dataTestId }) }));
|
|
1982
1982
|
};
|
|
1983
1983
|
EmailField.displayName = "EmailField";
|
|
1984
1984
|
|
|
@@ -1995,7 +1995,7 @@ function isWritableRef(r) {
|
|
|
1995
1995
|
* - passes through all remaining BaseSelect props with isMulti=true
|
|
1996
1996
|
*/
|
|
1997
1997
|
const FormFieldSelectAdapterMulti = (props) => {
|
|
1998
|
-
const { className, dataTestId, helpText, helpAddon, tip, label, isInvalid, errorMessage, name, onBlur, options, value, defaultValue, id, onChange, children, ref, ...selectProps } = props;
|
|
1998
|
+
const { className, "data-testid": dataTestId, helpText, helpAddon, tip, label, isInvalid, errorMessage, name, onBlur, options, value, defaultValue, id, onChange, children, ref, ...selectProps } = props;
|
|
1999
1999
|
// Hidden select for a stable DOM ref target (API parity with single adapter)
|
|
2000
2000
|
const innerRef = useRef(null);
|
|
2001
2001
|
// Bridge external ref (supports both callback and object refs)
|
|
@@ -2028,7 +2028,7 @@ const FormFieldSelectAdapterMulti = (props) => {
|
|
|
2028
2028
|
defaultValue,
|
|
2029
2029
|
onChange: next => onChange?.(next),
|
|
2030
2030
|
};
|
|
2031
|
-
return (jsxs(FormGroup, { className: className,
|
|
2031
|
+
return (jsxs(FormGroup, { className: className, "data-testid": dataTestId, helpAddon: helpAddon, helpText: (renderAsInvalid && errorMessage) || helpText, htmlFor: controlId, isInvalid: renderAsInvalid, label: label, required: "required" in selectProps && selectProps.required
|
|
2032
2032
|
? !(("disabled" in selectProps && Boolean(selectProps.disabled)) ||
|
|
2033
2033
|
("readOnly" in selectProps && Boolean(selectProps.readOnly)))
|
|
2034
2034
|
: false, tip: tip, children: [jsx("select", { "aria-hidden": "true", defaultValue: "", hidden: true, name: name, ref: innerRef }), typeof getOptionValue === "function" &&
|
|
@@ -2106,7 +2106,7 @@ const validateNumber = (number, required = false, min, max) => {
|
|
|
2106
2106
|
*
|
|
2107
2107
|
* _**Do not use**_ this fields for non-serialized numbers. Use TextField instead.
|
|
2108
2108
|
*/
|
|
2109
|
-
const NumberField = ({ label, id, tip, helpText, errorMessage, helpAddon, isInvalid, maxLength, className, value, dataTestId, defaultValue, onBlur, onChange, ref, ...rest }) => {
|
|
2109
|
+
const NumberField = ({ label, id, tip, helpText, errorMessage, helpAddon, isInvalid, maxLength, className, value, "data-testid": dataTestId, defaultValue, onBlur, onChange, ref, ...rest }) => {
|
|
2110
2110
|
const htmlForId = id ? id : "numberField-" + uuidv4();
|
|
2111
2111
|
const [t] = useTranslation();
|
|
2112
2112
|
const [innerValue, setInnerValue] = useState(() => {
|
|
@@ -2148,7 +2148,7 @@ const NumberField = ({ label, id, tip, helpText, errorMessage, helpAddon, isInva
|
|
|
2148
2148
|
onChange(event);
|
|
2149
2149
|
}
|
|
2150
2150
|
}, [onChange]);
|
|
2151
|
-
return (jsx(FormGroup, {
|
|
2151
|
+
return (jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && error) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: rest.required ? !(rest.disabled || rest.readOnly) : false, tip: tip, children: jsx(NumberBaseInput, { "aria-labelledby": htmlForId + "-label", id: htmlForId, isInvalid: renderAsInvalid, maxLength: maxLength, onBlur: handleBlur, onChange: handleChange, ref: ref, value: value, ...rest, className: className, "data-testid": dataTestId }) }));
|
|
2152
2152
|
};
|
|
2153
2153
|
NumberField.displayName = "NumberField";
|
|
2154
2154
|
|
|
@@ -2231,7 +2231,7 @@ const cvaTag = cvaMerge([], {
|
|
|
2231
2231
|
/**
|
|
2232
2232
|
* A card version of a radio button that includes an icon, headings and a description.
|
|
2233
2233
|
*/
|
|
2234
|
-
const OptionCard = ({ icon, heading, subheading, description, disabled, id, value, className, contentClassName, dataTestId, customImage, layout = "default", ref, tagProps, ...rest }) => {
|
|
2234
|
+
const OptionCard = ({ icon, heading, subheading, description, disabled, id, value, className, contentClassName, "data-testid": dataTestId, customImage, layout = "default", ref, tagProps, ...rest }) => {
|
|
2235
2235
|
const htmlForId = id ?? "option-card-" + uuidv4();
|
|
2236
2236
|
const subContent = useMemo(() => (jsxs("div", { className: cvaOptionCardContent({ className: contentClassName }), children: [subheading ? (jsx(Text, { align: "center", className: cvaOptionCardText({ type: "subheading", disabled }), type: "span", children: subheading })) : null, description ? (jsx(Text, { align: "center", className: cvaOptionCardText({ type: "description", disabled }), type: "span", children: description })) : null] })), [subheading, description, contentClassName, disabled]);
|
|
2237
2237
|
return (jsx(Tooltip, { className: "w-fit", disabled: layout !== "compact" || (!subheading && !description), label: subContent, mode: "light", placement: "top", children: jsxs("div", { className: cvaOptionCardContainer(), "data-testid": dataTestId, children: [jsx("input", { className: cvaInput(), "data-testid": `${dataTestId}-option-card`, disabled: disabled, id: htmlForId, ref: ref, type: "radio", value: value, ...rest }), jsxs("label", { className: cvaOptionCardLabel({ className, disabled, layout }), "data-testid": `${dataTestId}-option-card-label`, htmlFor: htmlForId, children: [disabled && icon && !customImage
|
|
@@ -2257,13 +2257,13 @@ const PasswordBaseInput = ({ ref, fieldSize, ...rest }) => {
|
|
|
2257
2257
|
*
|
|
2258
2258
|
* _**Do not use** to confirm user actions, such as deleting. Use a checkbox for such flows._
|
|
2259
2259
|
*/
|
|
2260
|
-
const PasswordField = ({ id, label, tip, helpText, helpAddon, errorMessage, isInvalid, maxLength, onChange, className, value, dataTestId, ref, ...rest }) => {
|
|
2260
|
+
const PasswordField = ({ id, label, tip, helpText, helpAddon, errorMessage, isInvalid, maxLength, onChange, className, value, "data-testid": dataTestId, ref, ...rest }) => {
|
|
2261
2261
|
const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
|
|
2262
2262
|
const htmlFor = id ? id : "passwordField-" + uuidv4();
|
|
2263
2263
|
const handleChange = useCallback((event) => {
|
|
2264
2264
|
onChange?.(event);
|
|
2265
2265
|
}, [onChange]);
|
|
2266
|
-
return (jsx(FormGroup, {
|
|
2266
|
+
return (jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && errorMessage) || helpText, htmlFor: htmlFor, isInvalid: renderAsInvalid, label: label, required: rest.required ? !(rest.disabled || rest.readOnly) : false, tip: tip, children: jsx(PasswordBaseInput, { ...rest, "aria-labelledby": htmlFor + "-label", className: className, "data-testid": dataTestId, disabled: rest.readOnly, id: htmlFor, isInvalid: renderAsInvalid, maxLength: maxLength, onChange: handleChange, ref: ref, value: value }) }));
|
|
2267
2267
|
};
|
|
2268
2268
|
PasswordField.displayName = "PasswordField";
|
|
2269
2269
|
|
|
@@ -2332,7 +2332,7 @@ const phoneErrorMessage = (phoneNumber, required) => {
|
|
|
2332
2332
|
* @param {string} [fieldSize="medium"] - The size of the input field.
|
|
2333
2333
|
* @param {boolean} [disableAction=false] - Whether the action button is disabled or not.
|
|
2334
2334
|
*/
|
|
2335
|
-
const PhoneField = ({ label, id, tip, helpText, isInvalid, errorMessage, value, helpAddon, className, defaultValue, dataTestId, name, onBlur, ref, ...rest }) => {
|
|
2335
|
+
const PhoneField = ({ label, id, tip, helpText, isInvalid, errorMessage, value, helpAddon, className, defaultValue, "data-testid": dataTestId, name, onBlur, ref, ...rest }) => {
|
|
2336
2336
|
const htmlForId = id ? id : "phoneField-" + uuidv4();
|
|
2337
2337
|
const [t] = useTranslation();
|
|
2338
2338
|
const [innerValue, setInnerValue] = useState(() => {
|
|
@@ -2366,7 +2366,7 @@ const PhoneField = ({ label, id, tip, helpText, isInvalid, errorMessage, value,
|
|
|
2366
2366
|
}
|
|
2367
2367
|
onBlur?.(event);
|
|
2368
2368
|
}, [errorMessage, onBlur, rest.required]);
|
|
2369
|
-
return (jsx(FormGroup, { className: className,
|
|
2369
|
+
return (jsx(FormGroup, { className: className, "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && error) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: rest.required ? !(rest.disabled || rest.readOnly) : false, tip: tip, children: jsx(PhoneBaseInput, { "aria-labelledby": htmlForId + "-label", "data-testid": dataTestId, defaultValue: defaultValue, id: htmlForId, isInvalid: renderAsInvalid, name: name, onBlur: handleBlur, ref: ref, value: value, ...rest }) }));
|
|
2370
2370
|
};
|
|
2371
2371
|
PhoneField.displayName = "PhoneField";
|
|
2372
2372
|
|
|
@@ -2464,8 +2464,8 @@ const RadioGroupContext = createContext(null);
|
|
|
2464
2464
|
* @param {RadioGroupProps} props - The props for the RadioGroup component
|
|
2465
2465
|
* @returns {ReactElement} RadioGroup component
|
|
2466
2466
|
*/
|
|
2467
|
-
const RadioGroup = ({ children, id, name, value, disabled, onChange, label, inline, className, dataTestId, isInvalid, }) => {
|
|
2468
|
-
return (jsx(FormGroup, {
|
|
2467
|
+
const RadioGroup = ({ children, id, name, value, disabled, onChange, label, inline, className, "data-testid": dataTestId, isInvalid, }) => {
|
|
2468
|
+
return (jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, label: label, children: jsx("div", { className: cvaRadioGroup({ layout: inline ? "inline" : null, className }), "data-testid": dataTestId, children: jsx(RadioGroupContext.Provider, { value: {
|
|
2469
2469
|
id,
|
|
2470
2470
|
value,
|
|
2471
2471
|
name: name || id,
|
|
@@ -2482,7 +2482,7 @@ RadioGroup.displayName = "RadioGroup";
|
|
|
2482
2482
|
* @param {RadioItemProps} props - The props for the RadioItem component
|
|
2483
2483
|
* @returns {ReactElement} RadioItem component
|
|
2484
2484
|
*/
|
|
2485
|
-
const RadioItem = ({ label, value, dataTestId, className, description, suffix, ...rest }) => {
|
|
2485
|
+
const RadioItem = ({ label, value, "data-testid": dataTestId, className, description, suffix, ...rest }) => {
|
|
2486
2486
|
const groupCtx = useContext(RadioGroupContext);
|
|
2487
2487
|
const isChecked = groupCtx?.value === value;
|
|
2488
2488
|
const { ref: labelRef, isTextTruncated: isLabelTruncated } = useIsTextTruncated();
|
|
@@ -2496,10 +2496,10 @@ const RadioItem = ({ label, value, dataTestId, className, description, suffix, .
|
|
|
2496
2496
|
checked: isChecked,
|
|
2497
2497
|
disabled: groupCtx?.disabled,
|
|
2498
2498
|
invalid: groupCtx?.isInvalid,
|
|
2499
|
-
}), "data-testid": dataTestId, id: inputId, onChange: groupCtx?.onChange, type: "radio", value: value, ...rest }), hasLabel ? (jsx(Tooltip, { className: cvaBinaryControlLabelTooltip(),
|
|
2499
|
+
}), "data-testid": dataTestId, id: inputId, onChange: groupCtx?.onChange, type: "radio", value: value, ...rest }), hasLabel ? (jsx(Tooltip, { className: cvaBinaryControlLabelTooltip(), "data-testid": dataTestId ? `${dataTestId}-Label-Tooltip` : undefined, disabled: !isLabelTruncated, label: label, placement: "top", children: jsx("span", { className: cvaLabel({
|
|
2500
2500
|
invalid: groupCtx?.isInvalid,
|
|
2501
2501
|
disabled: groupCtx?.disabled,
|
|
2502
|
-
}), "data-testid": dataTestId ? `${dataTestId}-Label` : undefined, ref: labelRef, children: label }) }, "tooltip-" + rest.name)) : null, suffix ? (jsx("div", { className: cvaBinaryControlSuffixContainer(), "data-testid": dataTestId ? `${dataTestId}-suffix-container` : undefined, children: suffix })) : null, description ? (jsx(Tooltip, { className: cvaBinaryControlDescriptionTooltip(),
|
|
2502
|
+
}), "data-testid": dataTestId ? `${dataTestId}-Label` : undefined, ref: labelRef, children: label }) }, "tooltip-" + rest.name)) : null, suffix ? (jsx("div", { className: cvaBinaryControlSuffixContainer(), "data-testid": dataTestId ? `${dataTestId}-suffix-container` : undefined, children: suffix })) : null, description ? (jsx(Tooltip, { className: cvaBinaryControlDescriptionTooltip(), "data-testid": dataTestId ? `${dataTestId}-Description-Tooltip` : undefined, disabled: !isDescriptionTruncated, label: description, placement: "top", children: jsx("span", { className: cvaBinaryControlDescription({ disabled: groupCtx?.disabled }), "data-testid": dataTestId ? `${dataTestId}-Description` : undefined, id: descriptionId, ref: descriptionRef, children: description }) }, "description-tooltip-" + rest.name)) : null] }));
|
|
2503
2503
|
};
|
|
2504
2504
|
|
|
2505
2505
|
const cvaTimeRange = cvaMerge([
|
|
@@ -2518,7 +2518,7 @@ const cvaTimeRange = cvaMerge([
|
|
|
2518
2518
|
* @param {TimeRangeProps} props - The props for the TimeRange component
|
|
2519
2519
|
* @returns {ReactElement} TimeRange component
|
|
2520
2520
|
*/
|
|
2521
|
-
const TimeRange = ({ id, className, dataTestId, children, range, onChange, disabled, isInvalid, }) => {
|
|
2521
|
+
const TimeRange = ({ id, className, "data-testid": dataTestId, children, range, onChange, disabled, isInvalid, }) => {
|
|
2522
2522
|
const [timeRange, setTimeRange] = useState(range ?? {
|
|
2523
2523
|
timeFrom: DEFAULT_TIME,
|
|
2524
2524
|
timeTo: DEFAULT_TIME,
|
|
@@ -2530,7 +2530,7 @@ const TimeRange = ({ id, className, dataTestId, children, range, onChange, disab
|
|
|
2530
2530
|
setTimeRange(prev => ({ ...prev, timeTo }));
|
|
2531
2531
|
};
|
|
2532
2532
|
const onRangeChange = () => onChange(timeRange);
|
|
2533
|
-
return (jsxs("div", { className: cvaTimeRange({ className }), "data-testid": dataTestId, id: id, children: [jsx(BaseInput, {
|
|
2533
|
+
return (jsxs("div", { className: cvaTimeRange({ className }), "data-testid": dataTestId, id: id, children: [jsx(BaseInput, { "data-testid": `${dataTestId}-from`, disabled: disabled, isInvalid: isInvalid, onBlur: onRangeChange, onChange: (time) => onChangeFrom(time.currentTarget.value), type: "time", value: timeRange.timeFrom === "" ? DEFAULT_TIME : timeRange.timeFrom }), children ?? jsx("div", { "data-testid": `${dataTestId}-separator`, children: "-" }), jsx(BaseInput, { "data-testid": `${dataTestId}-to`, disabled: disabled, isInvalid: isInvalid, onBlur: onRangeChange, onChange: (time) => onChangeTo(time.currentTarget.value), type: "time", value: timeRange.timeTo === "" ? DEFAULT_TIME : timeRange.timeTo })] }));
|
|
2534
2534
|
};
|
|
2535
2535
|
const DEFAULT_TIME = "12:00";
|
|
2536
2536
|
|
|
@@ -2549,7 +2549,7 @@ const cvaScheduleItemText = cvaMerge(["flex", "font-bold", "self-center"]);
|
|
|
2549
2549
|
* @param {ScheduleProps} props - The props for the Schedule component
|
|
2550
2550
|
* @returns {ReactElement} Schedule component
|
|
2551
2551
|
*/
|
|
2552
|
-
const Schedule = ({ className, dataTestId, schedule, onChange, invalidKeys = [] }) => {
|
|
2552
|
+
const Schedule = ({ className, "data-testid": dataTestId, schedule, onChange, invalidKeys = [], }) => {
|
|
2553
2553
|
const [t] = useTranslation();
|
|
2554
2554
|
const onRangeChange = (range, index) => {
|
|
2555
2555
|
const newSchedule = schedule.map((day, dayIndex) => (index === dayIndex ? { ...day, range: { ...range } } : day));
|
|
@@ -2582,7 +2582,7 @@ const Schedule = ({ className, dataTestId, schedule, onChange, invalidKeys = []
|
|
|
2582
2582
|
onChange(newSchedule);
|
|
2583
2583
|
};
|
|
2584
2584
|
return (jsx("div", { className: className, "data-testid": dataTestId, children: schedule.map(({ label, range, isActive, key, checkboxLabel, isAllDay }, index) => {
|
|
2585
|
-
return (jsxs("div", { className: cvaScheduleItem(), children: [jsxs("div", { className: "grid grid-cols-2 gap-4 sm:hidden", children: [jsx(Text, { className: "font-medium text-neutral-500", children: t("schedule.label.day") }), jsx(Text, { className: cvaScheduleItemText(), size: "medium", subtle: !isActive, children: label }), jsx(Text, { className: "font-medium text-neutral-500", children: t("schedule.label.active") }), jsx(Checkbox, { checked: isActive, label: checkboxLabel, onChange: (event) => onActiveChange(Boolean(event.currentTarget.checked), index) }), jsx(Text, { className: "font-medium text-neutral-500", children: t("schedule.label.allDay") }), jsx(Checkbox, { checked: isAllDay ? isActive : undefined, disabled: !isActive, onChange: (event) => onAllDayChange(Boolean(event.currentTarget.checked), index) }), jsx(TimeRange, { disabled: !isActive || isAllDay, isInvalid: !!invalidKeys.find((invalidKey) => invalidKey === key), onChange: (newRange) => onRangeChange(newRange, index), range: range })] }), jsxs("div", { className: "max-sm:hidden sm:grid sm:grid-cols-[100px,200px,60px,250px,250px] sm:gap-2", children: [jsx(Checkbox, { checked: isActive,
|
|
2585
|
+
return (jsxs("div", { className: cvaScheduleItem(), children: [jsxs("div", { className: "grid grid-cols-2 gap-4 sm:hidden", children: [jsx(Text, { className: "font-medium text-neutral-500", children: t("schedule.label.day") }), jsx(Text, { className: cvaScheduleItemText(), size: "medium", subtle: !isActive, children: label }), jsx(Text, { className: "font-medium text-neutral-500", children: t("schedule.label.active") }), jsx(Checkbox, { checked: isActive, label: checkboxLabel, onChange: (event) => onActiveChange(Boolean(event.currentTarget.checked), index) }), jsx(Text, { className: "font-medium text-neutral-500", children: t("schedule.label.allDay") }), jsx(Checkbox, { checked: isAllDay ? isActive : undefined, disabled: !isActive, onChange: (event) => onAllDayChange(Boolean(event.currentTarget.checked), index) }), jsx(TimeRange, { disabled: !isActive || isAllDay, isInvalid: !!invalidKeys.find((invalidKey) => invalidKey === key), onChange: (newRange) => onRangeChange(newRange, index), range: range })] }), jsxs("div", { className: "max-sm:hidden sm:grid sm:grid-cols-[100px,200px,60px,250px,250px] sm:gap-2", children: [jsx(Checkbox, { checked: isActive, "data-testid": `${dataTestId}-${key}-checkbox`, label: checkboxLabel, onChange: (event) => onActiveChange(Boolean(event.currentTarget.checked), index) }), jsx(Text, { className: cvaScheduleItemText(), size: "medium", subtle: !isActive, children: label }), jsx(Checkbox, { checked: isAllDay ? isActive : undefined, "data-testid": `${dataTestId}-${key}-allday-checkbox`, disabled: !isActive, onChange: (event) => onAllDayChange(Boolean(event.currentTarget.checked), index) }), jsx(TimeRange, { "data-testid": `${dataTestId}-${key}-range`, disabled: !isActive || isAllDay, isInvalid: !!invalidKeys.find((invalidKey) => invalidKey === key), onChange: (newRange) => onRangeChange(newRange, index), range: isAllDay ? undefined : range })] })] }, key + label));
|
|
2586
2586
|
}) }));
|
|
2587
2587
|
};
|
|
2588
2588
|
|
|
@@ -2739,9 +2739,9 @@ const cvaSearch = cvaMerge([
|
|
|
2739
2739
|
*
|
|
2740
2740
|
* @param {SearchProps} props - The props for the Search component
|
|
2741
2741
|
*/
|
|
2742
|
-
const Search = ({ className, placeholder, value, widenInputOnFocus, hideBorderWhenNotInFocus = false, disabled = false, onKeyUp, onChange, onFocus, onBlur, name, onClear, dataTestId, autoComplete = "on", loading = false, inputClassName, iconName = "MagnifyingGlass", style, xMarkRef, ref, ...rest }) => {
|
|
2742
|
+
const Search = ({ className, placeholder, value, widenInputOnFocus, hideBorderWhenNotInFocus = false, disabled = false, onKeyUp, onChange, onFocus, onBlur, name, onClear, "data-testid": dataTestId, autoComplete = "on", loading = false, inputClassName, iconName = "MagnifyingGlass", style, xMarkRef, ref, ...rest }) => {
|
|
2743
2743
|
const { t } = useTranslation();
|
|
2744
|
-
return (jsx(TextBaseInput, { ...rest, autoComplete: autoComplete, className: cvaSearch({ className, border: hideBorderWhenNotInFocus, widenOnFocus: widenInputOnFocus }),
|
|
2744
|
+
return (jsx(TextBaseInput, { ...rest, autoComplete: autoComplete, className: cvaSearch({ className, border: hideBorderWhenNotInFocus, widenOnFocus: widenInputOnFocus }), "data-testid": dataTestId, disabled: disabled, inputClassName: inputClassName, name: name, onBlur: onBlur, onChange: onChange, onFocus: onFocus, onKeyUp: onKeyUp, placeholder: placeholder ?? t("search.placeholder"), prefix: loading ? (jsx(Spinner, { centering: "centered", size: rest.fieldSize ?? undefined })) : (jsx(Icon, { name: iconName, size: rest.fieldSize ?? undefined })), ref: ref, suffix:
|
|
2745
2745
|
//only show the clear button if there is a value and the onClear function is provided
|
|
2746
2746
|
onClear && value ? (jsx("button", { className: "flex", "data-testid": dataTestId ? `${dataTestId}_suffix_component` : null, onClick: () => {
|
|
2747
2747
|
onClear();
|
|
@@ -2752,7 +2752,7 @@ Search.displayName = "Search";
|
|
|
2752
2752
|
/**
|
|
2753
2753
|
*
|
|
2754
2754
|
*/
|
|
2755
|
-
const FormFieldSelectAdapter = ({ className, dataTestId, helpText, helpAddon, tip, label, isInvalid, errorMessage, name, onBlur, options, value, defaultValue, id, onChange, children, ref, ...rest }) => {
|
|
2755
|
+
const FormFieldSelectAdapter = ({ className, "data-testid": dataTestId, helpText, helpAddon, tip, label, isInvalid, errorMessage, name, onBlur, options, value, defaultValue, id, onChange, children, ref, ...rest }) => {
|
|
2756
2756
|
const isFirstRender = useIsFirstRender();
|
|
2757
2757
|
const [innerValue, setInnerValue] = useState(value || defaultValue);
|
|
2758
2758
|
useEffect(() => {
|
|
@@ -2785,7 +2785,7 @@ const FormFieldSelectAdapter = ({ className, dataTestId, helpText, helpAddon, ti
|
|
|
2785
2785
|
return (jsxs(FormGroup, { isInvalid: renderAsInvalid,
|
|
2786
2786
|
htmlFor,
|
|
2787
2787
|
className,
|
|
2788
|
-
dataTestId,
|
|
2788
|
+
"data-testid": dataTestId,
|
|
2789
2789
|
helpText: (renderAsInvalid && errorMessage) || helpText,
|
|
2790
2790
|
helpAddon,
|
|
2791
2791
|
tip,
|
|
@@ -2852,7 +2852,7 @@ const TextLengthIndicator = ({ length, maxLength }) => {
|
|
|
2852
2852
|
/**
|
|
2853
2853
|
*
|
|
2854
2854
|
*/
|
|
2855
|
-
const TextAreaField = ({ id, label, tip, helpText, helpAddon, errorMessage, isInvalid, maxLength, onChange, className, value, dataTestId, ref, ...rest }) => {
|
|
2855
|
+
const TextAreaField = ({ id, label, tip, helpText, helpAddon, errorMessage, isInvalid, maxLength, onChange, className, value, "data-testid": dataTestId, ref, ...rest }) => {
|
|
2856
2856
|
const [valueLength, setValueLength] = useState(value ? `${value}`.length : 0);
|
|
2857
2857
|
const renderAsInvalid = isInvalid || Boolean(errorMessage);
|
|
2858
2858
|
const htmlForId = id ? id : "textAreaField-" + uuidv4();
|
|
@@ -2862,15 +2862,15 @@ const TextAreaField = ({ id, label, tip, helpText, helpAddon, errorMessage, isIn
|
|
|
2862
2862
|
onChange(event);
|
|
2863
2863
|
}
|
|
2864
2864
|
}, [onChange]);
|
|
2865
|
-
return (jsx(FormGroup, { className: twMerge(className, "grid", "grid-rows-[auto_1fr_auto]"),
|
|
2866
|
-
(typeof maxLength === "number" && jsx(TextLengthIndicator, { length: valueLength, maxLength: maxLength })), helpText: errorMessage || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: rest.required ? !(rest.disabled || rest.readOnly) : false, tip: tip, children: jsx(TextAreaBaseInput, { "aria-labelledby": htmlForId + "-label", id: htmlForId, isInvalid: renderAsInvalid, maxLength: maxLength, ref: ref, value: value, ...rest, className: "h-auto",
|
|
2865
|
+
return (jsx(FormGroup, { className: twMerge(className, "grid", "grid-rows-[auto_1fr_auto]"), "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon ||
|
|
2866
|
+
(typeof maxLength === "number" && jsx(TextLengthIndicator, { length: valueLength, maxLength: maxLength })), helpText: errorMessage || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: rest.required ? !(rest.disabled || rest.readOnly) : false, tip: tip, children: jsx(TextAreaBaseInput, { "aria-labelledby": htmlForId + "-label", id: htmlForId, isInvalid: renderAsInvalid, maxLength: maxLength, ref: ref, value: value, ...rest, className: "h-auto", "data-testid": dataTestId, onChange: handleChange }) }));
|
|
2867
2867
|
};
|
|
2868
2868
|
TextAreaField.displayName = "TextAreaField";
|
|
2869
2869
|
|
|
2870
2870
|
/**
|
|
2871
2871
|
* Text fields enable the user to interact with and input content and data. This component can be used for long and short form entries. Allow the size of the text input box to reflect the length of the content you expect the user to enter.
|
|
2872
2872
|
*/
|
|
2873
|
-
const TextField = ({ id, label, tip, helpText, helpAddon, errorMessage, isInvalid, maxLength, onChange, className, value, dataTestId, isWarning, ref, ...rest }) => {
|
|
2873
|
+
const TextField = ({ id, label, tip, helpText, helpAddon, errorMessage, isInvalid, maxLength, onChange, className, value, "data-testid": dataTestId, isWarning, ref, ...rest }) => {
|
|
2874
2874
|
const [valueLength, setValueLength] = useState(value ? `${value}`.length : 0);
|
|
2875
2875
|
const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
|
|
2876
2876
|
const htmlFor = id ? id : "textField-" + uuidv4();
|
|
@@ -2880,8 +2880,8 @@ const TextField = ({ id, label, tip, helpText, helpAddon, errorMessage, isInvali
|
|
|
2880
2880
|
onChange(event);
|
|
2881
2881
|
}
|
|
2882
2882
|
}, [onChange]);
|
|
2883
|
-
return (jsx(FormGroup, {
|
|
2884
|
-
(typeof maxLength === "number" && jsx(TextLengthIndicator, { length: valueLength, maxLength: maxLength })), helpText: (renderAsInvalid && errorMessage) || helpText, htmlFor: htmlFor, isInvalid: renderAsInvalid, isWarning: isWarning, label: label, required: rest.required ? !(rest.disabled || rest.readOnly) : false, tip: tip, children: jsx(TextBaseInput, { "aria-labelledby": htmlFor + "-label", id: htmlFor, isInvalid: renderAsInvalid, isWarning: isWarning, maxLength: maxLength, ref: ref, value: value, ...rest, className: className,
|
|
2883
|
+
return (jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon ||
|
|
2884
|
+
(typeof maxLength === "number" && jsx(TextLengthIndicator, { length: valueLength, maxLength: maxLength })), helpText: (renderAsInvalid && errorMessage) || helpText, htmlFor: htmlFor, isInvalid: renderAsInvalid, isWarning: isWarning, label: label, required: rest.required ? !(rest.disabled || rest.readOnly) : false, tip: tip, children: jsx(TextBaseInput, { "aria-labelledby": htmlFor + "-label", id: htmlFor, isInvalid: renderAsInvalid, isWarning: isWarning, maxLength: maxLength, ref: ref, value: value, ...rest, className: className, "data-testid": dataTestId, onChange: handleChange }) }));
|
|
2885
2885
|
};
|
|
2886
2886
|
TextField.displayName = "TextField";
|
|
2887
2887
|
|
|
@@ -2891,10 +2891,10 @@ TextField.displayName = "TextField";
|
|
|
2891
2891
|
* @param {TimeRangeFieldProps} props - The props for the TimeRangeField component
|
|
2892
2892
|
* @returns {ReactElement} TimeRangeField component
|
|
2893
2893
|
*/
|
|
2894
|
-
const TimeRangeField = ({ className, dataTestId, onChange, isInvalid, errorMessage, label, tip, children, helpText, id, ...rest }) => {
|
|
2894
|
+
const TimeRangeField = ({ className, "data-testid": dataTestId, onChange, isInvalid, errorMessage, label, tip, children, helpText, id, ...rest }) => {
|
|
2895
2895
|
const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
|
|
2896
2896
|
const htmlFor = id ? id : "timeRangeField-" + uuidv4();
|
|
2897
|
-
return (jsx(FormGroup, {
|
|
2897
|
+
return (jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpText: (renderAsInvalid && errorMessage) || helpText, htmlFor: htmlFor, isInvalid: renderAsInvalid, label: label, tip: tip, children: jsx(TimeRange, { className: className, "data-testid": dataTestId, isInvalid: renderAsInvalid, onChange: onChange, ...rest, children: children }) }));
|
|
2898
2898
|
};
|
|
2899
2899
|
|
|
2900
2900
|
const cvaToggleSwitchWrapper = cvaMerge(["grid", "grid-cols-[auto]", "items-center"]);
|
|
@@ -2979,9 +2979,17 @@ const cvaToggleSwitchThumb = cvaMerge(["block", "rounded-full", "bg-white", "asp
|
|
|
2979
2979
|
* @param {ToggleSwitchProps} props - The props for the ToggleSwitch component
|
|
2980
2980
|
* @returns {ReactElement} ToggleSwitch component
|
|
2981
2981
|
*/
|
|
2982
|
-
const ToggleSwitch = forwardRef(({ onChange, onClick, preventDefaultOnClick, className, dataTestId = "toggle-switch", showInputFocus, toggled, size = "medium", tabIndex = 0, readOnly, disabled, ...rest }, ref) => {
|
|
2982
|
+
const ToggleSwitch = forwardRef(({ onChange, onClick, preventDefaultOnClick, className, "data-testid": dataTestId = "toggle-switch", showInputFocus, toggled, size = "medium", tabIndex = 0, readOnly, disabled, ...rest }, ref) => {
|
|
2983
2983
|
const localInputRef = useRef(null);
|
|
2984
2984
|
const inputRef = typeof ref === "function" ? localInputRef : ref || localInputRef;
|
|
2985
|
+
// Extract data attributes to apply to wrapper
|
|
2986
|
+
const dataAttributes = useMemo(() => Object.keys(rest).reduce((acc, key) => {
|
|
2987
|
+
if (key.startsWith("data-")) {
|
|
2988
|
+
acc[key] = rest[key];
|
|
2989
|
+
delete rest[key];
|
|
2990
|
+
}
|
|
2991
|
+
return acc;
|
|
2992
|
+
}, {}), [rest]);
|
|
2985
2993
|
const handleWrapperClick = (e) => {
|
|
2986
2994
|
// Prevents double-toggling when wrapped in a label or if preventDefaultOnClick is true
|
|
2987
2995
|
const isFromLabel = e.target instanceof Element && e.target.closest("label");
|
|
@@ -3004,7 +3012,7 @@ const ToggleSwitch = forwardRef(({ onChange, onClick, preventDefaultOnClick, cla
|
|
|
3004
3012
|
e.stopPropagation();
|
|
3005
3013
|
onChange?.(!toggled, e);
|
|
3006
3014
|
};
|
|
3007
|
-
return (jsx("span", { className: cvaToggleSwitchWrapper({ className }), "data-testid": `${dataTestId}`, onClick: handleWrapperClick, onKeyDown: handleKeyPress, children: jsxs("span", { className: cvaToggleSwitchTrack({
|
|
3015
|
+
return (jsx("span", { className: cvaToggleSwitchWrapper({ className }), "data-testid": `${dataTestId}`, onClick: handleWrapperClick, onKeyDown: handleKeyPress, ...dataAttributes, children: jsxs("span", { className: cvaToggleSwitchTrack({
|
|
3008
3016
|
toggled,
|
|
3009
3017
|
disabled: disabled || readOnly,
|
|
3010
3018
|
size,
|
|
@@ -3024,13 +3032,13 @@ ToggleSwitch.displayName = "ToggleSwitch";
|
|
|
3024
3032
|
* @param {ToggleSwitchOptionProps} props - The props for the ToggleSwitchOption component
|
|
3025
3033
|
* @returns {ReactElement} ToggleSwitchOption component
|
|
3026
3034
|
*/
|
|
3027
|
-
const ToggleSwitchOption = ({ label, className, description, suffix, id, dataTestId = "toggle-switch-option", ...rest }) => {
|
|
3035
|
+
const ToggleSwitchOption = ({ label, className, description, suffix, id, "data-testid": dataTestId = "toggle-switch-option", ...rest }) => {
|
|
3028
3036
|
const { ref: labelRef, isTextTruncated: isLabelTruncated } = useIsTextTruncated();
|
|
3029
3037
|
const { ref: descriptionRef, isTextTruncated: isDescriptionTruncated } = useIsTextTruncated();
|
|
3030
|
-
return (jsxs("label", { className: cvaBinaryControlWrapper({ className }), "data-testid": dataTestId, htmlFor: `${id}-toggle-switch`, tabIndex: -1, children: [jsx(ToggleSwitch, {
|
|
3038
|
+
return (jsxs("label", { className: cvaBinaryControlWrapper({ className }), "data-testid": dataTestId, htmlFor: `${id}-toggle-switch`, tabIndex: -1, children: [jsx(ToggleSwitch, { "data-testid": `${dataTestId}-switcher`, id: `${id}-toggle-switch`, ...rest }), jsx(Tooltip, { className: cvaBinaryControlLabelTooltip(), "data-testid": `${dataTestId}-label-tooltip`, disabled: !isLabelTruncated, label: label, placement: "top", children: jsx("span", { className: cvaLabel({
|
|
3031
3039
|
disabled: rest.disabled || rest.readOnly,
|
|
3032
3040
|
className: "select-none",
|
|
3033
|
-
}), "data-testid": `${dataTestId}-label`, ref: labelRef, children: label }) }, `${id}-label-tooltip`), suffix ? (jsx("div", { className: cvaBinaryControlSuffixContainer(), "data-testid": `${dataTestId}-suffix-container`, children: suffix })) : null, description ? (jsx(Tooltip, { className: cvaBinaryControlDescriptionTooltip(),
|
|
3041
|
+
}), "data-testid": `${dataTestId}-label`, ref: labelRef, children: label }) }, `${id}-label-tooltip`), suffix ? (jsx("div", { className: cvaBinaryControlSuffixContainer(), "data-testid": `${dataTestId}-suffix-container`, children: suffix })) : null, description ? (jsx(Tooltip, { className: cvaBinaryControlDescriptionTooltip(), "data-testid": `${dataTestId}-description-tooltip`, disabled: !isDescriptionTruncated, label: description, placement: "top", children: jsx("span", { className: cvaBinaryControlDescription({ disabled: rest.disabled || rest.readOnly }), "data-testid": `${dataTestId}-description`, id: `${id}-description`, ref: descriptionRef, children: description }) }, `${id}-description-tooltip`)) : null] }));
|
|
3034
3042
|
};
|
|
3035
3043
|
ToggleSwitchOption.displayName = "ToggleSwitchOption";
|
|
3036
3044
|
|
|
@@ -3062,10 +3070,10 @@ UploadInput.displayName = "UploadInput";
|
|
|
3062
3070
|
/**
|
|
3063
3071
|
* Upload fields enable the user to upload Files.
|
|
3064
3072
|
*/
|
|
3065
|
-
const UploadField = ({ label, id, tip, helpText, errorMessage, isInvalid, className, value, dataTestId, ref, ...rest }) => {
|
|
3073
|
+
const UploadField = ({ label, id, tip, helpText, errorMessage, isInvalid, className, value, "data-testid": dataTestId, ref, ...rest }) => {
|
|
3066
3074
|
const renderAsInvalid = isInvalid || Boolean(errorMessage);
|
|
3067
3075
|
const htmlForId = id ? id : "uploadField-" + uuidv4();
|
|
3068
|
-
return (jsx(FormGroup, {
|
|
3076
|
+
return (jsx(FormGroup, { "data-testid": `${dataTestId}-FormGroup`, helpText: errorMessage || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: rest.required ? !(rest.disabled || rest.readOnly) : false, tip: tip, children: jsx(UploadInput, { "aria-labelledby": htmlForId + "-label", id: htmlForId, isInvalid: renderAsInvalid, ref: ref, ...rest, className: className, "data-testid": dataTestId }) }));
|
|
3069
3077
|
};
|
|
3070
3078
|
UploadField.displayName = "UploadField";
|
|
3071
3079
|
|
|
@@ -3105,10 +3113,10 @@ const validateUrl = (url, required) => {
|
|
|
3105
3113
|
*
|
|
3106
3114
|
* NOTE: If shown with a label, please use the `UrlField` component instead.
|
|
3107
3115
|
*/
|
|
3108
|
-
const UrlBaseInput = ({ dataTestId, isInvalid, disabled = false, fieldSize = "medium", disableAction = false, value, defaultValue, ref, ...rest }) => {
|
|
3116
|
+
const UrlBaseInput = ({ "data-testid": dataTestId, isInvalid, disabled = false, fieldSize = "medium", disableAction = false, value, defaultValue, ref, ...rest }) => {
|
|
3109
3117
|
const [url, setUrl] = useState(value?.toString() || defaultValue?.toString());
|
|
3110
3118
|
const renderAsInvalid = (url && typeof url === "string" && !validateUrlAddress(url)) || isInvalid;
|
|
3111
|
-
return (jsx(BaseInput, {
|
|
3119
|
+
return (jsx(BaseInput, { "data-testid": dataTestId ? `${dataTestId}-url-input` : undefined, disabled: disabled, id: "url-input", isInvalid: renderAsInvalid, onChange: e => setUrl(e.target.value), placeholder: rest.placeholder || "https://www.example.com", ref: ref, type: "url", value: url, ...rest, actions: !disableAction && (jsx(ActionButton, { "data-testid": (dataTestId && `${dataTestId}-url-input-Icon`) || "url-input-action-icon", disabled: renderAsInvalid || Boolean(disabled) || disableAction, size: fieldSize ?? undefined, type: "WEB_ADDRESS", value: url })) }));
|
|
3112
3120
|
};
|
|
3113
3121
|
|
|
3114
3122
|
/**
|
|
@@ -3116,7 +3124,7 @@ const UrlBaseInput = ({ dataTestId, isInvalid, disabled = false, fieldSize = "me
|
|
|
3116
3124
|
* UrlField validates that user enters a valid web address.
|
|
3117
3125
|
*
|
|
3118
3126
|
*/
|
|
3119
|
-
const UrlField = ({ label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, dataTestId, isInvalid = false, value, onBlur, ref, ...rest }) => {
|
|
3127
|
+
const UrlField = ({ label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, "data-testid": dataTestId, isInvalid = false, value, onBlur, ref, ...rest }) => {
|
|
3120
3128
|
const htmlForId = id ? id : "urlField-" + uuidv4();
|
|
3121
3129
|
const [t] = useTranslation();
|
|
3122
3130
|
const [innerValue, setInnerValue] = useState(() => {
|
|
@@ -3131,7 +3139,7 @@ const UrlField = ({ label, id, tip, helpText, errorMessage, helpAddon, className
|
|
|
3131
3139
|
setRenderAsInvalid(!!validateUrl(newValue, rest.required));
|
|
3132
3140
|
onBlur?.(event);
|
|
3133
3141
|
}, [onBlur, rest.required]);
|
|
3134
|
-
return (jsx(FormGroup, {
|
|
3142
|
+
return (jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: renderAsInvalid ? error : helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: rest.required ? !(rest.disabled || rest.readOnly) : false, tip: tip, children: jsx(UrlBaseInput, { "aria-labelledby": htmlForId + "-label", id: htmlForId, isInvalid: renderAsInvalid, onBlur: handleBlur, ref: ref, value: value || defaultValue, ...rest, className: className, "data-testid": dataTestId }) }));
|
|
3135
3143
|
};
|
|
3136
3144
|
UrlField.displayName = "UrlField";
|
|
3137
3145
|
|