@trackunit/react-form-components 2.3.8-alpha-90b6c9b97dd.0 → 2.3.8

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
@@ -1089,6 +1089,19 @@ const useCreateInputChangeEvent = () => react.useCallback((value, sourceInput) =
1089
1089
  */
1090
1090
  const useCreateInputBlurEvent = () => react.useCallback((value, sourceInput) => buildSyntheticInputEvent("blur", value, sourceInput), []);
1091
1091
 
1092
+ /**
1093
+ * Attaches `node` to `ref`. Kept as a plain module-scope function (rather than inline in the
1094
+ * hook) so mutating a ref's `.current` isn't flagged by `react-hooks/immutability`, which only
1095
+ * tracks mutation of values captured as hook-scoped arguments.
1096
+ */
1097
+ const attachRef = (ref, node) => {
1098
+ if (typeof ref === "function") {
1099
+ ref(node);
1100
+ }
1101
+ else if (ref !== null && ref !== undefined) {
1102
+ ref.current = node;
1103
+ }
1104
+ };
1092
1105
  /**
1093
1106
  * Owns the underlying `<input>` ref, ref forwarding, the DOM-value sync layout effect, and the
1094
1107
  * synthetic change/blur emitters used to surface the canonical (ISO) value to consumers while
@@ -1105,12 +1118,7 @@ const useCanonicalInputEmitter = ({ ref, onChange, onBlur, resolvedValue, }) =>
1105
1118
  const createInputBlurEvent = useCreateInputBlurEvent();
1106
1119
  const setInputRef = react.useCallback((node) => {
1107
1120
  inputRef.current = node;
1108
- if (typeof ref === "function") {
1109
- ref(node);
1110
- }
1111
- else if (ref !== null && ref !== undefined) {
1112
- ref.current = node;
1113
- }
1121
+ attachRef(ref, node);
1114
1122
  }, [ref]);
1115
1123
  react.useLayoutEffect(() => {
1116
1124
  const input = inputRef.current;
@@ -5335,13 +5343,9 @@ const ToggleSwitch = ({ onChange, onClick, preventDefaultOnClick = false, classN
5335
5343
  const localInputRef = react.useRef(null);
5336
5344
  const mergedRef = reactComponents.useMergeRefs([ref, localInputRef]);
5337
5345
  // Extract data attributes to apply to wrapper
5338
- const dataAttributes = react.useMemo(() => Object.keys(rest).reduce((acc, key) => {
5339
- if (key.startsWith("data-")) {
5340
- acc[key] = rest[key];
5341
- delete rest[key];
5342
- }
5343
- return acc;
5344
- }, {}), [rest]);
5346
+ const dataAttributes = react.useMemo(() => Object.fromEntries(Object.entries(rest).filter(([key]) => key.startsWith("data-"))), [rest]);
5347
+ // Remaining props (without data attributes) to apply to the input
5348
+ const nonDataRest = react.useMemo(() => Object.fromEntries(Object.entries(rest).filter(([key]) => !key.startsWith("data-"))), [rest]);
5345
5349
  const handleWrapperClick = (e) => {
5346
5350
  // Prevents double-toggling when wrapped in a label or if preventDefaultOnClick is true
5347
5351
  const isFromLabel = e.target instanceof Element ? e.target.closest("label") : null;
@@ -5371,7 +5375,7 @@ const ToggleSwitch = ({ onChange, onClick, preventDefaultOnClick = false, classN
5371
5375
  disabled: disabled || readOnly,
5372
5376
  size,
5373
5377
  focused: showInputFocus,
5374
- }), "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 })] }) }) }));
5378
+ }), "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", ...nonDataRest })] }) }) }));
5375
5379
  };
5376
5380
  ToggleSwitch.displayName = "ToggleSwitch";
5377
5381
 
package/index.esm.js CHANGED
@@ -1088,6 +1088,19 @@ const useCreateInputChangeEvent = () => useCallback((value, sourceInput) => buil
1088
1088
  */
1089
1089
  const useCreateInputBlurEvent = () => useCallback((value, sourceInput) => buildSyntheticInputEvent("blur", value, sourceInput), []);
1090
1090
 
1091
+ /**
1092
+ * Attaches `node` to `ref`. Kept as a plain module-scope function (rather than inline in the
1093
+ * hook) so mutating a ref's `.current` isn't flagged by `react-hooks/immutability`, which only
1094
+ * tracks mutation of values captured as hook-scoped arguments.
1095
+ */
1096
+ const attachRef = (ref, node) => {
1097
+ if (typeof ref === "function") {
1098
+ ref(node);
1099
+ }
1100
+ else if (ref !== null && ref !== undefined) {
1101
+ ref.current = node;
1102
+ }
1103
+ };
1091
1104
  /**
1092
1105
  * Owns the underlying `<input>` ref, ref forwarding, the DOM-value sync layout effect, and the
1093
1106
  * synthetic change/blur emitters used to surface the canonical (ISO) value to consumers while
@@ -1104,12 +1117,7 @@ const useCanonicalInputEmitter = ({ ref, onChange, onBlur, resolvedValue, }) =>
1104
1117
  const createInputBlurEvent = useCreateInputBlurEvent();
1105
1118
  const setInputRef = useCallback((node) => {
1106
1119
  inputRef.current = node;
1107
- if (typeof ref === "function") {
1108
- ref(node);
1109
- }
1110
- else if (ref !== null && ref !== undefined) {
1111
- ref.current = node;
1112
- }
1120
+ attachRef(ref, node);
1113
1121
  }, [ref]);
1114
1122
  useLayoutEffect(() => {
1115
1123
  const input = inputRef.current;
@@ -5334,13 +5342,9 @@ const ToggleSwitch = ({ onChange, onClick, preventDefaultOnClick = false, classN
5334
5342
  const localInputRef = useRef(null);
5335
5343
  const mergedRef = useMergeRefs([ref, localInputRef]);
5336
5344
  // Extract data attributes to apply to wrapper
5337
- const dataAttributes = useMemo(() => Object.keys(rest).reduce((acc, key) => {
5338
- if (key.startsWith("data-")) {
5339
- acc[key] = rest[key];
5340
- delete rest[key];
5341
- }
5342
- return acc;
5343
- }, {}), [rest]);
5345
+ const dataAttributes = useMemo(() => Object.fromEntries(Object.entries(rest).filter(([key]) => key.startsWith("data-"))), [rest]);
5346
+ // Remaining props (without data attributes) to apply to the input
5347
+ const nonDataRest = useMemo(() => Object.fromEntries(Object.entries(rest).filter(([key]) => !key.startsWith("data-"))), [rest]);
5344
5348
  const handleWrapperClick = (e) => {
5345
5349
  // Prevents double-toggling when wrapped in a label or if preventDefaultOnClick is true
5346
5350
  const isFromLabel = e.target instanceof Element ? e.target.closest("label") : null;
@@ -5370,7 +5374,7 @@ const ToggleSwitch = ({ onChange, onClick, preventDefaultOnClick = false, classN
5370
5374
  disabled: disabled || readOnly,
5371
5375
  size,
5372
5376
  focused: showInputFocus,
5373
- }), "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 })] }) }) }));
5377
+ }), "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", ...nonDataRest })] }) }) }));
5374
5378
  };
5375
5379
  ToggleSwitch.displayName = "ToggleSwitch";
5376
5380
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-form-components",
3
- "version": "2.3.8-alpha-90b6c9b97dd.0",
3
+ "version": "2.3.8",
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.13.95-alpha-90b6c9b97dd.0",
13
+ "@trackunit/date-and-time-utils": "1.13.95",
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.13.92-alpha-90b6c9b97dd.0",
19
- "@trackunit/react-components": "2.4.2-alpha-90b6c9b97dd.0",
20
- "@trackunit/ui-icons": "1.13.93-alpha-90b6c9b97dd.0",
21
- "@trackunit/shared-utils": "1.15.95-alpha-90b6c9b97dd.0",
22
- "@trackunit/ui-design-tokens": "1.13.91-alpha-90b6c9b97dd.0",
23
- "@trackunit/i18n-library-translation": "2.2.7-alpha-90b6c9b97dd.0",
18
+ "@trackunit/css-class-variance-utilities": "1.13.92",
19
+ "@trackunit/react-components": "2.4.2",
20
+ "@trackunit/ui-icons": "1.13.93",
21
+ "@trackunit/shared-utils": "1.15.95",
22
+ "@trackunit/ui-design-tokens": "1.13.91",
23
+ "@trackunit/i18n-library-translation": "2.2.7",
24
24
  "string-ts": "^2.0.0",
25
25
  "es-toolkit": "^1.39.10"
26
26
  },
@@ -18,20 +18,20 @@ export type SelectProps<TOption, TIsAsync extends boolean = false, TIsMulti exte
18
18
  */
19
19
  prefix?: ReactNode;
20
20
  /**
21
- * An string to render in field when there is no value selected.
22
- * Can be used as a description, example or a hint.
21
+ * Text to display when no value is selected.
22
+ * Can be used as a description, example, or a hint.
23
23
  *
24
24
  * @memberof SelectProps
25
25
  */
26
26
  placeholder?: string;
27
27
  /**
28
- * An boolean flag to disable field
28
+ * Whether the select is disabled.
29
29
  *
30
30
  * @memberof SelectProps
31
31
  */
32
32
  disabled?: boolean | LockedForReasons;
33
33
  /**
34
- * An boolean flag to make the field readonly
34
+ * Whether the select is read-only.
35
35
  *
36
36
  * @memberof SelectProps
37
37
  */
@@ -105,13 +105,14 @@ export type SelectProps<TOption, TIsAsync extends boolean = false, TIsMulti exte
105
105
  */
106
106
  hideSelectedOptions?: boolean;
107
107
  /**
108
- * This callback returns
108
+ * Resolves option data to a string to be displayed as a description for that option. The
109
+ * option description is only shown in the menu list, not in the selected value.
109
110
  *
110
111
  * @memberof SelectProps
111
112
  */
112
113
  getOptionLabelDescription?: (option: TOption) => string | undefined;
113
114
  /**
114
- * This callback returns
115
+ * Resolves option data to an element to be displayed as a prefix for that option.
115
116
  *
116
117
  * @memberof SelectProps
117
118
  */
@@ -22,13 +22,26 @@ type SelectExposedProps<TOption extends BaseOptionType = BaseOptionType, TIsAsyn
22
22
  export interface MultiSelectFieldProps<TOption extends BaseOptionType = BaseOptionType, TIsAsync extends boolean = false, TGroup extends GroupBase<TOption> = GroupBase<TOption>> extends CommonProps, FormGroupExposedProps, SelectExposedProps<TOption, TIsAsync, TGroup>, Refable<HTMLSelectElement>, Styleable {
23
23
  /** RHF/native-friendly blur signature */
24
24
  onBlur?: (event: FocusEvent<HTMLInputElement>) => void;
25
- /** Options to render (same shape as BaseSelect) */
25
+ /**
26
+ * Options to render (same shape as BaseSelect)
27
+ *
28
+ * @important
29
+ * @expand
30
+ */
26
31
  options: Array<TOption>;
27
- /** Multi-value from react-select */
32
+ /**
33
+ * Multi-value from react-select
34
+ *
35
+ * @important
36
+ */
28
37
  value?: MultiValue<TOption> | null;
29
38
  /** Default selected options (MultiValue) */
30
39
  defaultValue?: MultiValue<TOption>;
31
- /** onChange passes MultiValue<TOption> (or null when cleared) */
40
+ /**
41
+ * onChange passes MultiValue<TOption> (or null when cleared)
42
+ *
43
+ * @important
44
+ */
32
45
  onChange?: (value: MultiValue<TOption> | null) => void;
33
46
  /** Invalid state message rendered via FormGroup */
34
47
  errorMessage?: string;
@@ -14,10 +14,15 @@ export interface SelectFieldProps<TOption extends BaseOptionType = BaseOptionTyp
14
14
  onBlur?: (event: FocusEvent<HTMLInputElement>) => void;
15
15
  /**
16
16
  * The options available for the SelectField.
17
+ *
18
+ * @important
19
+ * @expand
17
20
  */
18
21
  options: Array<TOption>;
19
22
  /**
20
23
  * The selected value of the SelectField.
24
+ *
25
+ * @important
21
26
  */
22
27
  value?: TOption["value"];
23
28
  /**
@@ -26,6 +31,8 @@ export interface SelectFieldProps<TOption extends BaseOptionType = BaseOptionTyp
26
31
  defaultValue?: TOption["value"];
27
32
  /**
28
33
  * The onChange handler for the SelectField.
34
+ *
35
+ * @important
29
36
  */
30
37
  onChange?: (event: {
31
38
  target: {