@trackunit/react-form-components 1.25.12 → 1.25.15

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
@@ -35,6 +35,7 @@ var defaultTranslations = {
35
35
  "dropzone.label.default": "<clickable>Browse</clickable> or drag files here...",
36
36
  "emailField.error.INVALID_EMAIL": "Please enter a valid email address",
37
37
  "emailField.error.REQUIRED": "The email address is required",
38
+ "emailField.sendEmailAction.label": "Email",
38
39
  "field.notEditable.tooltip": "This field is not editable",
39
40
  "field.required.asterisk.tooltip": "This field is required",
40
41
  "numberField.error.GREATER_THAN": "Value must be greater than or equal to {{min}}",
@@ -42,6 +43,8 @@ var defaultTranslations = {
42
43
  "numberField.error.LESS_THAN": "Value must be less than or equal to {{max}}",
43
44
  "numberField.error.NOT_IN_BETWEEN": "Must be between {{min}} and {{max}}",
44
45
  "numberField.error.REQUIRED": "This field is required",
46
+ "passwordField.tooltip.hide": "Hide password",
47
+ "passwordField.tooltip.show": "Show password",
45
48
  "phoneField.error.INVALID_COUNTRY": "The country code is not valid",
46
49
  "phoneField.error.INVALID_LENGTH": "The phone number is not valid",
47
50
  "phoneField.error.INVALID_NUMBER": "The phone number is not valid",
@@ -51,14 +54,17 @@ var defaultTranslations = {
51
54
  "phoneField.error.TOO_LONG": "The phone number is too long",
52
55
  "phoneField.error.TOO_SHORT": "The phone number is too short",
53
56
  "phoneField.error.undefined": "",
57
+ "phoneField.phoneNumber.label": "Phone Number",
54
58
  "schedule.label.active": "Active",
55
59
  "schedule.label.allDay": "All Day",
56
60
  "schedule.label.day": "Day",
57
61
  "search.placeholder": "Search",
58
62
  "select.loadingMessage": "Loading...",
63
+ "select.multiValue.remove": "Remove",
59
64
  "select.noOptionsMessage": "No options found",
60
65
  "urlField.error.INVALID_URL": "Please enter a valid URL",
61
- "urlField.error.REQUIRED": "The URL is required"
66
+ "urlField.error.REQUIRED": "The URL is required",
67
+ "urlField.url.label": "Web address"
62
68
  };
63
69
 
64
70
  /** The translation namespace for this library */
@@ -608,7 +614,7 @@ const AddonRenderer = ({ addon, "data-testid": dataTestId, className, fieldSize,
608
614
  * @param {ActionButtonProps} props - The props for the ActionButton component
609
615
  * @returns {ReactElement} ActionButton component
610
616
  */
611
- const ActionButton = ({ type, value, "data-testid": dataTestId, size = "medium", disabled, className, onClick, style, ref, }) => {
617
+ const ActionButton = ({ type, value, "data-testid": dataTestId, size = "medium", disabled, className, title, style, ref, }) => {
612
618
  const [, copyToClipboard] = usehooksTs.useCopyToClipboard();
613
619
  const getIconName = () => {
614
620
  switch (type) {
@@ -647,15 +653,18 @@ const ActionButton = ({ type, value, "data-testid": dataTestId, size = "medium",
647
653
  }
648
654
  };
649
655
  const adjustedIconSize = size === "large" ? "medium" : size;
650
- return (jsxRuntime.jsx("div", { className: cvaActionContainer({ className, size }), ref: ref, style: style, children: jsxRuntime.jsx(reactComponents.IconButton, { className: cvaActionButton({ size: adjustedIconSize }), "data-testid": dataTestId || "testIconButtonId", disabled: disabled, icon: jsxRuntime.jsx(reactComponents.Icon, { name: getIconName(), size: adjustedIconSize }), onClick: buttonAction, size: "small", variant: "ghost-neutral" }) }));
656
+ return (jsxRuntime.jsx("div", { className: cvaActionContainer({ className, size }), ref: ref, style: style, children: jsxRuntime.jsx(reactComponents.IconButton, { className: cvaActionButton({ size: adjustedIconSize }), "data-testid": dataTestId || "testIconButtonId", disabled: disabled, icon: jsxRuntime.jsx(reactComponents.Icon, { name: getIconName(), size: adjustedIconSize }), onClick: buttonAction, size: "small", title: title, variant: "ghost-neutral" }) }));
651
657
  };
652
658
 
659
+ /**
660
+ *
661
+ */
653
662
  const GenericActionsRenderer = ({ genericAction = undefined, disabled, fieldSize = undefined, innerRef, tooltipLabel, }) => {
654
663
  const [t] = useTranslation();
655
664
  if (!genericAction) {
656
665
  return null;
657
666
  }
658
- return (jsxRuntime.jsx(reactComponents.Tooltip, { label: tooltipLabel ?? t("baseInput.copyAction.toolTip"), placement: "top", children: jsxRuntime.jsx(ActionButton, { "data-testid": "copy-value-button", disabled: disabled, size: fieldSize ?? undefined, type: genericAction === "edit" ? "EDIT" : "COPY", value: innerRef }) }));
667
+ return (jsxRuntime.jsx(ActionButton, { "data-testid": "copy-value-button", disabled: disabled, size: fieldSize ?? undefined, title: tooltipLabel ?? t("baseInput.copyAction.toolTip"), type: genericAction === "edit" ? "EDIT" : "COPY", value: innerRef }));
659
668
  };
660
669
 
661
670
  /**
@@ -1347,7 +1356,7 @@ const DateBaseInput = ({ min, max, defaultValue, value, ref, onChange, onBlur, o
1347
1356
  onPopoverOpenStateChange(true);
1348
1357
  }
1349
1358
  };
1350
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(reactComponents.PopoverTrigger, { children: jsxRuntime.jsx("div", { className: "flex w-full min-w-0 items-center", children: jsxRuntime.jsx(BaseInput, { ...rest, "aria-readonly": true, className: tailwindMerge.twMerge("w-full min-w-0", rest.className), "data-testid": dataTestId ? `${dataTestId}-input` : undefined, onBlur: handleInputBlur, onChange: handleInputChange, onFocus: handleInputFocus, onKeyDown: handleInputKeyDown, placeholder: rest.placeholder ?? getDateFieldPlaceholder(locale), ref: setInputRef, suffix: suffixProp ?? (jsxRuntime.jsx("div", { className: cvaActionContainer({ size: "medium" }), children: jsxRuntime.jsx(reactComponents.IconButton, { "aria-expanded": isOpen, "aria-label": t("dateField.openPicker.ariaLabel"), className: cvaActionButton({ size: "small" }), "data-testid": dataTestId ? `${dataTestId}-calendar` : "calendar", disabled: isPickerDisabled, icon: jsxRuntime.jsx(reactComponents.Icon, { "aria-label": undefined, name: "Calendar", size: "small", type: "solid" }), onClick: togglePopover, size: "small", tabIndex: isOpen ? -1 : undefined, variant: "ghost-neutral" }) })), tabIndex: isOpen ? -1 : rest.tabIndex, type: "text", value: resolvedValue }) }) }), jsxRuntime.jsx(reactComponents.PopoverContent, { initialFocus: 1, children: closePopover => (jsxRuntime.jsx(DateBaseInputPickerContent, { applyDate: applyDate, closePopover: closePopover, "data-testid": dataTestId, onApply: onApply, onCalendarChange: onCalendarChange, onCancel: onCancel, onClear: onClear, pendingDate: pendingDate, selectedDate: selectedDate, tileDisabled: tileDisabled })) })] }));
1359
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(reactComponents.PopoverTrigger, { children: jsxRuntime.jsx("div", { className: "flex w-full min-w-0 items-center", children: jsxRuntime.jsx(BaseInput, { ...rest, "aria-readonly": true, className: tailwindMerge.twMerge("w-full min-w-0", rest.className), "data-testid": dataTestId ? `${dataTestId}-input` : undefined, onBlur: handleInputBlur, onChange: handleInputChange, onFocus: handleInputFocus, onKeyDown: handleInputKeyDown, placeholder: rest.placeholder ?? getDateFieldPlaceholder(locale), ref: setInputRef, suffix: suffixProp ?? (jsxRuntime.jsx("div", { className: cvaActionContainer({ size: "medium" }), children: jsxRuntime.jsx(reactComponents.IconButton, { "aria-expanded": isOpen, ariaLabel: t("dateField.openPicker.ariaLabel"), className: cvaActionButton({ size: "small" }), "data-testid": dataTestId ? `${dataTestId}-calendar` : "calendar", disabled: isPickerDisabled, icon: jsxRuntime.jsx(reactComponents.Icon, { "aria-label": undefined, name: "Calendar", size: "small", type: "solid" }), onClick: togglePopover, size: "small", tabIndex: isOpen ? -1 : undefined, variant: "ghost-neutral" }) })), tabIndex: isOpen ? -1 : rest.tabIndex, type: "text", value: resolvedValue }) }) }), jsxRuntime.jsx(reactComponents.PopoverContent, { initialFocus: 1, children: closePopover => (jsxRuntime.jsx(DateBaseInputPickerContent, { applyDate: applyDate, closePopover: closePopover, "data-testid": dataTestId, onApply: onApply, onCalendarChange: onCalendarChange, onCancel: onCancel, onClear: onClear, pendingDate: pendingDate, selectedDate: selectedDate, tileDisabled: tileDisabled })) })] }));
1351
1360
  } }));
1352
1361
  };
1353
1362
 
@@ -1454,6 +1463,7 @@ const DEFAULT_COUNTRY_CODE = undefined;
1454
1463
  * @returns {ReactElement} The phone input component.
1455
1464
  */
1456
1465
  const PhoneBaseInput = ({ "data-testid": dataTestId, isInvalid, disabled = false, value, defaultValue, fieldSize = "medium", disableAction = false, onChange, readOnly, onFocus, onBlur, name, ref, ...rest }) => {
1466
+ const [t] = useTranslation();
1457
1467
  const [innerValue, setInnerValue] = react.useState(() => {
1458
1468
  return (value?.toString() || defaultValue?.toString()) ?? "";
1459
1469
  });
@@ -1495,7 +1505,7 @@ const PhoneBaseInput = ({ "data-testid": dataTestId, isInvalid, disabled = false
1495
1505
  onFocus?.(event);
1496
1506
  fieldIsFocused.current = true;
1497
1507
  }, [onFocus]);
1498
- return (jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2", "data-testid": dataTestId ? `${dataTestId}-container` : null, children: jsxRuntime.jsx(BaseInput, { actions: !disableAction && innerValue && innerValue.length > 0 ? (jsxRuntime.jsx(ActionButton, { "data-testid": dataTestId ? `${dataTestId}-phoneIcon` : undefined, disabled: isInvalid, size: fieldSize, type: "PHONE_NUMBER", value: value?.toString() || "" })) : null, "data-testid": dataTestId ? `${dataTestId}-phoneNumberInput` : undefined, disabled: disabled, fieldSize: fieldSize, id: "phoneInput-number", isInvalid: isInvalid, name: name, onBlur: handleBlur, onChange: handleChange, onFocus: handleFocus, prefix: (countryCode && countryCodeToFlagEmoji(countryCode)) || undefined, readOnly: readOnly, ref: ref, type: "tel", value: innerValue, ...rest }) }));
1508
+ return (jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2", "data-testid": dataTestId ? `${dataTestId}-container` : null, children: jsxRuntime.jsx(BaseInput, { ...rest, actions: !disableAction && innerValue && innerValue.length > 0 ? (jsxRuntime.jsx(ActionButton, { "data-testid": dataTestId ? `${dataTestId}-phoneIcon` : undefined, disabled: isInvalid, size: fieldSize, title: t("phoneField.phoneNumber.label"), type: "PHONE_NUMBER", value: value?.toString() || "" })) : null, "data-testid": dataTestId ? `${dataTestId}-phoneNumberInput` : undefined, disabled: disabled, fieldSize: fieldSize, id: "phoneInput-number", isInvalid: isInvalid, name: name, onBlur: handleBlur, onChange: handleChange, onFocus: handleFocus, prefix: (countryCode && countryCodeToFlagEmoji(countryCode)) || undefined, readOnly: readOnly, ref: ref, type: "tel", value: innerValue }) }));
1499
1509
  };
1500
1510
 
1501
1511
  const cvaTextAreaBaseInput = cssClassVarianceUtilities.cvaMerge([
@@ -1671,7 +1681,7 @@ const CounterTag = ({ fieldSize, hiddenCount, totalCount, ref, className, "data-
1671
1681
  * Internal component for rendering multi-select values with measurement support.
1672
1682
  * Uses the measurement state to determine if the value should be displayed or hidden based on available width.
1673
1683
  */
1674
- const MultiValue = ({ data, children, onClose, className, disabled, fieldSize, getOptionPrefix, ref, "data-testid": dataTestId, }) => {
1684
+ const MultiValue = ({ data, children, onClose, className, disabled, fieldSize, getOptionPrefix, removeTagLabel, ref, "data-testid": dataTestId, }) => {
1675
1685
  const optionPrefix = getOptionPrefix ? getOptionPrefix(data) : null;
1676
1686
  const handleOnClose = (e) => {
1677
1687
  if (disabled) {
@@ -1680,7 +1690,10 @@ const MultiValue = ({ data, children, onClose, className, disabled, fieldSize, g
1680
1690
  e.stopPropagation();
1681
1691
  onClose?.(e);
1682
1692
  };
1683
- return (jsxRuntime.jsx(reactComponents.Tag, { className: tailwindMerge.twMerge(className), color: disabled ? "neutral" : "white", "data-testid": dataTestId, icon: optionPrefix, onClickClose: disabled ? undefined : handleOnClose, ref: ref, size: fieldSize === "small" ? "small" : "medium", children: jsxRuntime.jsx("span", { className: "flex items-center gap-1", children: children }) }));
1693
+ if (disabled) {
1694
+ return (jsxRuntime.jsx(reactComponents.Tag, { className: tailwindMerge.twMerge(className), color: "neutral", "data-testid": dataTestId, icon: optionPrefix, ref: ref, size: fieldSize === "small" ? "small" : "medium", children: jsxRuntime.jsx("span", { className: "flex items-center gap-1", children: children }) }));
1695
+ }
1696
+ return (jsxRuntime.jsx(reactComponents.Tag, { className: tailwindMerge.twMerge(className), color: "white", "data-testid": dataTestId, icon: optionPrefix, onClickClose: handleOnClose, ref: ref, removeTagLabel: removeTagLabel, size: fieldSize === "small" ? "small" : "medium", children: jsxRuntime.jsx("span", { className: "flex items-center gap-1", children: children }) }));
1684
1697
  };
1685
1698
 
1686
1699
  /**
@@ -2483,7 +2496,7 @@ formatOptionLabel, }) => {
2483
2496
  return (jsxRuntime.jsx(ReactSelect.components.MultiValue, { ...selectMultiValue, getStyles: getNoStyles, children: jsxRuntime.jsx(MultiValue, { className: cvaSelectMultiValue({
2484
2497
  hidden: currentIsComplete && index + 1 > currentVisibleCount, // Hide if doesn't fit
2485
2498
  invisible: currentWithCounter && !currentIsComplete, // Make invisible if measuring with counter. When there's a counter, it would otherwise briefly change layout to make room for the "fake" counter
2486
- }), data: selectMultiValue.data, "data-testid": dataTestId ? `${dataTestId}-multiValue-${index}` : undefined, disabled: Boolean(disabled), fieldSize: fieldSize, getOptionPrefix: getOptionPrefix, onClose: selectMultiValue.removeProps.onClick, ref: setGeometryRef(index), children: selectMultiValue.children }) }));
2499
+ }), data: selectMultiValue.data, "data-testid": dataTestId ? `${dataTestId}-multiValue-${index}` : undefined, disabled: Boolean(disabled), fieldSize: fieldSize, getOptionPrefix: getOptionPrefix, onClose: selectMultiValue.removeProps.onClick, ref: setGeometryRef(index), removeTagLabel: t("select.multiValue.remove"), children: selectMultiValue.children }) }));
2487
2500
  },
2488
2501
  Menu: selectMenu => {
2489
2502
  return (jsxRuntime.jsx(ReactSelect.components.Menu, { ...selectMenu, className: cvaSelectMenu({ className: selectMenu.className, placement: selectMenu.placement }), getStyles: getNoStyles, innerProps: {
@@ -2937,7 +2950,7 @@ const FormGroup = ({ isInvalid = false, isWarning = false, helpText, helpAddon,
2937
2950
  const color = isInvalid ? "danger" : isWarning ? "warning" : null;
2938
2951
  return color ? jsxRuntime.jsx(reactComponents.Icon, { color: color, name: "ExclamationTriangle", size: "small" }) : null;
2939
2952
  }, [isInvalid, isWarning]);
2940
- return (jsxRuntime.jsxs("div", { className: cvaFormGroup({ className }), "data-testid": dataTestId, ref: ref, style: style, children: [label !== undefined && label !== null ? (jsxRuntime.jsxs("div", { className: cvaFormGroupContainerBefore(), children: [jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(Label, { className: "component-formGroup-font", "data-testid": dataTestId ? `${dataTestId}-label` : undefined, htmlFor: htmlFor, id: htmlFor + "-label", children: label }), required ? (jsxRuntime.jsx(reactComponents.Tooltip, { "data-testid": "required-asterisk", label: t("field.required.asterisk.tooltip"), children: jsxRuntime.jsx("span", { children: "*" }) })) : null] }), tip !== undefined && tip !== null ? (jsxRuntime.jsx("span", { className: "ml-1", children: jsxRuntime.jsx(reactComponents.Tooltip, { "data-testid": dataTestId ? `${dataTestId}-tooltip` : undefined, label: tip, placement: "bottom" }) })) : null] })) : null, children, (helpText !== undefined && helpText !== null) || (helpAddon !== undefined && helpAddon !== null) ? (jsxRuntime.jsxs("div", { className: cvaFormGroupContainerAfter({ invalid: isInvalid, isWarning: isWarning }), children: [helpText ? (jsxRuntime.jsxs("div", { className: "flex gap-1", children: [validationStateIcon, jsxRuntime.jsx("span", { "data-testid": dataTestId ? `${dataTestId}-helpText` : undefined, children: helpText })] })) : undefined, helpAddon !== undefined && helpAddon !== null ? (jsxRuntime.jsx("span", { className: cvaHelpAddon(), "data-testid": dataTestId ? `${dataTestId}-helpAddon` : null, children: helpAddon })) : null] })) : null] }));
2953
+ return (jsxRuntime.jsxs("div", { className: cvaFormGroup({ className }), "data-testid": dataTestId, ref: ref, style: style, children: [label !== undefined && label !== null ? (jsxRuntime.jsxs("div", { className: cvaFormGroupContainerBefore(), children: [jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(Label, { className: "component-formGroup-font", "data-testid": dataTestId ? `${dataTestId}-label` : undefined, htmlFor: htmlFor, id: htmlFor + "-label", children: label }), required ? (jsxRuntime.jsx(reactComponents.Tooltip, { "data-testid": "required-asterisk", label: t("field.required.asterisk.tooltip"), children: jsxRuntime.jsx("span", { children: "*" }) })) : null] }), tip !== undefined && tip !== null ? (jsxRuntime.jsx("span", { className: "ml-1 mt-1 flex items-center", children: jsxRuntime.jsx(reactComponents.Tooltip, { "data-testid": dataTestId ? `${dataTestId}-tooltip` : undefined, label: tip, placement: "bottom" }) })) : null] })) : null, children, (helpText !== undefined && helpText !== null) || (helpAddon !== undefined && helpAddon !== null) ? (jsxRuntime.jsxs("div", { className: cvaFormGroupContainerAfter({ invalid: isInvalid, isWarning: isWarning }), children: [helpText ? (jsxRuntime.jsxs("div", { className: "flex gap-1", children: [validationStateIcon, jsxRuntime.jsx("span", { "data-testid": dataTestId ? `${dataTestId}-helpText` : undefined, children: helpText })] })) : undefined, helpAddon !== undefined && helpAddon !== null ? (jsxRuntime.jsx("span", { className: cvaHelpAddon(), "data-testid": dataTestId ? `${dataTestId}-helpAddon` : null, children: helpAddon })) : null] })) : null] }));
2941
2954
  };
2942
2955
 
2943
2956
  /**
@@ -3429,6 +3442,7 @@ const validateEmailId = (emailId, required) => {
3429
3442
  * For specific input types make sure to use the corresponding input component.
3430
3443
  */
3431
3444
  const EmailBaseInput = ({ fieldSize = "medium", disabled = false, "data-testid": dataTestId, isInvalid = false, onChange, disableAction = false, ref, ...rest }) => {
3445
+ const [t] = useTranslation();
3432
3446
  const [email, setEmail] = react.useState(rest.value?.toString() || rest.defaultValue?.toString());
3433
3447
  const sendEmail = () => {
3434
3448
  return window.open(`mailto:${email}`);
@@ -3439,7 +3453,7 @@ const EmailBaseInput = ({ fieldSize = "medium", disabled = false, "data-testid":
3439
3453
  setEmail(newValue);
3440
3454
  }, [onChange]);
3441
3455
  const renderAsInvalid = (email && !validateEmailAddress(email)) || isInvalid;
3442
- return (jsxRuntime.jsx(BaseInput, { actions: email && email.length > 0 ? (jsxRuntime.jsx(ActionButton, { "data-testid": dataTestId ? `${dataTestId}-emailIcon` : undefined, disabled: disableAction || isInvalid, onClick: sendEmail, size: fieldSize, type: "EMAIL", value: email })) : null, "data-testid": dataTestId, disabled: disabled, fieldSize: fieldSize, isInvalid: renderAsInvalid, onChange: handleChange, placeholder: rest.placeholder || "mail@example.com", ref: ref, type: "email", ...rest }));
3456
+ return (jsxRuntime.jsx(BaseInput, { ...rest, actions: email && email.length > 0 ? (jsxRuntime.jsx(ActionButton, { "data-testid": dataTestId ? `${dataTestId}-emailIcon` : undefined, disabled: disableAction || isInvalid, onClick: sendEmail, size: fieldSize, title: t("emailField.sendEmailAction.label"), type: "EMAIL", value: email })) : null, "data-testid": dataTestId, disabled: disabled, fieldSize: fieldSize, isInvalid: renderAsInvalid, onChange: handleChange, placeholder: rest.placeholder || "mail@example.com", ref: ref, type: "email" }));
3443
3457
  };
3444
3458
 
3445
3459
  /**
@@ -3512,7 +3526,7 @@ const EmailField = ({ label, id, tip, helpText, errorMessage, helpAddon, classNa
3512
3526
  onChange(event);
3513
3527
  }
3514
3528
  }, [onChange]);
3515
- return (jsxRuntime.jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && error) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: required ? !(Boolean(rest.disabled) || Boolean(rest.readOnly)) : false, tip: tip, children: jsxRuntime.jsx(EmailBaseInput, { "aria-labelledby": htmlForId + "-label", defaultValue: defaultValue, id: htmlForId, isInvalid: renderAsInvalid, onBlur: handleBlur, onChange: handleChange, ref: ref, required: required, value: value, ...rest, className: className, "data-testid": dataTestId }) }));
3529
+ return (jsxRuntime.jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && error) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: required ? !(Boolean(rest.disabled) || Boolean(rest.readOnly)) : false, tip: tip, children: jsxRuntime.jsx(EmailBaseInput, { ...rest, "aria-labelledby": htmlForId + "-label", className: className, "data-testid": dataTestId, defaultValue: defaultValue, id: htmlForId, isInvalid: renderAsInvalid, onBlur: handleBlur, onChange: handleChange, ref: ref, required: required, value: value }) }));
3516
3530
  };
3517
3531
  EmailField.displayName = "EmailField";
3518
3532
 
@@ -3848,7 +3862,7 @@ const cvaOptionCardLabel = cssClassVarianceUtilities.cvaMerge([
3848
3862
  },
3849
3863
  });
3850
3864
  const cvaOptionCardContent = cssClassVarianceUtilities.cvaMerge(["flex", "flex-col", "items-center"]);
3851
- const cvaOptionCardContainer = cssClassVarianceUtilities.cvaMerge(["contents"]);
3865
+ const cvaOptionCardContainer = cssClassVarianceUtilities.cvaMerge(["flex", "grow-0"]);
3852
3866
  const cvaOptionCardTitle = cssClassVarianceUtilities.cvaMerge(["text-neutral-600"], {
3853
3867
  variants: {
3854
3868
  layout: {
@@ -3910,7 +3924,8 @@ OptionCard.displayName = "OptionCard";
3910
3924
  */
3911
3925
  const PasswordBaseInput = ({ ref, fieldSize = undefined, ...rest }) => {
3912
3926
  const [showPassword, setShowPassword] = react.useState(false);
3913
- return (jsxRuntime.jsx(BaseInput, { ref: ref, ...rest, actions: jsxRuntime.jsx("div", { className: cvaActionContainer({ size: fieldSize }), children: jsxRuntime.jsx(reactComponents.IconButton, { className: cvaActionButton({ size: fieldSize }), icon: jsxRuntime.jsx(reactComponents.Icon, { name: showPassword ? "EyeSlash" : "Eye", size: "small" }), onClick: () => setShowPassword(prevState => !prevState), size: "small", variant: "secondary" }) }), type: showPassword ? "text" : "password" }));
3927
+ const [t] = useTranslation();
3928
+ return (jsxRuntime.jsx(BaseInput, { ref: ref, ...rest, actions: jsxRuntime.jsx("div", { className: cvaActionContainer({ size: fieldSize }), children: jsxRuntime.jsx(reactComponents.IconButton, { className: cvaActionButton({ size: fieldSize }), icon: jsxRuntime.jsx(reactComponents.Icon, { name: showPassword ? "EyeSlash" : "Eye", size: "small" }), onClick: () => setShowPassword(prevState => !prevState), size: "small", title: showPassword ? t("passwordField.tooltip.hide") : t("passwordField.tooltip.show"), variant: "secondary" }) }), type: showPassword ? "text" : "password" }));
3914
3929
  };
3915
3930
 
3916
3931
  /**
@@ -5152,7 +5167,7 @@ const cvaToggleSwitchThumb = cssClassVarianceUtilities.cvaMerge(["block", "round
5152
5167
  * @param {ToggleSwitchProps} props - The props for the ToggleSwitch component
5153
5168
  * @returns {ReactElement} ToggleSwitch component
5154
5169
  */
5155
- const ToggleSwitch = ({ onChange, onClick, preventDefaultOnClick = false, className, "data-testid": dataTestId = "toggle-switch", showInputFocus = false, toggled, size = "medium", tabIndex = 0, readOnly = false, disabled = false, ref, ...rest }) => {
5170
+ const ToggleSwitch = ({ onChange, onClick, preventDefaultOnClick = false, className, "data-testid": dataTestId = "toggle-switch", showInputFocus = false, toggled, size = "medium", tabIndex = 0, readOnly = false, disabled = false, tooltipLabel, ref, ...rest }) => {
5156
5171
  const localInputRef = react.useRef(null);
5157
5172
  const mergedRef = reactComponents.useMergeRefs([ref, localInputRef]);
5158
5173
  // Extract data attributes to apply to wrapper
@@ -5187,12 +5202,12 @@ const ToggleSwitch = ({ onChange, onClick, preventDefaultOnClick = false, classN
5187
5202
  e.stopPropagation();
5188
5203
  onChange?.(!toggled, e);
5189
5204
  };
5190
- return (jsxRuntime.jsx("span", { className: cvaToggleSwitchWrapper({ className }), "data-testid": `${dataTestId}`, onClick: handleWrapperClick, onKeyDown: handleKeyPress, ...dataAttributes, children: jsxRuntime.jsxs("span", { className: cvaToggleSwitchTrack({
5191
- toggled,
5192
- disabled: disabled || readOnly,
5193
- size,
5194
- focused: showInputFocus,
5195
- }), "data-testid": `${dataTestId}-track`, children: [jsxRuntime.jsx("span", { className: cvaToggleSwitchThumb({ toggled, size }), "data-testid": `${dataTestId}-thumb` }), jsxRuntime.jsx("input", { "aria-disabled": disabled || readOnly, checked: toggled, className: cvaToggleSwitchInput(), "data-testid": `${dataTestId}-input`, disabled: disabled, onChange: handleInputChange, onClick: e => e.stopPropagation(), ref: mergedRef, role: "switch", tabIndex: tabIndex, type: "checkbox", ...rest })] }) }));
5205
+ return (jsxRuntime.jsx("span", { className: cvaToggleSwitchWrapper({ className }), "data-testid": `${dataTestId}`, onClick: handleWrapperClick, onKeyDown: handleKeyPress, ...dataAttributes, children: jsxRuntime.jsx(reactComponents.Tooltip, { disabled: !tooltipLabel, label: tooltipLabel, children: jsxRuntime.jsxs("span", { className: cvaToggleSwitchTrack({
5206
+ toggled,
5207
+ disabled: disabled || readOnly,
5208
+ size,
5209
+ focused: showInputFocus,
5210
+ }), "data-testid": `${dataTestId}-track`, children: [jsxRuntime.jsx("span", { className: cvaToggleSwitchThumb({ toggled, size }), "data-testid": `${dataTestId}-thumb` }), jsxRuntime.jsx("input", { "aria-disabled": disabled || readOnly, checked: toggled, className: cvaToggleSwitchInput(), "data-testid": `${dataTestId}-input`, disabled: disabled, onChange: handleInputChange, onClick: e => e.stopPropagation(), ref: mergedRef, role: "switch", tabIndex: tabIndex, type: "checkbox", ...rest })] }) }) }));
5196
5211
  };
5197
5212
  ToggleSwitch.displayName = "ToggleSwitch";
5198
5213
 
@@ -5408,9 +5423,10 @@ const validateUrl = (url, required) => {
5408
5423
  * NOTE: If shown with a label, please use the `UrlField` component instead.
5409
5424
  */
5410
5425
  const UrlBaseInput = ({ isInvalid = false, "data-testid": dataTestId, disabled = false, fieldSize = "medium", disableAction = false, value, defaultValue, ref, ...rest }) => {
5426
+ const [t] = useTranslation();
5411
5427
  const [url, setUrl] = react.useState(value?.toString() || defaultValue?.toString());
5412
5428
  const renderAsInvalid = (url && typeof url === "string" && !validateUrlAddress(url)) || isInvalid;
5413
- return (jsxRuntime.jsx(BaseInput, { "data-testid": dataTestId ? `${dataTestId}-url-input` : undefined, disabled: disabled, id: "url-input", isInvalid: renderAsInvalid, onChange: e => setUrl(e.target.value), placeholder: rest.placeholder || "https://www.example.com", ref: ref, type: "url", value: url, ...rest, actions: !disableAction && (jsxRuntime.jsx(ActionButton, { "data-testid": (dataTestId && `${dataTestId}-url-input-Icon`) || "url-input-action-icon", disabled: renderAsInvalid || Boolean(disabled) || disableAction, size: fieldSize, type: "WEB_ADDRESS", value: url })) }));
5429
+ return (jsxRuntime.jsx(BaseInput, { ...rest, actions: !disableAction && (jsxRuntime.jsx(ActionButton, { "data-testid": (dataTestId && `${dataTestId}-url-input-Icon`) || "url-input-action-icon", disabled: renderAsInvalid || Boolean(disabled) || disableAction, size: fieldSize, title: t("urlField.url.label"), type: "WEB_ADDRESS", value: url })), "data-testid": dataTestId ? `${dataTestId}-url-input` : undefined, disabled: disabled, id: "url-input", isInvalid: renderAsInvalid, onChange: e => setUrl(e.target.value), placeholder: rest.placeholder || "https://www.example.com", ref: ref, type: "url", value: url }));
5414
5430
  };
5415
5431
 
5416
5432
  /**
@@ -5477,7 +5493,7 @@ const UrlField = ({ label, id, tip, helpText, errorMessage, helpAddon, className
5477
5493
  setRenderAsInvalid(!!validateUrl(newValue, required));
5478
5494
  onBlur?.(event);
5479
5495
  }, [onBlur, required]);
5480
- return (jsxRuntime.jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: renderAsInvalid ? error : helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: required ? !(Boolean(rest.disabled) || Boolean(rest.readOnly)) : false, tip: tip, children: jsxRuntime.jsx(UrlBaseInput, { "aria-labelledby": htmlForId + "-label", id: htmlForId, isInvalid: renderAsInvalid, onBlur: handleBlur, ref: ref, required: required, value: value ?? defaultValue, ...rest, className: className, "data-testid": dataTestId }) }));
5496
+ return (jsxRuntime.jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: renderAsInvalid ? error : helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: required ? !(Boolean(rest.disabled) || Boolean(rest.readOnly)) : false, tip: tip, children: jsxRuntime.jsx(UrlBaseInput, { ...rest, "aria-labelledby": htmlForId + "-label", className: className, "data-testid": dataTestId, id: htmlForId, isInvalid: renderAsInvalid, onBlur: handleBlur, ref: ref, required: required, value: value ?? defaultValue }) }));
5481
5497
  };
5482
5498
  UrlField.displayName = "UrlField";
5483
5499
 
package/index.esm.js CHANGED
@@ -34,6 +34,7 @@ var defaultTranslations = {
34
34
  "dropzone.label.default": "<clickable>Browse</clickable> or drag files here...",
35
35
  "emailField.error.INVALID_EMAIL": "Please enter a valid email address",
36
36
  "emailField.error.REQUIRED": "The email address is required",
37
+ "emailField.sendEmailAction.label": "Email",
37
38
  "field.notEditable.tooltip": "This field is not editable",
38
39
  "field.required.asterisk.tooltip": "This field is required",
39
40
  "numberField.error.GREATER_THAN": "Value must be greater than or equal to {{min}}",
@@ -41,6 +42,8 @@ var defaultTranslations = {
41
42
  "numberField.error.LESS_THAN": "Value must be less than or equal to {{max}}",
42
43
  "numberField.error.NOT_IN_BETWEEN": "Must be between {{min}} and {{max}}",
43
44
  "numberField.error.REQUIRED": "This field is required",
45
+ "passwordField.tooltip.hide": "Hide password",
46
+ "passwordField.tooltip.show": "Show password",
44
47
  "phoneField.error.INVALID_COUNTRY": "The country code is not valid",
45
48
  "phoneField.error.INVALID_LENGTH": "The phone number is not valid",
46
49
  "phoneField.error.INVALID_NUMBER": "The phone number is not valid",
@@ -50,14 +53,17 @@ var defaultTranslations = {
50
53
  "phoneField.error.TOO_LONG": "The phone number is too long",
51
54
  "phoneField.error.TOO_SHORT": "The phone number is too short",
52
55
  "phoneField.error.undefined": "",
56
+ "phoneField.phoneNumber.label": "Phone Number",
53
57
  "schedule.label.active": "Active",
54
58
  "schedule.label.allDay": "All Day",
55
59
  "schedule.label.day": "Day",
56
60
  "search.placeholder": "Search",
57
61
  "select.loadingMessage": "Loading...",
62
+ "select.multiValue.remove": "Remove",
58
63
  "select.noOptionsMessage": "No options found",
59
64
  "urlField.error.INVALID_URL": "Please enter a valid URL",
60
- "urlField.error.REQUIRED": "The URL is required"
65
+ "urlField.error.REQUIRED": "The URL is required",
66
+ "urlField.url.label": "Web address"
61
67
  };
62
68
 
63
69
  /** The translation namespace for this library */
@@ -607,7 +613,7 @@ const AddonRenderer = ({ addon, "data-testid": dataTestId, className, fieldSize,
607
613
  * @param {ActionButtonProps} props - The props for the ActionButton component
608
614
  * @returns {ReactElement} ActionButton component
609
615
  */
610
- const ActionButton = ({ type, value, "data-testid": dataTestId, size = "medium", disabled, className, onClick, style, ref, }) => {
616
+ const ActionButton = ({ type, value, "data-testid": dataTestId, size = "medium", disabled, className, title, style, ref, }) => {
611
617
  const [, copyToClipboard] = useCopyToClipboard();
612
618
  const getIconName = () => {
613
619
  switch (type) {
@@ -646,15 +652,18 @@ const ActionButton = ({ type, value, "data-testid": dataTestId, size = "medium",
646
652
  }
647
653
  };
648
654
  const adjustedIconSize = size === "large" ? "medium" : size;
649
- return (jsx("div", { className: cvaActionContainer({ className, size }), ref: ref, style: style, children: jsx(IconButton, { className: cvaActionButton({ size: adjustedIconSize }), "data-testid": dataTestId || "testIconButtonId", disabled: disabled, icon: jsx(Icon, { name: getIconName(), size: adjustedIconSize }), onClick: buttonAction, size: "small", variant: "ghost-neutral" }) }));
655
+ return (jsx("div", { className: cvaActionContainer({ className, size }), ref: ref, style: style, children: jsx(IconButton, { className: cvaActionButton({ size: adjustedIconSize }), "data-testid": dataTestId || "testIconButtonId", disabled: disabled, icon: jsx(Icon, { name: getIconName(), size: adjustedIconSize }), onClick: buttonAction, size: "small", title: title, variant: "ghost-neutral" }) }));
650
656
  };
651
657
 
658
+ /**
659
+ *
660
+ */
652
661
  const GenericActionsRenderer = ({ genericAction = undefined, disabled, fieldSize = undefined, innerRef, tooltipLabel, }) => {
653
662
  const [t] = useTranslation();
654
663
  if (!genericAction) {
655
664
  return null;
656
665
  }
657
- return (jsx(Tooltip, { label: tooltipLabel ?? t("baseInput.copyAction.toolTip"), placement: "top", children: jsx(ActionButton, { "data-testid": "copy-value-button", disabled: disabled, size: fieldSize ?? undefined, type: genericAction === "edit" ? "EDIT" : "COPY", value: innerRef }) }));
666
+ return (jsx(ActionButton, { "data-testid": "copy-value-button", disabled: disabled, size: fieldSize ?? undefined, title: tooltipLabel ?? t("baseInput.copyAction.toolTip"), type: genericAction === "edit" ? "EDIT" : "COPY", value: innerRef }));
658
667
  };
659
668
 
660
669
  /**
@@ -1346,7 +1355,7 @@ const DateBaseInput = ({ min, max, defaultValue, value, ref, onChange, onBlur, o
1346
1355
  onPopoverOpenStateChange(true);
1347
1356
  }
1348
1357
  };
1349
- return (jsxs(Fragment, { children: [jsx(PopoverTrigger, { children: jsx("div", { className: "flex w-full min-w-0 items-center", children: jsx(BaseInput, { ...rest, "aria-readonly": true, className: twMerge("w-full min-w-0", rest.className), "data-testid": dataTestId ? `${dataTestId}-input` : undefined, onBlur: handleInputBlur, onChange: handleInputChange, onFocus: handleInputFocus, onKeyDown: handleInputKeyDown, placeholder: rest.placeholder ?? getDateFieldPlaceholder(locale), ref: setInputRef, suffix: suffixProp ?? (jsx("div", { className: cvaActionContainer({ size: "medium" }), children: jsx(IconButton, { "aria-expanded": isOpen, "aria-label": t("dateField.openPicker.ariaLabel"), className: cvaActionButton({ size: "small" }), "data-testid": dataTestId ? `${dataTestId}-calendar` : "calendar", disabled: isPickerDisabled, icon: jsx(Icon, { "aria-label": undefined, name: "Calendar", size: "small", type: "solid" }), onClick: togglePopover, size: "small", tabIndex: isOpen ? -1 : undefined, variant: "ghost-neutral" }) })), tabIndex: isOpen ? -1 : rest.tabIndex, type: "text", value: resolvedValue }) }) }), jsx(PopoverContent, { initialFocus: 1, children: closePopover => (jsx(DateBaseInputPickerContent, { applyDate: applyDate, closePopover: closePopover, "data-testid": dataTestId, onApply: onApply, onCalendarChange: onCalendarChange, onCancel: onCancel, onClear: onClear, pendingDate: pendingDate, selectedDate: selectedDate, tileDisabled: tileDisabled })) })] }));
1358
+ return (jsxs(Fragment, { children: [jsx(PopoverTrigger, { children: jsx("div", { className: "flex w-full min-w-0 items-center", children: jsx(BaseInput, { ...rest, "aria-readonly": true, className: twMerge("w-full min-w-0", rest.className), "data-testid": dataTestId ? `${dataTestId}-input` : undefined, onBlur: handleInputBlur, onChange: handleInputChange, onFocus: handleInputFocus, onKeyDown: handleInputKeyDown, placeholder: rest.placeholder ?? getDateFieldPlaceholder(locale), ref: setInputRef, suffix: suffixProp ?? (jsx("div", { className: cvaActionContainer({ size: "medium" }), children: jsx(IconButton, { "aria-expanded": isOpen, ariaLabel: t("dateField.openPicker.ariaLabel"), className: cvaActionButton({ size: "small" }), "data-testid": dataTestId ? `${dataTestId}-calendar` : "calendar", disabled: isPickerDisabled, icon: jsx(Icon, { "aria-label": undefined, name: "Calendar", size: "small", type: "solid" }), onClick: togglePopover, size: "small", tabIndex: isOpen ? -1 : undefined, variant: "ghost-neutral" }) })), tabIndex: isOpen ? -1 : rest.tabIndex, type: "text", value: resolvedValue }) }) }), jsx(PopoverContent, { initialFocus: 1, children: closePopover => (jsx(DateBaseInputPickerContent, { applyDate: applyDate, closePopover: closePopover, "data-testid": dataTestId, onApply: onApply, onCalendarChange: onCalendarChange, onCancel: onCancel, onClear: onClear, pendingDate: pendingDate, selectedDate: selectedDate, tileDisabled: tileDisabled })) })] }));
1350
1359
  } }));
1351
1360
  };
1352
1361
 
@@ -1453,6 +1462,7 @@ const DEFAULT_COUNTRY_CODE = undefined;
1453
1462
  * @returns {ReactElement} The phone input component.
1454
1463
  */
1455
1464
  const PhoneBaseInput = ({ "data-testid": dataTestId, isInvalid, disabled = false, value, defaultValue, fieldSize = "medium", disableAction = false, onChange, readOnly, onFocus, onBlur, name, ref, ...rest }) => {
1465
+ const [t] = useTranslation();
1456
1466
  const [innerValue, setInnerValue] = useState(() => {
1457
1467
  return (value?.toString() || defaultValue?.toString()) ?? "";
1458
1468
  });
@@ -1494,7 +1504,7 @@ const PhoneBaseInput = ({ "data-testid": dataTestId, isInvalid, disabled = false
1494
1504
  onFocus?.(event);
1495
1505
  fieldIsFocused.current = true;
1496
1506
  }, [onFocus]);
1497
- return (jsx("div", { className: "grid grid-cols-1 gap-2", "data-testid": dataTestId ? `${dataTestId}-container` : null, children: jsx(BaseInput, { actions: !disableAction && innerValue && innerValue.length > 0 ? (jsx(ActionButton, { "data-testid": dataTestId ? `${dataTestId}-phoneIcon` : undefined, disabled: isInvalid, size: fieldSize, type: "PHONE_NUMBER", value: value?.toString() || "" })) : null, "data-testid": dataTestId ? `${dataTestId}-phoneNumberInput` : undefined, disabled: disabled, fieldSize: fieldSize, id: "phoneInput-number", isInvalid: isInvalid, name: name, onBlur: handleBlur, onChange: handleChange, onFocus: handleFocus, prefix: (countryCode && countryCodeToFlagEmoji(countryCode)) || undefined, readOnly: readOnly, ref: ref, type: "tel", value: innerValue, ...rest }) }));
1507
+ return (jsx("div", { className: "grid grid-cols-1 gap-2", "data-testid": dataTestId ? `${dataTestId}-container` : null, children: jsx(BaseInput, { ...rest, actions: !disableAction && innerValue && innerValue.length > 0 ? (jsx(ActionButton, { "data-testid": dataTestId ? `${dataTestId}-phoneIcon` : undefined, disabled: isInvalid, size: fieldSize, title: t("phoneField.phoneNumber.label"), type: "PHONE_NUMBER", value: value?.toString() || "" })) : null, "data-testid": dataTestId ? `${dataTestId}-phoneNumberInput` : undefined, disabled: disabled, fieldSize: fieldSize, id: "phoneInput-number", isInvalid: isInvalid, name: name, onBlur: handleBlur, onChange: handleChange, onFocus: handleFocus, prefix: (countryCode && countryCodeToFlagEmoji(countryCode)) || undefined, readOnly: readOnly, ref: ref, type: "tel", value: innerValue }) }));
1498
1508
  };
1499
1509
 
1500
1510
  const cvaTextAreaBaseInput = cvaMerge([
@@ -1670,7 +1680,7 @@ const CounterTag = ({ fieldSize, hiddenCount, totalCount, ref, className, "data-
1670
1680
  * Internal component for rendering multi-select values with measurement support.
1671
1681
  * Uses the measurement state to determine if the value should be displayed or hidden based on available width.
1672
1682
  */
1673
- const MultiValue = ({ data, children, onClose, className, disabled, fieldSize, getOptionPrefix, ref, "data-testid": dataTestId, }) => {
1683
+ const MultiValue = ({ data, children, onClose, className, disabled, fieldSize, getOptionPrefix, removeTagLabel, ref, "data-testid": dataTestId, }) => {
1674
1684
  const optionPrefix = getOptionPrefix ? getOptionPrefix(data) : null;
1675
1685
  const handleOnClose = (e) => {
1676
1686
  if (disabled) {
@@ -1679,7 +1689,10 @@ const MultiValue = ({ data, children, onClose, className, disabled, fieldSize, g
1679
1689
  e.stopPropagation();
1680
1690
  onClose?.(e);
1681
1691
  };
1682
- return (jsx(Tag, { className: twMerge(className), color: disabled ? "neutral" : "white", "data-testid": dataTestId, icon: optionPrefix, onClickClose: disabled ? undefined : handleOnClose, ref: ref, size: fieldSize === "small" ? "small" : "medium", children: jsx("span", { className: "flex items-center gap-1", children: children }) }));
1692
+ if (disabled) {
1693
+ return (jsx(Tag, { className: twMerge(className), color: "neutral", "data-testid": dataTestId, icon: optionPrefix, ref: ref, size: fieldSize === "small" ? "small" : "medium", children: jsx("span", { className: "flex items-center gap-1", children: children }) }));
1694
+ }
1695
+ return (jsx(Tag, { className: twMerge(className), color: "white", "data-testid": dataTestId, icon: optionPrefix, onClickClose: handleOnClose, ref: ref, removeTagLabel: removeTagLabel, size: fieldSize === "small" ? "small" : "medium", children: jsx("span", { className: "flex items-center gap-1", children: children }) }));
1683
1696
  };
1684
1697
 
1685
1698
  /**
@@ -2482,7 +2495,7 @@ formatOptionLabel, }) => {
2482
2495
  return (jsx(components.MultiValue, { ...selectMultiValue, getStyles: getNoStyles, children: jsx(MultiValue, { className: cvaSelectMultiValue({
2483
2496
  hidden: currentIsComplete && index + 1 > currentVisibleCount, // Hide if doesn't fit
2484
2497
  invisible: currentWithCounter && !currentIsComplete, // Make invisible if measuring with counter. When there's a counter, it would otherwise briefly change layout to make room for the "fake" counter
2485
- }), data: selectMultiValue.data, "data-testid": dataTestId ? `${dataTestId}-multiValue-${index}` : undefined, disabled: Boolean(disabled), fieldSize: fieldSize, getOptionPrefix: getOptionPrefix, onClose: selectMultiValue.removeProps.onClick, ref: setGeometryRef(index), children: selectMultiValue.children }) }));
2498
+ }), data: selectMultiValue.data, "data-testid": dataTestId ? `${dataTestId}-multiValue-${index}` : undefined, disabled: Boolean(disabled), fieldSize: fieldSize, getOptionPrefix: getOptionPrefix, onClose: selectMultiValue.removeProps.onClick, ref: setGeometryRef(index), removeTagLabel: t("select.multiValue.remove"), children: selectMultiValue.children }) }));
2486
2499
  },
2487
2500
  Menu: selectMenu => {
2488
2501
  return (jsx(components.Menu, { ...selectMenu, className: cvaSelectMenu({ className: selectMenu.className, placement: selectMenu.placement }), getStyles: getNoStyles, innerProps: {
@@ -2936,7 +2949,7 @@ const FormGroup = ({ isInvalid = false, isWarning = false, helpText, helpAddon,
2936
2949
  const color = isInvalid ? "danger" : isWarning ? "warning" : null;
2937
2950
  return color ? jsx(Icon, { color: color, name: "ExclamationTriangle", size: "small" }) : null;
2938
2951
  }, [isInvalid, isWarning]);
2939
- return (jsxs("div", { className: cvaFormGroup({ className }), "data-testid": dataTestId, ref: ref, style: style, children: [label !== undefined && label !== null ? (jsxs("div", { className: cvaFormGroupContainerBefore(), children: [jsxs(Fragment, { children: [jsx(Label, { className: "component-formGroup-font", "data-testid": dataTestId ? `${dataTestId}-label` : undefined, htmlFor: htmlFor, id: htmlFor + "-label", children: label }), required ? (jsx(Tooltip, { "data-testid": "required-asterisk", label: t("field.required.asterisk.tooltip"), children: jsx("span", { children: "*" }) })) : null] }), tip !== undefined && tip !== null ? (jsx("span", { className: "ml-1", children: jsx(Tooltip, { "data-testid": dataTestId ? `${dataTestId}-tooltip` : undefined, label: tip, placement: "bottom" }) })) : null] })) : null, children, (helpText !== undefined && helpText !== null) || (helpAddon !== undefined && helpAddon !== null) ? (jsxs("div", { className: cvaFormGroupContainerAfter({ invalid: isInvalid, isWarning: isWarning }), children: [helpText ? (jsxs("div", { className: "flex gap-1", children: [validationStateIcon, jsx("span", { "data-testid": dataTestId ? `${dataTestId}-helpText` : undefined, children: helpText })] })) : undefined, helpAddon !== undefined && helpAddon !== null ? (jsx("span", { className: cvaHelpAddon(), "data-testid": dataTestId ? `${dataTestId}-helpAddon` : null, children: helpAddon })) : null] })) : null] }));
2952
+ return (jsxs("div", { className: cvaFormGroup({ className }), "data-testid": dataTestId, ref: ref, style: style, children: [label !== undefined && label !== null ? (jsxs("div", { className: cvaFormGroupContainerBefore(), children: [jsxs(Fragment, { children: [jsx(Label, { className: "component-formGroup-font", "data-testid": dataTestId ? `${dataTestId}-label` : undefined, htmlFor: htmlFor, id: htmlFor + "-label", children: label }), required ? (jsx(Tooltip, { "data-testid": "required-asterisk", label: t("field.required.asterisk.tooltip"), children: jsx("span", { children: "*" }) })) : null] }), tip !== undefined && tip !== null ? (jsx("span", { className: "ml-1 mt-1 flex items-center", children: jsx(Tooltip, { "data-testid": dataTestId ? `${dataTestId}-tooltip` : undefined, label: tip, placement: "bottom" }) })) : null] })) : null, children, (helpText !== undefined && helpText !== null) || (helpAddon !== undefined && helpAddon !== null) ? (jsxs("div", { className: cvaFormGroupContainerAfter({ invalid: isInvalid, isWarning: isWarning }), children: [helpText ? (jsxs("div", { className: "flex gap-1", children: [validationStateIcon, jsx("span", { "data-testid": dataTestId ? `${dataTestId}-helpText` : undefined, children: helpText })] })) : undefined, helpAddon !== undefined && helpAddon !== null ? (jsx("span", { className: cvaHelpAddon(), "data-testid": dataTestId ? `${dataTestId}-helpAddon` : null, children: helpAddon })) : null] })) : null] }));
2940
2953
  };
2941
2954
 
2942
2955
  /**
@@ -3428,6 +3441,7 @@ const validateEmailId = (emailId, required) => {
3428
3441
  * For specific input types make sure to use the corresponding input component.
3429
3442
  */
3430
3443
  const EmailBaseInput = ({ fieldSize = "medium", disabled = false, "data-testid": dataTestId, isInvalid = false, onChange, disableAction = false, ref, ...rest }) => {
3444
+ const [t] = useTranslation();
3431
3445
  const [email, setEmail] = useState(rest.value?.toString() || rest.defaultValue?.toString());
3432
3446
  const sendEmail = () => {
3433
3447
  return window.open(`mailto:${email}`);
@@ -3438,7 +3452,7 @@ const EmailBaseInput = ({ fieldSize = "medium", disabled = false, "data-testid":
3438
3452
  setEmail(newValue);
3439
3453
  }, [onChange]);
3440
3454
  const renderAsInvalid = (email && !validateEmailAddress(email)) || isInvalid;
3441
- return (jsx(BaseInput, { actions: email && email.length > 0 ? (jsx(ActionButton, { "data-testid": dataTestId ? `${dataTestId}-emailIcon` : undefined, disabled: disableAction || isInvalid, onClick: sendEmail, size: fieldSize, type: "EMAIL", value: email })) : null, "data-testid": dataTestId, disabled: disabled, fieldSize: fieldSize, isInvalid: renderAsInvalid, onChange: handleChange, placeholder: rest.placeholder || "mail@example.com", ref: ref, type: "email", ...rest }));
3455
+ return (jsx(BaseInput, { ...rest, actions: email && email.length > 0 ? (jsx(ActionButton, { "data-testid": dataTestId ? `${dataTestId}-emailIcon` : undefined, disabled: disableAction || isInvalid, onClick: sendEmail, size: fieldSize, title: t("emailField.sendEmailAction.label"), type: "EMAIL", value: email })) : null, "data-testid": dataTestId, disabled: disabled, fieldSize: fieldSize, isInvalid: renderAsInvalid, onChange: handleChange, placeholder: rest.placeholder || "mail@example.com", ref: ref, type: "email" }));
3442
3456
  };
3443
3457
 
3444
3458
  /**
@@ -3511,7 +3525,7 @@ const EmailField = ({ label, id, tip, helpText, errorMessage, helpAddon, classNa
3511
3525
  onChange(event);
3512
3526
  }
3513
3527
  }, [onChange]);
3514
- return (jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && error) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: required ? !(Boolean(rest.disabled) || Boolean(rest.readOnly)) : false, tip: tip, children: jsx(EmailBaseInput, { "aria-labelledby": htmlForId + "-label", defaultValue: defaultValue, id: htmlForId, isInvalid: renderAsInvalid, onBlur: handleBlur, onChange: handleChange, ref: ref, required: required, value: value, ...rest, className: className, "data-testid": dataTestId }) }));
3528
+ return (jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && error) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: required ? !(Boolean(rest.disabled) || Boolean(rest.readOnly)) : false, tip: tip, children: jsx(EmailBaseInput, { ...rest, "aria-labelledby": htmlForId + "-label", className: className, "data-testid": dataTestId, defaultValue: defaultValue, id: htmlForId, isInvalid: renderAsInvalid, onBlur: handleBlur, onChange: handleChange, ref: ref, required: required, value: value }) }));
3515
3529
  };
3516
3530
  EmailField.displayName = "EmailField";
3517
3531
 
@@ -3847,7 +3861,7 @@ const cvaOptionCardLabel = cvaMerge([
3847
3861
  },
3848
3862
  });
3849
3863
  const cvaOptionCardContent = cvaMerge(["flex", "flex-col", "items-center"]);
3850
- const cvaOptionCardContainer = cvaMerge(["contents"]);
3864
+ const cvaOptionCardContainer = cvaMerge(["flex", "grow-0"]);
3851
3865
  const cvaOptionCardTitle = cvaMerge(["text-neutral-600"], {
3852
3866
  variants: {
3853
3867
  layout: {
@@ -3909,7 +3923,8 @@ OptionCard.displayName = "OptionCard";
3909
3923
  */
3910
3924
  const PasswordBaseInput = ({ ref, fieldSize = undefined, ...rest }) => {
3911
3925
  const [showPassword, setShowPassword] = useState(false);
3912
- 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" }));
3926
+ const [t] = useTranslation();
3927
+ 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", title: showPassword ? t("passwordField.tooltip.hide") : t("passwordField.tooltip.show"), variant: "secondary" }) }), type: showPassword ? "text" : "password" }));
3913
3928
  };
3914
3929
 
3915
3930
  /**
@@ -5151,7 +5166,7 @@ const cvaToggleSwitchThumb = cvaMerge(["block", "rounded-full", "bg-white", "asp
5151
5166
  * @param {ToggleSwitchProps} props - The props for the ToggleSwitch component
5152
5167
  * @returns {ReactElement} ToggleSwitch component
5153
5168
  */
5154
- const ToggleSwitch = ({ onChange, onClick, preventDefaultOnClick = false, className, "data-testid": dataTestId = "toggle-switch", showInputFocus = false, toggled, size = "medium", tabIndex = 0, readOnly = false, disabled = false, ref, ...rest }) => {
5169
+ const ToggleSwitch = ({ onChange, onClick, preventDefaultOnClick = false, className, "data-testid": dataTestId = "toggle-switch", showInputFocus = false, toggled, size = "medium", tabIndex = 0, readOnly = false, disabled = false, tooltipLabel, ref, ...rest }) => {
5155
5170
  const localInputRef = useRef(null);
5156
5171
  const mergedRef = useMergeRefs([ref, localInputRef]);
5157
5172
  // Extract data attributes to apply to wrapper
@@ -5186,12 +5201,12 @@ const ToggleSwitch = ({ onChange, onClick, preventDefaultOnClick = false, classN
5186
5201
  e.stopPropagation();
5187
5202
  onChange?.(!toggled, e);
5188
5203
  };
5189
- return (jsx("span", { className: cvaToggleSwitchWrapper({ className }), "data-testid": `${dataTestId}`, onClick: handleWrapperClick, onKeyDown: handleKeyPress, ...dataAttributes, children: jsxs("span", { className: cvaToggleSwitchTrack({
5190
- toggled,
5191
- disabled: disabled || readOnly,
5192
- size,
5193
- focused: showInputFocus,
5194
- }), "data-testid": `${dataTestId}-track`, children: [jsx("span", { className: cvaToggleSwitchThumb({ toggled, size }), "data-testid": `${dataTestId}-thumb` }), jsx("input", { "aria-disabled": disabled || readOnly, checked: toggled, className: cvaToggleSwitchInput(), "data-testid": `${dataTestId}-input`, disabled: disabled, onChange: handleInputChange, onClick: e => e.stopPropagation(), ref: mergedRef, role: "switch", tabIndex: tabIndex, type: "checkbox", ...rest })] }) }));
5204
+ return (jsx("span", { className: cvaToggleSwitchWrapper({ className }), "data-testid": `${dataTestId}`, onClick: handleWrapperClick, onKeyDown: handleKeyPress, ...dataAttributes, children: jsx(Tooltip, { disabled: !tooltipLabel, label: tooltipLabel, children: jsxs("span", { className: cvaToggleSwitchTrack({
5205
+ toggled,
5206
+ disabled: disabled || readOnly,
5207
+ size,
5208
+ focused: showInputFocus,
5209
+ }), "data-testid": `${dataTestId}-track`, children: [jsx("span", { className: cvaToggleSwitchThumb({ toggled, size }), "data-testid": `${dataTestId}-thumb` }), jsx("input", { "aria-disabled": disabled || readOnly, checked: toggled, className: cvaToggleSwitchInput(), "data-testid": `${dataTestId}-input`, disabled: disabled, onChange: handleInputChange, onClick: e => e.stopPropagation(), ref: mergedRef, role: "switch", tabIndex: tabIndex, type: "checkbox", ...rest })] }) }) }));
5195
5210
  };
5196
5211
  ToggleSwitch.displayName = "ToggleSwitch";
5197
5212
 
@@ -5407,9 +5422,10 @@ const validateUrl = (url, required) => {
5407
5422
  * NOTE: If shown with a label, please use the `UrlField` component instead.
5408
5423
  */
5409
5424
  const UrlBaseInput = ({ isInvalid = false, "data-testid": dataTestId, disabled = false, fieldSize = "medium", disableAction = false, value, defaultValue, ref, ...rest }) => {
5425
+ const [t] = useTranslation();
5410
5426
  const [url, setUrl] = useState(value?.toString() || defaultValue?.toString());
5411
5427
  const renderAsInvalid = (url && typeof url === "string" && !validateUrlAddress(url)) || isInvalid;
5412
- return (jsx(BaseInput, { "data-testid": dataTestId ? `${dataTestId}-url-input` : undefined, disabled: disabled, id: "url-input", isInvalid: renderAsInvalid, onChange: e => setUrl(e.target.value), placeholder: rest.placeholder || "https://www.example.com", ref: ref, type: "url", value: url, ...rest, actions: !disableAction && (jsx(ActionButton, { "data-testid": (dataTestId && `${dataTestId}-url-input-Icon`) || "url-input-action-icon", disabled: renderAsInvalid || Boolean(disabled) || disableAction, size: fieldSize, type: "WEB_ADDRESS", value: url })) }));
5428
+ return (jsx(BaseInput, { ...rest, actions: !disableAction && (jsx(ActionButton, { "data-testid": (dataTestId && `${dataTestId}-url-input-Icon`) || "url-input-action-icon", disabled: renderAsInvalid || Boolean(disabled) || disableAction, size: fieldSize, title: t("urlField.url.label"), type: "WEB_ADDRESS", value: url })), "data-testid": dataTestId ? `${dataTestId}-url-input` : undefined, disabled: disabled, id: "url-input", isInvalid: renderAsInvalid, onChange: e => setUrl(e.target.value), placeholder: rest.placeholder || "https://www.example.com", ref: ref, type: "url", value: url }));
5413
5429
  };
5414
5430
 
5415
5431
  /**
@@ -5476,7 +5492,7 @@ const UrlField = ({ label, id, tip, helpText, errorMessage, helpAddon, className
5476
5492
  setRenderAsInvalid(!!validateUrl(newValue, required));
5477
5493
  onBlur?.(event);
5478
5494
  }, [onBlur, required]);
5479
- return (jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: renderAsInvalid ? error : helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: required ? !(Boolean(rest.disabled) || Boolean(rest.readOnly)) : false, tip: tip, children: jsx(UrlBaseInput, { "aria-labelledby": htmlForId + "-label", id: htmlForId, isInvalid: renderAsInvalid, onBlur: handleBlur, ref: ref, required: required, value: value ?? defaultValue, ...rest, className: className, "data-testid": dataTestId }) }));
5495
+ return (jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: renderAsInvalid ? error : helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: required ? !(Boolean(rest.disabled) || Boolean(rest.readOnly)) : false, tip: tip, children: jsx(UrlBaseInput, { ...rest, "aria-labelledby": htmlForId + "-label", className: className, "data-testid": dataTestId, id: htmlForId, isInvalid: renderAsInvalid, onBlur: handleBlur, ref: ref, required: required, value: value ?? defaultValue }) }));
5480
5496
  };
5481
5497
  UrlField.displayName = "UrlField";
5482
5498
 
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entry.js","sourceRoot":"","sources":["../../../../../libs/react/form-components/migrations/entry.ts"],"names":[],"mappings":"","sourcesContent":["// Migration entry point for @nx/js:tsc build target.\n// Migrations are registered in ../migrations.json and resolved by NX at runtime.\nexport {};\n"]}
@@ -0,0 +1,203 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.insertAttributeIntoOpeningTag = exports.logSummary = exports.tsquery = exports.parseTsx = exports.hasSpreadAttribute = exports.findJsxAttribute = exports.findJsxElements = exports.getLocalAliasFor = exports.getImportedAliases = exports.visitTsFiles = exports.visitTsxFiles = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const devkit_1 = require("@nx/devkit");
6
+ const tsquery_1 = require("@phenomnomnominal/tsquery");
7
+ Object.defineProperty(exports, "tsquery", { enumerable: true, get: function () { return tsquery_1.tsquery; } });
8
+ const ts = tslib_1.__importStar(require("typescript"));
9
+ const TSX_EXTENSIONS = [".tsx", ".jsx"];
10
+ const TS_EXTENSIONS = [".ts", ".tsx", ".jsx"];
11
+ const isTsxFile = (filePath) => TSX_EXTENSIONS.some(ext => filePath.endsWith(ext));
12
+ const isTsFile = (filePath) => TS_EXTENSIONS.some(ext => filePath.endsWith(ext));
13
+ const isUnderNodeModules = (filePath) => filePath.includes("/node_modules/") || filePath.startsWith("node_modules/");
14
+ const isUnderDist = (filePath) => filePath.includes("/dist/") || filePath.startsWith("dist/") || filePath.includes("/.nx/");
15
+ /**
16
+ * Visits every `.tsx`/`.jsx` file under the workspace root and invokes the
17
+ * callback with the file path and its current contents. Files that don't
18
+ * include the marker substring are skipped, which makes large workspaces
19
+ * cheap to scan.
20
+ */
21
+ const visitTsxFiles = (tree, marker, callback) => {
22
+ let touched = 0;
23
+ (0, devkit_1.visitNotIgnoredFiles)(tree, "/", filePath => {
24
+ if (!isTsxFile(filePath))
25
+ return;
26
+ if (isUnderNodeModules(filePath) || isUnderDist(filePath))
27
+ return;
28
+ const content = tree.read(filePath, "utf-8");
29
+ if (content === null)
30
+ return;
31
+ if (!content.includes(marker))
32
+ return;
33
+ const updated = callback(filePath, content);
34
+ if (updated !== null && updated !== undefined && updated !== content) {
35
+ tree.write(filePath, updated);
36
+ touched += 1;
37
+ }
38
+ });
39
+ return touched;
40
+ };
41
+ exports.visitTsxFiles = visitTsxFiles;
42
+ /**
43
+ * Same as {@link visitTsxFiles} but also includes plain `.ts` files. Use this
44
+ * when the codemod also rewrites non-JSX files such as helpers or hooks.
45
+ */
46
+ const visitTsFiles = (tree, marker, callback) => {
47
+ let touched = 0;
48
+ (0, devkit_1.visitNotIgnoredFiles)(tree, "/", filePath => {
49
+ if (!isTsFile(filePath))
50
+ return;
51
+ if (isUnderNodeModules(filePath) || isUnderDist(filePath))
52
+ return;
53
+ const content = tree.read(filePath, "utf-8");
54
+ if (content === null)
55
+ return;
56
+ if (!content.includes(marker))
57
+ return;
58
+ const updated = callback(filePath, content);
59
+ if (updated !== null && updated !== undefined && updated !== content) {
60
+ tree.write(filePath, updated);
61
+ touched += 1;
62
+ }
63
+ });
64
+ return touched;
65
+ };
66
+ exports.visitTsFiles = visitTsFiles;
67
+ /**
68
+ * Mapping of imported component aliases to their original names for a given
69
+ * package. For `import { IconButton as Btn } from "@trackunit/react-components"`
70
+ * this returns `{ Btn: "IconButton" }`.
71
+ *
72
+ * Returns `null` when the file imports nothing from the package, which lets
73
+ * callers short-circuit before parsing JSX.
74
+ */
75
+ const getImportedAliases = (sourceFile, packageName) => {
76
+ const result = {};
77
+ let found = false;
78
+ for (const stmt of sourceFile.statements) {
79
+ if (!ts.isImportDeclaration(stmt))
80
+ continue;
81
+ const moduleSpecifier = stmt.moduleSpecifier;
82
+ if (!ts.isStringLiteral(moduleSpecifier))
83
+ continue;
84
+ if (moduleSpecifier.text !== packageName)
85
+ continue;
86
+ const namedBindings = stmt.importClause?.namedBindings;
87
+ if (namedBindings === undefined || !ts.isNamedImports(namedBindings))
88
+ continue;
89
+ for (const element of namedBindings.elements) {
90
+ const localName = element.name.text;
91
+ const importedName = element.propertyName?.text ?? localName;
92
+ result[localName] = importedName;
93
+ found = true;
94
+ }
95
+ }
96
+ return found ? result : null;
97
+ };
98
+ exports.getImportedAliases = getImportedAliases;
99
+ /**
100
+ * Returns the local alias used in this file for `originalName` when imported
101
+ * from `packageName`, or `null` if the component is not imported.
102
+ */
103
+ const getLocalAliasFor = (sourceFile, packageName, originalName) => {
104
+ const aliases = (0, exports.getImportedAliases)(sourceFile, packageName);
105
+ if (aliases === null)
106
+ return null;
107
+ for (const [local, original] of Object.entries(aliases)) {
108
+ if (original === originalName)
109
+ return local;
110
+ }
111
+ return null;
112
+ };
113
+ exports.getLocalAliasFor = getLocalAliasFor;
114
+ /**
115
+ * Finds every JSX element whose tag name resolves to one of `tagNames`
116
+ * (typically the local aliases returned by {@link getImportedAliases}).
117
+ *
118
+ * The result intentionally includes both opening and full elements so callers
119
+ * can manipulate attributes (via `openingElement`) or wrap/replace the whole
120
+ * element (via `element`).
121
+ */
122
+ const findJsxElements = (sourceFile, tagNames) => {
123
+ const matches = [];
124
+ const tagSet = new Set(tagNames);
125
+ const visit = (node) => {
126
+ if (ts.isJsxSelfClosingElement(node)) {
127
+ if (ts.isIdentifier(node.tagName) && tagSet.has(node.tagName.text)) {
128
+ matches.push({ openingElement: node, element: node });
129
+ }
130
+ }
131
+ else if (ts.isJsxElement(node)) {
132
+ const opening = node.openingElement;
133
+ if (ts.isIdentifier(opening.tagName) && tagSet.has(opening.tagName.text)) {
134
+ matches.push({ openingElement: opening, element: node });
135
+ }
136
+ }
137
+ ts.forEachChild(node, visit);
138
+ };
139
+ visit(sourceFile);
140
+ return matches;
141
+ };
142
+ exports.findJsxElements = findJsxElements;
143
+ /**
144
+ * Looks up a named JSX attribute on the opening element. Returns `null` when
145
+ * the attribute is missing or part of a spread attribute (which we cannot
146
+ * statically inspect).
147
+ */
148
+ const findJsxAttribute = (openingElement, attributeName) => {
149
+ for (const attr of openingElement.attributes.properties) {
150
+ if (!ts.isJsxAttribute(attr))
151
+ continue;
152
+ if (!ts.isIdentifier(attr.name))
153
+ continue;
154
+ if (attr.name.text === attributeName)
155
+ return attr;
156
+ }
157
+ return null;
158
+ };
159
+ exports.findJsxAttribute = findJsxAttribute;
160
+ /**
161
+ * `true` when the element forwards a spread expression such as `{...rest}`,
162
+ * which means we can't be sure which attributes are actually set.
163
+ */
164
+ const hasSpreadAttribute = (openingElement) => {
165
+ return openingElement.attributes.properties.some(prop => ts.isJsxSpreadAttribute(prop));
166
+ };
167
+ exports.hasSpreadAttribute = hasSpreadAttribute;
168
+ /**
169
+ * Parses the file as TSX so JSX is recognised. We do not need a full program
170
+ * here; tsquery's `ast` helper produces a script-kind source file which loses
171
+ * JSX context, so we go through `createSourceFile` directly.
172
+ */
173
+ const parseTsx = (content, fileName = "file.tsx") => ts.createSourceFile(fileName, content, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
174
+ exports.parseTsx = parseTsx;
175
+ /**
176
+ * Helper for codemods to log a one-line summary at the end of a run. Migration
177
+ * runners aggregate logs per migration, so this keeps output focused.
178
+ */
179
+ const logSummary = (migrationName, touched, manualReviewNeeded) => {
180
+ if (touched === 0) {
181
+ devkit_1.logger.info(` ${migrationName}: no files changed`);
182
+ return;
183
+ }
184
+ const reviewSuffix = manualReviewNeeded !== undefined && manualReviewNeeded > 0
185
+ ? ` (${manualReviewNeeded} location(s) need manual review)`
186
+ : "";
187
+ devkit_1.logger.info(` ${migrationName}: updated ${touched} file(s)${reviewSuffix}`);
188
+ };
189
+ exports.logSummary = logSummary;
190
+ /**
191
+ * Inserts an attribute string immediately after the tag name (so the new
192
+ * attribute appears first). Returns the resulting source content.
193
+ *
194
+ * The added attribute is rendered verbatim, so callers are responsible for
195
+ * including the leading space (e.g. ` title="Close"`).
196
+ */
197
+ const insertAttributeIntoOpeningTag = (content, openingElement, attributeText) => {
198
+ const tagName = openingElement.tagName;
199
+ const insertPos = tagName.getEnd();
200
+ return content.slice(0, insertPos) + ` ${attributeText}` + content.slice(insertPos);
201
+ };
202
+ exports.insertAttributeIntoOpeningTag = insertAttributeIntoOpeningTag;
203
+ //# sourceMappingURL=jsx-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx-utils.js","sourceRoot":"","sources":["../../../../../../libs/react/form-components/migrations/utils/jsx-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { logger, type Tree, visitNotIgnoredFiles } from \"@nx/devkit\";\nimport { tsquery } from \"@phenomnomnominal/tsquery\";\nimport * as ts from \"typescript\";\n\nconst TSX_EXTENSIONS = [\".tsx\", \".jsx\"] as const;\nconst TS_EXTENSIONS = [\".ts\", \".tsx\", \".jsx\"] as const;\n\nconst isTsxFile = (filePath: string): boolean => TSX_EXTENSIONS.some(ext => filePath.endsWith(ext));\nconst isTsFile = (filePath: string): boolean => TS_EXTENSIONS.some(ext => filePath.endsWith(ext));\n\nconst isUnderNodeModules = (filePath: string): boolean =>\n filePath.includes(\"/node_modules/\") || filePath.startsWith(\"node_modules/\");\n\nconst isUnderDist = (filePath: string): boolean =>\n filePath.includes(\"/dist/\") || filePath.startsWith(\"dist/\") || filePath.includes(\"/.nx/\");\n\n/**\n * Visits every `.tsx`/`.jsx` file under the workspace root and invokes the\n * callback with the file path and its current contents. Files that don't\n * include the marker substring are skipped, which makes large workspaces\n * cheap to scan.\n */\nexport const visitTsxFiles = (\n tree: Tree,\n marker: string,\n callback: (filePath: string, content: string) => string | null | undefined\n): number => {\n let touched = 0;\n visitNotIgnoredFiles(tree, \"/\", filePath => {\n if (!isTsxFile(filePath)) return;\n if (isUnderNodeModules(filePath) || isUnderDist(filePath)) return;\n const content = tree.read(filePath, \"utf-8\");\n if (content === null) return;\n if (!content.includes(marker)) return;\n const updated = callback(filePath, content);\n if (updated !== null && updated !== undefined && updated !== content) {\n tree.write(filePath, updated);\n touched += 1;\n }\n });\n return touched;\n};\n\n/**\n * Same as {@link visitTsxFiles} but also includes plain `.ts` files. Use this\n * when the codemod also rewrites non-JSX files such as helpers or hooks.\n */\nexport const visitTsFiles = (\n tree: Tree,\n marker: string,\n callback: (filePath: string, content: string) => string | null | undefined\n): number => {\n let touched = 0;\n visitNotIgnoredFiles(tree, \"/\", filePath => {\n if (!isTsFile(filePath)) return;\n if (isUnderNodeModules(filePath) || isUnderDist(filePath)) return;\n const content = tree.read(filePath, \"utf-8\");\n if (content === null) return;\n if (!content.includes(marker)) return;\n const updated = callback(filePath, content);\n if (updated !== null && updated !== undefined && updated !== content) {\n tree.write(filePath, updated);\n touched += 1;\n }\n });\n return touched;\n};\n\n/**\n * Mapping of imported component aliases to their original names for a given\n * package. For `import { IconButton as Btn } from \"@trackunit/react-components\"`\n * this returns `{ Btn: \"IconButton\" }`.\n *\n * Returns `null` when the file imports nothing from the package, which lets\n * callers short-circuit before parsing JSX.\n */\nexport const getImportedAliases = (sourceFile: ts.SourceFile, packageName: string): Record<string, string> | null => {\n const result: Record<string, string> = {};\n let found = false;\n\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) continue;\n const moduleSpecifier = stmt.moduleSpecifier;\n if (!ts.isStringLiteral(moduleSpecifier)) continue;\n if (moduleSpecifier.text !== packageName) continue;\n\n const namedBindings = stmt.importClause?.namedBindings;\n if (namedBindings === undefined || !ts.isNamedImports(namedBindings)) continue;\n\n for (const element of namedBindings.elements) {\n const localName = element.name.text;\n const importedName = element.propertyName?.text ?? localName;\n result[localName] = importedName;\n found = true;\n }\n }\n\n return found ? result : null;\n};\n\n/**\n * Returns the local alias used in this file for `originalName` when imported\n * from `packageName`, or `null` if the component is not imported.\n */\nexport const getLocalAliasFor = (\n sourceFile: ts.SourceFile,\n packageName: string,\n originalName: string\n): string | null => {\n const aliases = getImportedAliases(sourceFile, packageName);\n if (aliases === null) return null;\n for (const [local, original] of Object.entries(aliases)) {\n if (original === originalName) return local;\n }\n return null;\n};\n\nexport type JsxElementMatch = {\n /** The opening JSX element (the one carrying the attributes). */\n openingElement: ts.JsxOpeningElement | ts.JsxSelfClosingElement;\n /** The full element including children, or the self-closing element. */\n element: ts.JsxElement | ts.JsxSelfClosingElement;\n};\n\n/**\n * Finds every JSX element whose tag name resolves to one of `tagNames`\n * (typically the local aliases returned by {@link getImportedAliases}).\n *\n * The result intentionally includes both opening and full elements so callers\n * can manipulate attributes (via `openingElement`) or wrap/replace the whole\n * element (via `element`).\n */\nexport const findJsxElements = (\n sourceFile: ts.SourceFile,\n tagNames: ReadonlyArray<string>\n): ReadonlyArray<JsxElementMatch> => {\n const matches: Array<JsxElementMatch> = [];\n const tagSet = new Set(tagNames);\n\n const visit = (node: ts.Node): void => {\n if (ts.isJsxSelfClosingElement(node)) {\n if (ts.isIdentifier(node.tagName) && tagSet.has(node.tagName.text)) {\n matches.push({ openingElement: node, element: node });\n }\n } else if (ts.isJsxElement(node)) {\n const opening = node.openingElement;\n if (ts.isIdentifier(opening.tagName) && tagSet.has(opening.tagName.text)) {\n matches.push({ openingElement: opening, element: node });\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n return matches;\n};\n\n/**\n * Looks up a named JSX attribute on the opening element. Returns `null` when\n * the attribute is missing or part of a spread attribute (which we cannot\n * statically inspect).\n */\nexport const findJsxAttribute = (\n openingElement: ts.JsxOpeningElement | ts.JsxSelfClosingElement,\n attributeName: string\n): ts.JsxAttribute | null => {\n for (const attr of openingElement.attributes.properties) {\n if (!ts.isJsxAttribute(attr)) continue;\n if (!ts.isIdentifier(attr.name)) continue;\n if (attr.name.text === attributeName) return attr;\n }\n return null;\n};\n\n/**\n * `true` when the element forwards a spread expression such as `{...rest}`,\n * which means we can't be sure which attributes are actually set.\n */\nexport const hasSpreadAttribute = (openingElement: ts.JsxOpeningElement | ts.JsxSelfClosingElement): boolean => {\n return openingElement.attributes.properties.some(prop => ts.isJsxSpreadAttribute(prop));\n};\n\n/**\n * Parses the file as TSX so JSX is recognised. We do not need a full program\n * here; tsquery's `ast` helper produces a script-kind source file which loses\n * JSX context, so we go through `createSourceFile` directly.\n */\nexport const parseTsx = (content: string, fileName = \"file.tsx\"): ts.SourceFile =>\n ts.createSourceFile(fileName, content, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);\n\n/** Re-exported for codemods that need direct AST queries. */\nexport { tsquery };\n\n/**\n * Helper for codemods to log a one-line summary at the end of a run. Migration\n * runners aggregate logs per migration, so this keeps output focused.\n */\nexport const logSummary = (migrationName: string, touched: number, manualReviewNeeded?: number): void => {\n if (touched === 0) {\n logger.info(` ${migrationName}: no files changed`);\n return;\n }\n const reviewSuffix =\n manualReviewNeeded !== undefined && manualReviewNeeded > 0\n ? ` (${manualReviewNeeded} location(s) need manual review)`\n : \"\";\n logger.info(` ${migrationName}: updated ${touched} file(s)${reviewSuffix}`);\n};\n\n/**\n * Inserts an attribute string immediately after the tag name (so the new\n * attribute appears first). Returns the resulting source content.\n *\n * The added attribute is rendered verbatim, so callers are responsible for\n * including the leading space (e.g. ` title=\"Close\"`).\n */\nexport const insertAttributeIntoOpeningTag = (\n content: string,\n openingElement: ts.JsxOpeningElement | ts.JsxSelfClosingElement,\n attributeText: string\n): string => {\n const tagName = openingElement.tagName;\n const insertPos = tagName.getEnd();\n return content.slice(0, insertPos) + ` ${attributeText}` + content.slice(insertPos);\n};\n"]}
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.actionButtonAddTitle = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const devkit_1 = require("@nx/devkit");
6
+ const ts = tslib_1.__importStar(require("typescript"));
7
+ const jsx_utils_1 = require("../utils/jsx-utils");
8
+ const PACKAGE_NAME = "@trackunit/react-form-components";
9
+ const COMPONENT_NAME = "ActionButton";
10
+ const ACTION_TYPE_TO_TITLE = {
11
+ COPY: "Copy value",
12
+ EDIT: "Edit value",
13
+ EMAIL: "Send email",
14
+ PHONE_NUMBER: "Call number",
15
+ WEB_ADDRESS: "Open link",
16
+ };
17
+ const DEFAULT_TITLE = "Action";
18
+ const resolveTitleForType = (typeAttr) => {
19
+ if (typeAttr === null)
20
+ return DEFAULT_TITLE;
21
+ const initializer = typeAttr.initializer;
22
+ if (initializer === undefined)
23
+ return DEFAULT_TITLE;
24
+ if (ts.isStringLiteral(initializer)) {
25
+ return ACTION_TYPE_TO_TITLE[initializer.text] ?? DEFAULT_TITLE;
26
+ }
27
+ return DEFAULT_TITLE;
28
+ };
29
+ const transformActionButtonUsage = (filePath, content) => {
30
+ const sourceFile = (0, jsx_utils_1.parseTsx)(content, filePath);
31
+ const aliases = (0, jsx_utils_1.getImportedAliases)(sourceFile, PACKAGE_NAME);
32
+ if (aliases === null)
33
+ return null;
34
+ const localAlias = Object.entries(aliases).find(([, name]) => name === COMPONENT_NAME)?.[0];
35
+ if (localAlias === undefined)
36
+ return null;
37
+ const matches = (0, jsx_utils_1.findJsxElements)(sourceFile, [localAlias]);
38
+ if (matches.length === 0)
39
+ return null;
40
+ const edits = [];
41
+ for (const { openingElement } of matches) {
42
+ if ((0, jsx_utils_1.hasSpreadAttribute)(openingElement))
43
+ continue;
44
+ if ((0, jsx_utils_1.findJsxAttribute)(openingElement, "title") !== null)
45
+ continue;
46
+ const typeAttr = (0, jsx_utils_1.findJsxAttribute)(openingElement, "type");
47
+ const title = resolveTitleForType(typeAttr);
48
+ edits.push({
49
+ offset: openingElement.tagName.getEnd(),
50
+ text: ` title="${title}"`,
51
+ });
52
+ }
53
+ if (edits.length === 0)
54
+ return null;
55
+ edits.sort((a, b) => (a.offset === b.offset ? 0 : b.offset - a.offset));
56
+ let updated = content;
57
+ for (const { offset, text } of edits) {
58
+ updated = updated.slice(0, offset) + text + updated.slice(offset);
59
+ }
60
+ return updated;
61
+ };
62
+ /**
63
+ * Adds the now-required `title` prop to `<ActionButton>` usages that don't
64
+ * already provide one. The default value is derived from the `type` prop when
65
+ * possible (e.g. `COPY` → "Copy value"); consumers should replace the
66
+ * placeholders with their own localized strings.
67
+ */
68
+ const actionButtonAddTitle = (tree) => {
69
+ const touched = (0, jsx_utils_1.visitTsxFiles)(tree, "ActionButton", transformActionButtonUsage);
70
+ (0, jsx_utils_1.logSummary)("actionbutton-add-title", touched);
71
+ if (touched > 0) {
72
+ devkit_1.logger.info(` Replace placeholder ActionButton titles with your own localized strings.`);
73
+ }
74
+ };
75
+ exports.actionButtonAddTitle = actionButtonAddTitle;
76
+ exports.default = exports.actionButtonAddTitle;
77
+ //# sourceMappingURL=actionbutton-add-title.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actionbutton-add-title.js","sourceRoot":"","sources":["../../../../../../libs/react/form-components/migrations/v2-0-0/actionbutton-add-title.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Tree, logger } from \"@nx/devkit\";\nimport * as ts from \"typescript\";\nimport {\n findJsxAttribute,\n findJsxElements,\n getImportedAliases,\n hasSpreadAttribute,\n logSummary,\n parseTsx,\n visitTsxFiles,\n} from \"../utils/jsx-utils\";\n\nconst PACKAGE_NAME = \"@trackunit/react-form-components\";\nconst COMPONENT_NAME = \"ActionButton\";\n\nconst ACTION_TYPE_TO_TITLE: Record<string, string> = {\n COPY: \"Copy value\",\n EDIT: \"Edit value\",\n EMAIL: \"Send email\",\n PHONE_NUMBER: \"Call number\",\n WEB_ADDRESS: \"Open link\",\n};\n\nconst DEFAULT_TITLE = \"Action\";\n\nconst resolveTitleForType = (typeAttr: ts.JsxAttribute | null): string => {\n if (typeAttr === null) return DEFAULT_TITLE;\n const initializer = typeAttr.initializer;\n if (initializer === undefined) return DEFAULT_TITLE;\n if (ts.isStringLiteral(initializer)) {\n return ACTION_TYPE_TO_TITLE[initializer.text] ?? DEFAULT_TITLE;\n }\n return DEFAULT_TITLE;\n};\n\nconst transformActionButtonUsage = (filePath: string, content: string): string | null => {\n const sourceFile = parseTsx(content, filePath);\n\n const aliases = getImportedAliases(sourceFile, PACKAGE_NAME);\n if (aliases === null) return null;\n\n const localAlias = Object.entries(aliases).find(([, name]) => name === COMPONENT_NAME)?.[0];\n if (localAlias === undefined) return null;\n\n const matches = findJsxElements(sourceFile, [localAlias]);\n if (matches.length === 0) return null;\n\n type Edit = { offset: number; text: string };\n const edits: Array<Edit> = [];\n\n for (const { openingElement } of matches) {\n if (hasSpreadAttribute(openingElement)) continue;\n if (findJsxAttribute(openingElement, \"title\") !== null) continue;\n\n const typeAttr = findJsxAttribute(openingElement, \"type\");\n const title = resolveTitleForType(typeAttr);\n edits.push({\n offset: openingElement.tagName.getEnd(),\n text: ` title=\"${title}\"`,\n });\n }\n\n if (edits.length === 0) return null;\n\n edits.sort((a, b) => (a.offset === b.offset ? 0 : b.offset - a.offset));\n\n let updated = content;\n for (const { offset, text } of edits) {\n updated = updated.slice(0, offset) + text + updated.slice(offset);\n }\n return updated;\n};\n\n/**\n * Adds the now-required `title` prop to `<ActionButton>` usages that don't\n * already provide one. The default value is derived from the `type` prop when\n * possible (e.g. `COPY` → \"Copy value\"); consumers should replace the\n * placeholders with their own localized strings.\n */\nexport const actionButtonAddTitle = (tree: Tree): void => {\n const touched = visitTsxFiles(tree, \"ActionButton\", transformActionButtonUsage);\n logSummary(\"actionbutton-add-title\", touched);\n if (touched > 0) {\n logger.info(` Replace placeholder ActionButton titles with your own localized strings.`);\n }\n};\n\nexport default actionButtonAddTitle;\n"]}
@@ -0,0 +1,9 @@
1
+ {
2
+ "generators": {
3
+ "v2-0-0-actionbutton-add-title": {
4
+ "version": "2.0.0",
5
+ "description": "Add the now-required title prop to ActionButton usages, defaulting to a sensible English string per action type.",
6
+ "implementation": "./migrations/v2-0-0/actionbutton-add-title"
7
+ }
8
+ }
9
+ }
package/package.json CHANGED
@@ -1,25 +1,26 @@
1
1
  {
2
2
  "name": "@trackunit/react-form-components",
3
- "version": "1.25.12",
3
+ "version": "1.25.15",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
+ "migrations": "./migrations.json",
6
7
  "engines": {
7
8
  "node": ">=24.x"
8
9
  },
9
10
  "dependencies": {
10
11
  "react-calendar": "^6.0.0",
11
12
  "react-select": "^5.10.2",
12
- "@trackunit/date-and-time-utils": "1.13.4",
13
+ "@trackunit/date-and-time-utils": "1.13.5",
13
14
  "usehooks-ts": "^3.1.0",
14
15
  "libphonenumber-js": "^1.12.22",
15
16
  "zod": "^3.25.76",
16
17
  "tailwind-merge": "^2.0.0",
17
- "@trackunit/css-class-variance-utilities": "1.13.4",
18
- "@trackunit/react-components": "1.24.7",
19
- "@trackunit/ui-icons": "1.13.4",
20
- "@trackunit/shared-utils": "1.15.4",
21
- "@trackunit/ui-design-tokens": "1.13.4",
22
- "@trackunit/i18n-library-translation": "1.21.8",
18
+ "@trackunit/css-class-variance-utilities": "1.13.5",
19
+ "@trackunit/react-components": "1.24.10",
20
+ "@trackunit/ui-icons": "1.13.5",
21
+ "@trackunit/shared-utils": "1.15.5",
22
+ "@trackunit/ui-design-tokens": "1.13.5",
23
+ "@trackunit/i18n-library-translation": "1.21.10",
23
24
  "string-ts": "^2.0.0",
24
25
  "es-toolkit": "^1.39.10"
25
26
  },
@@ -1,7 +1,7 @@
1
1
  import { ButtonCommonProps, CommonProps, Refable, type Styleable } from "@trackunit/react-components";
2
- import { RefObject } from "react";
2
+ import { ReactElement, RefObject } from "react";
3
3
  export type ActionType = "PHONE_NUMBER" | "WEB_ADDRESS" | "EMAIL" | "COPY" | "EDIT";
4
- interface AbstractActionButtonProps extends ButtonCommonProps, CommonProps, Refable<HTMLDivElement>, Styleable {
4
+ interface AbstractActionButtonProps extends Omit<ButtonCommonProps, "title">, CommonProps, Refable<HTMLDivElement>, Styleable {
5
5
  /**
6
6
  * The type of action performed when clicking the button.
7
7
  */
@@ -10,6 +10,10 @@ interface AbstractActionButtonProps extends ButtonCommonProps, CommonProps, Refa
10
10
  * The value to be passed into the button.
11
11
  */
12
12
  value?: string | RefObject<HTMLInputElement | null> | null;
13
+ /**
14
+ * The title of the action button.
15
+ */
16
+ title: string;
13
17
  }
14
18
  interface GenericActionButtonProps extends AbstractActionButtonProps {
15
19
  /**
@@ -48,5 +52,5 @@ type ActionButtonProps = CopyActionButtonProps | GenericActionButtonProps | Edit
48
52
  * @param {ActionButtonProps} props - The props for the ActionButton component
49
53
  * @returns {ReactElement} ActionButton component
50
54
  */
51
- export declare const ActionButton: ({ type, value, "data-testid": dataTestId, size, disabled, className, onClick, style, ref, }: ActionButtonProps) => import("react/jsx-runtime").JSX.Element;
55
+ export declare const ActionButton: ({ type, value, "data-testid": dataTestId, size, disabled, className, title, style, ref, }: ActionButtonProps) => ReactElement;
52
56
  export {};
@@ -8,5 +8,8 @@ type GenericActionsRendererProps = {
8
8
  innerRef: RefObject<HTMLInputElement | null>;
9
9
  tooltipLabel?: string;
10
10
  };
11
+ /**
12
+ *
13
+ */
11
14
  export declare const GenericActionsRenderer: ({ genericAction, disabled, fieldSize, innerRef, tooltipLabel, }: GenericActionsRendererProps) => import("react/jsx-runtime").JSX.Element | null;
12
15
  export {};
@@ -8,11 +8,12 @@ type MultiValueProps<TOption> = {
8
8
  disabled: boolean;
9
9
  fieldSize: FormComponentSizes;
10
10
  getOptionPrefix?: (option: TOption) => ReactNode;
11
+ removeTagLabel: string;
11
12
  ref: (el: HTMLDivElement | null) => void;
12
13
  } & CommonProps;
13
14
  /**
14
15
  * Internal component for rendering multi-select values with measurement support.
15
16
  * Uses the measurement state to determine if the value should be displayed or hidden based on available width.
16
17
  */
17
- export declare const MultiValue: <TOption>({ data, children, onClose, className, disabled, fieldSize, getOptionPrefix, ref, "data-testid": dataTestId, }: MultiValueProps<TOption>) => ReactElement | null;
18
+ export declare const MultiValue: <TOption>({ data, children, onClose, className, disabled, fieldSize, getOptionPrefix, removeTagLabel, ref, "data-testid": dataTestId, }: MultiValueProps<TOption>) => ReactElement | null;
18
19
  export {};
@@ -1,3 +1,4 @@
1
+ import { ReactElement } from "react";
1
2
  import { BaseInputProps } from "../../BaseInput/BaseInput";
2
3
  type BaseInputExposedProps = Omit<BaseInputProps, "type">;
3
4
  export interface EmailBaseInputProps extends BaseInputExposedProps {
@@ -21,5 +22,5 @@ export interface EmailBaseInputProps extends BaseInputExposedProps {
21
22
  * A reference to the input element is provided as the `ref` prop.
22
23
  * For specific input types make sure to use the corresponding input component.
23
24
  */
24
- export declare const EmailBaseInput: ({ fieldSize, disabled, "data-testid": dataTestId, isInvalid, onChange, disableAction, ref, ...rest }: EmailBaseInputProps) => import("react/jsx-runtime").JSX.Element;
25
+ export declare const EmailBaseInput: ({ fieldSize, disabled, "data-testid": dataTestId, isInvalid, onChange, disableAction, ref, ...rest }: EmailBaseInputProps) => ReactElement;
25
26
  export {};
@@ -38,6 +38,10 @@ export interface ToggleSwitchProps extends CommonProps, MappedOmit<InputHTMLAttr
38
38
  * Prevents the native checkbox toggle behavior of the toggle switch.
39
39
  */
40
40
  preventDefaultOnClick?: boolean;
41
+ /**
42
+ * Tooltip label for the toggle switch.
43
+ */
44
+ tooltipLabel?: string;
41
45
  }
42
46
  /**
43
47
  * The `<ToggleSwitch>` is a low-level checkbox input wrapper with `role="switch"`.
@@ -93,6 +97,6 @@ export interface ToggleSwitchProps extends CommonProps, MappedOmit<InputHTMLAttr
93
97
  * @returns {ReactElement} ToggleSwitch component
94
98
  */
95
99
  export declare const ToggleSwitch: {
96
- ({ onChange, onClick, preventDefaultOnClick, className, "data-testid": dataTestId, showInputFocus, toggled, size, tabIndex, readOnly, disabled, ref, ...rest }: ToggleSwitchProps): ReactElement;
100
+ ({ onChange, onClick, preventDefaultOnClick, className, "data-testid": dataTestId, showInputFocus, toggled, size, tabIndex, readOnly, disabled, tooltipLabel, ref, ...rest }: ToggleSwitchProps): ReactElement;
97
101
  displayName: string;
98
102
  };
@@ -14,8 +14,8 @@ export declare const translations: TranslationResource<TranslationKeys>;
14
14
  /**
15
15
  * Local useTranslation for this specific library
16
16
  */
17
- export declare const useTranslation: () => [TransForLibs<"baseInput.copyAction.toolTip" | "clearIndicator.icon.tooltip.clearAll" | "colorField.error.INVALID_HEX_CODE" | "colorField.error.REQUIRED" | "colorField.tooltip" | "dateField.actions.apply" | "dateField.actions.cancel" | "dateField.actions.clear" | "dateField.openPicker.ariaLabel" | "dropzone.input.title" | "dropzone.label.default" | "emailField.error.INVALID_EMAIL" | "emailField.error.REQUIRED" | "field.notEditable.tooltip" | "field.required.asterisk.tooltip" | "numberField.error.GREATER_THAN" | "numberField.error.INVALID_NUMBER" | "numberField.error.LESS_THAN" | "numberField.error.NOT_IN_BETWEEN" | "numberField.error.REQUIRED" | "phoneField.error.INVALID_COUNTRY" | "phoneField.error.INVALID_LENGTH" | "phoneField.error.INVALID_NUMBER" | "phoneField.error.NOT_A_NUMBER" | "phoneField.error.REQUIRED" | "phoneField.error.REQUIRED_COUNTRY" | "phoneField.error.TOO_LONG" | "phoneField.error.TOO_SHORT" | "phoneField.error.undefined" | "schedule.label.active" | "schedule.label.allDay" | "schedule.label.day" | "search.placeholder" | "select.loadingMessage" | "select.noOptionsMessage" | "urlField.error.INVALID_URL" | "urlField.error.REQUIRED">, import("i18next").i18n, boolean] & {
18
- t: TransForLibs<"baseInput.copyAction.toolTip" | "clearIndicator.icon.tooltip.clearAll" | "colorField.error.INVALID_HEX_CODE" | "colorField.error.REQUIRED" | "colorField.tooltip" | "dateField.actions.apply" | "dateField.actions.cancel" | "dateField.actions.clear" | "dateField.openPicker.ariaLabel" | "dropzone.input.title" | "dropzone.label.default" | "emailField.error.INVALID_EMAIL" | "emailField.error.REQUIRED" | "field.notEditable.tooltip" | "field.required.asterisk.tooltip" | "numberField.error.GREATER_THAN" | "numberField.error.INVALID_NUMBER" | "numberField.error.LESS_THAN" | "numberField.error.NOT_IN_BETWEEN" | "numberField.error.REQUIRED" | "phoneField.error.INVALID_COUNTRY" | "phoneField.error.INVALID_LENGTH" | "phoneField.error.INVALID_NUMBER" | "phoneField.error.NOT_A_NUMBER" | "phoneField.error.REQUIRED" | "phoneField.error.REQUIRED_COUNTRY" | "phoneField.error.TOO_LONG" | "phoneField.error.TOO_SHORT" | "phoneField.error.undefined" | "schedule.label.active" | "schedule.label.allDay" | "schedule.label.day" | "search.placeholder" | "select.loadingMessage" | "select.noOptionsMessage" | "urlField.error.INVALID_URL" | "urlField.error.REQUIRED">;
17
+ export declare const useTranslation: () => [TransForLibs<"baseInput.copyAction.toolTip" | "clearIndicator.icon.tooltip.clearAll" | "colorField.error.INVALID_HEX_CODE" | "colorField.error.REQUIRED" | "colorField.tooltip" | "dateField.actions.apply" | "dateField.actions.cancel" | "dateField.actions.clear" | "dateField.openPicker.ariaLabel" | "dropzone.input.title" | "dropzone.label.default" | "emailField.error.INVALID_EMAIL" | "emailField.error.REQUIRED" | "emailField.sendEmailAction.label" | "field.notEditable.tooltip" | "field.required.asterisk.tooltip" | "numberField.error.GREATER_THAN" | "numberField.error.INVALID_NUMBER" | "numberField.error.LESS_THAN" | "numberField.error.NOT_IN_BETWEEN" | "numberField.error.REQUIRED" | "passwordField.tooltip.hide" | "passwordField.tooltip.show" | "phoneField.error.INVALID_COUNTRY" | "phoneField.error.INVALID_LENGTH" | "phoneField.error.INVALID_NUMBER" | "phoneField.error.NOT_A_NUMBER" | "phoneField.error.REQUIRED" | "phoneField.error.REQUIRED_COUNTRY" | "phoneField.error.TOO_LONG" | "phoneField.error.TOO_SHORT" | "phoneField.error.undefined" | "phoneField.phoneNumber.label" | "schedule.label.active" | "schedule.label.allDay" | "schedule.label.day" | "search.placeholder" | "select.loadingMessage" | "select.multiValue.remove" | "select.noOptionsMessage" | "urlField.error.INVALID_URL" | "urlField.error.REQUIRED" | "urlField.url.label">, import("i18next").i18n, boolean] & {
18
+ t: TransForLibs<"baseInput.copyAction.toolTip" | "clearIndicator.icon.tooltip.clearAll" | "colorField.error.INVALID_HEX_CODE" | "colorField.error.REQUIRED" | "colorField.tooltip" | "dateField.actions.apply" | "dateField.actions.cancel" | "dateField.actions.clear" | "dateField.openPicker.ariaLabel" | "dropzone.input.title" | "dropzone.label.default" | "emailField.error.INVALID_EMAIL" | "emailField.error.REQUIRED" | "emailField.sendEmailAction.label" | "field.notEditable.tooltip" | "field.required.asterisk.tooltip" | "numberField.error.GREATER_THAN" | "numberField.error.INVALID_NUMBER" | "numberField.error.LESS_THAN" | "numberField.error.NOT_IN_BETWEEN" | "numberField.error.REQUIRED" | "passwordField.tooltip.hide" | "passwordField.tooltip.show" | "phoneField.error.INVALID_COUNTRY" | "phoneField.error.INVALID_LENGTH" | "phoneField.error.INVALID_NUMBER" | "phoneField.error.NOT_A_NUMBER" | "phoneField.error.REQUIRED" | "phoneField.error.REQUIRED_COUNTRY" | "phoneField.error.TOO_LONG" | "phoneField.error.TOO_SHORT" | "phoneField.error.undefined" | "phoneField.phoneNumber.label" | "schedule.label.active" | "schedule.label.allDay" | "schedule.label.day" | "search.placeholder" | "select.loadingMessage" | "select.multiValue.remove" | "select.noOptionsMessage" | "urlField.error.INVALID_URL" | "urlField.error.REQUIRED" | "urlField.url.label">;
19
19
  i18n: import("i18next").i18n;
20
20
  ready: boolean;
21
21
  };