@trackunit/custom-field-components 1.7.123 → 1.7.125

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
@@ -187,34 +187,60 @@ const convertToValueFormat = (value) => {
187
187
  * @param options DropdownCustomFieldProps - an object with all the props
188
188
  * @returns {ReactElement} - a dropdown component
189
189
  */
190
- const DropdownCustomField = ({ defaultValue, "data-testid": dataTestId, onChange, onBlur, id, disabled = false, allValues, multiSelect = false, register, validationRules, setValue, label, tip, errorMessage, helpText, isInvalid, helpAddon, }) => {
190
+ const DropdownCustomField = ({ defaultValue, "data-testid": dataTestId, onChange, onBlur, id, disabled = false, allValues, multiSelect = false, register, validationRules, setValue, label, tip, errorMessage, helpText, isInvalid = false, helpAddon, }) => {
191
191
  const renderAsInvalid = isInvalid || Boolean(errorMessage);
192
- const htmlForId = id ? id : "dropdown-custom-field-" + sharedUtils.uuidv4();
193
- const [selectedValue, setSelectedValue] = react.useState(defaultValue ? defaultValue.map(convertToValueFormat) : []);
194
- const onChangeHandler = react.useCallback((selected) => {
195
- if (selected) {
196
- const values = Array.isArray(selected) ? selected : [selected];
197
- if (selectedValue.length === 1 && values.length === 1 && values[0]?.value === selectedValue[0]?.value) {
198
- setSelectedValue([]);
199
- setValue && setValue(id, [], { shouldDirty: true, shouldValidate: true });
200
- }
201
- else {
202
- setSelectedValue(values);
203
- setValue && setValue(id, values, { shouldDirty: true, shouldValidate: true });
204
- }
205
- }
206
- else {
207
- setSelectedValue([]);
208
- setValue && setValue(id, []);
209
- }
210
- }, [id, selectedValue, setValue]);
192
+ const htmlFor = id ? id : "dropdown-custom-field-" + sharedUtils.uuidv4();
211
193
  const options = react.useMemo(() => {
212
194
  return allValues ? allValues.map(convertToValueFormat) : [];
213
195
  }, [allValues]);
196
+ // For single select: use primitive string value
197
+ const [singleSelectValue, setSingleSelectValue] = react.useState(defaultValue && defaultValue.length > 0 ? defaultValue[0] : undefined);
198
+ // For multi select: use MultiValue array
199
+ const [multiSelectValue, setMultiSelectValue] = react.useState(defaultValue ? defaultValue.map(convertToValueFormat) : []);
200
+ // Single select onChange handler (RHF-style)
201
+ const singleSelectOnChange = react.useCallback((event) => {
202
+ const newValue = event.target.value;
203
+ setSingleSelectValue(newValue);
204
+ const formValue = newValue ? [newValue] : [];
205
+ setValue?.(id, formValue, { shouldDirty: true, shouldValidate: true });
206
+ onChange?.();
207
+ }, [id, setValue, onChange]);
208
+ // Multi select onChange handler (direct value)
209
+ const multiSelectOnChange = react.useCallback((selected) => {
210
+ const values = selected ?? [];
211
+ setMultiSelectValue(values);
212
+ const formValue = values.map(option => option.value);
213
+ setValue?.(id, formValue, { shouldDirty: true, shouldValidate: true });
214
+ onChange?.();
215
+ }, [id, setValue, onChange]);
216
+ // Register with React Hook Form
214
217
  react.useEffect(() => {
215
- register && register(id, { ...validationRules, value: selectedValue });
216
- }, [register, validationRules, selectedValue, id]);
217
- return (jsxRuntime.jsx(reactFormComponents.FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon || null, helpText: errorMessage || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, tip: tip, children: jsxRuntime.jsx(reactFormComponents.BaseSelect, { "aria-labelledby": htmlForId + "-label", "data-testid": dataTestId, disabled: disabled, hasError: renderAsInvalid, inputId: htmlForId, isClearable: true, isMulti: multiSelect, onChange: onChangeHandler, options: options, value: selectedValue }) }));
218
+ if (multiSelect) {
219
+ const formValue = multiSelectValue.map(option => option.value);
220
+ register?.(id, { ...validationRules, value: formValue });
221
+ }
222
+ else {
223
+ const formValue = singleSelectValue ? [singleSelectValue] : [];
224
+ register?.(id, { ...validationRules, value: formValue });
225
+ }
226
+ }, [register, validationRules, multiSelect, multiSelectValue, singleSelectValue, id]);
227
+ const sharedProps = react.useMemo(() => ({
228
+ "data-testid": dataTestId,
229
+ helpAddon,
230
+ helpText,
231
+ id,
232
+ htmlFor,
233
+ isInvalid: renderAsInvalid,
234
+ label,
235
+ isClearable: true,
236
+ tip,
237
+ disabled,
238
+ hasError: renderAsInvalid,
239
+ }), [dataTestId, helpAddon, helpText, id, htmlFor, renderAsInvalid, label, tip, disabled]);
240
+ if (multiSelect) {
241
+ return (jsxRuntime.jsx(reactFormComponents.MultiSelectField, { onChange: multiSelectOnChange, options: options, value: multiSelectValue, ...sharedProps }));
242
+ }
243
+ return (jsxRuntime.jsx(reactFormComponents.SelectField, { onBlur: onBlur, onChange: singleSelectOnChange, options: options, value: singleSelectValue, ...sharedProps }));
218
244
  };
