@trackunit/react-form-components 2.4.12 → 2.4.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.cjs.js CHANGED
@@ -53,7 +53,6 @@ var defaultTranslations = {
53
53
  "phoneField.error.REQUIRED_COUNTRY": "The country code is required",
54
54
  "phoneField.error.TOO_LONG": "The phone number is too long",
55
55
  "phoneField.error.TOO_SHORT": "The phone number is too short",
56
- "phoneField.error.undefined": "",
57
56
  "phoneField.phoneNumber.label": "Phone Number",
58
57
  "schedule.label.active": "Active",
59
58
  "schedule.label.allDay": "All Day",
@@ -3955,7 +3954,7 @@ const validateNumber = (number, required = false, min, max) => {
3955
3954
  * };
3956
3955
  * ```
3957
3956
  */
3958
- const NumberField = ({ label, id, tip, helpText, errorMessage, helpAddon, isInvalid = undefined, maxLength, className, value, "data-testid": dataTestId, defaultValue, onBlur, onChange, ref, required = false, ...rest }) => {
3957
+ const NumberField = ({ label, id, tip, helpText, errorMessage, helpAddon, isInvalid = undefined, isWarning = false, maxLength, className, value, "data-testid": dataTestId, defaultValue, onBlur, onChange, ref, required = false, ...rest }) => {
3959
3958
  const htmlForId = id ? id : `numberField-${sharedUtils.uuidv4()}`;
3960
3959
  const [t] = useTranslation();
3961
3960
  const [innerValue, setInnerValue] = react.useState(() => {
@@ -3975,10 +3974,15 @@ const NumberField = ({ label, id, tip, helpText, errorMessage, helpAddon, isInva
3975
3974
  return errorMessage;
3976
3975
  }, [errorMessage, errorType, rest.max, rest.min, t]);
3977
3976
  react.useEffect(() => {
3978
- if (errorMessage) {
3977
+ // A controlled isInvalid must be able to lower the invalid state too, not just raise it —
3978
+ // otherwise a consumer switching from invalid to warning keeps the error treatment until blur.
3979
+ if (isInvalid !== undefined) {
3980
+ setRenderAsInvalid(isInvalid);
3981
+ }
3982
+ else if (errorMessage) {
3979
3983
  setRenderAsInvalid(Boolean(errorMessage));
3980
3984
  }
3981
- }, [errorMessage]);
3985
+ }, [errorMessage, isInvalid]);
3982
3986
  const handleBlur = react.useCallback(event => {
3983
3987
  const newValue = event.target.value;
3984
3988
  setInnerValue(newValue.toString());
@@ -3997,7 +4001,7 @@ const NumberField = ({ label, id, tip, helpText, errorMessage, helpAddon, isInva
3997
4001
  onChange(event);
3998
4002
  }
3999
4003
  }, [onChange]);
4000
- 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(NumberBaseInput, { "aria-labelledby": `${htmlForId}-label`, id: htmlForId, isInvalid: renderAsInvalid, maxLength: maxLength, onBlur: handleBlur, onChange: handleChange, ref: ref, required: required, value: value, ...rest, className: className, "data-testid": dataTestId }) }));
4004
+ return (jsxRuntime.jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && error) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, isWarning: isWarning, label: label, required: required ? !(Boolean(rest.disabled) || Boolean(rest.readOnly)) : false, tip: tip, children: jsxRuntime.jsx(NumberBaseInput, { "aria-labelledby": `${htmlForId}-label`, id: htmlForId, isInvalid: renderAsInvalid, isWarning: isWarning, maxLength: maxLength, onBlur: handleBlur, onChange: handleChange, ref: ref, required: required, value: value, ...rest, className: className, "data-testid": dataTestId }) }));
4001
4005
  };
4002
4006
  NumberField.displayName = "NumberField";
4003
4007
 
package/index.esm.js CHANGED
@@ -52,7 +52,6 @@ var defaultTranslations = {
52
52
  "phoneField.error.REQUIRED_COUNTRY": "The country code is required",
53
53
  "phoneField.error.TOO_LONG": "The phone number is too long",
54
54
  "phoneField.error.TOO_SHORT": "The phone number is too short",
55
- "phoneField.error.undefined": "",
56
55
  "phoneField.phoneNumber.label": "Phone Number",
57
56
  "schedule.label.active": "Active",
58
57
  "schedule.label.allDay": "All Day",
@@ -3954,7 +3953,7 @@ const validateNumber = (number, required = false, min, max) => {
3954
3953
  * };
3955
3954
  * ```
3956
3955
  */
3957
- const NumberField = ({ label, id, tip, helpText, errorMessage, helpAddon, isInvalid = undefined, maxLength, className, value, "data-testid": dataTestId, defaultValue, onBlur, onChange, ref, required = false, ...rest }) => {
3956
+ const NumberField = ({ label, id, tip, helpText, errorMessage, helpAddon, isInvalid = undefined, isWarning = false, maxLength, className, value, "data-testid": dataTestId, defaultValue, onBlur, onChange, ref, required = false, ...rest }) => {
3958
3957
  const htmlForId = id ? id : `numberField-${uuidv4()}`;
3959
3958
  const [t] = useTranslation();
3960
3959
  const [innerValue, setInnerValue] = useState(() => {
@@ -3974,10 +3973,15 @@ const NumberField = ({ label, id, tip, helpText, errorMessage, helpAddon, isInva
3974
3973
  return errorMessage;
3975
3974
  }, [errorMessage, errorType, rest.max, rest.min, t]);
3976
3975
  useEffect(() => {
3977
- if (errorMessage) {
3976
+ // A controlled isInvalid must be able to lower the invalid state too, not just raise it —
3977
+ // otherwise a consumer switching from invalid to warning keeps the error treatment until blur.
3978
+ if (isInvalid !== undefined) {
3979
+ setRenderAsInvalid(isInvalid);
3980
+ }
3981
+ else if (errorMessage) {
3978
3982
  setRenderAsInvalid(Boolean(errorMessage));
3979
3983
  }
3980
- }, [errorMessage]);
3984
+ }, [errorMessage, isInvalid]);
3981
3985
  const handleBlur = useCallback(event => {
3982
3986
  const newValue = event.target.value;
3983
3987
  setInnerValue(newValue.toString());
@@ -3996,7 +4000,7 @@ const NumberField = ({ label, id, tip, helpText, errorMessage, helpAddon, isInva
3996
4000
  onChange(event);
3997
4001
  }
3998
4002
  }, [onChange]);
3999
- 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(NumberBaseInput, { "aria-labelledby": `${htmlForId}-label`, id: htmlForId, isInvalid: renderAsInvalid, maxLength: maxLength, onBlur: handleBlur, onChange: handleChange, ref: ref, required: required, value: value, ...rest, className: className, "data-testid": dataTestId }) }));
4003
+ return (jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && error) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, isWarning: isWarning, label: label, required: required ? !(Boolean(rest.disabled) || Boolean(rest.readOnly)) : false, tip: tip, children: jsx(NumberBaseInput, { "aria-labelledby": `${htmlForId}-label`, id: htmlForId, isInvalid: renderAsInvalid, isWarning: isWarning, maxLength: maxLength, onBlur: handleBlur, onChange: handleChange, ref: ref, required: required, value: value, ...rest, className: className, "data-testid": dataTestId }) }));
4000
4004
  };
