@trackunit/custom-field-components 0.0.541 → 0.0.545

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
@@ -4,8 +4,8 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var irisAppRuntimeCore = require('@trackunit/iris-app-runtime-core');
7
- var irisAppRuntimeCoreApi = require('@trackunit/iris-app-runtime-core-api');
8
7
  var reactFormComponents = require('@trackunit/react-form-components');
8
+ var sharedUtils = require('@trackunit/shared-utils');
9
9
  var React = require('react');
10
10
  var uuid = require('uuid');
11
11
  var libphonenumberJs = require('libphonenumber-js');
@@ -143,10 +143,10 @@ const DropdownCustomField = ({ defaultValue, dataTestId, onChange, onBlur, id, d
143
143
  };
144
144
 
145
145
  /**
146
- * Get validation rules for a field
146
+ * Generates validation rules for a web address field.
147
147
  *
148
- * @param { WebAddressFieldDefinition } definition the field definition
149
- * @returns { ValidationRules} the validation rules
148
+ * @param {GetWebAddressValidationRulesDefinition} definition - The definition of the web address field.
149
+ * @returns {ValidationRules} The generated validation rules.
150
150
  */
151
151
  const getWebAddressValidationRules = (definition) => {
152
152
  const defaultRules = {};
@@ -160,10 +160,10 @@ const getWebAddressValidationRules = (definition) => {
160
160
  ? Object.assign(Object.assign({}, pattern), defaultRules) : defaultRules;
161
161
  };
162
162
  /**
163
- * Get validation rules for a field.
163
+ * Generates validation rules for a number field.
164
164
  *
165
- * @param { NumberFieldDefinition } definition the field definition
166
- * @returns { ValidationRules} the validation rules
165
+ * @param {GetNumberValidationRulesDefinition} definition - The definition of the number field.
166
+ * @returns {ValidationRules} The generated validation rules.
167
167
  */
168
168
  const getNumberValidationRules = (definition) => {
169
169
  const defaultRules = { valueAsNumber: true };
@@ -184,10 +184,10 @@ const getNumberValidationRules = (definition) => {
184
184
  ? Object.assign(Object.assign(Object.assign({}, maximum), minimum), defaultRules) : defaultRules;
185
185
  };
186
186
  /**
187
- * Get validation rules for a string field.
187
+ * Generates validation rules for a string field.
188
188
  *
189
- * @param { StringFieldDefinition } definition the field definition
190
- * @returns { ValidationRules} the validation rules
189
+ * @param {GetStringValidationRulesDefinition} definition - The definition of the string field.
190
+ * @returns {ValidationRules} The generated validation rules.
191
191
  */
192
192
  const getStringValidationRules = (definition) => {
193
193
  const defaultRules = {};
@@ -223,40 +223,40 @@ const getStringValidationRules = (definition) => {
223
223
  ? Object.assign(Object.assign(Object.assign(Object.assign({}, maxLength), minLength), pattern), defaultRules) : defaultRules;
224
224
  };
225
225
  /**
226
- * Get validation rules for a boolean field.
226
+ * Generates validation rules for a boolean field.
227
227
  *
228
- * @param { BooleanFieldDefinition } definition the field definition
229
- * @returns { ValidationRules} the validation rules
228
+ * @param {CommonValidationRulesDefinition} definition - The definition of the boolean field.
229
+ * @returns {ValidationRules} The generated validation rules.
230
230
  */
231
231
  const getBooleanValidationRules = (definition) => {
232
232
  const defaultRules = {};
233
233
  return defaultRules;
234
234
  };
235
235
  /**
236
- * Get validation rules for a dropdown field.
236
+ * Generates validation rules for a dropdown field.
237
237
  *
238
- * @param { DropDownFieldDefinition } definition the field definition
239
- * @returns { ValidationRules} the validation rules
238
+ * @param {CommonValidationRulesDefinition} definition - The definition of the dropdown field.
239
+ * @returns {ValidationRules} The generated validation rules.
240
240
  */
241
241
  const getDropdownValidationRules = (definition) => {
242
242
  const defaultRules = {};
243
243
  return defaultRules;
244
244
  };
245
245
  /**
246
- * Get validation rules for a date field.
246
+ * Generates validation rules for a date field.
247
247
  *
248
- * @param { DateFieldDefinition } definition the field definition
249
- * @returns { ValidationRules} the validation rules
248
+ * @param {CommonValidationRulesDefinition} definition - The definition of the date field.
249
+ * @returns {ValidationRules} The generated validation rules.
250
250
  */
251
251
  const getDateValidationRules = (definition) => {
252
252
  const defaultRules = {};
253
253
  return defaultRules;
254
254
  };
255
255
  /**
256
- * Get validation rules for an email field.
256
+ * Generates validation rules for an email field.
257
257
  *
258
- * @param { EmailFieldDefinition } definition the field definition
259
- * @returns { ValidationRules} the validation rules
258
+ * @param {CommonValidationRulesDefinition} definition - The definition of the email field.
259
+ * @returns {ValidationRules} The generated validation rules.
260
260
  */
261
261
  const getEmailValidationRules = (definition) => {
262
262
  const defaultRules = {};
@@ -270,10 +270,10 @@ const getEmailValidationRules = (definition) => {
270
270
  ? Object.assign(Object.assign({}, pattern), defaultRules) : defaultRules;
271
271
  };
272
272
  /**
273
- * Get validation rules for a phonenumber field.
273
+ * Generates validation rules for a phone number field.
274
274
  *
275
- * @param { PhoneNumberFieldDefinition } definition the field definition
276
- * @returns { ValidationRules} the validation rules
275
+ * @param {CommonValidationRulesDefinition} definition - The definition of the phone number field.
276
+ * @returns {ValidationRules} The generated validation rules.
277
277
  */
278
278
  const getPhoneNumberValidationRules = (definition) => {
279
279
  const defaultRules = {};
@@ -285,129 +285,127 @@ const getPhoneNumberValidationRules = (definition) => {
285
285
  };
286
286
 
287
287
  /**
288
- * A component that renders a custom field based on the field definition
288
+ * A hook that resolves and returns a JSX Element for a given custom field.
289
+ * It handles various custom field types by providing appropriate validation rules
290
+ * and input components with the necessary props.
289
291
  *
290
- * @param field A field definition and value
291
- * @param validation A validation object that contains the register, setValue and formState
292
- * @param unitPreference A unit preference that can be used to override the default unit preference
293
- * @param fieldId An optional Id to override the definition.key
294
- * @returns { JSX.Element } A JSX.Element or null if the field definition is undefined
292
+ * @param {CustomFieldProps} props - The properties of the custom field, including its definition, value,
293
+ * and functions for form registration and state management.
294
+ * @returns {JSX.Element | null} - The JSX Element for the custom field or null if the field definition is not provided.
295
295
  */
296
- const useCustomFieldResolver = (field, validation, unitPreference = "SI", language, fieldId) => {
297
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
296
+ const useCustomFieldResolver = ({ field, register, setValue, formState, unitPreference = "SI", language, fieldId, isEditable, }) => {
297
+ var _a, _b, _c, _d, _e, _f, _g;
298
+ const validation = { register, setValue, formState };
298
299
  const [numberValue, setNumberValue] = React.useState(() => {
299
- if ((field === null || field === void 0 ? void 0 : field.definition) && field.definition.type === irisAppRuntimeCoreApi.CustomFieldType.NUMBER) {
300
- const typedValue = field.value;
300
+ if (field.definition && field.__typename === "NumberFieldValueAndDefinition") {
301
+ const fieldValue = field.numberValue;
301
302
  const unit = unitPreference === "US_CUSTOMARY" && field.definition.unitUs
302
303
  ? `${field.definition.unitUs}`
303
304
  : field.definition.unitSi
304
305
  ? `${field.definition.unitSi}`
305
306
  : null;
306
- const value = irisAppRuntimeCore.CustomFieldRuntime.getCustomFieldValueForDisplayInUI(typedValue.numberValue, unit, unitPreference, language);
307
+ const value = irisAppRuntimeCore.CustomFieldRuntime.getCustomFieldValueForDisplayInUI(fieldValue, unit, unitPreference, language);
307
308
  return value;
308
309
  }
309
310
  else {
310
311
  return "";
311
312
  }
312
313
  });
313
- if ((field === null || field === void 0 ? void 0 : field.definition) === undefined || ((_a = field === null || field === void 0 ? void 0 : field.definition) === null || _a === void 0 ? void 0 : _a.type) === undefined) {
314
+ if ((field === null || field === void 0 ? void 0 : field.definition) === undefined) {
314
315
  return null;
315
316
  }
316
- const key = (_b = fieldId !== null && fieldId !== void 0 ? fieldId : field.definition.key) !== null && _b !== void 0 ? _b : "";
317
+ const key = (_a = fieldId !== null && fieldId !== void 0 ? fieldId : field.definition.key) !== null && _a !== void 0 ? _a : "";
318
+ const uniqueIdentifier = fieldId !== null && fieldId !== void 0 ? fieldId : field.definition.definitionId;
317
319
  const fieldError = key ? validation.formState.errors[key] : undefined;
318
320
  const errorMessage = fieldError ? fieldError.message + "" : undefined;
319
- const { type, description, title } = field.definition;
320
- switch (type) {
321
- case irisAppRuntimeCoreApi.CustomFieldType.WEB_ADDRESS: {
322
- const typedDefinition = field.definition;
323
- const typedValue = field.value;
324
- const rules = getWebAddressValidationRules(typedDefinition);
325
- return (jsxRuntime.jsx(reactFormComponents.TextField, Object.assign({ id: key, label: title, placeholder: (_c = typedDefinition.title) !== null && _c !== void 0 ? _c : "", defaultValue: (_d = typedValue.stringValue) !== null && _d !== void 0 ? _d : "", dataTestId: `${typedDefinition.key}`, actions: !typedDefinition.uiEditable &&
326
- typedValue.stringValue && jsxRuntime.jsx(reactFormComponents.ActionButton, { value: typedValue.stringValue, type: "WEB_ADDRESS" }), readOnly: !typedDefinition.uiEditable, helpText: description, errorMessage: errorMessage }, validation.register(key, rules))));
321
+ const { description, title } = field.definition;
322
+ const isEditableCombined = isEditable !== null && isEditable !== void 0 ? isEditable : field.definition.uiEditable;
323
+ switch (field.__typename) {
324
+ case "WebAddressFieldValueAndDefinition": {
325
+ const value = field.stringValue;
326
+ const rules = getWebAddressValidationRules(field.definition);
327
+ return (jsxRuntime.jsx(reactFormComponents.TextField, Object.assign({ id: uniqueIdentifier, label: title, placeholder: title !== null && title !== void 0 ? title : "", defaultValue: value !== null && value !== void 0 ? value : "", dataTestId: `${field.definition.key}`, actions: !isEditableCombined && value && jsxRuntime.jsx(reactFormComponents.ActionButton, { value: value, type: "WEB_ADDRESS" }), readOnly: !isEditableCombined, helpText: description, errorMessage: errorMessage }, validation.register(key, rules))));
327
328
  }
328
- case irisAppRuntimeCoreApi.CustomFieldType.EMAIL: {
329
- const typedDefinition = field.definition;
330
- const typedValue = field.value;
331
- const rules = getEmailValidationRules(typedDefinition);
332
- return (jsxRuntime.jsx(reactFormComponents.TextField, Object.assign({ id: key, label: title, placeholder: (_e = typedDefinition.title) !== null && _e !== void 0 ? _e : "", defaultValue: (_f = typedValue.stringValue) !== null && _f !== void 0 ? _f : "", dataTestId: `${typedDefinition.key}`, actions: !typedDefinition.uiEditable &&
333
- typedValue.stringValue && jsxRuntime.jsx(reactFormComponents.ActionButton, { value: typedValue.stringValue, type: "EMAIL" }), readOnly: !typedDefinition.uiEditable, helpText: description, errorMessage: errorMessage }, validation.register(key, rules))));
329
+ case "EmailFieldValueAndDefinition": {
330
+ const value = field.stringValue;
331
+ const rules = getEmailValidationRules(field.definition);
332
+ return (jsxRuntime.jsx(reactFormComponents.TextField, Object.assign({ id: uniqueIdentifier, label: title, placeholder: title !== null && title !== void 0 ? title : "", defaultValue: value !== null && value !== void 0 ? value : "", dataTestId: `${field.definition.key}`, actions: !isEditableCombined && value && jsxRuntime.jsx(reactFormComponents.ActionButton, { value: value, type: "EMAIL" }), readOnly: !isEditableCombined, helpText: description, errorMessage: errorMessage }, validation.register(key, rules))));
334
333
  }
335
- case irisAppRuntimeCoreApi.CustomFieldType.PHONE_NUMBER: {
336
- const typedDefinition = field.definition;
337
- const typedValue = field.value;
338
- const rules = getPhoneNumberValidationRules(typedDefinition);
339
- return (jsxRuntime.jsx(reactFormComponents.TextField, Object.assign({ label: title, id: key, placeholder: (_g = typedDefinition.title) !== null && _g !== void 0 ? _g : "", defaultValue: (_h = typedValue.stringValue) !== null && _h !== void 0 ? _h : "", dataTestId: `${typedDefinition.key}`, actions: !typedDefinition.uiEditable &&
340
- typedValue.stringValue && jsxRuntime.jsx(reactFormComponents.ActionButton, { value: typedValue.stringValue, type: "PHONE_NUMBER" }), readOnly: !typedDefinition.uiEditable, helpText: description, errorMessage: errorMessage === "" ? "Must be a phone number" : undefined }, validation.register(key, rules))));
334
+ case "PhoneNumberFieldValueAndDefinition": {
335
+ const value = field.stringValue;
336
+ const rules = getPhoneNumberValidationRules(field.definition);
337
+ return (jsxRuntime.jsx(reactFormComponents.TextField, Object.assign({ label: title, id: uniqueIdentifier, placeholder: title !== null && title !== void 0 ? title : "", defaultValue: value !== null && value !== void 0 ? value : "", dataTestId: `${field.definition.key}`, actions: !isEditableCombined && value && jsxRuntime.jsx(reactFormComponents.ActionButton, { value: value, type: "PHONE_NUMBER" }), readOnly: !isEditableCombined, helpText: description, errorMessage: errorMessage === "" ? "Must be a phone number" : undefined }, validation.register(key, rules))));
341
338
  }
342
- case irisAppRuntimeCoreApi.CustomFieldType.STRING: {
343
- const typedDefinition = field.definition;
344
- const typedValue = field.value;
345
- const rules = getStringValidationRules(typedDefinition);
346
- return (jsxRuntime.jsx(reactFormComponents.TextField, Object.assign({ label: title, id: key || "string-field", placeholder: (_j = typedDefinition.title) !== null && _j !== void 0 ? _j : "", defaultValue: (_k = typedValue.stringValue) !== null && _k !== void 0 ? _k : "", readOnly: !typedDefinition.uiEditable, helpText: description, errorMessage: errorMessage, dataTestId: `${typedDefinition.key}` }, validation.register(key, rules))));
339
+ case "StringFieldValueAndDefinition": {
340
+ const value = field.stringValue;
341
+ const rules = getStringValidationRules(field.definition);
342
+ return (jsxRuntime.jsx(reactFormComponents.TextField, Object.assign({ label: title, id: uniqueIdentifier, placeholder: title !== null && title !== void 0 ? title : "", defaultValue: value !== null && value !== void 0 ? value : "", readOnly: !isEditableCombined, helpText: description, errorMessage: errorMessage, dataTestId: `${field.definition.key}` }, validation.register(key, rules))));
347
343
  }
348
- case irisAppRuntimeCoreApi.CustomFieldType.NUMBER: {
349
- const typedDefinition = field.definition;
350
- const typedValue = field.value;
351
- const rules = getNumberValidationRules(typedDefinition);
352
- const unit = unitPreference === "US_CUSTOMARY" && typedDefinition.unitUs
353
- ? `${typedDefinition.unitUs}`
354
- : typedDefinition.unitSi
355
- ? `${typedDefinition.unitSi}`
344
+ case "NumberFieldValueAndDefinition": {
345
+ const value = field.numberValue;
346
+ const rules = getNumberValidationRules(field.definition);
347
+ const unit = unitPreference === "US_CUSTOMARY" && field.definition.unitUs
348
+ ? `${field.definition.unitUs}`
349
+ : field.definition.unitSi
350
+ ? `${field.definition.unitSi}`
356
351
  : null;
357
352
  const numberProps = {
358
- placeholder: (_l = typedDefinition.title) !== null && _l !== void 0 ? _l : "",
353
+ placeholder: title !== null && title !== void 0 ? title : "",
359
354
  addonAfter: unit,
360
355
  };
361
- return (jsxRuntime.jsx(reactFormComponents.NumberField, Object.assign({ label: title, id: key || "number-field", defaultValue: (_m = typedValue.numberValue) !== null && _m !== void 0 ? _m : "", step: typedDefinition.isInteger ? 1 : "any", min: (_o = typedDefinition.minimumNumber) !== null && _o !== void 0 ? _o : undefined, max: (_p = typedDefinition.maximumNumber) !== null && _p !== void 0 ? _p : undefined, readOnly: !typedDefinition.uiEditable, helpText: description, errorMessage: errorMessage, dataTestId: `${typedDefinition.key}` }, validation.register(key, rules), numberProps)));
356
+ return (jsxRuntime.jsx(reactFormComponents.NumberField, Object.assign({ label: title, id: uniqueIdentifier, defaultValue: value !== null && value !== void 0 ? value : "", step: field.definition.isInteger ? 1 : "any", min: (_b = field.definition.minimumNumber) !== null && _b !== void 0 ? _b : undefined, max: (_c = field.definition.maximumNumber) !== null && _c !== void 0 ? _c : undefined, readOnly: !isEditableCombined, helpText: description, errorMessage: errorMessage, dataTestId: `${field.definition.key}` }, validation.register(key, rules), numberProps)));
362
357
  }
363
- case irisAppRuntimeCoreApi.CustomFieldType.BOOLEAN: {
364
- const typedDefinition = field.definition;
365
- const typedValue = field.value;
366
- const rules = getBooleanValidationRules();
367
- return (jsxRuntime.jsx(BooleanCustomField, { label: (_q = typedDefinition.title) !== null && _q !== void 0 ? _q : "", id: key || "boolean-field", defaultValue: (_r = typedValue.booleanValue) !== null && _r !== void 0 ? _r : undefined, readOnly: !typedDefinition.uiEditable, register: validation.register, validationRules: rules, helpText: description, setValue: validation.setValue, errorMessage: errorMessage, dataTestId: `${typedDefinition.key}` }, key));
358
+ case "BooleanFieldValueAndDefinition": {
359
+ const value = field.booleanValue;
360
+ const rules = getBooleanValidationRules(field.definition);
361
+ return (jsxRuntime.jsx(BooleanCustomField, { label: title !== null && title !== void 0 ? title : "", id: uniqueIdentifier, defaultValue: value !== null && value !== void 0 ? value : undefined, readOnly: !isEditableCombined, register: validation.register, validationRules: rules, helpText: description, setValue: validation.setValue, errorMessage: errorMessage, dataTestId: `${field.definition.key}` }));
368
362
  }
369
- case irisAppRuntimeCoreApi.CustomFieldType.DROPDOWN: {
370
- const typedDefinition = field.definition;
371
- const typedValue = field.value;
372
- const rules = getDropdownValidationRules();
373
- return (jsxRuntime.jsx(DropdownCustomField, { label: typedDefinition.title || "", id: key || "dropdown-field", defaultValue: (_s = typedValue.stringArrayValue) !== null && _s !== void 0 ? _s : undefined, disabled: !typedDefinition.uiEditable, allValues: (_t = typedDefinition.allValues) !== null && _t !== void 0 ? _t : undefined, multiSelect: (_u = typedDefinition.multiSelect) !== null && _u !== void 0 ? _u : false, register: validation.register, validationRules: rules, helpText: description, setValue: validation.setValue, errorMessage: errorMessage, dataTestId: `${typedDefinition.key}` }, key));
363
+ case "DropDownFieldValueAndDefinition": {
364
+ const value = field.stringArrayValue;
365
+ const rules = getDropdownValidationRules(field.definition);
366
+ return (jsxRuntime.jsx(DropdownCustomField, { label: title || "", id: uniqueIdentifier, defaultValue: value !== null && value !== void 0 ? value : undefined, disabled: !isEditableCombined, allValues: (_d = field.definition.allValues) !== null && _d !== void 0 ? _d : undefined, multiSelect: (_e = field.definition.multiSelect) !== null && _e !== void 0 ? _e : false, register: validation.register, validationRules: rules, helpText: description, setValue: validation.setValue, errorMessage: errorMessage, dataTestId: `${field.definition.key}` }));
374
367
  }
375
- case irisAppRuntimeCoreApi.CustomFieldType.DATE: {
376
- const typedDefinition = field.definition;
377
- const typedValue = field.value;
378
- const rules = getDateValidationRules();
368
+ case "DateFieldValueAndDefinition": {
369
+ const value = field.dateValue;
370
+ const rules = getDateValidationRules(field.definition);
379
371
  let defaultValue;
380
- if (typedValue.dateValue !== undefined && typedValue.dateValue !== null) {
381
- defaultValue = new Date(typedValue.dateValue);
372
+ if (value !== undefined && value !== null) {
373
+ defaultValue = new Date(value);
382
374
  }
383
- return (jsxRuntime.jsx(DateCustomField, { dataTestId: `${typedDefinition.key}`, id: key || "date-field", defaultValue: defaultValue, readOnly: !typedDefinition.uiEditable, register: validation.register, label: typedDefinition.title || "", validationRules: rules, helpText: description, errorMessage: errorMessage, setValue: validation.setValue, title: field.definition.title || "" }, key));
375
+ return (jsxRuntime.jsx(DateCustomField, { dataTestId: `${field.definition.key}`, id: uniqueIdentifier, defaultValue: defaultValue, readOnly: !isEditableCombined, register: validation.register, label: title || "", validationRules: rules, helpText: description, errorMessage: errorMessage, setValue: validation.setValue, title: title || "" }));
384
376
  }
385
- case irisAppRuntimeCoreApi.CustomFieldType.JSON: {
386
- return jsxRuntime.jsx("div", {});
377
+ case "JsonFieldValueAndDefinition": {
378
+ return null;
387
379
  }
388
- case irisAppRuntimeCoreApi.CustomFieldType.MONETARY: {
380
+ case "MonetaryFieldValueAndDefinition": {
389
381
  const rules = getNumberValidationRules(field.definition);
390
382
  const numberProps = {
391
- placeholder: (_v = field.definition.title) !== null && _v !== void 0 ? _v : "",
383
+ placeholder: title !== null && title !== void 0 ? title : "",
392
384
  addonAfter: field.definition.currency,
393
385
  };
394
386
  const value = numberValue === undefined || numberValue === null || numberValue === ""
395
387
  ? ""
396
388
  : parseFloat(Number(numberValue).toPrecision(4));
397
- return (jsxRuntime.jsx(reactFormComponents.FormGroup, { htmlFor: key || "number-field", label: title, isInvalid: errorMessage ? true : false, helpText: errorMessage || description, dataTestId: `${field.definition.key}-FormGroup`, disabled: !field.definition.uiEditable, children: jsxRuntime.jsx(reactFormComponents.NumberInput, Object.assign({ id: key || "number-field", dataTestId: field.definition.key ? field.definition.key : `monetaryField`, defaultValue: value, readOnly: !field.definition.uiEditable, step: "any", min: (_w = field.definition.minimumNumber) !== null && _w !== void 0 ? _w : undefined, max: (_x = field.definition.maximumNumber) !== null && _x !== void 0 ? _x : undefined }, validation.register(key, rules), { onChange: e => {
398
- setNumberValue(e.target.value === "" ? null : e.target.value);
399
- validation.register(key, rules).onChange(e);
400
- } }, numberProps)) }));
389
+ return (jsxRuntime.jsx(reactFormComponents.NumberField, Object.assign({ label: title, isInvalid: errorMessage ? true : false, helpText: errorMessage || description, disabled: !isEditableCombined, id: uniqueIdentifier, dataTestId: field.definition.key ? field.definition.key : `monetaryField`, defaultValue: value, readOnly: !isEditableCombined, step: "any", min: (_f = field.definition.minimumNumber) !== null && _f !== void 0 ? _f : undefined, max: (_g = field.definition.maximumNumber) !== null && _g !== void 0 ? _g : undefined }, validation.register(key, rules), { onChange: e => {
390
+ setNumberValue(e.target.value === "" ? null : e.target.value);
391
+ validation.register(key, rules).onChange(e);
392
+ } }, numberProps)));
401
393
  }
402
394
  default:
403
- throw new Error(`Type not supported: ${type}`);
395
+ return sharedUtils.exhaustiveCheck(field);
404
396
  }
405
397
  };
406
398
  /**
399
+ * CustomField is a React component that takes in the properties of a custom field and renders it.
400
+ * It utilizes the `useCustomFieldResolver` hook to resolve the field into an input element
401
+ * based on the field's type and definition.
407
402
  *
403
+ * @param {CustomFieldProps} props - Props for defining the custom field, including its type, value,
404
+ * validation rules, and form registration functions from react-hook-form.
405
+ * @returns {JSX.Element | null} - The resolved custom field component or null if the field cannot be resolved.
408
406
  */
409
- const CustomField = ({ field, register, formState, setValue, unitPreference, fieldId, language, }) => {
410
- const fieldComponent = useCustomFieldResolver(field, { register, setValue, formState }, unitPreference, language, fieldId);
407
+ const CustomField = (props) => {
408
+ const fieldComponent = useCustomFieldResolver(props);
411
409
  return fieldComponent;
412
410
  };
413
411
 
package/index.esm.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import { CustomFieldRuntime } from '@trackunit/iris-app-runtime-core';
3
- import { CustomFieldType } from '@trackunit/iris-app-runtime-core-api';
4
- import { FormGroup, Checkbox, DateField, Select, NumberInput, NumberField, TextField, ActionButton } from '@trackunit/react-form-components';
3
+ import { FormGroup, Checkbox, DateField, Select, NumberField, TextField, ActionButton } from '@trackunit/react-form-components';
4
+ import { exhaustiveCheck } from '@trackunit/shared-utils';
5
5
  import * as React from 'react';
6
6
  import { useCallback, useEffect, createElement, useState } from 'react';
7
7
  import { v4 } from 'uuid';
@@ -120,10 +120,10 @@ const DropdownCustomField = ({ defaultValue, dataTestId, onChange, onBlur, id, d
120
120
  };
121
121
 
122
122
  /**
123
- * Get validation rules for a field
123
+ * Generates validation rules for a web address field.
124
124
  *
125
- * @param { WebAddressFieldDefinition } definition the field definition
126
- * @returns { ValidationRules} the validation rules
125
+ * @param {GetWebAddressValidationRulesDefinition} definition - The definition of the web address field.
126
+ * @returns {ValidationRules} The generated validation rules.
127
127
  */
128
128
  const getWebAddressValidationRules = (definition) => {
129
129
  const defaultRules = {};
@@ -137,10 +137,10 @@ const getWebAddressValidationRules = (definition) => {
137
137
  ? Object.assign(Object.assign({}, pattern), defaultRules) : defaultRules;
138
138
  };
139
139
  /**
140
- * Get validation rules for a field.
140
+ * Generates validation rules for a number field.
141
141
  *
142
- * @param { NumberFieldDefinition } definition the field definition
143
- * @returns { ValidationRules} the validation rules
142
+ * @param {GetNumberValidationRulesDefinition} definition - The definition of the number field.
143
+ * @returns {ValidationRules} The generated validation rules.
144
144
  */
145
145
  const getNumberValidationRules = (definition) => {
146
146
  const defaultRules = { valueAsNumber: true };
@@ -161,10 +161,10 @@ const getNumberValidationRules = (definition) => {
161
161
  ? Object.assign(Object.assign(Object.assign({}, maximum), minimum), defaultRules) : defaultRules;
162
162
  };
163
163
  /**
164
- * Get validation rules for a string field.
164
+ * Generates validation rules for a string field.
165
165
  *
166
- * @param { StringFieldDefinition } definition the field definition
167
- * @returns { ValidationRules} the validation rules
166
+ * @param {GetStringValidationRulesDefinition} definition - The definition of the string field.
167
+ * @returns {ValidationRules} The generated validation rules.
168
168
  */
169
169
  const getStringValidationRules = (definition) => {
170
170
  const defaultRules = {};
@@ -200,40 +200,40 @@ const getStringValidationRules = (definition) => {
200
200
  ? Object.assign(Object.assign(Object.assign(Object.assign({}, maxLength), minLength), pattern), defaultRules) : defaultRules;
201
201
  };
202
202
  /**
203
- * Get validation rules for a boolean field.
203
+ * Generates validation rules for a boolean field.
204
204
  *
205
- * @param { BooleanFieldDefinition } definition the field definition
206
- * @returns { ValidationRules} the validation rules
205
+ * @param {CommonValidationRulesDefinition} definition - The definition of the boolean field.
206
+ * @returns {ValidationRules} The generated validation rules.
207
207
  */
208
208
  const getBooleanValidationRules = (definition) => {
209
209
  const defaultRules = {};
210
210
  return defaultRules;
211
211
  };
212
212
  /**
213
- * Get validation rules for a dropdown field.
213
+ * Generates validation rules for a dropdown field.
214
214
  *
215
- * @param { DropDownFieldDefinition } definition the field definition
216
- * @returns { ValidationRules} the validation rules
215
+ * @param {CommonValidationRulesDefinition} definition - The definition of the dropdown field.
216
+ * @returns {ValidationRules} The generated validation rules.
217
217
  */
218
218
  const getDropdownValidationRules = (definition) => {
219
219
  const defaultRules = {};
220
220
  return defaultRules;
221
221
  };
222
222
  /**
223
- * Get validation rules for a date field.
223
+ * Generates validation rules for a date field.
224
224
  *
225
- * @param { DateFieldDefinition } definition the field definition
226
- * @returns { ValidationRules} the validation rules
225
+ * @param {CommonValidationRulesDefinition} definition - The definition of the date field.
226
+ * @returns {ValidationRules} The generated validation rules.
227
227
  */
228
228
  const getDateValidationRules = (definition) => {
229
229
  const defaultRules = {};
230
230
  return defaultRules;
231
231
  };
232
232
  /**
233
- * Get validation rules for an email field.
233
+ * Generates validation rules for an email field.
234
234
  *
235
- * @param { EmailFieldDefinition } definition the field definition
236
- * @returns { ValidationRules} the validation rules
235
+ * @param {CommonValidationRulesDefinition} definition - The definition of the email field.
236
+ * @returns {ValidationRules} The generated validation rules.
237
237
  */
238
238
  const getEmailValidationRules = (definition) => {
239
239
  const defaultRules = {};
@@ -247,10 +247,10 @@ const getEmailValidationRules = (definition) => {
247
247
  ? Object.assign(Object.assign({}, pattern), defaultRules) : defaultRules;
248
248
  };
249
249
  /**
250
- * Get validation rules for a phonenumber field.
250
+ * Generates validation rules for a phone number field.
251
251
  *
252
- * @param { PhoneNumberFieldDefinition } definition the field definition
253
- * @returns { ValidationRules} the validation rules
252
+ * @param {CommonValidationRulesDefinition} definition - The definition of the phone number field.
253
+ * @returns {ValidationRules} The generated validation rules.
254
254
  */
255
255
  const getPhoneNumberValidationRules = (definition) => {
256
256
  const defaultRules = {};
@@ -262,129 +262,127 @@ const getPhoneNumberValidationRules = (definition) => {
262
262
  };
263
263
 
264
264
  /**
265
- * A component that renders a custom field based on the field definition
265
+ * A hook that resolves and returns a JSX Element for a given custom field.
266
+ * It handles various custom field types by providing appropriate validation rules
267
+ * and input components with the necessary props.
266
268
  *
267
- * @param field A field definition and value
268
- * @param validation A validation object that contains the register, setValue and formState
269
- * @param unitPreference A unit preference that can be used to override the default unit preference
270
- * @param fieldId An optional Id to override the definition.key
271
- * @returns { JSX.Element } A JSX.Element or null if the field definition is undefined
269
+ * @param {CustomFieldProps} props - The properties of the custom field, including its definition, value,
270
+ * and functions for form registration and state management.
271
+ * @returns {JSX.Element | null} - The JSX Element for the custom field or null if the field definition is not provided.
272
272
  */
273
- const useCustomFieldResolver = (field, validation, unitPreference = "SI", language, fieldId) => {
274
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
273
+ const useCustomFieldResolver = ({ field, register, setValue, formState, unitPreference = "SI", language, fieldId, isEditable, }) => {
274
+ var _a, _b, _c, _d, _e, _f, _g;
275
+ const validation = { register, setValue, formState };
275
276
  const [numberValue, setNumberValue] = useState(() => {
276
- if ((field === null || field === void 0 ? void 0 : field.definition) && field.definition.type === CustomFieldType.NUMBER) {
277
- const typedValue = field.value;
277
+ if (field.definition && field.__typename === "NumberFieldValueAndDefinition") {
278
+ const fieldValue = field.numberValue;
278
279
  const unit = unitPreference === "US_CUSTOMARY" && field.definition.unitUs
279
280
  ? `${field.definition.unitUs}`
280
281
  : field.definition.unitSi
281
282
  ? `${field.definition.unitSi}`
282
283
  : null;
283
- const value = CustomFieldRuntime.getCustomFieldValueForDisplayInUI(typedValue.numberValue, unit, unitPreference, language);
284
+ const value = CustomFieldRuntime.getCustomFieldValueForDisplayInUI(fieldValue, unit, unitPreference, language);
284
285
  return value;
285
286
  }
286
287
  else {
287
288
  return "";
288
289
  }
289
290
  });
290
- if ((field === null || field === void 0 ? void 0 : field.definition) === undefined || ((_a = field === null || field === void 0 ? void 0 : field.definition) === null || _a === void 0 ? void 0 : _a.type) === undefined) {
291
+ if ((field === null || field === void 0 ? void 0 : field.definition) === undefined) {
291
292
  return null;
292
293
  }
293
- const key = (_b = fieldId !== null && fieldId !== void 0 ? fieldId : field.definition.key) !== null && _b !== void 0 ? _b : "";
294
+ const key = (_a = fieldId !== null && fieldId !== void 0 ? fieldId : field.definition.key) !== null && _a !== void 0 ? _a : "";
295
+ const uniqueIdentifier = fieldId !== null && fieldId !== void 0 ? fieldId : field.definition.definitionId;
294
296
  const fieldError = key ? validation.formState.errors[key] : undefined;
295
297
  const errorMessage = fieldError ? fieldError.message + "" : undefined;
296
- const { type, description, title } = field.definition;
297
- switch (type) {
298
- case CustomFieldType.WEB_ADDRESS: {
299
- const typedDefinition = field.definition;
300
- const typedValue = field.value;
301
- const rules = getWebAddressValidationRules(typedDefinition);
302
- return (jsx(TextField, Object.assign({ id: key, label: title, placeholder: (_c = typedDefinition.title) !== null && _c !== void 0 ? _c : "", defaultValue: (_d = typedValue.stringValue) !== null && _d !== void 0 ? _d : "", dataTestId: `${typedDefinition.key}`, actions: !typedDefinition.uiEditable &&
303
- typedValue.stringValue && jsx(ActionButton, { value: typedValue.stringValue, type: "WEB_ADDRESS" }), readOnly: !typedDefinition.uiEditable, helpText: description, errorMessage: errorMessage }, validation.register(key, rules))));
298
+ const { description, title } = field.definition;
299
+ const isEditableCombined = isEditable !== null && isEditable !== void 0 ? isEditable : field.definition.uiEditable;
300
+ switch (field.__typename) {
301
+ case "WebAddressFieldValueAndDefinition": {
302
+ const value = field.stringValue;
303
+ const rules = getWebAddressValidationRules(field.definition);
304
+ return (jsx(TextField, Object.assign({ id: uniqueIdentifier, label: title, placeholder: title !== null && title !== void 0 ? title : "", defaultValue: value !== null && value !== void 0 ? value : "", dataTestId: `${field.definition.key}`, actions: !isEditableCombined && value && jsx(ActionButton, { value: value, type: "WEB_ADDRESS" }), readOnly: !isEditableCombined, helpText: description, errorMessage: errorMessage }, validation.register(key, rules))));
304
305
  }
305
- case CustomFieldType.EMAIL: {
306
- const typedDefinition = field.definition;
307
- const typedValue = field.value;
308
- const rules = getEmailValidationRules(typedDefinition);
309
- return (jsx(TextField, Object.assign({ id: key, label: title, placeholder: (_e = typedDefinition.title) !== null && _e !== void 0 ? _e : "", defaultValue: (_f = typedValue.stringValue) !== null && _f !== void 0 ? _f : "", dataTestId: `${typedDefinition.key}`, actions: !typedDefinition.uiEditable &&
310
- typedValue.stringValue && jsx(ActionButton, { value: typedValue.stringValue, type: "EMAIL" }), readOnly: !typedDefinition.uiEditable, helpText: description, errorMessage: errorMessage }, validation.register(key, rules))));
306
+ case "EmailFieldValueAndDefinition": {
307
+ const value = field.stringValue;
308
+ const rules = getEmailValidationRules(field.definition);
309
+ return (jsx(TextField, Object.assign({ id: uniqueIdentifier, label: title, placeholder: title !== null && title !== void 0 ? title : "", defaultValue: value !== null && value !== void 0 ? value : "", dataTestId: `${field.definition.key}`, actions: !isEditableCombined && value && jsx(ActionButton, { value: value, type: "EMAIL" }), readOnly: !isEditableCombined, helpText: description, errorMessage: errorMessage }, validation.register(key, rules))));
311
310
  }
312
- case CustomFieldType.PHONE_NUMBER: {
313
- const typedDefinition = field.definition;
314
- const typedValue = field.value;
315
- const rules = getPhoneNumberValidationRules(typedDefinition);
316
- return (jsx(TextField, Object.assign({ label: title, id: key, placeholder: (_g = typedDefinition.title) !== null && _g !== void 0 ? _g : "", defaultValue: (_h = typedValue.stringValue) !== null && _h !== void 0 ? _h : "", dataTestId: `${typedDefinition.key}`, actions: !typedDefinition.uiEditable &&
317
- typedValue.stringValue && jsx(ActionButton, { value: typedValue.stringValue, type: "PHONE_NUMBER" }), readOnly: !typedDefinition.uiEditable, helpText: description, errorMessage: errorMessage === "" ? "Must be a phone number" : undefined }, validation.register(key, rules))));
311
+ case "PhoneNumberFieldValueAndDefinition": {
312
+ const value = field.stringValue;
313
+ const rules = getPhoneNumberValidationRules(field.definition);
314
+ return (jsx(TextField, Object.assign({ label: title, id: uniqueIdentifier, placeholder: title !== null && title !== void 0 ? title : "", defaultValue: value !== null && value !== void 0 ? value : "", dataTestId: `${field.definition.key}`, actions: !isEditableCombined && value && jsx(ActionButton, { value: value, type: "PHONE_NUMBER" }), readOnly: !isEditableCombined, helpText: description, errorMessage: errorMessage === "" ? "Must be a phone number" : undefined }, validation.register(key, rules))));
318
315
  }
319
- case CustomFieldType.STRING: {
320
- const typedDefinition = field.definition;
321
- const typedValue = field.value;
322
- const rules = getStringValidationRules(typedDefinition);
323
- return (jsx(TextField, Object.assign({ label: title, id: key || "string-field", placeholder: (_j = typedDefinition.title) !== null && _j !== void 0 ? _j : "", defaultValue: (_k = typedValue.stringValue) !== null && _k !== void 0 ? _k : "", readOnly: !typedDefinition.uiEditable, helpText: description, errorMessage: errorMessage, dataTestId: `${typedDefinition.key}` }, validation.register(key, rules))));
316
+ case "StringFieldValueAndDefinition": {
317
+ const value = field.stringValue;
318
+ const rules = getStringValidationRules(field.definition);
319
+ return (jsx(TextField, Object.assign({ label: title, id: uniqueIdentifier, placeholder: title !== null && title !== void 0 ? title : "", defaultValue: value !== null && value !== void 0 ? value : "", readOnly: !isEditableCombined, helpText: description, errorMessage: errorMessage, dataTestId: `${field.definition.key}` }, validation.register(key, rules))));
324
320
  }
325
- case CustomFieldType.NUMBER: {
326
- const typedDefinition = field.definition;
327
- const typedValue = field.value;
328
- const rules = getNumberValidationRules(typedDefinition);
329
- const unit = unitPreference === "US_CUSTOMARY" && typedDefinition.unitUs
330
- ? `${typedDefinition.unitUs}`
331
- : typedDefinition.unitSi
332
- ? `${typedDefinition.unitSi}`
321
+ case "NumberFieldValueAndDefinition": {
322
+ const value = field.numberValue;
323
+ const rules = getNumberValidationRules(field.definition);
324
+ const unit = unitPreference === "US_CUSTOMARY" && field.definition.unitUs
325
+ ? `${field.definition.unitUs}`
326
+ : field.definition.unitSi
327
+ ? `${field.definition.unitSi}`
333
328
  : null;
334
329
  const numberProps = {
335
- placeholder: (_l = typedDefinition.title) !== null && _l !== void 0 ? _l : "",
330
+ placeholder: title !== null && title !== void 0 ? title : "",
336
331
  addonAfter: unit,
337
332
  };
338
- return (jsx(NumberField, Object.assign({ label: title, id: key || "number-field", defaultValue: (_m = typedValue.numberValue) !== null && _m !== void 0 ? _m : "", step: typedDefinition.isInteger ? 1 : "any", min: (_o = typedDefinition.minimumNumber) !== null && _o !== void 0 ? _o : undefined, max: (_p = typedDefinition.maximumNumber) !== null && _p !== void 0 ? _p : undefined, readOnly: !typedDefinition.uiEditable, helpText: description, errorMessage: errorMessage, dataTestId: `${typedDefinition.key}` }, validation.register(key, rules), numberProps)));
333
+ return (jsx(NumberField, Object.assign({ label: title, id: uniqueIdentifier, defaultValue: value !== null && value !== void 0 ? value : "", step: field.definition.isInteger ? 1 : "any", min: (_b = field.definition.minimumNumber) !== null && _b !== void 0 ? _b : undefined, max: (_c = field.definition.maximumNumber) !== null && _c !== void 0 ? _c : undefined, readOnly: !isEditableCombined, helpText: description, errorMessage: errorMessage, dataTestId: `${field.definition.key}` }, validation.register(key, rules), numberProps)));
339
334
  }
340
- case CustomFieldType.BOOLEAN: {
341
- const typedDefinition = field.definition;
342
- const typedValue = field.value;
343
- const rules = getBooleanValidationRules();
344
- return (jsx(BooleanCustomField, { label: (_q = typedDefinition.title) !== null && _q !== void 0 ? _q : "", id: key || "boolean-field", defaultValue: (_r = typedValue.booleanValue) !== null && _r !== void 0 ? _r : undefined, readOnly: !typedDefinition.uiEditable, register: validation.register, validationRules: rules, helpText: description, setValue: validation.setValue, errorMessage: errorMessage, dataTestId: `${typedDefinition.key}` }, key));
335
+ case "BooleanFieldValueAndDefinition": {
336
+ const value = field.booleanValue;
337
+ const rules = getBooleanValidationRules(field.definition);
338
+ return (jsx(BooleanCustomField, { label: title !== null && title !== void 0 ? title : "", id: uniqueIdentifier, defaultValue: value !== null && value !== void 0 ? value : undefined, readOnly: !isEditableCombined, register: validation.register, validationRules: rules, helpText: description, setValue: validation.setValue, errorMessage: errorMessage, dataTestId: `${field.definition.key}` }));
345
339
  }
346
- case CustomFieldType.DROPDOWN: {
347
- const typedDefinition = field.definition;
348
- const typedValue = field.value;
349
- const rules = getDropdownValidationRules();
350
- return (jsx(DropdownCustomField, { label: typedDefinition.title || "", id: key || "dropdown-field", defaultValue: (_s = typedValue.stringArrayValue) !== null && _s !== void 0 ? _s : undefined, disabled: !typedDefinition.uiEditable, allValues: (_t = typedDefinition.allValues) !== null && _t !== void 0 ? _t : undefined, multiSelect: (_u = typedDefinition.multiSelect) !== null && _u !== void 0 ? _u : false, register: validation.register, validationRules: rules, helpText: description, setValue: validation.setValue, errorMessage: errorMessage, dataTestId: `${typedDefinition.key}` }, key));
340
+ case "DropDownFieldValueAndDefinition": {
341
+ const value = field.stringArrayValue;
342
+ const rules = getDropdownValidationRules(field.definition);
343
+ return (jsx(DropdownCustomField, { label: title || "", id: uniqueIdentifier, defaultValue: value !== null && value !== void 0 ? value : undefined, disabled: !isEditableCombined, allValues: (_d = field.definition.allValues) !== null && _d !== void 0 ? _d : undefined, multiSelect: (_e = field.definition.multiSelect) !== null && _e !== void 0 ? _e : false, register: validation.register, validationRules: rules, helpText: description, setValue: validation.setValue, errorMessage: errorMessage, dataTestId: `${field.definition.key}` }));
351
344
  }
352
- case CustomFieldType.DATE: {
353
- const typedDefinition = field.definition;
354
- const typedValue = field.value;
355
- const rules = getDateValidationRules();
345
+ case "DateFieldValueAndDefinition": {
346
+ const value = field.dateValue;
347
+ const rules = getDateValidationRules(field.definition);
356
348
  let defaultValue;
357
- if (typedValue.dateValue !== undefined && typedValue.dateValue !== null) {
358
- defaultValue = new Date(typedValue.dateValue);
349
+ if (value !== undefined && value !== null) {
350
+ defaultValue = new Date(value);
359
351
  }
360
- return (jsx(DateCustomField, { dataTestId: `${typedDefinition.key}`, id: key || "date-field", defaultValue: defaultValue, readOnly: !typedDefinition.uiEditable, register: validation.register, label: typedDefinition.title || "", validationRules: rules, helpText: description, errorMessage: errorMessage, setValue: validation.setValue, title: field.definition.title || "" }, key));
352
+ return (jsx(DateCustomField, { dataTestId: `${field.definition.key}`, id: uniqueIdentifier, defaultValue: defaultValue, readOnly: !isEditableCombined, register: validation.register, label: title || "", validationRules: rules, helpText: description, errorMessage: errorMessage, setValue: validation.setValue, title: title || "" }));
361
353
  }
362
- case CustomFieldType.JSON: {
363
- return jsx("div", {});
354
+ case "JsonFieldValueAndDefinition": {
355
+ return null;
364
356
  }
365
- case CustomFieldType.MONETARY: {
357
+ case "MonetaryFieldValueAndDefinition": {
366
358
  const rules = getNumberValidationRules(field.definition);
367
359
  const numberProps = {
368
- placeholder: (_v = field.definition.title) !== null && _v !== void 0 ? _v : "",
360
+ placeholder: title !== null && title !== void 0 ? title : "",
369
361
  addonAfter: field.definition.currency,
370
362
  };
371
363
  const value = numberValue === undefined || numberValue === null || numberValue === ""
372
364
  ? ""
373
365
  : parseFloat(Number(numberValue).toPrecision(4));
374
- return (jsx(FormGroup, { htmlFor: key || "number-field", label: title, isInvalid: errorMessage ? true : false, helpText: errorMessage || description, dataTestId: `${field.definition.key}-FormGroup`, disabled: !field.definition.uiEditable, children: jsx(NumberInput, Object.assign({ id: key || "number-field", dataTestId: field.definition.key ? field.definition.key : `monetaryField`, defaultValue: value, readOnly: !field.definition.uiEditable, step: "any", min: (_w = field.definition.minimumNumber) !== null && _w !== void 0 ? _w : undefined, max: (_x = field.definition.maximumNumber) !== null && _x !== void 0 ? _x : undefined }, validation.register(key, rules), { onChange: e => {
375
- setNumberValue(e.target.value === "" ? null : e.target.value);
376
- validation.register(key, rules).onChange(e);
377
- } }, numberProps)) }));
366
+ return (jsx(NumberField, Object.assign({ label: title, isInvalid: errorMessage ? true : false, helpText: errorMessage || description, disabled: !isEditableCombined, id: uniqueIdentifier, dataTestId: field.definition.key ? field.definition.key : `monetaryField`, defaultValue: value, readOnly: !isEditableCombined, step: "any", min: (_f = field.definition.minimumNumber) !== null && _f !== void 0 ? _f : undefined, max: (_g = field.definition.maximumNumber) !== null && _g !== void 0 ? _g : undefined }, validation.register(key, rules), { onChange: e => {
367
+ setNumberValue(e.target.value === "" ? null : e.target.value);
368
+ validation.register(key, rules).onChange(e);
369
+ } }, numberProps)));
378
370
  }
379
371
  default:
380
- throw new Error(`Type not supported: ${type}`);
372
+ return exhaustiveCheck(field);
381
373
  }
382
374
  };
383
375
  /**
376
+ * CustomField is a React component that takes in the properties of a custom field and renders it.
377
+ * It utilizes the `useCustomFieldResolver` hook to resolve the field into an input element
378
+ * based on the field's type and definition.
384
379
  *
380
+ * @param {CustomFieldProps} props - Props for defining the custom field, including its type, value,
381
+ * validation rules, and form registration functions from react-hook-form.
382
+ * @returns {JSX.Element | null} - The resolved custom field component or null if the field cannot be resolved.
385
383
  */
386
- const CustomField = ({ field, register, formState, setValue, unitPreference, fieldId, language, }) => {
387
- const fieldComponent = useCustomFieldResolver(field, { register, setValue, formState }, unitPreference, language, fieldId);
384
+ const CustomField = (props) => {
385
+ const fieldComponent = useCustomFieldResolver(props);
388
386
  return fieldComponent;
389
387
  };
390
388
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/custom-field-components",
3
- "version": "0.0.541",
3
+ "version": "0.0.545",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -10,11 +10,13 @@
10
10
  "@trackunit/react-form-components": "*",
11
11
  "react": "^18.2.0",
12
12
  "react-hook-form": "7.40.0",
13
- "uuid": "^8.3.2",
13
+ "@trackunit/custom-field-api": "*",
14
+ "@trackunit/shared-utils": "*",
15
+ "uuid": "^9.0.1",
14
16
  "@trackunit/iris-app-runtime-core": "*",
15
17
  "@trackunit/iris-app-runtime-core-api": "*",
16
- "react-select": "^5.7.7",
17
- "libphonenumber-js": "^1.10.36",
18
+ "react-select": "^5.8.0",
19
+ "libphonenumber-js": "1.10.36",
18
20
  "@testing-library/react": "14.0.0",
19
21
  "jest-fetch-mock": "^3.0.3"
20
22
  },
@@ -1,36 +1,63 @@
1
1
  /// <reference types="react" />
2
- import { ValueAndDefinition } from "@trackunit/iris-app-runtime-core-api";
2
+ import { CustomFieldValueAndDefinition } from "@trackunit/custom-field-api";
3
3
  import { FieldValues, FormState, UseFormRegister, UseFormSetValue } from "react-hook-form";
4
4
  import { UnitPreference } from "./UnitPreference";
5
- interface ICustomFieldProps {
6
- field: ValueAndDefinition;
5
+ /**
6
+ * CustomFieldProps interface defines the structure for the properties
7
+ * accepted by the CustomField component and useCustomFieldResolver hook.
8
+ */
9
+ interface CustomFieldProps {
10
+ /**
11
+ * The value and definition of the custom field to be rendered.
12
+ */
13
+ field: CustomFieldValueAndDefinition;
14
+ /**
15
+ * A function from react-hook-form to register input for validation.
16
+ */
7
17
  register: UseFormRegister<FieldValues>;
18
+ /**
19
+ * The current state of the form from react-hook-form, including any validation errors.
20
+ */
8
21
  formState: FormState<FieldValues>;
22
+ /**
23
+ * A function from react-hook-form to update the value of a registered field.
24
+ */
9
25
  setValue: UseFormSetValue<FieldValues>;
26
+ /**
27
+ * (Optional) Specifies the unit system to be used (e.g., 'SI' or 'US_CUSTOMARY').
28
+ */
10
29
  unitPreference?: UnitPreference;
30
+ /**
31
+ * (Optional) The language code to use for displaying field values and validation messages.
32
+ */
11
33
  language?: string;
12
34
  /**
13
- * An optional Id to override the definition.key
35
+ * (Optional) Indicates if the field is editable or should be displayed in read-only mode.
36
+ */
37
+ isEditable?: boolean;
38
+ /**
39
+ * (Optional) An alternative identifier for the field, which overrides the default definition.key.
14
40
  */
15
41
  fieldId?: string;
16
42
  }
17
- export interface ICustomFieldValidation {
18
- register: UseFormRegister<FieldValues>;
19
- setValue: UseFormSetValue<FieldValues>;
20
- formState: FormState<FieldValues>;
21
- }
22
43
  /**
23
- * A component that renders a custom field based on the field definition
44
+ * A hook that resolves and returns a JSX Element for a given custom field.
45
+ * It handles various custom field types by providing appropriate validation rules
46
+ * and input components with the necessary props.
24
47
  *
25
- * @param field A field definition and value
26
- * @param validation A validation object that contains the register, setValue and formState
27
- * @param unitPreference A unit preference that can be used to override the default unit preference
28
- * @param fieldId An optional Id to override the definition.key
29
- * @returns { JSX.Element } A JSX.Element or null if the field definition is undefined
48
+ * @param {CustomFieldProps} props - The properties of the custom field, including its definition, value,
49
+ * and functions for form registration and state management.
50
+ * @returns {JSX.Element | null} - The JSX Element for the custom field or null if the field definition is not provided.
30
51
  */
31
- export declare const useCustomFieldResolver: (field: ValueAndDefinition, validation: ICustomFieldValidation, unitPreference?: UnitPreference, language?: string, fieldId?: string) => JSX.Element | null;
52
+ export declare const useCustomFieldResolver: ({ field, register, setValue, formState, unitPreference, language, fieldId, isEditable, }: CustomFieldProps) => JSX.Element | null;
32
53
  /**
54
+ * CustomField is a React component that takes in the properties of a custom field and renders it.
55
+ * It utilizes the `useCustomFieldResolver` hook to resolve the field into an input element
56
+ * based on the field's type and definition.
33
57
  *
58
+ * @param {CustomFieldProps} props - Props for defining the custom field, including its type, value,
59
+ * validation rules, and form registration functions from react-hook-form.
60
+ * @returns {JSX.Element | null} - The resolved custom field component or null if the field cannot be resolved.
34
61
  */
35
- export declare const CustomField: ({ field, register, formState, setValue, unitPreference, fieldId, language, }: ICustomFieldProps) => JSX.Element | null;
62
+ export declare const CustomField: (props: CustomFieldProps) => JSX.Element | null;
36
63
  export {};
@@ -1,62 +1,76 @@
1
- import { BooleanFieldDefinition, DateFieldDefinition, DropDownFieldDefinition, EmailFieldDefinition, MonetaryFieldDefinition, NumberFieldDefinition, PhoneNumberFieldDefinition, StringFieldDefinition, WebAddressFieldDefinition } from "@trackunit/iris-app-runtime-core-api";
2
1
  import { RegisterOptions } from "react-hook-form";
3
2
  /**
4
- * Validation rules for a field
3
+ * Represents a collection of validation rules for a form field.
5
4
  */
6
5
  export type ValidationRules = RegisterOptions;
6
+ interface CommonValidationRulesDefinition {
7
+ uiEditable?: boolean | null;
8
+ }
9
+ interface GetWebAddressValidationRulesDefinition extends CommonValidationRulesDefinition {
10
+ }
7
11
  /**
8
- * Get validation rules for a field
12
+ * Generates validation rules for a web address field.
9
13
  *
10
- * @param { WebAddressFieldDefinition } definition the field definition
11
- * @returns { ValidationRules} the validation rules
14
+ * @param {GetWebAddressValidationRulesDefinition} definition - The definition of the web address field.
15
+ * @returns {ValidationRules} The generated validation rules.
12
16
  */
13
- export declare const getWebAddressValidationRules: (definition: WebAddressFieldDefinition) => ValidationRules;
17
+ export declare const getWebAddressValidationRules: (definition: GetWebAddressValidationRulesDefinition) => ValidationRules;
18
+ interface GetNumberValidationRulesDefinition extends CommonValidationRulesDefinition {
19
+ minimumNumber?: number | null;
20
+ maximumNumber?: number | null;
21
+ }
14
22
  /**
15
- * Get validation rules for a field.
23
+ * Generates validation rules for a number field.
16
24
  *
17
- * @param { NumberFieldDefinition } definition the field definition
18
- * @returns { ValidationRules} the validation rules
25
+ * @param {GetNumberValidationRulesDefinition} definition - The definition of the number field.
26
+ * @returns {ValidationRules} The generated validation rules.
19
27
  */
20
- export declare const getNumberValidationRules: (definition: NumberFieldDefinition | MonetaryFieldDefinition) => ValidationRules;
28
+ export declare const getNumberValidationRules: (definition: GetNumberValidationRulesDefinition) => ValidationRules;
29
+ interface GetStringValidationRulesDefinition extends CommonValidationRulesDefinition {
30
+ minimumLength?: number | null;
31
+ maximumLength?: number | null;
32
+ pattern?: string | null;
33
+ }
21
34
  /**
22
- * Get validation rules for a string field.
35
+ * Generates validation rules for a string field.
23
36
  *
24
- * @param { StringFieldDefinition } definition the field definition
25
- * @returns { ValidationRules} the validation rules
37
+ * @param {GetStringValidationRulesDefinition} definition - The definition of the string field.
38
+ * @returns {ValidationRules} The generated validation rules.
26
39
  */
27
- export declare const getStringValidationRules: (definition: StringFieldDefinition) => ValidationRules;
40
+ export declare const getStringValidationRules: (definition: GetStringValidationRulesDefinition) => ValidationRules;
28
41
  /**
29
- * Get validation rules for a boolean field.
42
+ * Generates validation rules for a boolean field.
30
43
  *
31
- * @param { BooleanFieldDefinition } definition the field definition
32
- * @returns { ValidationRules} the validation rules
44
+ * @param {CommonValidationRulesDefinition} definition - The definition of the boolean field.
45
+ * @returns {ValidationRules} The generated validation rules.
33
46
  */
34
- export declare const getBooleanValidationRules: (definition: BooleanFieldDefinition) => ValidationRules;
47
+ export declare const getBooleanValidationRules: (definition: CommonValidationRulesDefinition) => ValidationRules;
35
48
  /**
36
- * Get validation rules for a dropdown field.
49
+ * Generates validation rules for a dropdown field.
37
50
  *
38
- * @param { DropDownFieldDefinition } definition the field definition
39
- * @returns { ValidationRules} the validation rules
51
+ * @param {CommonValidationRulesDefinition} definition - The definition of the dropdown field.
52
+ * @returns {ValidationRules} The generated validation rules.
40
53
  */
41
- export declare const getDropdownValidationRules: (definition: DropDownFieldDefinition) => ValidationRules;
54
+ export declare const getDropdownValidationRules: (definition: CommonValidationRulesDefinition) => ValidationRules;
42
55
  /**
43
- * Get validation rules for a date field.
56
+ * Generates validation rules for a date field.
44
57
  *
45
- * @param { DateFieldDefinition } definition the field definition
46
- * @returns { ValidationRules} the validation rules
58
+ * @param {CommonValidationRulesDefinition} definition - The definition of the date field.
59
+ * @returns {ValidationRules} The generated validation rules.
47
60
  */
48
- export declare const getDateValidationRules: (definition: DateFieldDefinition) => ValidationRules;
61
+ export declare const getDateValidationRules: (definition: CommonValidationRulesDefinition) => ValidationRules;
49
62
  /**
50
- * Get validation rules for an email field.
63
+ * Generates validation rules for an email field.
51
64
  *
52
- * @param { EmailFieldDefinition } definition the field definition
53
- * @returns { ValidationRules} the validation rules
65
+ * @param {CommonValidationRulesDefinition} definition - The definition of the email field.
66
+ * @returns {ValidationRules} The generated validation rules.
54
67
  */
55
- export declare const getEmailValidationRules: (definition: EmailFieldDefinition) => ValidationRules;
68
+ export declare const getEmailValidationRules: (definition: CommonValidationRulesDefinition) => ValidationRules;
56
69
  /**
57
- * Get validation rules for a phonenumber field.
70
+ * Generates validation rules for a phone number field.
58
71
  *
59
- * @param { PhoneNumberFieldDefinition } definition the field definition
60
- * @returns { ValidationRules} the validation rules
72
+ * @param {CommonValidationRulesDefinition} definition - The definition of the phone number field.
73
+ * @returns {ValidationRules} The generated validation rules.
61
74
  */
62
- export declare const getPhoneNumberValidationRules: (definition: PhoneNumberFieldDefinition) => ValidationRules;
75
+ export declare const getPhoneNumberValidationRules: (definition: CommonValidationRulesDefinition) => ValidationRules;
76
+ export {};