219
245
 
220
246
  /**
package/index.esm.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import { registerTranslations, useNamespaceTranslation } from '@trackunit/i18n-library-translation';
3
3
  import { getCustomFieldValueForDisplayInUI } from '@trackunit/iris-app-runtime-core';
4
- import { FormGroup, Checkbox, DateField, BaseSelect, TextBaseInput, useGetPhoneValidationRules, NumberField, TextField, PhoneField, ActionButton } from '@trackunit/react-form-components';
4
+ import { FormGroup, Checkbox, DateField, MultiSelectField, SelectField, TextBaseInput, useGetPhoneValidationRules, NumberField, TextField, PhoneField, ActionButton } from '@trackunit/react-form-components';
5
5
  import { uuidv4, exhaustiveCheck } from '@trackunit/shared-utils';
6
6
  import { useState, useEffect, useCallback, createElement, useMemo } from 'react';
7
7
  import { Controller, useWatch } from 'react-hook-form';
@@ -185,34 +185,60 @@ const convertToValueFormat = (value) => {
185
185
  * @param options DropdownCustomFieldProps - an object with all the props
186
186
  * @returns {ReactElement} - a dropdown component
187
187
  */
188
- const DropdownCustomField = ({ defaultValue, "data-testid": dataTestId, onChange, onBlur, id, disabled = false, allValues, multiSelect = false, register, validationRules, setValue, label, tip, errorMessage, helpText, isInvalid, helpAddon, }) => {
188
+ const DropdownCustomField = ({ defaultValue, "data-testid": dataTestId, onChange, onBlur, id, disabled = false, allValues, multiSelect = false, register, validationRules, setValue, label, tip, errorMessage, helpText, isInvalid = false, helpAddon, }) => {
189
189
  const renderAsInvalid = isInvalid || Boolean(errorMessage);
190
- const htmlForId = id ? id : "dropdown-custom-field-" + uuidv4();
191
- const [selectedValue, setSelectedValue] = useState(defaultValue ? defaultValue.map(convertToValueFormat) : []);
192
- const onChangeHandler = useCallback((selected) => {
193
- if (selected) {
194
- const values = Array.isArray(selected) ? selected : [selected];
195
- if (selectedValue.length === 1 && values.length === 1 && values[0]?.value === selectedValue[0]?.value) {
196
- setSelectedValue([]);
197
- setValue && setValue(id, [], { shouldDirty: true, shouldValidate: true });
198
- }
199
- else {
200
- setSelectedValue(values);
201
- setValue && setValue(id, values, { shouldDirty: true, shouldValidate: true });
202
- }
203
- }
204
- else {
205
- setSelectedValue([]);
206
- setValue && setValue(id, []);
207
- }
208
- }, [id, selectedValue, setValue]);
190
+ const htmlFor = id ? id : "dropdown-custom-field-" + uuidv4();
209
191
  const options = useMemo(() => {
210
192
  return allValues ? allValues.map(convertToValueFormat) : [];
211
193
  }, [allValues]);
194
+ // For single select: use primitive string value
195
+ const [singleSelectValue, setSingleSelectValue] = useState(defaultValue && defaultValue.length > 0 ? defaultValue[0] : undefined);
196
+ // For multi select: use MultiValue array
197
+ const [multiSelectValue, setMultiSelectValue] = useState(defaultValue ? defaultValue.map(convertToValueFormat) : []);
198
+ // Single select onChange handler (RHF-style)
199
+ const singleSelectOnChange = useCallback((event) => {
200
+ const newValue = event.target.value;
201
+ setSingleSelectValue(newValue);
202
+ const formValue = newValue ? [newValue] : [];
203
+ setValue?.(id, formValue, { shouldDirty: true, shouldValidate: true });
204
+ onChange?.();
205
+ }, [id, setValue, onChange]);
206
+ // Multi select onChange handler (direct value)
207
+ const multiSelectOnChange = useCallback((selected) => {
208
+ const values = selected ?? [];
209
+ setMultiSelectValue(values);
210
+ const formValue = values.map(option => option.value);
211
+ setValue?.(id, formValue, { shouldDirty: true, shouldValidate: true });
212
+ onChange?.();
213
+ }, [id, setValue, onChange]);
214
+ // Register with React Hook Form
212
215
  useEffect(() => {
213
- register && register(id, { ...validationRules, value: selectedValue });
214
- }, [register, validationRules, selectedValue, id]);
215
- return (jsx(FormGroup, { "data-testid": dataTestId ? `${dataTestId}-FormGroup` : undefined, helpAddon: helpAddon || null, helpText: errorMessage || helpText, htmlFor: htmlForId, isInvalid: renderAsInvalid, label: label, tip: tip, children: jsx(BaseSelect, { "aria-labelledby": htmlForId + "-label", "data-testid": dataTestId, disabled: disabled, hasError: renderAsInvalid, inputId: htmlForId, isClearable: true, isMulti: multiSelect, onChange: onChangeHandler, options: options, value: selectedValue }) }));
216
+ if (multiSelect) {
217
+ const formValue = multiSelectValue.map(option => option.value);
218
+ register?.(id, { ...validationRules, value: formValue });
219
+ }
220
+ else {
221
+ const formValue = singleSelectValue ? [singleSelectValue] : [];
222
+ register?.(id, { ...validationRules, value: formValue });
223
+ }
224
+ }, [register, validationRules, multiSelect, multiSelectValue, singleSelectValue, id]);
225
+ const sharedProps = useMemo(() => ({
226
+ "data-testid": dataTestId,
227
+ helpAddon,
228
+ helpText,
229
+ id,
230
+ htmlFor,
231
+ isInvalid: renderAsInvalid,
232
+ label,
233
+ isClearable: true,
234
+ tip,
235
+ disabled,
236
+ hasError: renderAsInvalid,
237
+ }), [dataTestId, helpAddon, helpText, id, htmlFor, renderAsInvalid, label, tip, disabled]);
238
+ if (multiSelect) {
239
+ return (jsx(MultiSelectField, { onChange: multiSelectOnChange, options: options, value: multiSelectValue, ...sharedProps }));
240
+ }
241
+ return (jsx(SelectField, { onBlur: onBlur, onChange: singleSelectOnChange, options: options, value: singleSelectValue, ...sharedProps }));
216
242
  };