4001
4005
  NumberField.displayName = "NumberField";
4002
4006
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-form-components",
3
- "version": "2.4.12",
3
+ "version": "2.4.14",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "migrations": "./migrations.json",
@@ -10,17 +10,17 @@
10
10
  "dependencies": {
11
11
  "react-calendar": "^6.0.0",
12
12
  "react-select": "^5.10.2",
13
- "@trackunit/date-and-time-utils": "1.14.7",
13
+ "@trackunit/date-and-time-utils": "1.14.9",
14
14
  "usehooks-ts": "^3.1.0",
15
15
  "libphonenumber-js": "^1.13.6",
16
16
  "zod": "^3.25.76",
17
17
  "tailwind-merge": "^2.0.0",
18
- "@trackunit/css-class-variance-utilities": "1.14.6",
19
- "@trackunit/react-components": "2.7.1",
20
- "@trackunit/ui-icons": "1.14.6",
21
- "@trackunit/shared-utils": "1.16.6",
22
- "@trackunit/ui-design-tokens": "1.14.6",
23
- "@trackunit/i18n-library-translation": "2.3.8",
18
+ "@trackunit/css-class-variance-utilities": "1.14.8",
19
+ "@trackunit/react-components": "2.7.3",
20
+ "@trackunit/ui-icons": "1.14.8",
21
+ "@trackunit/shared-utils": "1.16.8",
22
+ "@trackunit/ui-design-tokens": "1.14.8",
23
+ "@trackunit/i18n-library-translation": "2.3.10",
24
24
  "string-ts": "^2.0.0",
25
25
  "es-toolkit": "^1.39.10"
26
26
  },
@@ -59,7 +59,7 @@ export interface NumberFieldProps extends NumberBaseInputProps, FormGroupExposed
59
59
  * ```
60
60
  */
61
61
  export declare const NumberField: {
62
- ({ label, id, tip, helpText, errorMessage, helpAddon, isInvalid, maxLength, className, value, "data-testid": dataTestId, defaultValue, onBlur, onChange, ref, required, ...rest }: NumberFieldProps): import("react/jsx-runtime").JSX.Element;
62
+ ({ label, id, tip, helpText, errorMessage, helpAddon, isInvalid, isWarning, maxLength, className, value, "data-testid": dataTestId, defaultValue, onBlur, onChange, ref, required, ...rest }: NumberFieldProps): import("react/jsx-runtime").JSX.Element;
63
63
  displayName: string;
64
64
  };
65
65
  export {};
@@ -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" | "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">;
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.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.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
  };