@trackunit/react-form-components 1.10.11 → 1.10.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.cjs.js CHANGED
@@ -821,7 +821,7 @@ const CounterTag = ({ fieldSize, hiddenCount, totalCount, ref, className, "data-
821
821
  if (hiddenCount === 0) {
822
822
  return null;
823
823
  }
824
- return (jsxRuntime.jsx(reactComponents.Tag, { className: tailwindMerge.twMerge("inline-flex shrink-0", className), color: "neutral", "data-testid": dataTestId ?? "select-counter", ref: ref, size: fieldSize === "small" ? "small" : "medium", children: totalCount > hiddenCount ? `+${hiddenCount}` : hiddenCount }));
824
+ return (jsxRuntime.jsx(reactComponents.Tag, { className: className, color: "neutral", "data-testid": dataTestId ?? "select-counter", ref: ref, size: fieldSize === "small" ? "small" : "medium", children: totalCount > hiddenCount ? `+${hiddenCount}` : hiddenCount }));
825
825
  };
826
826
 
827
827
  /**
@@ -837,7 +837,7 @@ const MultiValue = ({ data, children, onClose, className, disabled, fieldSize, g
837
837
  e.stopPropagation();
838
838
  onClose?.(e);
839
839
  };
840
- return (jsxRuntime.jsx(reactComponents.Tag, { className: tailwindMerge.twMerge(className, "shrink-0", "inline-flex"), color: disabled ? "neutral" : "white", "data-testid": dataTestId, icon: optionPrefix, onClose: disabled ? undefined : handleOnClose, ref: ref, size: fieldSize === "small" ? "small" : "medium", children: jsxRuntime.jsx("span", { className: "flex items-center gap-1", children: children }) }));
840
+ return (jsxRuntime.jsx(reactComponents.Tag, { className: tailwindMerge.twMerge(className), color: disabled ? "neutral" : "white", "data-testid": dataTestId, icon: optionPrefix, onClose: disabled ? undefined : handleOnClose, ref: ref, size: fieldSize === "small" ? "small" : "medium", children: jsxRuntime.jsx("span", { className: "flex items-center gap-1", children: children }) }));
841
841
  };
842
842
 
843
843
  /**
@@ -911,31 +911,33 @@ const CheckIcon = ({ className, "data-testid": dataTestId }) => {
911
911
  return (jsxRuntime.jsx("svg", { className: className, "data-testid": dataTestId, fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 10 10", xmlns: "http://www.w3.org/2000/svg", children: jsxRuntime.jsx("path", { d: "m2 5.5 2 2L8.5 3", strokeLinecap: "round", strokeLinejoin: "round" }) }));
912
912
  };
913
913
 
914
+ /**
915
+ * Checkbox input styling - directly styles the input element (no wrapper span needed).
916
+ * Uses appearance-none to remove native styling, similar to RadioItem.
917
+ */
914
918
  const cvaCheckbox = cssClassVarianceUtilities.cvaMerge([
919
+ "appearance-none",
915
920
  "w-4",
916
921
  "h-4",
917
922
  "border-solid",
918
923
  "border",
919
924
  "shrink-0",
920
925
  "border-neutral-300",
921
- "flex",
922
926
  "rounded",
923
927
  "hover:bg-neutral-100",
924
928
  "bg-white",
925
- "items-center",
926
929
  "shadow-sm",
927
- "justify-center",
928
930
  "box-border",
929
931
  "transition",
930
- "outline-0",
932
+ "cursor-pointer",
931
933
  "active:bg-neutral-200",
932
934
  "active:ring-2",
933
935
  "active:ring-inset",
934
936
  "active:ring-primary-700",
935
- "cursor-pointer",
936
937
  "group-active:ring-2",
937
938
  "group-active:ring-inset",
938
939
  "group-active:ring-primary-700",
940
+ "focus:outline-native",
939
941
  ], {
940
942
  variants: {
941
943
  invalid: {
@@ -1008,7 +1010,17 @@ const cvaCheckbox = cssClassVarianceUtilities.cvaMerge([
1008
1010
  state: "deselected",
1009
1011
  },
1010
1012
  });
1011
- const cvaCheckboxInput = cssClassVarianceUtilities.cvaMerge(["absolute", "opacity-0", "m-0", "pointer-events-none", "hidden"]);
1013
+ /**
1014
+ * Icon overlay container - positioned on top of the input, receives no pointer events
1015
+ */
1016
+ const cvaCheckboxIconOverlay = cssClassVarianceUtilities.cvaMerge([
1017
+ "flex",
1018
+ "items-center",
1019
+ "justify-center",
1020
+ "w-4",
1021
+ "h-4",
1022
+ "pointer-events-none",
1023
+ ]);
1012
1024
  const cvaCheckboxIcon = cssClassVarianceUtilities.cvaMerge(["w-2.5", "h-2.5", "text-white"]);
1013
1025
 
1014
1026
  /**
@@ -1032,36 +1044,21 @@ const IndeterminateIcon = ({ className }) => (jsxRuntime.jsx("svg", { className:
1032
1044
  * @augments props from [React.InputHTMLAttributes](https://reactjs.org/docs/dom-elements.html#input)
1033
1045
  * @param {CheckboxProps} props - The props for the Checkbox component
1034
1046
  */
1035
- const Checkbox = ({ className, "data-testid": dataTestId = "checkbox", onChange, checked = false, disabled = false, isInvalid = false, readOnly, indeterminate = false, suffix, label, tabIndex = 0, stopPropagation, ref, ...rest }) => {
1036
- const icon = indeterminate ? (jsxRuntime.jsx(IndeterminateIcon, { className: cvaCheckboxIcon() })) : (checked && jsxRuntime.jsx(CheckIcon, { className: cvaCheckboxIcon() }));
1037
- const internalRef = react.useRef(null);
1047
+ const Checkbox = ({ className, "data-testid": dataTestId = "checkbox", onChange, checked = false, disabled = false, isInvalid = false, readOnly = false, indeterminate = false, suffix, label, tabIndex = 0, stopPropagation = false, ref, ...rest }) => {
1038
1048
  const { isTextTruncated: isLabelCutOff, ref: labelRef } = reactComponents.useIsTextTruncated();
1039
1049
  const isReadonly = disabled || readOnly;
1040
1050
  const hasLabel = label !== undefined && label !== null && label !== "";
1041
- const onKeyPress = e => {
1042
- if (isReadonly) {
1043
- e.preventDefault();
1044
- return;
1045
- }
1046
- if ("Space" === e.code) {
1047
- e.preventDefault();
1048
- internalRef.current?.click();
1049
- }
1050
- if ("Enter" === e.code) {
1051
- internalRef.current?.click();
1052
- }
1053
- };
1054
- const uuid = rest.id;
1051
+ const state = indeterminate ? "indeterminate" : checked ? "selected" : "deselected";
1055
1052
  return (jsxRuntime.jsxs("label", { className: hasLabel
1056
1053
  ? cvaBinaryControlWrapper({ className })
1057
- : `inline-flex w-fit items-center gap-2${isReadonly ? " pointer-events-none" : ""}${className ? ` ${className}` : ""}`, "data-testid": dataTestId ? `${dataTestId}-container` : null, htmlFor: uuid, onClick: e => stopPropagation && e.stopPropagation(), onKeyDown: onKeyPress, ref: internalRef, children: [jsxRuntime.jsxs("div", { className: "self-center", children: [jsxRuntime.jsx("input", { "aria-checked": !indeterminate && checked, checked: !indeterminate && checked, className: cvaCheckboxInput(), "data-testid": dataTestId, disabled: disabled, id: uuid, onChange: onChange, readOnly: readOnly, ref: ref, type: "checkbox", ...rest }), jsxRuntime.jsx("span", { className: cvaCheckbox({
1054
+ : `inline-flex w-fit items-center gap-2${isReadonly ? " pointer-events-none" : ""}${className ? ` ${className}` : ""}`, "data-testid": dataTestId ? `${dataTestId}-container` : null, onClick: e => stopPropagation && e.stopPropagation(), children: [jsxRuntime.jsxs(reactComponents.ZStack, { className: "h-4 w-4 self-center", children: [jsxRuntime.jsx("input", { "aria-checked": indeterminate ? "mixed" : checked, checked: !indeterminate && checked, className: cvaCheckbox({
1058
1055
  disabled: isReadonly,
1059
1056
  invalid: isReadonly ? false : isInvalid,
1060
- state: indeterminate ? "indeterminate" : checked ? "selected" : "deselected",
1061
- }), id: uuid, tabIndex: isReadonly ? -1 : tabIndex, children: icon })] }), hasLabel ? (jsxRuntime.jsx(reactComponents.Tooltip, { className: cvaBinaryControlLabelTooltip(), disabled: !isLabelCutOff, label: label, placement: "top", children: jsxRuntime.jsx("span", { className: cvaLabel({
1057
+ state,
1058
+ }), "data-testid": dataTestId, disabled: disabled, onChange: onChange, readOnly: readOnly, ref: ref, tabIndex: isReadonly ? -1 : tabIndex, type: "checkbox", ...rest }), checked || indeterminate ? (jsxRuntime.jsx("div", { className: cvaCheckboxIconOverlay(), children: indeterminate ? (jsxRuntime.jsx(IndeterminateIcon, { className: cvaCheckboxIcon() })) : (jsxRuntime.jsx(CheckIcon, { className: cvaCheckboxIcon() })) })) : null] }), hasLabel ? (jsxRuntime.jsx(reactComponents.Tooltip, { className: cvaBinaryControlLabelTooltip(), disabled: !isLabelCutOff, label: label, placement: "top", children: jsxRuntime.jsx("span", { className: cvaLabel({
1062
1059
  invalid: isReadonly ? false : isInvalid,
1063
1060
  disabled: isReadonly,
1064
- }), id: `checkbox-label-${label}`, ref: labelRef, children: label }) }, "tooltip-" + rest.name)) : null, suffix ? (jsxRuntime.jsx("div", { className: cvaBinaryControlSuffixContainer(), "data-testid": dataTestId ? `${dataTestId}-suffix-container` : undefined, children: suffix })) : null] }));
1061
+ }), id: `checkbox-label-${label}`, ref: labelRef, children: label }) }, "tooltip-" + rest.name)) : null, suffix !== undefined && suffix !== null && suffix !== "" ? (jsxRuntime.jsx("div", { className: cvaBinaryControlSuffixContainer(), "data-testid": dataTestId ? `${dataTestId}-suffix-container` : undefined, children: suffix })) : null] }));
1065
1062
  };
1066
1063
  Checkbox.displayName = "Checkbox";
1067
1064
 
@@ -2797,7 +2794,7 @@ const PhoneFieldWithController = ({ control, controllerProps, name, value, ref,
2797
2794
  };
2798
2795
  PhoneFieldWithController.displayName = "PhoneFieldWithController";
2799
2796
 
2800
- const cvaRadioGroup = cssClassVarianceUtilities.cvaMerge(["flex", "gap-2", "flex-col", "items-start"], {
2797
+ const cvaInputGroup = cssClassVarianceUtilities.cvaMerge(["flex", "gap-2", "flex-col", "items-start"], {
2801
2798
  variants: {
2802
2799
  layout: {
2803
2800
  inline: ["flex", "gap-3", "flex-row", "items-center"],
@@ -2820,7 +2817,7 @@ const cvaRadioItem = cssClassVarianceUtilities.cvaMerge([
2820
2817
  "box-border",
2821
2818
  "hover:cursor-pointer",
2822
2819
  "hover:bg-neutral-100",
2823
- "focus-visible:outline-primary-700",
2820
+ "focus:outline-native",
2824
2821
  ], {
2825
2822
  variants: {
2826
2823
  checked: {
@@ -2831,19 +2828,12 @@ const cvaRadioItem = cssClassVarianceUtilities.cvaMerge([
2831
2828
  "bg-white",
2832
2829
  "hover:bg-neutral-100",
2833
2830
  "hover:cursor-pointer",
2834
- "outline-0",
2835
2831
  "active:bg-neutral-200",
2836
- "active:ring-2",
2837
- "active:ring-inset",
2838
- "active:ring-primary-700",
2839
- "group-active:ring-2",
2840
- "group-active:ring-inset",
2841
- "group-active:ring-primary-700",
2842
2832
  ],
2843
2833
  false: "",
2844
2834
  },
2845
2835
  invalid: {
2846
- true: ["border-red-600", "active:ring-red-700"],
2836
+ true: ["border-red-600"],
2847
2837
  false: "",
2848
2838
  },
2849
2839
  disabled: {
@@ -2853,8 +2843,6 @@ const cvaRadioItem = cssClassVarianceUtilities.cvaMerge([
2853
2843
  "cursor-not-allowed",
2854
2844
  "hover:bg-neutral-400",
2855
2845
  "active:bg-neutral-400",
2856
- "group-active:ring-0",
2857
- "group-active:ring-inset",
2858
2846
  ],
2859
2847
  false: "",
2860
2848
  },
@@ -2882,8 +2870,8 @@ const RadioGroupContext = react.createContext(null);
2882
2870
  * @param {RadioGroupProps} props - The props for the RadioGroup component
2883
2871
  * @returns {ReactElement} RadioGroup component
2884
2872
  */
2885
- const RadioGroup = ({ children, id, name, value, disabled, onChange, label, inline, className, "data-testid": dataTestId, isInvalid, }) => {
2886
- return (jsxRuntime.jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, label: label, children: jsxRuntime.jsx("div", { className: cvaRadioGroup({ layout: inline ? "inline" : null, className }), "data-testid": dataTestId, children: jsxRuntime.jsx(RadioGroupContext.Provider, { value: {
2873
+ const RadioGroup = ({ children, id, name, value, disabled, onChange, label, inline = false, className, "data-testid": dataTestId, isInvalid, }) => {
2874
+ return (jsxRuntime.jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, label: label, children: jsxRuntime.jsx("div", { className: cvaInputGroup({ layout: inline ? "inline" : null, className }), "data-testid": dataTestId, role: "radiogroup", children: jsxRuntime.jsx(RadioGroupContext.Provider, { value: {
2887
2875
  id,
2888
2876
  value,
2889
2877
  name: name || id,
@@ -2900,24 +2888,35 @@ RadioGroup.displayName = "RadioGroup";
2900
2888
  * @param {RadioItemProps} props - The props for the RadioItem component
2901
2889
  * @returns {ReactElement} RadioItem component
2902
2890
  */
2903
- const RadioItem = ({ label, value, "data-testid": dataTestId, className, description, suffix, ...rest }) => {
2891
+ const RadioItem = ({ label, value, "data-testid": dataTestId, className, description, suffix, tabIndex, ...rest }) => {
2904
2892
  const groupCtx = react.useContext(RadioGroupContext);
2905
2893
  const isChecked = groupCtx?.value === value;
2894
+ // Empty string is treated as "no selection" to allow tabbing into the group when no radio is checked
2895
+ const hasGroupValue = groupCtx?.value !== undefined && groupCtx.value !== "";
2896
+ const inputRef = react.useRef(null);
2897
+ const wasCheckedRef = react.useRef(isChecked);
2906
2898
  const { ref: labelRef, isTextTruncated: isLabelTruncated } = reactComponents.useIsTextTruncated();
2907
2899
  const { ref: descriptionRef, isTextTruncated: isDescriptionTruncated } = reactComponents.useIsTextTruncated();
2908
2900
  const descriptionId = description ? `${groupCtx?.id}-${value}-description` : undefined;
2909
2901
  const inputId = `${groupCtx?.id}-${value}`;
2910
2902
  const hasLabel = label !== undefined && label !== null && label !== "";
2903
+ // Restore focus after React re-render when this radio becomes checked via arrow keys
2904
+ react.useEffect(() => {
2905
+ if (isChecked && !wasCheckedRef.current) {
2906
+ inputRef.current?.focus();
2907
+ }
2908
+ wasCheckedRef.current = isChecked;
2909
+ }, [isChecked]);
2911
2910
  return (jsxRuntime.jsxs("label", { className: hasLabel
2912
2911
  ? cvaBinaryControlWrapper({ className })
2913
- : `inline-flex w-fit items-center gap-2 ${className || ""}`.trim(), "data-testid": dataTestId ? `${dataTestId}-Wrapper` : undefined, htmlFor: inputId, children: [jsxRuntime.jsx("input", { "aria-describedby": descriptionId, checked: isChecked, className: cvaRadioItem({
2912
+ : `inline-flex w-fit items-center gap-2 ${className || ""}`.trim(), "data-testid": dataTestId ? `${dataTestId}-Wrapper` : undefined, children: [jsxRuntime.jsx("input", { "aria-describedby": descriptionId, checked: isChecked, className: cvaRadioItem({
2914
2913
  checked: isChecked,
2915
2914
  disabled: groupCtx?.disabled,
2916
2915
  invalid: groupCtx?.isInvalid,
2917
- }), "data-testid": dataTestId, id: inputId, onChange: groupCtx?.onChange, type: "radio", value: value, ...rest }), hasLabel ? (jsxRuntime.jsx(reactComponents.Tooltip, { className: cvaBinaryControlLabelTooltip(), "data-testid": dataTestId ? `${dataTestId}-Label-Tooltip` : undefined, disabled: !isLabelTruncated, label: label, placement: "top", children: jsxRuntime.jsx("span", { className: cvaLabel({
2916
+ }), "data-testid": dataTestId, id: inputId, name: groupCtx?.name, onChange: groupCtx?.onChange, ref: inputRef, tabIndex: tabIndex ?? (groupCtx?.disabled ? -1 : isChecked ? 0 : hasGroupValue ? -1 : 0), type: "radio", value: value, ...rest }), hasLabel ? (jsxRuntime.jsx(reactComponents.Tooltip, { className: cvaBinaryControlLabelTooltip(), "data-testid": dataTestId ? `${dataTestId}-Label-Tooltip` : undefined, disabled: !isLabelTruncated, label: label, placement: "top", children: jsxRuntime.jsx("span", { className: cvaLabel({
2918
2917
  invalid: groupCtx?.isInvalid,
2919
2918
  disabled: groupCtx?.disabled,
2920
- }), "data-testid": dataTestId ? `${dataTestId}-Label` : undefined, ref: labelRef, children: label }) }, "tooltip-" + rest.name)) : null, suffix ? (jsxRuntime.jsx("div", { className: cvaBinaryControlSuffixContainer(), "data-testid": dataTestId ? `${dataTestId}-suffix-container` : undefined, children: suffix })) : null, description ? (jsxRuntime.jsx(reactComponents.Tooltip, { className: cvaBinaryControlDescriptionTooltip(), "data-testid": dataTestId ? `${dataTestId}-Description-Tooltip` : undefined, disabled: !isDescriptionTruncated, label: description, placement: "top", children: jsxRuntime.jsx("span", { className: cvaBinaryControlDescription({ disabled: groupCtx?.disabled }), "data-testid": dataTestId ? `${dataTestId}-Description` : undefined, id: descriptionId, ref: descriptionRef, children: description }) }, "description-tooltip-" + rest.name)) : null] }));
2919
+ }), "data-testid": dataTestId ? `${dataTestId}-Label` : undefined, ref: labelRef, children: label }) }, "tooltip-" + rest.name)) : null, suffix !== undefined && suffix !== null && suffix !== "" ? (jsxRuntime.jsx("div", { className: cvaBinaryControlSuffixContainer(), "data-testid": dataTestId ? `${dataTestId}-suffix-container` : undefined, children: suffix })) : null, description ? (jsxRuntime.jsx(reactComponents.Tooltip, { className: cvaBinaryControlDescriptionTooltip(), "data-testid": dataTestId ? `${dataTestId}-Description-Tooltip` : undefined, disabled: !isDescriptionTruncated, label: description, placement: "top", children: jsxRuntime.jsx("span", { className: cvaBinaryControlDescription({ disabled: groupCtx?.disabled }), "data-testid": dataTestId ? `${dataTestId}-Description` : undefined, id: descriptionId, ref: descriptionRef, children: description }) }, "description-tooltip-" + rest.name)) : null] }));
2921
2920
  };
2922
2921
 
2923
2922
  const cvaTimeRange = cssClassVarianceUtilities.cvaMerge([
@@ -3275,7 +3274,14 @@ const TextLengthIndicator = ({ length, maxLength }) => {
3275
3274
  };
3276
3275
 
3277
3276
  /**
3277
+ * Use a text area when you need to allow users to enter a large amount of text, such as a comment or a description.
3278
+ *
3279
+ * _**Do use** Text areas for larger text inputs, such as comments or descriptions._
3280
+ *
3281
+ * _**Do not use** Text areas for small text inputs, such as single-line inputs._
3278
3282
  *
3283
+ * @param {TextAreaFieldProps} props - The props for the TextAreaField component
3284
+ * @returns {ReactElement} TextAreaField component
3279
3285
  */
3280
3286
  const TextAreaField = ({ id, label, tip, helpText, helpAddon, errorMessage, isInvalid, maxLength, onChange, className, value, "data-testid": dataTestId, ref, ...rest }) => {
3281
3287
  const [valueLength, setValueLength] = react.useState(value ? `${value}`.length : 0);
package/index.esm.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { useNamespaceTranslation, registerTranslations, NamespaceTrans } from '@trackunit/i18n-library-translation';
3
3
  import { Temporal } from '@js-temporal/polyfill';
4
- import { IconButton, Icon, Tooltip, cvaMenu, cvaMenuList, Tag, useIsTextTruncated, MenuItem, useMeasure, useDebounce, Spinner, useMergeRefs, useScrollBlock, Text, Heading, useIsFirstRender } from '@trackunit/react-components';
4
+ import { IconButton, Icon, Tooltip, cvaMenu, cvaMenuList, Tag, useIsTextTruncated, ZStack, MenuItem, useMeasure, useDebounce, Spinner, useMergeRefs, useScrollBlock, Text, Heading, useIsFirstRender } from '@trackunit/react-components';
5
5
  import { themeSpacing } from '@trackunit/ui-design-tokens';
6
6
  import { forwardRef, useRef, useEffect, useImperativeHandle, useCallback, useState, isValidElement, cloneElement, useLayoutEffect, useReducer, useMemo, createContext, useContext } from 'react';
7
7
  import { cvaMerge } from '@trackunit/css-class-variance-utilities';
@@ -820,7 +820,7 @@ const CounterTag = ({ fieldSize, hiddenCount, totalCount, ref, className, "data-
820
820
  if (hiddenCount === 0) {
821
821
  return null;
822
822
  }
823
- return (jsx(Tag, { className: twMerge("inline-flex shrink-0", className), color: "neutral", "data-testid": dataTestId ?? "select-counter", ref: ref, size: fieldSize === "small" ? "small" : "medium", children: totalCount > hiddenCount ? `+${hiddenCount}` : hiddenCount }));
823
+ return (jsx(Tag, { className: className, color: "neutral", "data-testid": dataTestId ?? "select-counter", ref: ref, size: fieldSize === "small" ? "small" : "medium", children: totalCount > hiddenCount ? `+${hiddenCount}` : hiddenCount }));
824
824
  };
825
825
 
826
826
  /**
@@ -836,7 +836,7 @@ const MultiValue = ({ data, children, onClose, className, disabled, fieldSize, g
836
836
  e.stopPropagation();
837
837
  onClose?.(e);
838
838
  };
839
- return (jsx(Tag, { className: twMerge(className, "shrink-0", "inline-flex"), color: disabled ? "neutral" : "white", "data-testid": dataTestId, icon: optionPrefix, onClose: disabled ? undefined : handleOnClose, ref: ref, size: fieldSize === "small" ? "small" : "medium", children: jsx("span", { className: "flex items-center gap-1", children: children }) }));
839
+ return (jsx(Tag, { className: twMerge(className), color: disabled ? "neutral" : "white", "data-testid": dataTestId, icon: optionPrefix, onClose: disabled ? undefined : handleOnClose, ref: ref, size: fieldSize === "small" ? "small" : "medium", children: jsx("span", { className: "flex items-center gap-1", children: children }) }));
840
840
  };
841
841
 
842
842
  /**
@@ -910,31 +910,33 @@ const CheckIcon = ({ className, "data-testid": dataTestId }) => {
910
910
  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" }) }));
911
911
  };
912
912
 
913
+ /**
914
+ * Checkbox input styling - directly styles the input element (no wrapper span needed).
915
+ * Uses appearance-none to remove native styling, similar to RadioItem.
916
+ */
913
917
  const cvaCheckbox = cvaMerge([
918
+ "appearance-none",
914
919
  "w-4",
915
920
  "h-4",
916
921
  "border-solid",
917
922
  "border",
918
923
  "shrink-0",
919
924
  "border-neutral-300",
920
- "flex",
921
925
  "rounded",
922
926
  "hover:bg-neutral-100",
923
927
  "bg-white",
924
- "items-center",
925
928
  "shadow-sm",
926
- "justify-center",
927
929
  "box-border",
928
930
  "transition",
929
- "outline-0",
931
+ "cursor-pointer",
930
932
  "active:bg-neutral-200",
931
933
  "active:ring-2",
932
934
  "active:ring-inset",
933
935
  "active:ring-primary-700",
934
- "cursor-pointer",
935
936
  "group-active:ring-2",
936
937
  "group-active:ring-inset",
937
938
  "group-active:ring-primary-700",
939
+ "focus:outline-native",
938
940
  ], {
939
941
  variants: {
940
942
  invalid: {
@@ -1007,7 +1009,17 @@ const cvaCheckbox = cvaMerge([
1007
1009
  state: "deselected",
1008
1010
  },
1009
1011
  });
1010
- const cvaCheckboxInput = cvaMerge(["absolute", "opacity-0", "m-0", "pointer-events-none", "hidden"]);
1012
+ /**
1013
+ * Icon overlay container - positioned on top of the input, receives no pointer events
1014
+ */
1015
+ const cvaCheckboxIconOverlay = cvaMerge([
1016
+ "flex",
1017
+ "items-center",
1018
+ "justify-center",
1019
+ "w-4",
1020
+ "h-4",
1021
+ "pointer-events-none",
1022
+ ]);
1011
1023
  const cvaCheckboxIcon = cvaMerge(["w-2.5", "h-2.5", "text-white"]);
1012
1024
 
1013
1025
  /**
@@ -1031,36 +1043,21 @@ const IndeterminateIcon = ({ className }) => (jsx("svg", { className: className,
1031
1043
  * @augments props from [React.InputHTMLAttributes](https://reactjs.org/docs/dom-elements.html#input)
1032
1044
  * @param {CheckboxProps} props - The props for the Checkbox component
1033
1045
  */
1034
- const Checkbox = ({ className, "data-testid": dataTestId = "checkbox", onChange, checked = false, disabled = false, isInvalid = false, readOnly, indeterminate = false, suffix, label, tabIndex = 0, stopPropagation, ref, ...rest }) => {
1035
- const icon = indeterminate ? (jsx(IndeterminateIcon, { className: cvaCheckboxIcon() })) : (checked && jsx(CheckIcon, { className: cvaCheckboxIcon() }));
1036
- const internalRef = useRef(null);
1046
+ const Checkbox = ({ className, "data-testid": dataTestId = "checkbox", onChange, checked = false, disabled = false, isInvalid = false, readOnly = false, indeterminate = false, suffix, label, tabIndex = 0, stopPropagation = false, ref, ...rest }) => {
1037
1047
  const { isTextTruncated: isLabelCutOff, ref: labelRef } = useIsTextTruncated();
1038
1048
  const isReadonly = disabled || readOnly;
1039
1049
  const hasLabel = label !== undefined && label !== null && label !== "";
1040
- const onKeyPress = e => {
1041
- if (isReadonly) {
1042
- e.preventDefault();
1043
- return;
1044
- }
1045
- if ("Space" === e.code) {
1046
- e.preventDefault();
1047
- internalRef.current?.click();
1048
- }
1049
- if ("Enter" === e.code) {
1050
- internalRef.current?.click();
1051
- }
1052
- };
1053
- const uuid = rest.id;
1050
+ const state = indeterminate ? "indeterminate" : checked ? "selected" : "deselected";
1054
1051
  return (jsxs("label", { className: hasLabel
1055
1052
  ? cvaBinaryControlWrapper({ className })
1056
- : `inline-flex w-fit items-center gap-2${isReadonly ? " pointer-events-none" : ""}${className ? ` ${className}` : ""}`, "data-testid": dataTestId ? `${dataTestId}-container` : null, htmlFor: uuid, onClick: e => stopPropagation && e.stopPropagation(), onKeyDown: onKeyPress, ref: internalRef, children: [jsxs("div", { className: "self-center", children: [jsx("input", { "aria-checked": !indeterminate && checked, checked: !indeterminate && checked, className: cvaCheckboxInput(), "data-testid": dataTestId, disabled: disabled, id: uuid, onChange: onChange, readOnly: readOnly, ref: ref, type: "checkbox", ...rest }), jsx("span", { className: cvaCheckbox({
1053
+ : `inline-flex w-fit items-center gap-2${isReadonly ? " pointer-events-none" : ""}${className ? ` ${className}` : ""}`, "data-testid": dataTestId ? `${dataTestId}-container` : null, onClick: e => stopPropagation && e.stopPropagation(), children: [jsxs(ZStack, { className: "h-4 w-4 self-center", children: [jsx("input", { "aria-checked": indeterminate ? "mixed" : checked, checked: !indeterminate && checked, className: cvaCheckbox({
1057
1054
  disabled: isReadonly,
1058
1055
  invalid: isReadonly ? false : isInvalid,
1059
- state: indeterminate ? "indeterminate" : checked ? "selected" : "deselected",
1060
- }), id: uuid, tabIndex: isReadonly ? -1 : tabIndex, children: icon })] }), hasLabel ? (jsx(Tooltip, { className: cvaBinaryControlLabelTooltip(), disabled: !isLabelCutOff, label: label, placement: "top", children: jsx("span", { className: cvaLabel({
1056
+ state,
1057
+ }), "data-testid": dataTestId, disabled: disabled, onChange: onChange, readOnly: readOnly, ref: ref, tabIndex: isReadonly ? -1 : tabIndex, type: "checkbox", ...rest }), checked || indeterminate ? (jsx("div", { className: cvaCheckboxIconOverlay(), children: indeterminate ? (jsx(IndeterminateIcon, { className: cvaCheckboxIcon() })) : (jsx(CheckIcon, { className: cvaCheckboxIcon() })) })) : null] }), hasLabel ? (jsx(Tooltip, { className: cvaBinaryControlLabelTooltip(), disabled: !isLabelCutOff, label: label, placement: "top", children: jsx("span", { className: cvaLabel({
1061
1058
  invalid: isReadonly ? false : isInvalid,
1062
1059
  disabled: isReadonly,
1063
- }), 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] }));
1060
+ }), id: `checkbox-label-${label}`, ref: labelRef, children: label }) }, "tooltip-" + rest.name)) : null, suffix !== undefined && suffix !== null && suffix !== "" ? (jsx("div", { className: cvaBinaryControlSuffixContainer(), "data-testid": dataTestId ? `${dataTestId}-suffix-container` : undefined, children: suffix })) : null] }));
1064
1061
  };
1065
1062
  Checkbox.displayName = "Checkbox";
1066
1063
 
@@ -2796,7 +2793,7 @@ const PhoneFieldWithController = ({ control, controllerProps, name, value, ref,
2796
2793
  };
2797
2794
  PhoneFieldWithController.displayName = "PhoneFieldWithController";
2798
2795
 
2799
- const cvaRadioGroup = cvaMerge(["flex", "gap-2", "flex-col", "items-start"], {
2796
+ const cvaInputGroup = cvaMerge(["flex", "gap-2", "flex-col", "items-start"], {
2800
2797
  variants: {
2801
2798
  layout: {
2802
2799
  inline: ["flex", "gap-3", "flex-row", "items-center"],
@@ -2819,7 +2816,7 @@ const cvaRadioItem = cvaMerge([
2819
2816
  "box-border",
2820
2817
  "hover:cursor-pointer",
2821
2818
  "hover:bg-neutral-100",
2822
- "focus-visible:outline-primary-700",
2819
+ "focus:outline-native",
2823
2820
  ], {
2824
2821
  variants: {
2825
2822
  checked: {
@@ -2830,19 +2827,12 @@ const cvaRadioItem = cvaMerge([
2830
2827
  "bg-white",
2831
2828
  "hover:bg-neutral-100",
2832
2829
  "hover:cursor-pointer",
2833
- "outline-0",
2834
2830
  "active:bg-neutral-200",
2835
- "active:ring-2",
2836
- "active:ring-inset",
2837
- "active:ring-primary-700",
2838
- "group-active:ring-2",
2839
- "group-active:ring-inset",
2840
- "group-active:ring-primary-700",
2841
2831
  ],
2842
2832
  false: "",
2843
2833
  },
2844
2834
  invalid: {
2845
- true: ["border-red-600", "active:ring-red-700"],
2835
+ true: ["border-red-600"],
2846
2836
  false: "",
2847
2837
  },
2848
2838
  disabled: {
@@ -2852,8 +2842,6 @@ const cvaRadioItem = cvaMerge([
2852
2842
  "cursor-not-allowed",
2853
2843
  "hover:bg-neutral-400",
2854
2844
  "active:bg-neutral-400",
2855
- "group-active:ring-0",
2856
- "group-active:ring-inset",
2857
2845
  ],
2858
2846
  false: "",
2859
2847
  },
@@ -2881,8 +2869,8 @@ const RadioGroupContext = createContext(null);
2881
2869
  * @param {RadioGroupProps} props - The props for the RadioGroup component
2882
2870
  * @returns {ReactElement} RadioGroup component
2883
2871
  */
2884
- const RadioGroup = ({ children, id, name, value, disabled, onChange, label, inline, className, "data-testid": dataTestId, isInvalid, }) => {
2885
- 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: {
2872
+ const RadioGroup = ({ children, id, name, value, disabled, onChange, label, inline = false, className, "data-testid": dataTestId, isInvalid, }) => {
2873
+ return (jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, label: label, children: jsx("div", { className: cvaInputGroup({ layout: inline ? "inline" : null, className }), "data-testid": dataTestId, role: "radiogroup", children: jsx(RadioGroupContext.Provider, { value: {
2886
2874
  id,
2887
2875
  value,
2888
2876
  name: name || id,
@@ -2899,24 +2887,35 @@ RadioGroup.displayName = "RadioGroup";
2899
2887
  * @param {RadioItemProps} props - The props for the RadioItem component
2900
2888
  * @returns {ReactElement} RadioItem component
2901
2889
  */
2902
- const RadioItem = ({ label, value, "data-testid": dataTestId, className, description, suffix, ...rest }) => {
2890
+ const RadioItem = ({ label, value, "data-testid": dataTestId, className, description, suffix, tabIndex, ...rest }) => {
2903
2891
  const groupCtx = useContext(RadioGroupContext);
2904
2892
  const isChecked = groupCtx?.value === value;
2893
+ // Empty string is treated as "no selection" to allow tabbing into the group when no radio is checked
2894
+ const hasGroupValue = groupCtx?.value !== undefined && groupCtx.value !== "";
2895
+ const inputRef = useRef(null);
2896
+ const wasCheckedRef = useRef(isChecked);
2905
2897
  const { ref: labelRef, isTextTruncated: isLabelTruncated } = useIsTextTruncated();
2906
2898
  const { ref: descriptionRef, isTextTruncated: isDescriptionTruncated } = useIsTextTruncated();
2907
2899
  const descriptionId = description ? `${groupCtx?.id}-${value}-description` : undefined;
2908
2900
  const inputId = `${groupCtx?.id}-${value}`;
2909
2901
  const hasLabel = label !== undefined && label !== null && label !== "";
2902
+ // Restore focus after React re-render when this radio becomes checked via arrow keys
2903
+ useEffect(() => {
2904
+ if (isChecked && !wasCheckedRef.current) {
2905
+ inputRef.current?.focus();
2906
+ }
2907
+ wasCheckedRef.current = isChecked;
2908
+ }, [isChecked]);
2910
2909
  return (jsxs("label", { className: hasLabel
2911
2910
  ? cvaBinaryControlWrapper({ className })
2912
- : `inline-flex w-fit items-center gap-2 ${className || ""}`.trim(), "data-testid": dataTestId ? `${dataTestId}-Wrapper` : undefined, htmlFor: inputId, children: [jsx("input", { "aria-describedby": descriptionId, checked: isChecked, className: cvaRadioItem({
2911
+ : `inline-flex w-fit items-center gap-2 ${className || ""}`.trim(), "data-testid": dataTestId ? `${dataTestId}-Wrapper` : undefined, children: [jsx("input", { "aria-describedby": descriptionId, checked: isChecked, className: cvaRadioItem({
2913
2912
  checked: isChecked,
2914
2913
  disabled: groupCtx?.disabled,
2915
2914
  invalid: groupCtx?.isInvalid,
2916
- }), "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({
2915
+ }), "data-testid": dataTestId, id: inputId, name: groupCtx?.name, onChange: groupCtx?.onChange, ref: inputRef, tabIndex: tabIndex ?? (groupCtx?.disabled ? -1 : isChecked ? 0 : hasGroupValue ? -1 : 0), 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({
2917
2916
  invalid: groupCtx?.isInvalid,
2918
2917
  disabled: groupCtx?.disabled,
2919
- }), "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] }));
2918
+ }), "data-testid": dataTestId ? `${dataTestId}-Label` : undefined, ref: labelRef, children: label }) }, "tooltip-" + rest.name)) : null, suffix !== undefined && suffix !== 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] }));
2920
2919
  };
2921
2920
 
2922
2921
  const cvaTimeRange = cvaMerge([
@@ -3274,7 +3273,14 @@ const TextLengthIndicator = ({ length, maxLength }) => {
3274
3273
  };
3275
3274
 
3276
3275
  /**
3276
+ * Use a text area when you need to allow users to enter a large amount of text, such as a comment or a description.
3277
+ *
3278
+ * _**Do use** Text areas for larger text inputs, such as comments or descriptions._
3279
+ *
3280
+ * _**Do not use** Text areas for small text inputs, such as single-line inputs._
3277
3281
  *
3282
+ * @param {TextAreaFieldProps} props - The props for the TextAreaField component
3283
+ * @returns {ReactElement} TextAreaField component
3278
3284
  */
3279
3285
  const TextAreaField = ({ id, label, tip, helpText, helpAddon, errorMessage, isInvalid, maxLength, onChange, className, value, "data-testid": dataTestId, ref, ...rest }) => {
3280
3286
  const [valueLength, setValueLength] = useState(value ? `${value}`.length : 0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-form-components",
3
- "version": "1.10.11",
3
+ "version": "1.10.14",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -14,12 +14,12 @@
14
14
  "zod": "^3.23.8",
15
15
  "react-hook-form": "7.62.0",
16
16
  "tailwind-merge": "^2.0.0",
17
- "@trackunit/css-class-variance-utilities": "1.9.7",
18
- "@trackunit/react-components": "1.12.11",
19
- "@trackunit/ui-icons": "1.9.7",
20
- "@trackunit/shared-utils": "1.11.7",
21
- "@trackunit/ui-design-tokens": "1.9.7",
22
- "@trackunit/i18n-library-translation": "1.9.10",
17
+ "@trackunit/css-class-variance-utilities": "1.9.10",
18
+ "@trackunit/react-components": "1.13.0",
19
+ "@trackunit/ui-icons": "1.9.10",
20
+ "@trackunit/shared-utils": "1.11.10",
21
+ "@trackunit/ui-design-tokens": "1.9.10",
22
+ "@trackunit/i18n-library-translation": "1.9.13",
23
23
  "string-ts": "^2.0.0",
24
24
  "@js-temporal/polyfill": "^0.5.1",
25
25
  "es-toolkit": "^1.39.10",
@@ -54,6 +54,6 @@ export interface CheckboxProps extends CommonProps, MappedOmit<InputHTMLAttribut
54
54
  * @param {CheckboxProps} props - The props for the Checkbox component
55
55
  */
56
56
  export declare const Checkbox: {
57
- ({ className, "data-testid": dataTestId, onChange, checked, disabled, isInvalid, readOnly, indeterminate, suffix, label, tabIndex, stopPropagation, ref, ...rest }: CheckboxProps): import("react/jsx-runtime").JSX.Element;
57
+ ({ className, "data-testid": dataTestId, onChange, checked, disabled, isInvalid, readOnly, indeterminate, suffix, label, tabIndex, stopPropagation, ref, ...rest }: CheckboxProps): ReactNode;
58
58
  displayName: string;
59
59
  };
@@ -1,7 +1,14 @@
1
+ /**
2
+ * Checkbox input styling - directly styles the input element (no wrapper span needed).
3
+ * Uses appearance-none to remove native styling, similar to RadioItem.
4
+ */
1
5
  export declare const cvaCheckbox: (props?: ({
2
6
  invalid?: boolean | null | undefined;
3
7
  state?: "selected" | "deselected" | "indeterminate" | null | undefined;
4
8
  disabled?: boolean | null | undefined;
5
9
  } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
6
- export declare const cvaCheckboxInput: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
10
+ /**
11
+ * Icon overlay container - positioned on top of the input, receives no pointer events
12
+ */
13
+ export declare const cvaCheckboxIconOverlay: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
7
14
  export declare const cvaCheckboxIcon: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
@@ -1,6 +1,6 @@
1
1
  import { CommonProps } from "@trackunit/react-components";
2
2
  import { ChangeEvent, InputHTMLAttributes, ReactElement, ReactNode } from "react";
3
- export interface RadioGroupProps<V extends string | number> extends CommonProps, InputHTMLAttributes<HTMLInputElement> {
3
+ export interface RadioGroupProps<TValue extends string | number> extends CommonProps, InputHTMLAttributes<HTMLInputElement> {
4
4
  /**
5
5
  */
6
6
  children: ReactNode;
@@ -15,7 +15,7 @@ export interface RadioGroupProps<V extends string | number> extends CommonProps,
15
15
  /**
16
16
  * The value of the radio group.
17
17
  */
18
- value: V;
18
+ value: TValue;
19
19
  /**
20
20
  * The name of the radio group.
21
21
  */
@@ -51,6 +51,6 @@ export interface RadioGroupProps<V extends string | number> extends CommonProps,
51
51
  * @returns {ReactElement} RadioGroup component
52
52
  */
53
53
  export declare const RadioGroup: {
54
- <V extends string | number = string>({ children, id, name, value, disabled, onChange, label, inline, className, "data-testid": dataTestId, isInvalid, }: RadioGroupProps<V>): ReactElement;
54
+ <TValue extends string | number = string>({ children, id, name, value, disabled, onChange, label, inline, className, "data-testid": dataTestId, isInvalid, }: RadioGroupProps<TValue>): ReactElement;
55
55
  displayName: string;
56
56
  };
@@ -1,4 +1,4 @@
1
- export declare const cvaRadioGroup: (props?: ({
1
+ export declare const cvaInputGroup: (props?: ({
2
2
  layout?: "inline" | null | undefined;
3
3
  } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
4
4
  export declare const cvaRadioItem: (props?: ({
@@ -1,7 +1,7 @@
1
1
  import { CommonProps } from "@trackunit/react-components";
2
2
  import { MappedOmit } from "@trackunit/shared-utils";
3
3
  import { InputHTMLAttributes, ReactElement, ReactNode } from "react";
4
- export interface RadioItemProps<V extends string | number = string> extends CommonProps, MappedOmit<InputHTMLAttributes<HTMLInputElement>, "prefix"> {
4
+ export interface RadioItemProps<TValue extends string | number = string> extends CommonProps, MappedOmit<InputHTMLAttributes<HTMLInputElement>, "prefix"> {
5
5
  /**
6
6
  * The label of the radio item.
7
7
  */
@@ -9,7 +9,7 @@ export interface RadioItemProps<V extends string | number = string> extends Comm
9
9
  /**
10
10
  * The value of the radio item.
11
11
  */
12
- value: V;
12
+ value: TValue;
13
13
  /**
14
14
  * The description of the radio item.
15
15
  */
@@ -25,4 +25,4 @@ export interface RadioItemProps<V extends string | number = string> extends Comm
25
25
  * @param {RadioItemProps} props - The props for the RadioItem component
26
26
  * @returns {ReactElement} RadioItem component
27
27
  */
28
- export declare const RadioItem: <V extends string | number>({ label, value, "data-testid": dataTestId, className, description, suffix, ...rest }: RadioItemProps<V>) => ReactElement;
28
+ export declare const RadioItem: <TValue extends string | number>({ label, value, "data-testid": dataTestId, className, description, suffix, tabIndex, ...rest }: RadioItemProps<TValue>) => ReactElement;
@@ -19,7 +19,14 @@ export interface TextAreaFieldProps extends TextAreaBaseInputProps, FormGroupExp
19
19
  ref?: Ref<HTMLTextAreaElement>;
20
20
  }
21
21
  /**
22
+ * Use a text area when you need to allow users to enter a large amount of text, such as a comment or a description.
22
23
  *
24
+ * _**Do use** Text areas for larger text inputs, such as comments or descriptions._
25
+ *
26
+ * _**Do not use** Text areas for small text inputs, such as single-line inputs._
27
+ *
28
+ * @param {TextAreaFieldProps} props - The props for the TextAreaField component
29
+ * @returns {ReactElement} TextAreaField component
23
30
  */
24
31
  export declare const TextAreaField: {
25
32
  ({ id, label, tip, helpText, helpAddon, errorMessage, isInvalid, maxLength, onChange, className, value, "data-testid": dataTestId, ref, ...rest }: TextAreaFieldProps): import("react/jsx-runtime").JSX.Element;