@trackunit/react-form-components 1.8.120 → 1.8.122
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 +32 -13
- package/index.esm.js +32 -13
- package/package.json +7 -7
- package/src/components/ColorField/ColorField.d.ts +3 -1
package/index.cjs.js
CHANGED
|
@@ -15,8 +15,8 @@ var ReactAsyncSelect = require('react-select/async');
|
|
|
15
15
|
var ReactAsyncCreatableSelect = require('react-select/async-creatable');
|
|
16
16
|
var ReactCreatableSelect = require('react-select/creatable');
|
|
17
17
|
var sharedUtils = require('@trackunit/shared-utils');
|
|
18
|
-
var reactHookForm = require('react-hook-form');
|
|
19
18
|
var tailwindMerge = require('tailwind-merge');
|
|
19
|
+
var reactHookForm = require('react-hook-form');
|
|
20
20
|
var zod = require('zod');
|
|
21
21
|
|
|
22
22
|
var defaultTranslations = {
|
|
@@ -1731,18 +1731,36 @@ const isValidHEXColor = (value) => {
|
|
|
1731
1731
|
* ColorField validates that user enters a valid color address.
|
|
1732
1732
|
*
|
|
1733
1733
|
*/
|
|
1734
|
-
const ColorField = react.forwardRef(({ label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, "data-testid": dataTestId, value: propValue, onChange, isInvalid
|
|
1735
|
-
const renderAsDisabled = Boolean(
|
|
1736
|
-
const renderAsReadonly = Boolean(
|
|
1734
|
+
const ColorField = react.forwardRef(({ label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, "data-testid": dataTestId, value: propValue, onChange, isInvalid, onBlur, fieldSize = "medium", style, disabled, readOnly, nonInteractive, isWarning, inputClassName, ...inputProps }, ref) => {
|
|
1735
|
+
const renderAsDisabled = Boolean(disabled);
|
|
1736
|
+
const renderAsReadonly = Boolean(readOnly);
|
|
1737
1737
|
const htmlForId = react.useMemo(() => (id ? id : "colorField-" + sharedUtils.uuidv4()), [id]);
|
|
1738
1738
|
const innerRef = react.useRef(null);
|
|
1739
1739
|
react.useImperativeHandle(ref, () => innerRef.current, []);
|
|
1740
1740
|
const [t] = useTranslation();
|
|
1741
1741
|
// Internal state for color value
|
|
1742
|
-
const [innerValue, setInnerValue] = react.useState(propValue
|
|
1743
|
-
const [
|
|
1744
|
-
const errorType = react.useMemo(() => validateColorCode(innerValue,
|
|
1742
|
+
const [innerValue, setInnerValue] = react.useState(propValue ?? defaultValue ?? "");
|
|
1743
|
+
const [hasBeenBlurred, setHasBeenBlurred] = react.useState(false);
|
|
1744
|
+
const errorType = react.useMemo(() => validateColorCode(innerValue, inputProps.required), [inputProps.required, innerValue]);
|
|
1745
1745
|
const error = react.useMemo(() => (errorType ? t(`colorField.error.${errorType}`) : errorMessage), [errorType, errorMessage, t]);
|
|
1746
|
+
// Derive renderAsInvalid from props and internal validation
|
|
1747
|
+
const renderAsInvalid = react.useMemo(() => {
|
|
1748
|
+
if (isInvalid !== undefined) {
|
|
1749
|
+
return isInvalid;
|
|
1750
|
+
}
|
|
1751
|
+
if (errorMessage) {
|
|
1752
|
+
return true;
|
|
1753
|
+
}
|
|
1754
|
+
// Show invalid immediately if value is invalid
|
|
1755
|
+
if (Boolean(innerValue) && isString(innerValue) && !isValidHEXColor(innerValue)) {
|
|
1756
|
+
return true;
|
|
1757
|
+
}
|
|
1758
|
+
// Show invalid after blur if validation error exists
|
|
1759
|
+
if (hasBeenBlurred && errorType) {
|
|
1760
|
+
return true;
|
|
1761
|
+
}
|
|
1762
|
+
return false;
|
|
1763
|
+
}, [isInvalid, errorMessage, innerValue, hasBeenBlurred, errorType]);
|
|
1746
1764
|
const handleInputChange = react.useCallback((event) => {
|
|
1747
1765
|
const newValue = event.target.value;
|
|
1748
1766
|
setInnerValue(newValue);
|
|
@@ -1753,18 +1771,19 @@ const ColorField = react.forwardRef(({ label, id, tip, helpText, errorMessage, h
|
|
|
1753
1771
|
const handleBlur = react.useCallback(event => {
|
|
1754
1772
|
const newValue = event.target.value;
|
|
1755
1773
|
setInnerValue(newValue);
|
|
1756
|
-
|
|
1774
|
+
setHasBeenBlurred(true);
|
|
1757
1775
|
onBlur?.(event);
|
|
1758
|
-
}, [
|
|
1759
|
-
return (jsxRuntime.jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && error) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required:
|
|
1776
|
+
}, [onBlur]);
|
|
1777
|
+
return (jsxRuntime.jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && error) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: inputProps.required ? !(renderAsDisabled || renderAsReadonly) : false, tip: tip, children: jsxRuntime.jsxs("div", { className: cvaInput$1({
|
|
1760
1778
|
size: fieldSize,
|
|
1761
1779
|
disabled: renderAsDisabled,
|
|
1762
1780
|
invalid: renderAsInvalid,
|
|
1763
1781
|
readOnly: renderAsReadonly,
|
|
1782
|
+
isWarning,
|
|
1764
1783
|
className,
|
|
1765
|
-
}), "data-testid": dataTestId ? `${dataTestId}-container` : undefined, children: [jsxRuntime.jsx("input", { "aria-labelledby": htmlForId + "-label", className: cvaInputColorField({ readOnly: renderAsReadonly }), "data-testid": dataTestId, defaultValue: defaultValue, disabled: renderAsDisabled, id: htmlForId, onBlur: handleBlur, onChange: handleInputChange, readOnly: renderAsReadonly, ref: innerRef, type: "color", value: innerValue }), jsxRuntime.jsx("input", { "aria-labelledby": htmlForId + "-label-text", className: cvaInputElement({
|
|
1766
|
-
className: "px-1 focus-visible:outline-none",
|
|
1767
|
-
}), "data-testid": dataTestId ? `${dataTestId}-textField` : undefined, disabled: renderAsDisabled, onBlur: handleBlur, onChange: handleInputChange, readOnly: renderAsReadonly, type: "text", value: innerValue }), jsxRuntime.jsx(GenericActionsRenderer, { disabled: renderAsDisabled || renderAsReadonly, fieldSize: fieldSize, genericAction: "edit", innerRef: innerRef, tooltipLabel: t("colorField.tooltip") })] }) }));
|
|
1784
|
+
}), "data-testid": dataTestId ? `${dataTestId}-container` : undefined, style: style, children: [jsxRuntime.jsx("input", { "aria-labelledby": htmlForId + "-label", className: cvaInputColorField({ readOnly: renderAsReadonly }), "data-testid": dataTestId, defaultValue: defaultValue, disabled: renderAsDisabled, id: htmlForId, onBlur: handleBlur, onChange: handleInputChange, readOnly: renderAsReadonly, ref: innerRef, type: "color", value: innerValue }), jsxRuntime.jsx("input", { "aria-labelledby": htmlForId + "-label-text", className: cvaInputElement({
|
|
1785
|
+
className: tailwindMerge.twMerge("px-1 focus-visible:outline-none", inputClassName),
|
|
1786
|
+
}), "data-testid": dataTestId ? `${dataTestId}-textField` : undefined, disabled: renderAsDisabled, onBlur: handleBlur, onChange: handleInputChange, readOnly: renderAsReadonly || nonInteractive, type: "text", value: innerValue, ...inputProps }), jsxRuntime.jsx(GenericActionsRenderer, { disabled: renderAsDisabled || renderAsReadonly, fieldSize: fieldSize, genericAction: "edit", innerRef: innerRef, tooltipLabel: t("colorField.tooltip") })] }) }));
|
|
1768
1787
|
});
|
|
1769
1788
|
ColorField.displayName = "ColorField";
|
|
1770
1789
|
|
package/index.esm.js
CHANGED
|
@@ -14,8 +14,8 @@ import ReactAsyncSelect from 'react-select/async';
|
|
|
14
14
|
import ReactAsyncCreatableSelect from 'react-select/async-creatable';
|
|
15
15
|
import ReactCreatableSelect from 'react-select/creatable';
|
|
16
16
|
import { uuidv4, nonNullable } from '@trackunit/shared-utils';
|
|
17
|
-
import { Controller } from 'react-hook-form';
|
|
18
17
|
import { twMerge } from 'tailwind-merge';
|
|
18
|
+
import { Controller } from 'react-hook-form';
|
|
19
19
|
import { z } from 'zod';
|
|
20
20
|
|
|
21
21
|
var defaultTranslations = {
|
|
@@ -1730,18 +1730,36 @@ const isValidHEXColor = (value) => {
|
|
|
1730
1730
|
* ColorField validates that user enters a valid color address.
|
|
1731
1731
|
*
|
|
1732
1732
|
*/
|
|
1733
|
-
const ColorField = forwardRef(({ label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, "data-testid": dataTestId, value: propValue, onChange, isInvalid
|
|
1734
|
-
const renderAsDisabled = Boolean(
|
|
1735
|
-
const renderAsReadonly = Boolean(
|
|
1733
|
+
const ColorField = forwardRef(({ label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, "data-testid": dataTestId, value: propValue, onChange, isInvalid, onBlur, fieldSize = "medium", style, disabled, readOnly, nonInteractive, isWarning, inputClassName, ...inputProps }, ref) => {
|
|
1734
|
+
const renderAsDisabled = Boolean(disabled);
|
|
1735
|
+
const renderAsReadonly = Boolean(readOnly);
|
|
1736
1736
|
const htmlForId = useMemo(() => (id ? id : "colorField-" + uuidv4()), [id]);
|
|
1737
1737
|
const innerRef = useRef(null);
|
|
1738
1738
|
useImperativeHandle(ref, () => innerRef.current, []);
|
|
1739
1739
|
const [t] = useTranslation();
|
|
1740
1740
|
// Internal state for color value
|
|
1741
|
-
const [innerValue, setInnerValue] = useState(propValue
|
|
1742
|
-
const [
|
|
1743
|
-
const errorType = useMemo(() => validateColorCode(innerValue,
|
|
1741
|
+
const [innerValue, setInnerValue] = useState(propValue ?? defaultValue ?? "");
|
|
1742
|
+
const [hasBeenBlurred, setHasBeenBlurred] = useState(false);
|
|
1743
|
+
const errorType = useMemo(() => validateColorCode(innerValue, inputProps.required), [inputProps.required, innerValue]);
|
|
1744
1744
|
const error = useMemo(() => (errorType ? t(`colorField.error.${errorType}`) : errorMessage), [errorType, errorMessage, t]);
|
|
1745
|
+
// Derive renderAsInvalid from props and internal validation
|
|
1746
|
+
const renderAsInvalid = useMemo(() => {
|
|
1747
|
+
if (isInvalid !== undefined) {
|
|
1748
|
+
return isInvalid;
|
|
1749
|
+
}
|
|
1750
|
+
if (errorMessage) {
|
|
1751
|
+
return true;
|
|
1752
|
+
}
|
|
1753
|
+
// Show invalid immediately if value is invalid
|
|
1754
|
+
if (Boolean(innerValue) && isString(innerValue) && !isValidHEXColor(innerValue)) {
|
|
1755
|
+
return true;
|
|
1756
|
+
}
|
|
1757
|
+
// Show invalid after blur if validation error exists
|
|
1758
|
+
if (hasBeenBlurred && errorType) {
|
|
1759
|
+
return true;
|
|
1760
|
+
}
|
|
1761
|
+
return false;
|
|
1762
|
+
}, [isInvalid, errorMessage, innerValue, hasBeenBlurred, errorType]);
|
|
1745
1763
|
const handleInputChange = useCallback((event) => {
|
|
1746
1764
|
const newValue = event.target.value;
|
|
1747
1765
|
setInnerValue(newValue);
|
|
@@ -1752,18 +1770,19 @@ const ColorField = forwardRef(({ label, id, tip, helpText, errorMessage, helpAdd
|
|
|
1752
1770
|
const handleBlur = useCallback(event => {
|
|
1753
1771
|
const newValue = event.target.value;
|
|
1754
1772
|
setInnerValue(newValue);
|
|
1755
|
-
|
|
1773
|
+
setHasBeenBlurred(true);
|
|
1756
1774
|
onBlur?.(event);
|
|
1757
|
-
}, [
|
|
1758
|
-
return (jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && error) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required:
|
|
1775
|
+
}, [onBlur]);
|
|
1776
|
+
return (jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon, helpText: (renderAsInvalid && error) || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, required: inputProps.required ? !(renderAsDisabled || renderAsReadonly) : false, tip: tip, children: jsxs("div", { className: cvaInput$1({
|
|
1759
1777
|
size: fieldSize,
|
|
1760
1778
|
disabled: renderAsDisabled,
|
|
1761
1779
|
invalid: renderAsInvalid,
|
|
1762
1780
|
readOnly: renderAsReadonly,
|
|
1781
|
+
isWarning,
|
|
1763
1782
|
className,
|
|
1764
|
-
}), "data-testid": dataTestId ? `${dataTestId}-container` : undefined, children: [jsx("input", { "aria-labelledby": htmlForId + "-label", className: cvaInputColorField({ readOnly: renderAsReadonly }), "data-testid": dataTestId, defaultValue: defaultValue, disabled: renderAsDisabled, id: htmlForId, onBlur: handleBlur, onChange: handleInputChange, readOnly: renderAsReadonly, ref: innerRef, type: "color", value: innerValue }), jsx("input", { "aria-labelledby": htmlForId + "-label-text", className: cvaInputElement({
|
|
1765
|
-
className: "px-1 focus-visible:outline-none",
|
|
1766
|
-
}), "data-testid": dataTestId ? `${dataTestId}-textField` : undefined, disabled: renderAsDisabled, onBlur: handleBlur, onChange: handleInputChange, readOnly: renderAsReadonly, type: "text", value: innerValue }), jsx(GenericActionsRenderer, { disabled: renderAsDisabled || renderAsReadonly, fieldSize: fieldSize, genericAction: "edit", innerRef: innerRef, tooltipLabel: t("colorField.tooltip") })] }) }));
|
|
1783
|
+
}), "data-testid": dataTestId ? `${dataTestId}-container` : undefined, style: style, children: [jsx("input", { "aria-labelledby": htmlForId + "-label", className: cvaInputColorField({ readOnly: renderAsReadonly }), "data-testid": dataTestId, defaultValue: defaultValue, disabled: renderAsDisabled, id: htmlForId, onBlur: handleBlur, onChange: handleInputChange, readOnly: renderAsReadonly, ref: innerRef, type: "color", value: innerValue }), jsx("input", { "aria-labelledby": htmlForId + "-label-text", className: cvaInputElement({
|
|
1784
|
+
className: twMerge("px-1 focus-visible:outline-none", inputClassName),
|
|
1785
|
+
}), "data-testid": dataTestId ? `${dataTestId}-textField` : undefined, disabled: renderAsDisabled, onBlur: handleBlur, onChange: handleInputChange, readOnly: renderAsReadonly || nonInteractive, type: "text", value: innerValue, ...inputProps }), jsx(GenericActionsRenderer, { disabled: renderAsDisabled || renderAsReadonly, fieldSize: fieldSize, genericAction: "edit", innerRef: innerRef, tooltipLabel: t("colorField.tooltip") })] }) }));
|
|
1767
1786
|
});
|
|
1768
1787
|
ColorField.displayName = "ColorField";
|
|
1769
1788
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-form-components",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.122",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"engines": {
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
"zod": "^3.23.8",
|
|
15
15
|
"react-hook-form": "7.62.0",
|
|
16
16
|
"tailwind-merge": "^2.0.0",
|
|
17
|
-
"@trackunit/css-class-variance-utilities": "1.7.
|
|
18
|
-
"@trackunit/react-components": "1.10.
|
|
19
|
-
"@trackunit/ui-icons": "1.7.
|
|
20
|
-
"@trackunit/shared-utils": "1.9.
|
|
21
|
-
"@trackunit/ui-design-tokens": "1.7.
|
|
22
|
-
"@trackunit/i18n-library-translation": "1.7.
|
|
17
|
+
"@trackunit/css-class-variance-utilities": "1.7.79",
|
|
18
|
+
"@trackunit/react-components": "1.10.54",
|
|
19
|
+
"@trackunit/ui-icons": "1.7.80",
|
|
20
|
+
"@trackunit/shared-utils": "1.9.79",
|
|
21
|
+
"@trackunit/ui-design-tokens": "1.7.79",
|
|
22
|
+
"@trackunit/i18n-library-translation": "1.7.97",
|
|
23
23
|
"string-ts": "^2.0.0",
|
|
24
24
|
"@js-temporal/polyfill": "^0.5.1",
|
|
25
25
|
"@storybook/react-webpack5": "9.1.13"
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { MappedOmit } from "@trackunit/shared-utils";
|
|
1
2
|
import { BaseInputProps } from "../BaseInput";
|
|
2
3
|
import { FormGroupProps } from "../FormGroup/FormGroup";
|
|
3
4
|
type FormGroupExposedProps = Pick<FormGroupProps, "label" | "tip" | "helpText" | "helpAddon">;
|
|
5
|
+
type ColorFieldBaseInputProps = MappedOmit<BaseInputProps, "prefix" | "suffix" | "addonBefore" | "addonAfter" | "actions" | "genericAction">;
|
|
4
6
|
/**
|
|
5
7
|
* Validates if the given value is a valid hex color.
|
|
6
8
|
*
|
|
@@ -8,7 +10,7 @@ type FormGroupExposedProps = Pick<FormGroupProps, "label" | "tip" | "helpText" |
|
|
|
8
10
|
* @returns {boolean} True if the value is a valid hex color, otherwise false.
|
|
9
11
|
*/
|
|
10
12
|
export declare const isValidHEXColor: (value: string) => boolean;
|
|
11
|
-
export interface ColorFieldProps extends FormGroupExposedProps,
|
|
13
|
+
export interface ColorFieldProps extends FormGroupExposedProps, ColorFieldBaseInputProps {
|
|
12
14
|
/**
|
|
13
15
|
* If a value is set, the field is rendered in its invalid state.
|
|
14
16
|
*/
|