217
243
 
218
244
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/custom-field-components",
3
- "version": "1.7.123",
3
+ "version": "1.7.125",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -9,16 +9,16 @@
9
9
  "dependencies": {
10
10
  "react": "19.0.0",
11
11
  "react-hook-form": "7.62.0",
12
- "react-select": "^5.10.0",
13
- "@trackunit/react-form-components": "1.8.121",
14
- "@trackunit/shared-utils": "1.9.78",
15
- "@trackunit/custom-field-api": "1.7.109",
16
- "@trackunit/iris-app-runtime-core": "1.8.88",
17
- "@trackunit/react-components": "1.10.53",
18
- "@trackunit/react-modal": "1.8.114",
19
- "@trackunit/react-core-hooks": "1.7.92",
20
- "@trackunit/i18n-library-translation": "1.7.96",
21
- "@trackunit/iris-app-runtime-core-api": "1.7.88"
12
+ "react-select": "^5.10.2",
13
+ "@trackunit/react-form-components": "1.8.123",
14
+ "@trackunit/shared-utils": "1.9.80",
15
+ "@trackunit/custom-field-api": "1.7.111",
16
+ "@trackunit/iris-app-runtime-core": "1.8.90",
17
+ "@trackunit/react-components": "1.10.55",
18
+ "@trackunit/react-modal": "1.8.116",
19
+ "@trackunit/react-core-hooks": "1.7.94",
20
+ "@trackunit/i18n-library-translation": "1.7.98",
21
+ "@trackunit/iris-app-runtime-core-api": "1.7.90"
22
22
  },
23
23
  "module": "./index.esm.js",
24
24
  "main": "./index.cjs.js",
@@ -83,7 +83,7 @@ export interface DropdownCustomFieldProps extends FormGroupExposedProps {
83
83
  isInvalid?: boolean;
84
84
  }
85
85
  type OnChange = (event?: ChangeEvent<HTMLInputElement>) => void;
86
- type OnBlur = (event: FocusEvent<HTMLDivElement>) => void;
86
+ type OnBlur = (event: FocusEvent<HTMLInputElement>) => void;
87
87
  /**
88
88
  * A custom field that can be used to render a dropdown
89
89
  *