@trackunit/react-form-components 1.3.28 → 1.3.33
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 +112 -109
- package/index.esm.js +125 -122
- package/package.json +11 -11
- package/src/components/ActionButton/ActionButton.d.ts +5 -4
- package/src/components/BaseInput/BaseInput.d.ts +9 -2
- package/src/components/BaseInput/components/GenericActionsRenderer.d.ts +1 -1
- package/src/components/Checkbox/CheckIcon.d.ts +1 -1
- package/src/components/Checkbox/Checkbox.d.ts +9 -3
- package/src/components/Checkbox/IndeterminateIcon.d.ts +1 -1
- package/src/components/CheckboxField/CheckboxField.d.ts +9 -2
- package/src/components/ColorField/ColorField.d.ts +1 -2
- package/src/components/DateField/DateField.d.ts +9 -1
- package/src/components/DateInput/DateInput.d.ts +7 -1
- package/src/components/DropZone/DropZone.d.ts +4 -3
- package/src/components/EmailField/EmailField.d.ts +4 -2
- package/src/components/EmailInput/EmailInput.d.ts +4 -1
- package/src/components/FormGroup/FormGroup.d.ts +6 -6
- package/src/components/Label/Label.d.ts +4 -4
- package/src/components/NumberField/NumberField.d.ts +9 -1
- package/src/components/NumberInput/NumberInput.d.ts +4 -1
- package/src/components/OptionCard/OptionCard.d.ts +11 -4
- package/src/components/PasswordField/PasswordField.d.ts +9 -1
- package/src/components/PasswordInput/PasswordInput.d.ts +4 -1
- package/src/components/PhoneField/PhoneField.d.ts +9 -2
- package/src/components/PhoneFieldWithController/PhoneFieldWithController.d.ts +9 -2
- package/src/components/PhoneInput/CountryCodeSelect.d.ts +1 -1
- package/src/components/PhoneInput/PhoneInput.d.ts +4 -2
- package/src/components/RadioGroup/RadioGroup.d.ts +6 -6
- package/src/components/RadioGroup/RadioItem.d.ts +3 -3
- package/src/components/Schedule/Schedule.d.ts +1 -1
- package/src/components/Search/Search.d.ts +11 -5
- package/src/components/Select/CreatableSelect.d.ts +1 -1
- package/src/components/Select/Select.d.ts +1 -1
- package/src/components/Select/SelectMenuItem/SelectMenuItem.d.ts +5 -5
- package/src/components/Select/TagWithWidth.d.ts +1 -1
- package/src/components/Select/TagsContainer.d.ts +3 -2
- package/src/components/Select/useCustomComponents.d.ts +7 -7
- package/src/components/Select/useCustomStyles.d.ts +3 -3
- package/src/components/Select/useSelect.d.ts +3 -3
- package/src/components/SelectField/CreatableSelectField.d.ts +8 -20
- package/src/components/SelectField/FormFieldSelectAdapter.d.ts +14 -3
- package/src/components/SelectField/SelectField.d.ts +5 -20
- package/src/components/TextArea/TextArea.d.ts +9 -2
- package/src/components/TextAreaField/TextAreaField.d.ts +12 -2
- package/src/components/TextField/TextField.d.ts +4 -2
- package/src/components/TextField/TextLenghtIndicator.d.ts +1 -1
- package/src/components/TextInput/TextInput.d.ts +4 -1
- package/src/components/TimeRange/TimeRange.d.ts +3 -3
- package/src/components/TimeRangeField/TimeRangeField.d.ts +1 -1
- package/src/components/UploadField/UploadField.d.ts +4 -1
- package/src/components/UploadInput/UploadInput.d.ts +4 -1
- package/src/components/UrlField/UrlField.d.ts +4 -1
- package/src/components/UrlInput/UrlInput.d.ts +4 -1
- package/src/test-utils/test-utils.d.ts +0 -1
- package/src/utilities/compareReactNodes.d.ts +1 -1
package/index.esm.js
CHANGED
|
@@ -5,7 +5,7 @@ import { useCopyToClipboard } from 'usehooks-ts';
|
|
|
5
5
|
import { cvaMerge } from '@trackunit/css-class-variance-utilities';
|
|
6
6
|
import { themeSpacing } from '@trackunit/ui-design-tokens';
|
|
7
7
|
import * as React from 'react';
|
|
8
|
-
import
|
|
8
|
+
import { forwardRef, useRef, useImperativeHandle, useMemo, useState, useCallback, cloneElement, useEffect, useContext, useLayoutEffect } from 'react';
|
|
9
9
|
import { titleCase } from 'string-ts';
|
|
10
10
|
import { uuidv4, nonNullable } from '@trackunit/shared-utils';
|
|
11
11
|
import { Temporal } from '@js-temporal/polyfill';
|
|
@@ -130,7 +130,7 @@ const cvaActionContainer = cvaMerge(["flex", "items-center"], {
|
|
|
130
130
|
* The ActionButton component is a wrapper over IconButton to perform an action when the onClick event is triggered.
|
|
131
131
|
*
|
|
132
132
|
* @param {ActionButtonProps} props - The props for the ActionButton component
|
|
133
|
-
* @returns {
|
|
133
|
+
* @returns {ReactElement} ActionButton component
|
|
134
134
|
*/
|
|
135
135
|
const ActionButton = ({ type, value, dataTestId, size, disabled, className, onClick }) => {
|
|
136
136
|
const [, copyToClipboard] = useCopyToClipboard();
|
|
@@ -419,7 +419,7 @@ const SuffixRenderer = ({ suffix, isInvalid, isWarning, dataTestId, disabled, })
|
|
|
419
419
|
* For specific input types make sure to use the corresponding input component.
|
|
420
420
|
* This is a base used by our other input components such as TextInput, NumberInput, PasswordInput, etc.
|
|
421
421
|
*/
|
|
422
|
-
const BaseInput =
|
|
422
|
+
const BaseInput = ({ className, isInvalid, dataTestId, prefix, suffix, addonBefore, addonAfter, actions, fieldSize = "medium", nonInteractive = false, inputClassName, placeholder, isWarning, type, genericAction, style, ref, ...rest }) => {
|
|
423
423
|
// Derive final flags
|
|
424
424
|
const renderAsDisabled = Boolean(rest.disabled);
|
|
425
425
|
const renderAsReadonly = Boolean(rest.readOnly);
|
|
@@ -445,7 +445,7 @@ const BaseInput = forwardRef(({ className, isInvalid, dataTestId, prefix, suffix
|
|
|
445
445
|
paddingLeft: beforeContainerWidth ? `calc(${beforeContainerWidth}px + ${themeSpacing[2]})` : undefined,
|
|
446
446
|
paddingRight: afterContainerWidth ? `calc(${afterContainerWidth}px + ${themeSpacing[2]})` : undefined,
|
|
447
447
|
}, 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, { dataTestId: dataTestId + "-disabled", lockReason: rest.disabled }), jsx(LockReasonRenderer, { dataTestId: dataTestId + "-readonly", lockReason: rest.readOnly && !rest.disabled ? rest.readOnly : undefined }), jsx(GenericActionsRenderer, { fieldSize: fieldSize, genericAction: genericAction, innerRef: innerRef }), jsx(SuffixRenderer, { dataTestId: dataTestId, disabled: renderAsDisabled, isInvalid: isInvalid, isWarning: isWarning, suffix: suffix }), actions, jsx(AddonRenderer, { addon: addonAfter, dataTestId: dataTestId, fieldSize: fieldSize, position: "after" })] })] }));
|
|
448
|
-
}
|
|
448
|
+
};
|
|
449
449
|
BaseInput.displayName = "BaseInput";
|
|
450
450
|
|
|
451
451
|
/**
|
|
@@ -513,7 +513,7 @@ const cvaLabel = cvaMerge([
|
|
|
513
513
|
* The CheckIcon component is used by the checkbox to display the checked state.
|
|
514
514
|
*
|
|
515
515
|
* @param {CheckIconProps} props - The props for the CheckIcon component
|
|
516
|
-
* @returns {
|
|
516
|
+
* @returns {ReactElement} CheckIcon component
|
|
517
517
|
*/
|
|
518
518
|
const CheckIcon = ({ className, dataTestId }) => {
|
|
519
519
|
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" }) }));
|
|
@@ -623,7 +623,7 @@ const cvaCheckboxIcon = cvaMerge(["w-2.5", "h-2.5", "text-white"]);
|
|
|
623
623
|
* The IndeterminateIcon component is used by the checkbox to display the Indeterminate state.
|
|
624
624
|
*
|
|
625
625
|
* @param {IndeterminateIconProps} props - The props for the IndeterminateIcon component
|
|
626
|
-
* @returns {
|
|
626
|
+
* @returns {ReactElement} IndeterminateIcon component
|
|
627
627
|
*/
|
|
628
628
|
const IndeterminateIcon = ({ className }) => (jsx("svg", { className: className, fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 10 10", xmlns: "http://www.w3.org/2000/svg", children: jsx("path", { d: "M3 5h4", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
629
629
|
|
|
@@ -639,9 +639,8 @@ const IndeterminateIcon = ({ className }) => (jsx("svg", { className: className,
|
|
|
639
639
|
* @description A reference to the input element is provided as the `ref` prop.
|
|
640
640
|
* @augments props from [React.InputHTMLAttributes](https://reactjs.org/docs/dom-elements.html#input)
|
|
641
641
|
* @param {CheckboxProps} props - The props for the Checkbox component
|
|
642
|
-
* @returns {JSX.Element} Checkbox component
|
|
643
642
|
*/
|
|
644
|
-
const Checkbox =
|
|
643
|
+
const Checkbox = ({ className, dataTestId = "checkbox", onChange, checked = false, disabled = false, isInvalid = false, readOnly, indeterminate = false, suffix, label, tabIndex = 0, stopPropagation, ref, ...rest }) => {
|
|
645
644
|
const icon = indeterminate ? (jsx(IndeterminateIcon, { className: cvaCheckboxIcon() })) : (checked && jsx(CheckIcon, { className: cvaCheckboxIcon() }));
|
|
646
645
|
const internalRef = useRef(null);
|
|
647
646
|
const { isTextTruncated: isLabelCutOff, ref: labelRef } = useIsTextTruncated();
|
|
@@ -664,7 +663,7 @@ const Checkbox = forwardRef(({ className, dataTestId = "checkbox", onChange, che
|
|
|
664
663
|
invalid: isReadonly ? false : isInvalid,
|
|
665
664
|
disabled: isReadonly,
|
|
666
665
|
}), id: `checkbox-label-${label}`, ref: labelRef, children: label }) }, "tooltip-" + rest.name)) : null, suffix ? (jsx("div", { className: cvaBinaryControlSuffixContainer(), "data-testid": dataTestId ? `${dataTestId}-suffix-container` : undefined, children: suffix })) : null] }));
|
|
667
|
-
}
|
|
666
|
+
};
|
|
668
667
|
Checkbox.displayName = "Checkbox";
|
|
669
668
|
|
|
670
669
|
/**
|
|
@@ -672,7 +671,7 @@ Checkbox.displayName = "Checkbox";
|
|
|
672
671
|
* This component is **not used directly**, but is part of the FormGroup and Field components.
|
|
673
672
|
*
|
|
674
673
|
* @param {LabelProps} props - The props for the Label component
|
|
675
|
-
* @returns {
|
|
674
|
+
* @returns {ReactElement} Label component
|
|
676
675
|
*/
|
|
677
676
|
const Label = ({ id, htmlFor, children, className, dataTestId, disabled, isInvalid, }) => {
|
|
678
677
|
return (jsx("label", { className: cvaLabel({ invalid: isInvalid, disabled, className }), "data-testid": dataTestId, htmlFor: htmlFor || "", id: id || "", children: children }));
|
|
@@ -706,11 +705,11 @@ const cvaHelpAddon = cvaMerge(["ml-auto"]);
|
|
|
706
705
|
* Besides a label the component supplies an optional Tooltip, HelpText and HelpAddon support.
|
|
707
706
|
*
|
|
708
707
|
* @param {FormGroupProps} props - The props for the FormGroup component
|
|
709
|
-
* @returns {
|
|
708
|
+
* @returns {ReactElement} FormGroup component
|
|
710
709
|
*/
|
|
711
710
|
const FormGroup = ({ isInvalid, isWarning, helpText, helpAddon, tip, className, dataTestId, label, htmlFor, children, required = false, }) => {
|
|
712
711
|
const [t] = useTranslation();
|
|
713
|
-
const validationStateIcon =
|
|
712
|
+
const validationStateIcon = useMemo(() => {
|
|
714
713
|
const color = isInvalid ? "danger" : isWarning ? "warning" : null;
|
|
715
714
|
return color ? jsx(Icon, { color: color, name: "ExclamationTriangle", size: "small" }) : null;
|
|
716
715
|
}, [isInvalid, isWarning]);
|
|
@@ -722,10 +721,10 @@ const FormGroup = ({ isInvalid, isWarning, helpText, helpAddon, tip, className,
|
|
|
722
721
|
*
|
|
723
722
|
* _**Do use**_ the CheckboxField for boolean input.
|
|
724
723
|
*/
|
|
725
|
-
const CheckboxField =
|
|
724
|
+
const CheckboxField = ({ label, id, tip, helpText, helpAddon, isInvalid, className, checked, dataTestId, checkboxLabel, onChange, ref, ...rest }) => {
|
|
726
725
|
const htmlForId = id ? id : "checkboxField-" + uuidv4();
|
|
727
726
|
return (jsx(FormGroup, { className: "flex flex-col gap-1", dataTestId: 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, dataTestId: dataTestId, id: htmlForId, label: checkboxLabel, onChange: onChange, ref: ref, ...rest }) }));
|
|
728
|
-
}
|
|
727
|
+
};
|
|
729
728
|
CheckboxField.displayName = "CheckboxField";
|
|
730
729
|
|
|
731
730
|
/**
|
|
@@ -806,37 +805,37 @@ const ColorField = forwardRef(({ label, id, tip, helpText, errorMessage, helpAdd
|
|
|
806
805
|
const renderAsDisabled = Boolean(rest.disabled);
|
|
807
806
|
const renderAsReadonly = Boolean(rest.readOnly);
|
|
808
807
|
const htmlForId = useMemo(() => (id ? id : "colorField-" + uuidv4()), [id]);
|
|
809
|
-
const innerRef =
|
|
810
|
-
|
|
808
|
+
const innerRef = useRef(null);
|
|
809
|
+
useImperativeHandle(ref, () => innerRef.current, []);
|
|
811
810
|
const [t] = useTranslation();
|
|
812
811
|
// Internal state for color value
|
|
813
812
|
const [innerValue, setInnerValue] = useState(propValue || defaultValue || "");
|
|
814
813
|
const [renderAsInvalid, setRenderAsInvalid] = useState(!!errorMessage || (innerValue && typeof innerValue === "string" && !isValidHEXColor(innerValue)) || isInvalid);
|
|
815
814
|
const errorType = useMemo(() => validateColorCode(innerValue, rest.required), [rest.required, innerValue]);
|
|
816
815
|
const error = useMemo(() => (errorType ? t(`colorField.error.${errorType}`) : errorMessage), [errorType, errorMessage, t]);
|
|
817
|
-
const
|
|
818
|
-
const newValue = event.target.value;
|
|
819
|
-
setInnerValue(newValue);
|
|
820
|
-
setRenderAsInvalid(!!errorType);
|
|
821
|
-
onBlur?.(event);
|
|
822
|
-
}, [errorType, onBlur]);
|
|
823
|
-
const handleChange = useCallback((event) => {
|
|
816
|
+
const handleInputChange = useCallback((event) => {
|
|
824
817
|
const newValue = event.target.value;
|
|
825
818
|
setInnerValue(newValue);
|
|
826
819
|
if (onChange) {
|
|
827
820
|
onChange(event);
|
|
828
821
|
}
|
|
829
822
|
}, [onChange]);
|
|
823
|
+
const handleBlur = useCallback(event => {
|
|
824
|
+
const newValue = event.target.value;
|
|
825
|
+
setInnerValue(newValue);
|
|
826
|
+
setRenderAsInvalid(!!errorType);
|
|
827
|
+
onBlur?.(event);
|
|
828
|
+
}, [errorType, onBlur]);
|
|
830
829
|
return (jsx(FormGroup, { dataTestId: 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({
|
|
831
830
|
size: fieldSize,
|
|
832
831
|
disabled: renderAsDisabled,
|
|
833
832
|
invalid: renderAsInvalid,
|
|
834
833
|
className,
|
|
835
|
-
}), "data-testid": dataTestId ? `${dataTestId}-container` : undefined, children: [jsx("input", { "aria-labelledby": htmlForId + "-label", className: cvaInputColorField({ readOnly: renderAsReadonly }), "data-testid": dataTestId, defaultValue: defaultValue, disabled: renderAsDisabled, id: htmlForId, onBlur: handleBlur, onChange:
|
|
834
|
+
}), "data-testid": dataTestId ? `${dataTestId}-container` : undefined, children: [jsx("input", { "aria-labelledby": htmlForId + "-label", className: cvaInputColorField({ readOnly: renderAsReadonly }), "data-testid": dataTestId, defaultValue: defaultValue, disabled: renderAsDisabled, id: htmlForId, onBlur: handleBlur, onChange: handleInputChange, readOnly: renderAsReadonly, ref: innerRef, type: "color", value: innerValue }), jsx("input", { "aria-labelledby": htmlForId + "-label-text", className: cvaInputField({
|
|
836
835
|
readOnly: renderAsReadonly,
|
|
837
836
|
disabled: renderAsDisabled,
|
|
838
837
|
className: "px-1 focus-visible:outline-none",
|
|
839
|
-
}), "data-testid": dataTestId ? `${dataTestId}-textField` : undefined, disabled: renderAsDisabled, onBlur: handleBlur, onChange:
|
|
838
|
+
}), "data-testid": dataTestId ? `${dataTestId}-textField` : undefined, disabled: renderAsDisabled, onBlur: handleBlur, onChange: handleInputChange, readOnly: renderAsReadonly, type: "text", value: innerValue }), jsx(GenericActionsRenderer, { disabled: renderAsDisabled || renderAsReadonly, fieldSize: fieldSize, genericAction: "edit", innerRef: innerRef, tooltipLabel: t("colorField.tooltip") })] }) }));
|
|
840
839
|
});
|
|
841
840
|
ColorField.displayName = "ColorField";
|
|
842
841
|
|
|
@@ -845,18 +844,23 @@ ColorField.displayName = "ColorField";
|
|
|
845
844
|
*
|
|
846
845
|
* NOTE: If shown with a label, please use the `DateField` component instead.
|
|
847
846
|
*/
|
|
848
|
-
|
|
847
|
+
/**
|
|
848
|
+
*
|
|
849
|
+
*/
|
|
850
|
+
const DateInput = ({ min, max, defaultValue, value, ref, ...rest }) => {
|
|
849
851
|
const formatDateToInputString = (date) => date instanceof Date
|
|
850
852
|
? Temporal.PlainDateTime.from({
|
|
851
853
|
year: date.getFullYear(),
|
|
852
854
|
month: date.getMonth() + 1,
|
|
853
855
|
day: date.getDate(),
|
|
854
|
-
})
|
|
856
|
+
})
|
|
857
|
+
.toPlainDate()
|
|
858
|
+
.toString()
|
|
855
859
|
: date;
|
|
856
860
|
// Chrome and Firefox need their default icon to have datepicker functionality.
|
|
857
861
|
const showIcon = !/Chrome/.test(navigator.userAgent) && !/Firefox/.test(navigator.userAgent);
|
|
858
862
|
return (jsx(BaseInput, { defaultValue: formatDateToInputString(defaultValue), max: formatDateToInputString(max), min: formatDateToInputString(min), ref: ref, suffix: showIcon ? jsx(Icon, { dataTestId: "calendar", name: "Calendar", size: "medium", type: "solid" }) : null, type: "date", value: formatDateToInputString(value), ...rest }));
|
|
859
|
-
}
|
|
863
|
+
};
|
|
860
864
|
DateInput.displayName = "DateInput";
|
|
861
865
|
|
|
862
866
|
/**
|
|
@@ -866,11 +870,11 @@ DateInput.displayName = "DateInput";
|
|
|
866
870
|
*
|
|
867
871
|
* _**Do not use**_ this fields for non-serialized dates. Use TextField instead.
|
|
868
872
|
*/
|
|
869
|
-
const DateField =
|
|
873
|
+
const DateField = ({ label, id, tip, helpText, errorMessage, helpAddon, isInvalid, className, defaultValue, dataTestId, ref, ...rest }) => {
|
|
870
874
|
const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
|
|
871
875
|
const htmlForId = id ? id : "dateField-" + uuidv4();
|
|
872
876
|
return (jsx(FormGroup, { dataTestId: 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(DateInput, { "aria-labelledby": htmlForId + "-label", defaultValue: defaultValue, id: htmlForId, isInvalid: renderAsInvalid, ref: ref, ...rest, className: className, dataTestId: dataTestId }) }));
|
|
873
|
-
}
|
|
877
|
+
};
|
|
874
878
|
DateField.displayName = "DateField";
|
|
875
879
|
|
|
876
880
|
const cvaDropZone = cvaMerge([
|
|
@@ -929,7 +933,7 @@ const DropZoneDefaultLabel = () => (jsx(Trans, { components: {
|
|
|
929
933
|
* The Drop Zone can be used to drag and drop files or to browse and select files from the file system.
|
|
930
934
|
*
|
|
931
935
|
* @param {DropZoneProps} props - The props for the DropZone component
|
|
932
|
-
* @returns {
|
|
936
|
+
* @returns {ReactElement} DropZone component
|
|
933
937
|
*/
|
|
934
938
|
const DropZone = ({ className, dataTestId, filesSelected, label = jsx(DropZoneDefaultLabel, {}), size = "large", isInvalid = false, disabled = false, accept, multiple = false, ...rest }) => {
|
|
935
939
|
const [dragActive, setDragActive] = useState(false);
|
|
@@ -1024,7 +1028,7 @@ const validateEmailId = (emailId, required) => {
|
|
|
1024
1028
|
* A reference to the input element is provided as the `ref` prop.
|
|
1025
1029
|
* For specific input types make sure to use the corresponding input component.
|
|
1026
1030
|
*/
|
|
1027
|
-
const EmailInput =
|
|
1031
|
+
const EmailInput = ({ fieldSize = "medium", disabled = false, dataTestId, isInvalid = false, onChange, disableAction = false, ref, ...rest }) => {
|
|
1028
1032
|
const [email, setEmail] = useState("");
|
|
1029
1033
|
const sendEmail = () => {
|
|
1030
1034
|
return window.open(`mailto:${email}`);
|
|
@@ -1036,7 +1040,7 @@ const EmailInput = forwardRef(({ fieldSize = "medium", disabled = false, dataTes
|
|
|
1036
1040
|
}, [onChange]);
|
|
1037
1041
|
const renderAsInvalid = (email && !validateEmailAddress(email)) || isInvalid;
|
|
1038
1042
|
return (jsx(BaseInput, { actions: email && email.length > 0 ? (jsx(ActionButton, { dataTestId: dataTestId ? `${dataTestId}-emailIcon` : undefined, disabled: disableAction || isInvalid, onClick: sendEmail, size: fieldSize ?? undefined, type: "EMAIL", value: email })) : null, dataTestId: dataTestId, disabled: disabled, isInvalid: renderAsInvalid, onChange: handleChange, placeholder: rest.placeholder || "mail@example.com", ref: ref, type: "email", ...rest }));
|
|
1039
|
-
}
|
|
1043
|
+
};
|
|
1040
1044
|
EmailInput.displayName = "EmailInput";
|
|
1041
1045
|
|
|
1042
1046
|
/**
|
|
@@ -1044,7 +1048,7 @@ EmailInput.displayName = "EmailInput";
|
|
|
1044
1048
|
* EmailField validates that user enters a valid email address.
|
|
1045
1049
|
*
|
|
1046
1050
|
*/
|
|
1047
|
-
const EmailField =
|
|
1051
|
+
const EmailField = ({ label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, dataTestId, value, onChange, onBlur, isInvalid = false, ref, ...rest }) => {
|
|
1048
1052
|
const htmlForId = id ? id : "emailField-" + uuidv4();
|
|
1049
1053
|
const [t] = useTranslation();
|
|
1050
1054
|
const [innerValue, setInnerValue] = useState(() => {
|
|
@@ -1066,7 +1070,7 @@ const EmailField = forwardRef(({ label, id, tip, helpText, errorMessage, helpAdd
|
|
|
1066
1070
|
}
|
|
1067
1071
|
}, [onChange]);
|
|
1068
1072
|
return (jsx(FormGroup, { dataTestId: 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(EmailInput, { "aria-labelledby": htmlForId + "-label", defaultValue: defaultValue, id: htmlForId, isInvalid: renderAsInvalid, onBlur: handleBlur, onChange: handleChange, ref: ref, value: value, ...rest, className: className, dataTestId: dataTestId }) }));
|
|
1069
|
-
}
|
|
1073
|
+
};
|
|
1070
1074
|
EmailField.displayName = "EmailField";
|
|
1071
1075
|
|
|
1072
1076
|
const isNumberValid = (number) => {
|
|
@@ -1124,9 +1128,9 @@ const validateNumber = (number, required = false, min, max) => {
|
|
|
1124
1128
|
*
|
|
1125
1129
|
* NOTE: If shown with a label, please use the `NumberField` component instead.
|
|
1126
1130
|
*/
|
|
1127
|
-
const NumberInput =
|
|
1128
|
-
return jsx(BaseInput, { ref: ref, type: "number", ...
|
|
1129
|
-
}
|
|
1131
|
+
const NumberInput = ({ ref, ...rest }) => {
|
|
1132
|
+
return jsx(BaseInput, { ref: ref, type: "number", ...rest, value: rest.value });
|
|
1133
|
+
};
|
|
1130
1134
|
NumberInput.displayName = "NumberInput";
|
|
1131
1135
|
|
|
1132
1136
|
/**
|
|
@@ -1136,7 +1140,7 @@ NumberInput.displayName = "NumberInput";
|
|
|
1136
1140
|
*
|
|
1137
1141
|
* _**Do not use**_ this fields for non-serialized numbers. Use TextField instead.
|
|
1138
1142
|
*/
|
|
1139
|
-
const NumberField =
|
|
1143
|
+
const NumberField = ({ label, id, tip, helpText, errorMessage, helpAddon, isInvalid, maxLength, className, value, dataTestId, defaultValue, onBlur, onChange, ref, ...rest }) => {
|
|
1140
1144
|
const htmlForId = id ? id : "numberField-" + uuidv4();
|
|
1141
1145
|
const [t] = useTranslation();
|
|
1142
1146
|
const [innerValue, setInnerValue] = useState(() => {
|
|
@@ -1175,7 +1179,7 @@ const NumberField = forwardRef(({ label, id, tip, helpText, errorMessage, helpAd
|
|
|
1175
1179
|
}
|
|
1176
1180
|
}, [onChange]);
|
|
1177
1181
|
return (jsx(FormGroup, { dataTestId: 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(NumberInput, { "aria-labelledby": htmlForId + "-label", id: htmlForId, isInvalid: renderAsInvalid, maxLength: maxLength, onBlur: handleBlur, onChange: handleChange, ref: ref, value: value, ...rest, className: className, dataTestId: dataTestId }) }));
|
|
1178
|
-
}
|
|
1182
|
+
};
|
|
1179
1183
|
NumberField.displayName = "NumberField";
|
|
1180
1184
|
|
|
1181
1185
|
const cvaOptionCardLabel = cvaMerge([
|
|
@@ -1207,12 +1211,12 @@ const cvaOptionCardContainer = cvaMerge(["contents"]);
|
|
|
1207
1211
|
/**
|
|
1208
1212
|
* A card version of a radio button that includes an icon, headings and a description.
|
|
1209
1213
|
*/
|
|
1210
|
-
const OptionCard =
|
|
1214
|
+
const OptionCard = ({ icon, heading, subheading, description, disabled, id, value, className, contentClassName, dataTestId, customImage, ref, ...rest }) => {
|
|
1211
1215
|
const htmlForId = id ?? "option-card-" + uuidv4();
|
|
1212
1216
|
return (jsxs("div", { className: cvaOptionCardContainer(), "data-testid": dataTestId, children: [jsx("input", { className: "peer absolute h-0 w-0 opacity-0", "data-testid": `${dataTestId}-option-card`, disabled: disabled, id: htmlForId, ref: ref, type: "radio", value: value, ...rest }), jsxs("label", { className: cvaOptionCardLabel({ className, disabled }), "data-testid": `${dataTestId}-option-card-label`, htmlFor: htmlForId, children: [disabled && icon && !customImage
|
|
1213
1217
|
? cloneElement(icon, { className: `${icon.props.className} text-secondary-400` })
|
|
1214
1218
|
: null, disabled && customImage ? jsx("img", { alt: "logo", className: customImage.className, src: customImage.src }) : null, !disabled && !customImage && icon, !disabled && customImage ? jsx("img", { alt: "logo", className: customImage.className, src: customImage.src }) : null, heading ? (jsx(Heading, { subtle: disabled, variant: "secondary", children: heading })) : null, subheading || description ? (jsxs("div", { className: cvaOptionCardContent({ className: contentClassName }), children: [subheading ? (jsx(Text, { align: "center", subtle: disabled, type: "span", weight: "thick", children: subheading })) : null, description ? (jsx(Text, { align: "center", subtle: true, type: "span", children: description })) : null] })) : null] })] }));
|
|
1215
|
-
}
|
|
1219
|
+
};
|
|
1216
1220
|
OptionCard.displayName = "OptionCard";
|
|
1217
1221
|
|
|
1218
1222
|
/**
|
|
@@ -1220,10 +1224,10 @@ OptionCard.displayName = "OptionCard";
|
|
|
1220
1224
|
*
|
|
1221
1225
|
* NOTE: If shown with a label, please use the `PasswordField` component instead.
|
|
1222
1226
|
*/
|
|
1223
|
-
const PasswordInput =
|
|
1227
|
+
const PasswordInput = ({ ref, fieldSize, ...rest }) => {
|
|
1224
1228
|
const [showPassword, setShowPassword] = useState(false);
|
|
1225
|
-
return (jsx(BaseInput, { ref: ref, ...
|
|
1226
|
-
}
|
|
1229
|
+
return (jsx(BaseInput, { ref: ref, ...rest, actions: jsx("div", { className: cvaActionContainer({ size: fieldSize }), children: jsx(IconButton, { className: cvaActionButton({ size: fieldSize }), icon: jsx(Icon, { name: showPassword ? "EyeSlash" : "Eye", size: "small" }), onClick: () => setShowPassword(prevState => !prevState), size: "small", variant: "secondary" }) }), type: showPassword ? "text" : "password" }));
|
|
1230
|
+
};
|
|
1227
1231
|
PasswordInput.displayName = "PasswordInput";
|
|
1228
1232
|
|
|
1229
1233
|
/**
|
|
@@ -1233,14 +1237,14 @@ PasswordInput.displayName = "PasswordInput";
|
|
|
1233
1237
|
*
|
|
1234
1238
|
* _**Do not use** to confirm user actions, such as deleting. Use a checkbox for such flows._
|
|
1235
1239
|
*/
|
|
1236
|
-
const PasswordField =
|
|
1240
|
+
const PasswordField = ({ id, label, tip, helpText, helpAddon, errorMessage, isInvalid, maxLength, onChange, className, value, dataTestId, ref, ...rest }) => {
|
|
1237
1241
|
const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
|
|
1238
1242
|
const htmlFor = id ? id : "passwordField-" + uuidv4();
|
|
1239
1243
|
const handleChange = useCallback((event) => {
|
|
1240
1244
|
onChange?.(event);
|
|
1241
1245
|
}, [onChange]);
|
|
1242
1246
|
return (jsx(FormGroup, { dataTestId: 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(PasswordInput, { ...rest, "aria-labelledby": htmlFor + "-label", className: className, dataTestId: dataTestId, disabled: rest.readOnly, id: htmlFor, isInvalid: renderAsInvalid, maxLength: maxLength, onChange: handleChange, ref: ref, value: value }) }));
|
|
1243
|
-
}
|
|
1247
|
+
};
|
|
1244
1248
|
PasswordField.displayName = "PasswordField";
|
|
1245
1249
|
|
|
1246
1250
|
/**
|
|
@@ -1305,9 +1309,8 @@ const DEFAULT_COUNTRY_CODE = undefined;
|
|
|
1305
1309
|
* @param {boolean} [disabled=false] - Whether the component is disabled or not.
|
|
1306
1310
|
* @param {string} [fieldSize="medium"] - The size of the input field.
|
|
1307
1311
|
* @param {boolean} [disableAction=false] - Whether the action button is disabled or not.
|
|
1308
|
-
* @returns {JSX.Element} - The PhoneInput component.
|
|
1309
1312
|
*/
|
|
1310
|
-
const PhoneInput =
|
|
1313
|
+
const PhoneInput = ({ dataTestId, isInvalid, disabled = false, value, defaultValue, fieldSize = "medium", disableAction = false, onChange, readOnly, onFocus, onBlur, name, ref, ...rest }) => {
|
|
1311
1314
|
const [innerValue, setInnerValue] = useState(() => {
|
|
1312
1315
|
return (value?.toString() || defaultValue?.toString()) ?? "";
|
|
1313
1316
|
});
|
|
@@ -1320,8 +1323,7 @@ const PhoneInput = forwardRef(({ dataTestId, isInvalid, disabled = false, value,
|
|
|
1320
1323
|
}, []);
|
|
1321
1324
|
const handleChange = useCallback(event => {
|
|
1322
1325
|
const newValue = event.target.value;
|
|
1323
|
-
|
|
1324
|
-
event.target.value = noneFormattedValue;
|
|
1326
|
+
event.target.value = parseIncompletePhoneNumber(newValue);
|
|
1325
1327
|
onChange?.(event);
|
|
1326
1328
|
setInnerValue(newValue);
|
|
1327
1329
|
determineCountry(newValue);
|
|
@@ -1351,7 +1353,7 @@ const PhoneInput = forwardRef(({ dataTestId, isInvalid, disabled = false, value,
|
|
|
1351
1353
|
fieldIsFocused.current = true;
|
|
1352
1354
|
}, [onFocus]);
|
|
1353
1355
|
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, { dataTestId: dataTestId ? `${dataTestId}-phoneIcon` : undefined, disabled: isInvalid, size: fieldSize ?? undefined, type: "PHONE_NUMBER", value: value?.toString() || "" })) : null, dataTestId: 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 }) }));
|
|
1354
|
-
}
|
|
1356
|
+
};
|
|
1355
1357
|
PhoneInput.displayName = "PhoneInput";
|
|
1356
1358
|
|
|
1357
1359
|
/**
|
|
@@ -1418,9 +1420,8 @@ const phoneErrorMessage = (phoneNumber, required) => {
|
|
|
1418
1420
|
* @param {boolean} [disabled=false] - Whether the component is disabled or not.
|
|
1419
1421
|
* @param {string} [fieldSize="medium"] - The size of the input field.
|
|
1420
1422
|
* @param {boolean} [disableAction=false] - Whether the action button is disabled or not.
|
|
1421
|
-
* @returns {JSX.Element} - The PhoneField component.
|
|
1422
1423
|
*/
|
|
1423
|
-
const PhoneField =
|
|
1424
|
+
const PhoneField = ({ label, id, tip, helpText, isInvalid, errorMessage, value, helpAddon, className, defaultValue, dataTestId, name, onBlur, ref, ...rest }) => {
|
|
1424
1425
|
const htmlForId = id ? id : "phoneField-" + uuidv4();
|
|
1425
1426
|
const [t] = useTranslation();
|
|
1426
1427
|
const [innerValue, setInnerValue] = useState(() => {
|
|
@@ -1453,17 +1454,16 @@ const PhoneField = forwardRef(({ label, id, tip, helpText, isInvalid, errorMessa
|
|
|
1453
1454
|
onBlur?.(event);
|
|
1454
1455
|
}, [errorMessage, onBlur, rest.required]);
|
|
1455
1456
|
return (jsx(FormGroup, { className: className, dataTestId: 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(PhoneInput, { "aria-labelledby": htmlForId + "-label", dataTestId: dataTestId, defaultValue: defaultValue, id: htmlForId, isInvalid: renderAsInvalid, name: name, onBlur: handleBlur, ref: ref, value: value, ...rest }) }));
|
|
1456
|
-
}
|
|
1457
|
+
};
|
|
1457
1458
|
PhoneField.displayName = "PhoneField";
|
|
1458
1459
|
|
|
1459
1460
|
/**
|
|
1460
1461
|
* The PhoneFieldWithController component is a wrapper for the PhoneField component to connect it to react-hook-form.
|
|
1461
1462
|
*
|
|
1462
|
-
* @returns {JSX.Element} - The PhoneFieldWithController component.
|
|
1463
1463
|
*/
|
|
1464
|
-
const PhoneFieldWithController =
|
|
1464
|
+
const PhoneFieldWithController = ({ control, controllerProps, name, value, ref, ...rest }) => {
|
|
1465
1465
|
return (jsx(Controller, { control: control, defaultValue: value, name: name, ...controllerProps, render: ({ field }) => jsx(PhoneField, { ...rest, ...field, ref: ref }) }));
|
|
1466
|
-
}
|
|
1466
|
+
};
|
|
1467
1467
|
PhoneFieldWithController.displayName = "PhoneFieldWithController";
|
|
1468
1468
|
|
|
1469
1469
|
const cvaRadioGroup = cvaMerge(["flex", "gap-2", "flex-col", "items-start"], {
|
|
@@ -1549,7 +1549,7 @@ const RadioGroupContext = React.createContext(null);
|
|
|
1549
1549
|
* _**Do not use** Radio buttons if a user can select many option from a list, use checkboxes instead of radio buttons._
|
|
1550
1550
|
*
|
|
1551
1551
|
* @param {RadioGroupProps} props - The props for the RadioGroup component
|
|
1552
|
-
* @returns {
|
|
1552
|
+
* @returns {ReactElement} RadioGroup component
|
|
1553
1553
|
*/
|
|
1554
1554
|
const RadioGroup = ({ children, id, name, value, disabled, onChange, label, inline, className, dataTestId, isInvalid, }) => {
|
|
1555
1555
|
return (jsx(FormGroup, { dataTestId: dataTestId ? `${dataTestId}-FormGroup` : undefined, label: label, children: jsx("div", { className: cvaRadioGroup({ layout: inline ? "inline" : null, className }), "data-testid": dataTestId, children: jsx(RadioGroupContext.Provider, { value: {
|
|
@@ -1567,7 +1567,7 @@ RadioGroup.displayName = "RadioGroup";
|
|
|
1567
1567
|
* The RadioItem component.
|
|
1568
1568
|
*
|
|
1569
1569
|
* @param {RadioItemProps} props - The props for the RadioItem component
|
|
1570
|
-
* @returns {
|
|
1570
|
+
* @returns {ReactElement} RadioItem component
|
|
1571
1571
|
*/
|
|
1572
1572
|
const RadioItem = ({ label, value, dataTestId, className, description, suffix, ...rest }) => {
|
|
1573
1573
|
const groupCtx = useContext(RadioGroupContext);
|
|
@@ -1600,10 +1600,10 @@ const cvaTimeRange = cvaMerge([
|
|
|
1600
1600
|
* TimeRange is used to create a time range entry.
|
|
1601
1601
|
*
|
|
1602
1602
|
* @param {TimeRangeProps} props - The props for the TimeRange component
|
|
1603
|
-
* @returns {
|
|
1603
|
+
* @returns {ReactElement} TimeRange component
|
|
1604
1604
|
*/
|
|
1605
1605
|
const TimeRange = ({ id, className, dataTestId, children, range, onChange, disabled, isInvalid, }) => {
|
|
1606
|
-
const [timeRange, setTimeRange] =
|
|
1606
|
+
const [timeRange, setTimeRange] = useState(range ?? {
|
|
1607
1607
|
timeFrom: "",
|
|
1608
1608
|
timeTo: "",
|
|
1609
1609
|
});
|
|
@@ -1630,7 +1630,7 @@ const cvaScheduleItemText = cvaMerge(["flex", "font-bold", "self-center"]);
|
|
|
1630
1630
|
* Schedule is used to create a time range entries.
|
|
1631
1631
|
*
|
|
1632
1632
|
* @param {ScheduleProps} props - The props for the Schedule component
|
|
1633
|
-
* @returns {
|
|
1633
|
+
* @returns {ReactElement} Schedule component
|
|
1634
1634
|
*/
|
|
1635
1635
|
const Schedule = ({ className, dataTestId, schedule, onChange, invalidKeys = [] }) => {
|
|
1636
1636
|
const [t] = useTranslation();
|
|
@@ -1786,7 +1786,7 @@ const hasConsecutiveDays = (schedule) => {
|
|
|
1786
1786
|
*
|
|
1787
1787
|
* NOTE: If shown with a label, please use the `TextField` component instead.
|
|
1788
1788
|
*/
|
|
1789
|
-
const TextInput =
|
|
1789
|
+
const TextInput = ({ ref, ...rest }) => jsx(BaseInput, { ref: ref, type: "text", ...rest });
|
|
1790
1790
|
TextInput.displayName = "TextInput";
|
|
1791
1791
|
|
|
1792
1792
|
const cvaSearch = cvaMerge([
|
|
@@ -1817,15 +1817,14 @@ const cvaSearch = cvaMerge([
|
|
|
1817
1817
|
* The Search component is used to render a search input field.
|
|
1818
1818
|
*
|
|
1819
1819
|
* @param {SearchProps} props - The props for the Search component
|
|
1820
|
-
* @returns {JSX.Element} Search component
|
|
1821
1820
|
*/
|
|
1822
|
-
const Search =
|
|
1821
|
+
const Search = ({ className, placeholder = "Search", value, widenInputOnFocus, hideBorderWhenNotInFocus = false, disabled, onKeyUp, onChange, onFocus, onBlur, name, onClear, dataTestId, autoComplete = "on", loading, inputClassName, iconName = "MagnifyingGlass", style, xMarkRef, ref, ...rest }) => {
|
|
1823
1822
|
return (jsx(TextInput, { ...rest, autoComplete: autoComplete, className: cvaSearch({ className, border: hideBorderWhenNotInFocus, widenOnFocus: widenInputOnFocus }), dataTestId: dataTestId, disabled: disabled, inputClassName: inputClassName, name: name, onBlur: onBlur, onChange: onChange, onFocus: onFocus, onKeyUp: onKeyUp, placeholder: placeholder, prefix: loading ? (jsx(Spinner, { centering: "centered", size: rest.fieldSize ?? undefined })) : (jsx(Icon, { name: iconName, size: rest.fieldSize ?? undefined })), ref: ref, suffix:
|
|
1824
1823
|
//only show the clear button if there is a value and the onClear function is provided
|
|
1825
1824
|
onClear && value ? (jsx("button", { className: "flex", "data-testid": dataTestId ? `${dataTestId}_suffix_component` : null, onClick: () => {
|
|
1826
1825
|
onClear();
|
|
1827
1826
|
}, ref: xMarkRef, type: "button", children: jsx(Icon, { name: "XMark", size: "small" }) })) : undefined, value: value }));
|
|
1828
|
-
}
|
|
1827
|
+
};
|
|
1829
1828
|
Search.displayName = "Search";
|
|
1830
1829
|
|
|
1831
1830
|
const cvaSelect = cvaMerge([
|
|
@@ -1929,7 +1928,7 @@ const cvaSelectMenu = cvaMerge(["relative", "p-1", "grid", "gap-1"]);
|
|
|
1929
1928
|
* A single select menu item is a basic wrapper around Menu item designed to be used as a single value render in Select list
|
|
1930
1929
|
*
|
|
1931
1930
|
* @param {SelectMenuItemProps} props - The props for the SingleSelectMenuItem
|
|
1932
|
-
* @returns {
|
|
1931
|
+
* @returns {ReactElement} SingleSelectMenuItem
|
|
1933
1932
|
*/
|
|
1934
1933
|
const SingleSelectMenuItem = ({ label, icon, onClick, selected, dataTestId, disabled, optionLabelDescription, fieldSize, }) => {
|
|
1935
1934
|
return (jsx(MenuItem, { dataTestId: dataTestId, disabled: disabled, fieldSize: fieldSize, label: label, onClick: onClick, optionLabelDescription: optionLabelDescription, prefix: icon, selected: selected, suffix: selected ? jsx(Icon, { className: "block text-blue-600", name: "Check", size: "medium" }) : undefined }));
|
|
@@ -1938,7 +1937,7 @@ const SingleSelectMenuItem = ({ label, icon, onClick, selected, dataTestId, disa
|
|
|
1938
1937
|
* A multi select menu item is a basic wrapper around Menu item designed to be used as a multi value render in Select list
|
|
1939
1938
|
*
|
|
1940
1939
|
* @param {SelectMenuItemProps} props - The props for the MultiSelectMenuItem
|
|
1941
|
-
* @returns {
|
|
1940
|
+
* @returns {ReactElement} multi select menu item
|
|
1942
1941
|
*/
|
|
1943
1942
|
const MultiSelectMenuItem = ({ label, onClick, selected, dataTestId, disabled, optionLabelDescription, fieldSize, }) => {
|
|
1944
1943
|
return (jsx(MenuItem, { dataTestId: dataTestId, disabled: disabled, fieldSize: fieldSize, label: label, onClick: e => {
|
|
@@ -1954,11 +1953,11 @@ const MultiSelectMenuItem = ({ label, onClick, selected, dataTestId, disabled, o
|
|
|
1954
1953
|
* Used in the select component.
|
|
1955
1954
|
*
|
|
1956
1955
|
* @param {TagProps} props - The props for the tag component
|
|
1957
|
-
* @returns {
|
|
1956
|
+
* @returns {ReactElement} TagWithWidth component
|
|
1958
1957
|
*/
|
|
1959
1958
|
const TagWithWidth = ({ onWidthKnown, children, ...rest }) => {
|
|
1960
|
-
const ref =
|
|
1961
|
-
|
|
1959
|
+
const ref = useRef(null);
|
|
1960
|
+
useLayoutEffect(() => {
|
|
1962
1961
|
onWidthKnown && onWidthKnown({ width: ref.current?.offsetWidth || 0 });
|
|
1963
1962
|
}, [ref, onWidthKnown]);
|
|
1964
1963
|
return (jsx(Tag, { ref: ref, ...rest, children: children }));
|
|
@@ -1968,16 +1967,16 @@ const TagWithWidth = ({ onWidthKnown, children, ...rest }) => {
|
|
|
1968
1967
|
* TagsContainer component to display tags in limited space when children can't fit space it displays counter
|
|
1969
1968
|
*
|
|
1970
1969
|
* @param {TagsContainerProps} props - The props for the TagContainer
|
|
1971
|
-
* @returns {
|
|
1970
|
+
* @returns {ReactElement} TagsContainer
|
|
1972
1971
|
*/
|
|
1973
1972
|
const TagsContainer = ({ items, width = "100%", itemsGap = 5, postFix, disabled }) => {
|
|
1974
|
-
const [isReady, setIsReady] =
|
|
1975
|
-
const [counterWidth, setCounterWidth] =
|
|
1976
|
-
const containerRef =
|
|
1977
|
-
const availableWidth =
|
|
1978
|
-
const childrenWidth =
|
|
1973
|
+
const [isReady, setIsReady] = useState(false);
|
|
1974
|
+
const [counterWidth, setCounterWidth] = useState(0);
|
|
1975
|
+
const containerRef = useRef(null);
|
|
1976
|
+
const availableWidth = useRef(undefined);
|
|
1977
|
+
const childrenWidth = useRef([]);
|
|
1979
1978
|
const itemsCount = items.length;
|
|
1980
|
-
|
|
1979
|
+
useLayoutEffect(() => {
|
|
1981
1980
|
availableWidth.current = containerRef.current?.offsetWidth || 0;
|
|
1982
1981
|
}, [containerRef]);
|
|
1983
1982
|
const onWidthKnownHandler = ({ width: reportedWidth }) => {
|
|
@@ -2033,12 +2032,12 @@ const TagsContainer = ({ items, width = "100%", itemsGap = 5, postFix, disabled
|
|
|
2033
2032
|
* @param {Partial<SelectComponents<Option, IsMulti, Group>> | undefined} componentsProps a custom component prop that you can to override defaults
|
|
2034
2033
|
* @param {boolean} disabled decide to override disabled variant
|
|
2035
2034
|
* @param {boolean} menuIsOpen menu is open state
|
|
2036
|
-
* @param {
|
|
2035
|
+
* @param {RefObject<boolean>} refMenuIsEnabled a flag to block menu from open
|
|
2037
2036
|
* @param {string} dataTestId a test id
|
|
2038
2037
|
* @param {number} maxSelectedDisplayCount a number of max display count
|
|
2039
|
-
* @param {
|
|
2038
|
+
* @param {ReactElement} dropdownIcon an custom dropdown icon
|
|
2040
2039
|
* @param {boolean} hasError decide to override hasError variant
|
|
2041
|
-
* @param {
|
|
2040
|
+
* @param {ReactElement} prefix a prefix element
|
|
2042
2041
|
* @returns {Partial<SelectComponents<Option, boolean, GroupBase<Option>>> | undefined} components object to override react-select default components
|
|
2043
2042
|
*/
|
|
2044
2043
|
const useCustomComponents = ({ componentsProps, disabled, readOnly, refMenuIsEnabled, dataTestId, maxSelectedDisplayCount, dropdownIcon, prefix, hasError, fieldSize, getOptionLabelDescription, }) => {
|
|
@@ -2079,7 +2078,7 @@ const useCustomComponents = ({ componentsProps, disabled, readOnly, refMenuIsEna
|
|
|
2079
2078
|
})
|
|
2080
2079
|
: null, tags && tags.length > maxSelectedDisplayCount ? (jsxs(Tag, { color: "neutral", dataTestId: "counter-tag", children: ["+", tags.length - maxSelectedDisplayCount] })) : null, searchInput] })) }));
|
|
2081
2080
|
}
|
|
2082
|
-
return (jsx(components.ValueContainer, { ...props, isDisabled: props.selectProps.isDisabled, children: props.children }));
|
|
2081
|
+
return (jsx(Fragment, { children: jsx(components.ValueContainer, { ...props, isDisabled: props.selectProps.isDisabled, children: props.children }) }));
|
|
2083
2082
|
},
|
|
2084
2083
|
LoadingIndicator: () => {
|
|
2085
2084
|
return jsx(Spinner, { centering: "vertically", className: "mr-2", size: "small" });
|
|
@@ -2261,8 +2260,8 @@ const useCustomStyles = ({ refContainer, refPrefix, maxSelectedDisplayCount, sty
|
|
|
2261
2260
|
* @returns {UseSelectProps} Select component
|
|
2262
2261
|
*/
|
|
2263
2262
|
const useSelect = ({ 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, getOptionLabelDescription, fieldSize = "medium", ...props }) => {
|
|
2264
|
-
const refContainer =
|
|
2265
|
-
const refPrefix =
|
|
2263
|
+
const refContainer = useRef(document.createElement("div"));
|
|
2264
|
+
const refPrefix = useRef(document.createElement("div"));
|
|
2266
2265
|
const { customStyles } = useCustomStyles({
|
|
2267
2266
|
refContainer,
|
|
2268
2267
|
refPrefix,
|
|
@@ -2271,8 +2270,8 @@ const useSelect = ({ id, className, dataTestId = "select", prefix, async, dropdo
|
|
|
2271
2270
|
disabled: Boolean(disabled),
|
|
2272
2271
|
fieldSize,
|
|
2273
2272
|
});
|
|
2274
|
-
const [menuIsOpen, setMenuIsOpen] =
|
|
2275
|
-
const refMenuIsEnabled =
|
|
2273
|
+
const [menuIsOpen, setMenuIsOpen] = useState(props.menuIsOpen ?? false);
|
|
2274
|
+
const refMenuIsEnabled = useRef(true);
|
|
2276
2275
|
const customComponents = useCustomComponents({
|
|
2277
2276
|
componentsProps: components,
|
|
2278
2277
|
disabled: Boolean(disabled),
|
|
@@ -2316,7 +2315,7 @@ const useSelect = ({ id, className, dataTestId = "select", prefix, async, dropdo
|
|
|
2316
2315
|
* CreatableSelects are input components used to choose a value from a set.
|
|
2317
2316
|
*
|
|
2318
2317
|
* @param {CreatableSelectProps} props - The props for the CreatableSelect component
|
|
2319
|
-
* @returns {
|
|
2318
|
+
* @returns {ReactElement} CreatableSelect component
|
|
2320
2319
|
*/
|
|
2321
2320
|
const CreatableSelect = (props) => {
|
|
2322
2321
|
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;
|
|
@@ -2388,7 +2387,7 @@ const ReactSyncSelect = ReactSelect.default || ReactSelect;
|
|
|
2388
2387
|
* Selects are input components used to choose a value from a set.
|
|
2389
2388
|
*
|
|
2390
2389
|
* @param {SelectProps} props - The props for the Select component
|
|
2391
|
-
* @returns {
|
|
2390
|
+
* @returns {ReactElement} Select component
|
|
2392
2391
|
*/
|
|
2393
2392
|
const Select = (props) => {
|
|
2394
2393
|
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 = !disabled, hideSelectedOptions = false, } = props;
|
|
@@ -2459,7 +2458,10 @@ const Select = (props) => {
|
|
|
2459
2458
|
};
|
|
2460
2459
|
Select.displayName = "Select";
|
|
2461
2460
|
|
|
2462
|
-
|
|
2461
|
+
/**
|
|
2462
|
+
*
|
|
2463
|
+
*/
|
|
2464
|
+
const FormFieldSelectAdapter = ({ className, dataTestId, helpText, helpAddon, tip, label, isInvalid, errorMessage, name, onBlur, options, value, defaultValue, id, onChange, children, ref, ...rest }) => {
|
|
2463
2465
|
const isFirstRender = useIsFirstRender();
|
|
2464
2466
|
const [innerValue, setInnerValue] = useState(value || defaultValue);
|
|
2465
2467
|
useEffect(() => {
|
|
@@ -2513,7 +2515,7 @@ const FormFieldSelectAdapter = forwardRef(({ className, dataTestId, helpText, he
|
|
|
2513
2515
|
value: selectedOption,
|
|
2514
2516
|
defaultValue: selectedOption,
|
|
2515
2517
|
})] }));
|
|
2516
|
-
}
|
|
2518
|
+
};
|
|
2517
2519
|
FormFieldSelectAdapter.displayName = "FormFieldSelectAdapter";
|
|
2518
2520
|
|
|
2519
2521
|
/**
|
|
@@ -2524,12 +2526,11 @@ FormFieldSelectAdapter.displayName = "FormFieldSelectAdapter";
|
|
|
2524
2526
|
* This is done to make the field compatible with the React-hook-form library.
|
|
2525
2527
|
*
|
|
2526
2528
|
* @param {SelectFieldProps & CreatableSelectProps} props - The props for the CreatableSelectField component
|
|
2527
|
-
* @returns {JSX.Element} CreatableSelectField component
|
|
2528
2529
|
*/
|
|
2529
|
-
const CreatableSelectField =
|
|
2530
|
+
const CreatableSelectField = ({ allowCreateWhileLoading, onCreateOption, ref, ...props }) => {
|
|
2530
2531
|
const creatableSelectOnlyProps = { allowCreateWhileLoading, onCreateOption };
|
|
2531
2532
|
return (jsx(FormFieldSelectAdapter, { ...props, ref: ref, children: convertedProps => jsx(CreatableSelect, { ...convertedProps, ...creatableSelectOnlyProps }) }));
|
|
2532
|
-
}
|
|
2533
|
+
};
|
|
2533
2534
|
CreatableSelectField.displayName = "CreatableSelectField";
|
|
2534
2535
|
|
|
2535
2536
|
/**
|
|
@@ -2540,11 +2541,10 @@ CreatableSelectField.displayName = "CreatableSelectField";
|
|
|
2540
2541
|
* This is done to make the field compatible with the React-hook-form library.
|
|
2541
2542
|
*
|
|
2542
2543
|
* @param {SelectFieldProps} props - The props for the SelectField component
|
|
2543
|
-
* @returns {JSX.Element} SelectField component
|
|
2544
2544
|
*/
|
|
2545
|
-
const SelectField =
|
|
2545
|
+
const SelectField = ({ ref, ...props }) => {
|
|
2546
2546
|
return (jsx(FormFieldSelectAdapter, { ...props, ref: ref, children: convertedProps => jsx(Select, { ...convertedProps }) }));
|
|
2547
|
-
}
|
|
2547
|
+
};
|
|
2548
2548
|
SelectField.displayName = "SelectField";
|
|
2549
2549
|
|
|
2550
2550
|
const cvaTextArea = cvaMerge([
|
|
@@ -2583,9 +2583,9 @@ const cvaTextArea = cvaMerge([
|
|
|
2583
2583
|
* The TextArea is a base component, and should not be used very often.
|
|
2584
2584
|
* For most cases the TextAreaField is the correct component.
|
|
2585
2585
|
*/
|
|
2586
|
-
const TextArea =
|
|
2586
|
+
const TextArea = ({ id, name, value, rows, disabled, placeholder, readOnly, tabIndex, onChange, onFocus, onBlur, maxLength, resize = "vertical", defaultValue, required, dataTestId, isInvalid, className, ref, ...rest }) => {
|
|
2587
2587
|
return (jsx("textarea", { className: cvaTextArea({ 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 }));
|
|
2588
|
-
}
|
|
2588
|
+
};
|
|
2589
2589
|
TextArea.displayName = "TextArea";
|
|
2590
2590
|
|
|
2591
2591
|
/**
|
|
@@ -2593,17 +2593,20 @@ TextArea.displayName = "TextArea";
|
|
|
2593
2593
|
* Used for TextFields to communicate a maximum allowed input length.
|
|
2594
2594
|
*
|
|
2595
2595
|
* @param {TextLengthIndicatorProps} props - The props for the TextLengthIndicator component
|
|
2596
|
-
* @returns {
|
|
2596
|
+
* @returns {ReactElement} TextLengthIndicator component
|
|
2597
2597
|
*/
|
|
2598
2598
|
const TextLengthIndicator = ({ length, maxLength }) => {
|
|
2599
2599
|
return (jsxs("span", { className: "font-mono", children: [length, "/", maxLength] }));
|
|
2600
2600
|
};
|
|
2601
2601
|
|
|
2602
|
-
|
|
2603
|
-
|
|
2602
|
+
/**
|
|
2603
|
+
*
|
|
2604
|
+
*/
|
|
2605
|
+
const TextAreaField = ({ id, label, tip, helpText, helpAddon, errorMessage, isInvalid, maxLength, onChange, className, value, dataTestId, ref, ...rest }) => {
|
|
2606
|
+
const [valueLength, setValueLength] = useState(value ? `${value}`.length : 0);
|
|
2604
2607
|
const renderAsInvalid = isInvalid || Boolean(errorMessage);
|
|
2605
2608
|
const htmlForId = id ? id : "textAreaField-" + uuidv4();
|
|
2606
|
-
const handleChange =
|
|
2609
|
+
const handleChange = useCallback((event) => {
|
|
2607
2610
|
setValueLength(event.target.value.length);
|
|
2608
2611
|
if (onChange) {
|
|
2609
2612
|
onChange(event);
|
|
@@ -2611,17 +2614,17 @@ const TextAreaField = React.forwardRef(({ id, label, tip, helpText, helpAddon, e
|
|
|
2611
2614
|
}, [onChange]);
|
|
2612
2615
|
return (jsx(FormGroup, { className: twMerge(className, "grid", "grid-rows-[auto_1fr_auto]"), dataTestId: dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon ||
|
|
2613
2616
|
(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(TextArea, { "aria-labelledby": htmlForId + "-label", id: htmlForId, isInvalid: renderAsInvalid, maxLength: maxLength, ref: ref, value: value, ...rest, className: "h-auto", dataTestId: dataTestId, onChange: handleChange }) }));
|
|
2614
|
-
}
|
|
2617
|
+
};
|
|
2615
2618
|
TextAreaField.displayName = "TextAreaField";
|
|
2616
2619
|
|
|
2617
2620
|
/**
|
|
2618
2621
|
* 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.
|
|
2619
2622
|
*/
|
|
2620
|
-
const TextField =
|
|
2621
|
-
const [valueLength, setValueLength] =
|
|
2623
|
+
const TextField = ({ id, label, tip, helpText, helpAddon, errorMessage, isInvalid, maxLength, onChange, className, value, dataTestId, isWarning, ref, ...rest }) => {
|
|
2624
|
+
const [valueLength, setValueLength] = useState(value ? `${value}`.length : 0);
|
|
2622
2625
|
const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
|
|
2623
2626
|
const htmlFor = id ? id : "textField-" + uuidv4();
|
|
2624
|
-
const handleChange =
|
|
2627
|
+
const handleChange = useCallback((event) => {
|
|
2625
2628
|
setValueLength(event.target.value.length);
|
|
2626
2629
|
if (onChange) {
|
|
2627
2630
|
onChange(event);
|
|
@@ -2629,14 +2632,14 @@ const TextField = React.forwardRef(({ id, label, tip, helpText, helpAddon, error
|
|
|
2629
2632
|
}, [onChange]);
|
|
2630
2633
|
return (jsx(FormGroup, { dataTestId: dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon ||
|
|
2631
2634
|
(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(TextInput, { "aria-labelledby": htmlFor + "-label", id: htmlFor, isInvalid: renderAsInvalid, isWarning: isWarning, maxLength: maxLength, ref: ref, value: value, ...rest, className: className, dataTestId: dataTestId, onChange: handleChange }) }));
|
|
2632
|
-
}
|
|
2635
|
+
};
|
|
2633
2636
|
TextField.displayName = "TextField";
|
|
2634
2637
|
|
|
2635
2638
|
/**
|
|
2636
2639
|
* TimeRangeField Description. <-- Please add a proper Description this is used in Storybook.
|
|
2637
2640
|
*
|
|
2638
2641
|
* @param {TimeRangeFieldProps} props - The props for the TimeRangeField component
|
|
2639
|
-
* @returns {
|
|
2642
|
+
* @returns {ReactElement} TimeRangeField component
|
|
2640
2643
|
*/
|
|
2641
2644
|
const TimeRangeField = ({ className, dataTestId, onChange, isInvalid, errorMessage, label, tip, children, helpText, id, ...rest }) => {
|
|
2642
2645
|
const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
|
|
@@ -2797,23 +2800,23 @@ const cvaUploadInputField = cvaMerge([
|
|
|
2797
2800
|
*
|
|
2798
2801
|
* NOTE: If shown with a label, please use the `UploadField` component instead.
|
|
2799
2802
|
*/
|
|
2800
|
-
const UploadInput =
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2803
|
+
const UploadInput = ({ disabled, acceptedTypes, nonInteractive, uploadLabel, multipleFiles, ref, ...rest }) => (jsx("label", { className: "tu-upload-input", children: jsx(BaseInput, { accept: acceptedTypes, addonBefore: uploadLabel, disabled: disabled, inputClassName: cvaUploadInputField(), multiple: multipleFiles, nonInteractive: nonInteractive, onClick: event => {
|
|
2804
|
+
// onClick used to work with nonInteractive option
|
|
2805
|
+
if (nonInteractive) {
|
|
2806
|
+
event.preventDefault();
|
|
2807
|
+
event.stopPropagation();
|
|
2808
|
+
}
|
|
2809
|
+
}, ref: ref, type: "file", ...rest }) }));
|
|
2807
2810
|
UploadInput.displayName = "UploadInput";
|
|
2808
2811
|
|
|
2809
2812
|
/**
|
|
2810
2813
|
* Upload fields enable the user to upload Files.
|
|
2811
2814
|
*/
|
|
2812
|
-
const UploadField =
|
|
2815
|
+
const UploadField = ({ label, id, tip, helpText, errorMessage, isInvalid, className, value, dataTestId, ref, ...rest }) => {
|
|
2813
2816
|
const renderAsInvalid = isInvalid || Boolean(errorMessage);
|
|
2814
2817
|
const htmlForId = id ? id : "uploadField-" + uuidv4();
|
|
2815
2818
|
return (jsx(FormGroup, { dataTestId: `${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, dataTestId: dataTestId }) }));
|
|
2816
|
-
}
|
|
2819
|
+
};
|
|
2817
2820
|
UploadField.displayName = "UploadField";
|
|
2818
2821
|
|
|
2819
2822
|
/**
|
|
@@ -2852,11 +2855,11 @@ const validateUrl = (url, required) => {
|
|
|
2852
2855
|
*
|
|
2853
2856
|
* NOTE: If shown with a label, please use the `UrlField` component instead.
|
|
2854
2857
|
*/
|
|
2855
|
-
const UrlInput =
|
|
2858
|
+
const UrlInput = ({ dataTestId, isInvalid, disabled = false, fieldSize = "medium", disableAction = false, value, defaultValue, ref, ...rest }) => {
|
|
2856
2859
|
const [url, setUrl] = useState(value?.toString() || defaultValue?.toString());
|
|
2857
2860
|
const renderAsInvalid = (url && typeof url === "string" && !validateUrlAddress(url)) || isInvalid;
|
|
2858
2861
|
return (jsx(BaseInput, { dataTestId: 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, { dataTestId: (dataTestId && `${dataTestId}-url-input-Icon`) || "url-input-action-icon", disabled: renderAsInvalid || Boolean(disabled) || disableAction, size: fieldSize ?? undefined, type: "WEB_ADDRESS", value: url })) }));
|
|
2859
|
-
}
|
|
2862
|
+
};
|
|
2860
2863
|
UrlInput.displayName = "UrlField";
|
|
2861
2864
|
|
|
2862
2865
|
/**
|
|
@@ -2864,7 +2867,7 @@ UrlInput.displayName = "UrlField";
|
|
|
2864
2867
|
* UrlField validates that user enters a valid web address.
|
|
2865
2868
|
*
|
|
2866
2869
|
*/
|
|
2867
|
-
const UrlField =
|
|
2870
|
+
const UrlField = ({ label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, dataTestId, isInvalid = false, value, onBlur, ref, ...rest }) => {
|
|
2868
2871
|
const htmlForId = id ? id : "urlField-" + uuidv4();
|
|
2869
2872
|
const [t] = useTranslation();
|
|
2870
2873
|
const [innerValue, setInnerValue] = useState(() => {
|
|
@@ -2880,7 +2883,7 @@ const UrlField = forwardRef(({ label, id, tip, helpText, errorMessage, helpAddon
|
|
|
2880
2883
|
onBlur?.(event);
|
|
2881
2884
|
}, [onBlur, rest.required]);
|
|
2882
2885
|
return (jsx(FormGroup, { dataTestId: 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(UrlInput, { "aria-labelledby": htmlForId + "-label", id: htmlForId, isInvalid: renderAsInvalid, onBlur: handleBlur, ref: ref, value: value || defaultValue, ...rest, className: className, dataTestId: dataTestId }) }));
|
|
2883
|
-
}
|
|
2886
|
+
};
|
|
2884
2887
|
UrlField.displayName = "UrlField";
|
|
2885
2888
|
|
|
2886
2889
|
/**
|