@nwon/react-mui-hook-form 3.0.4 → 3.1.0

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.
Files changed (47) hide show
  1. package/package.json +50 -16
  2. package/dist/LoadingButton/LoadingButton.d.ts +0 -6
  3. package/dist/LoadingButton/LoadingButtonInterfaces.d.ts +0 -33
  4. package/dist/LoadingButton/getLoadingButtonState.d.ts +0 -20
  5. package/dist/LoadingButton/index.d.ts +0 -4
  6. package/dist/formFields/HookFormProvider.d.ts +0 -7
  7. package/dist/formFields/InputEmail/InputEmail.d.ts +0 -10
  8. package/dist/formFields/InputPasswordSet/InputPasswordSet.d.ts +0 -8
  9. package/dist/formFields/InputPasswordSet/InputPasswordSetInterfaces.d.ts +0 -18
  10. package/dist/formFields/TranslatedString.d.ts +0 -13
  11. package/dist/formFields/baseTypes/BaseInputProps.d.ts +0 -33
  12. package/dist/formFields/baseTypes/InputAutocomplete/InputAutocomplete.d.ts +0 -9
  13. package/dist/formFields/baseTypes/InputAutocomplete/InputAutocompleteInterfaces.d.ts +0 -24
  14. package/dist/formFields/baseTypes/InputAutocomplete/useSortedOptionsWithGroup.d.ts +0 -9
  15. package/dist/formFields/baseTypes/InputCheckbox/InputCheckbox.d.ts +0 -18
  16. package/dist/formFields/baseTypes/InputDatePicker/InputDatePicker.d.ts +0 -16
  17. package/dist/formFields/baseTypes/InputDateTimePicker/InputDateTimePicker.d.ts +0 -16
  18. package/dist/formFields/baseTypes/InputNumber/InputNumber.d.ts +0 -15
  19. package/dist/formFields/baseTypes/InputOutlinedInput/InputOutlinedInput.d.ts +0 -13
  20. package/dist/formFields/baseTypes/InputRadio/InputRadio.d.ts +0 -13
  21. package/dist/formFields/baseTypes/InputSelect/InputSelect.d.ts +0 -26
  22. package/dist/formFields/baseTypes/InputSelectFromEnum/InputSelectFromEnum.d.ts +0 -7
  23. package/dist/formFields/baseTypes/InputSelectFromEnum/InputSelectFromEnumInterfaces.d.ts +0 -10
  24. package/dist/formFields/baseTypes/InputSlider/InputSlider.d.ts +0 -13
  25. package/dist/formFields/baseTypes/InputSwitch/InputSwitch.d.ts +0 -11
  26. package/dist/formFields/baseTypes/InputTextField/InputTextField.d.ts +0 -13
  27. package/dist/formFields/baseTypes/InputTimePicker/InputTimePicker.d.ts +0 -16
  28. package/dist/formFields/baseTypes/InputToggleButton/InputToggleButton.d.ts +0 -12
  29. package/dist/formFields/baseTypes/InputToggleButtonGroup/InputToggleButtonGroup.d.ts +0 -34
  30. package/dist/formFields/baseTypes/useEffectFieldUnregisterOnUnmount.d.ts +0 -12
  31. package/dist/formFields/errorMessages.d.ts +0 -1
  32. package/dist/formFields/errors/FormFieldError.d.ts +0 -11
  33. package/dist/formFields/errors/FormFieldErrorDisplay.d.ts +0 -11
  34. package/dist/formFields/errors/getFormErrorForNestedKeys.d.ts +0 -14
  35. package/dist/formFields/errors/useFormFieldError.d.ts +0 -7
  36. package/dist/formFields/errors/useFormFieldHasError.d.ts +0 -6
  37. package/dist/formFields/formHelper/syncSubmit.d.ts +0 -15
  38. package/dist/formFields/formHelper/useHookForm.d.ts +0 -56
  39. package/dist/formFields/formHelper/useHookFormContext.d.ts +0 -9
  40. package/dist/formFields/formHelper/useMergedFormField.d.ts +0 -6
  41. package/dist/formFields/formHelper/useSortedOptionsWithGroup.d.ts +0 -5
  42. package/dist/formFields/formHelper/useTranslateString.d.ts +0 -8
  43. package/dist/formFields/index.d.ts +0 -49
  44. package/dist/formFields/inputTypes.d.ts +0 -76
  45. package/dist/packageExports.d.ts +0 -9
  46. package/dist/packageExports.js +0 -1761
  47. package/dist/packageExports.js.map +0 -1
@@ -1,1761 +0,0 @@
1
- import { CheckBoxOutlineBlank, CheckBox } from '@mui/icons-material';
2
- import { FormHelperText, Checkbox, FormControl, Autocomplete, TextField, FormControlLabel, Box, InputLabel, OutlinedInput, FormLabel, RadioGroup, Radio, Select, MenuItem, Typography, Stack, Tooltip, ListSubheader, Slider, Switch, ToggleButton, ToggleButtonGroup } from '@mui/material';
3
- import { useFormControl } from '@mui/material/FormControl';
4
- import { filterNoUndefinedNoNull, uppercaseFirstLetter, assertTruthy, objectHasKey, rethrow } from '@nvon/baseline';
5
- import { useCallback, useMemo, useState, useEffect } from 'react';
6
- import { useFormContext, useWatch, Controller, useForm, useFieldArray, FormProvider } from 'react-hook-form';
7
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
- import { identity } from 'lodash-es';
9
- import { t } from 'i18next';
10
- import { DatePicker, DateTimePicker, TimePicker } from '@mui/x-date-pickers';
11
- import dayjs from 'dayjs';
12
- import { NumericFormat } from 'react-number-format';
13
- import { LoadingButton as LoadingButton$1 } from '@mui/lab';
14
-
15
- const formContextNull = "FormContext is null. This should not happen. You may need to use the HookFormProvider instead of the FormProvider exported by react-hook-form";
16
-
17
- const FormFieldErrorDisplay = ({
18
- error,
19
- formHelperTextProps
20
- }) => {
21
- if (Array.isArray(error)) {
22
- return /*#__PURE__*/jsx(FormHelperText, {
23
- ...formHelperTextProps,
24
- error: true,
25
- children: error.map(e => e.message).filter(filterNoUndefinedNoNull).join(", ")
26
- });
27
- }
28
- if (error?.message) {
29
- return /*#__PURE__*/jsx(FormHelperText, {
30
- ...formHelperTextProps,
31
- error: true,
32
- children: error?.message
33
- });
34
- }
35
- return null;
36
- };
37
-
38
- /**
39
- * Wrapper around react-hook-form's useFormContext.
40
- *
41
- * Should behave like the original function, only exposing a "fieldName"
42
- * function on top which is used to validate field names.
43
- */
44
- const useHookFormContext = () => {
45
- const form = useFormContext();
46
- return {
47
- ...form,
48
- fieldName: identity
49
- };
50
- };
51
-
52
- /**
53
- * Get the field errors for a (possibly nested) field name.
54
- *
55
- * Checking `formState.errors[fieldName]` only works if fieldName is not a path
56
- * (e.g. Does not include dots).
57
- *
58
- * Did not find a built-in way to do this … there might be one though.
59
- *
60
- * Supports both dot notation (e.g., "response.receipts.0.field") and
61
- * bracket notation (e.g., "response.receipts[0].field") for array fields.
62
- */
63
- const getFormErrorForNestedKeys = (errors, fieldName) => {
64
- // Parse the field name to handle both dot notation and bracket notation
65
- // e.g., "response.receipts.0.field" or "response.receipts[0].field"
66
- const keys = [];
67
- let currentKey = "";
68
- let i = 0;
69
- while (i < fieldName.length) {
70
- const char = fieldName[i];
71
- if (char === "[") {
72
- // Save the current key if any
73
- if (currentKey) {
74
- keys.push(currentKey);
75
- currentKey = "";
76
- }
77
- // Find the closing bracket
78
- i++; // Skip the opening bracket
79
- let bracketContent = "";
80
- while (i < fieldName.length && fieldName[i] !== "]") {
81
- bracketContent += fieldName[i];
82
- i++;
83
- }
84
- // Parse the bracket content as a number if possible, otherwise as string
85
- const numIndex = Number(bracketContent);
86
- keys.push(isNaN(numIndex) ? bracketContent : numIndex);
87
- i++; // Skip the closing bracket
88
- } else if (char === ".") {
89
- // Save the current key if any
90
- if (currentKey) {
91
- keys.push(currentKey);
92
- currentKey = "";
93
- }
94
- i++; // Skip the dot
95
- } else {
96
- currentKey += char;
97
- i++;
98
- }
99
- }
100
- // Don't forget the last key
101
- if (currentKey) {
102
- keys.push(currentKey);
103
- }
104
- //
105
- // To my best knowledge, this works as expected.
106
- //
107
- // It recursively walks the error object by the given keys
108
- // until the lowest level is reached, or undefined returned.
109
- //
110
- // Handles both object properties and array indices.
111
- //
112
- // Typescript is just not very happy with the dynamic nature of this,
113
- // hence the errors.
114
- //
115
- /* eslint-disable @typescript-eslint/ban-ts-comment,@typescript-eslint/no-unsafe-return */
116
- // @ts-expect-error
117
- return keys.reduce((errorObj, pathKey) => {
118
- if (errorObj === undefined || errorObj === null) {
119
- return undefined;
120
- }
121
- // Handle array access
122
- if (typeof pathKey === "number") {
123
- return Array.isArray(errorObj) ? errorObj[pathKey] :
124
- // @ts-expect-error
125
- errorObj?.[pathKey];
126
- }
127
- // Handle object property access
128
- // @ts-expect-error
129
- return errorObj?.[pathKey];
130
- }, errors);
131
- /* eslint-enable */
132
- };
133
-
134
- /**
135
- * Returns the error for a given field name.
136
- *
137
- * @throws Error when FormContext is null.
138
- */
139
- const useFormFieldError = fieldName => {
140
- const form = useHookFormContext();
141
- if (!form) {
142
- throw Error(formContextNull);
143
- }
144
- const {
145
- formState
146
- } = form;
147
- const errors = getFormErrorForNestedKeys(formState.errors, fieldName);
148
- return errors;
149
- };
150
-
151
- const FormFieldError = ({
152
- fieldName,
153
- formHelperTextProps
154
- }) => {
155
- const error = useFormFieldError(fieldName);
156
- return /*#__PURE__*/jsx(FormFieldErrorDisplay, {
157
- error: error,
158
- formHelperTextProps: formHelperTextProps
159
- });
160
- };
161
-
162
- /**
163
- * Returns whether or not a field has an error.
164
- *
165
- * @throws Error when FormContext is null.
166
- */
167
- const useFormFieldHasError = fieldName => !!useFormFieldError(fieldName);
168
-
169
- /**
170
- * Return a function which turns our TranslatedString into a plain string.
171
- *
172
- * @throws Error if no t was provided but a translated string.
173
- */
174
- const useTranslateString = () => {
175
- if (!t) {
176
- throw Error("If you pass in a translated validate function you need to provide a t");
177
- }
178
- return useCallback(input => {
179
- return typeof input === "string" ? input : input(t);
180
- }, []);
181
- };
182
-
183
- /**
184
- * Merge a form field with defaults.
185
- */
186
- const useMergedFormField = (
187
- /**
188
- * Form fields, typically those passed into a component.
189
- *
190
- */
191
- formField, t,
192
- /**
193
- * Additional defaults. Duplicate values will be overridden by the formField.
194
- */
195
- formFieldDefaults) => {
196
- const translate = useTranslateString();
197
- const merged = useMemo(() => {
198
- const builtInDefaults = {
199
- label: uppercaseFirstLetter(formField.name),
200
- required: false,
201
- requiredErrorMessage: "Please fill in required information",
202
- validate: undefined
203
- };
204
- return {
205
- ...builtInDefaults,
206
- ...formFieldDefaults,
207
- ...formField
208
- };
209
- }, [formField, formFieldDefaults]);
210
- const withPlainStrings = useMemo(() => {
211
- // Translating the validate function is a bit tricky,
212
- // since it can be an object in both cases.
213
- const validate = (() => {
214
- if (typeof merged.validate === "object" && typeof merged.validate.translated === "function") {
215
- if (!t) {
216
- throw Error("If you pass in a translated validate function you need to provide a t");
217
- }
218
- return merged.validate.translated(t);
219
- }
220
- return merged.validate;
221
- })(); // This should be fine. Not sure why TS is complaining.
222
- return {
223
- ...merged,
224
- label: translate(merged.label, t),
225
- requiredErrorMessage: translate(merged.requiredErrorMessage, t),
226
- validate
227
- };
228
- }, [merged, t, translate]);
229
- return withPlainStrings;
230
- };
231
-
232
- /**
233
- * An effect that unregisters a field from the form when the component unmounts.
234
- *
235
- * @throws Error when FormContext is null.
236
- */
237
- const useEffectFieldUnregisterOnUnmount = ({
238
- name,
239
- unregisterOptions,
240
- isUnregisteringOnUnmount
241
- }) => {
242
- const form = useHookFormContext();
243
- /**
244
- * Default options for unregistering the field.
245
- *
246
- * Needed to wrap this in a state in order to prevent infinite rerenders.
247
- */
248
- const [options] = useState(unregisterOptions);
249
- if (!form) {
250
- throw Error(formContextNull);
251
- }
252
- const {
253
- unregister
254
- } = form;
255
- useEffect(() => {
256
- return () => {
257
- if (isUnregisteringOnUnmount) {
258
- unregister(name, options);
259
- }
260
- };
261
- }, [isUnregisteringOnUnmount, name, unregister, options]);
262
- };
263
-
264
- var GroupLabelSorting;
265
- (function (GroupLabelSorting) {
266
- GroupLabelSorting["Alphabetical"] = "alphabetical";
267
- GroupLabelSorting["GroupMemberCountAsc"] = "groupMemberCountAsc";
268
- })(GroupLabelSorting || (GroupLabelSorting = {}));
269
- /**
270
- * Sorts option in the desired order.
271
- */
272
- const useSortedOptionsWithGroup$1 = (selectableOptions, sorting = GroupLabelSorting.Alphabetical) => {
273
- return useMemo(() => {
274
- if (sorting === GroupLabelSorting.GroupMemberCountAsc) {
275
- const groupCounts = selectableOptions.reduce((acc, option) => {
276
- if (option.group) {
277
- acc[option.group] = (acc[option.group] || 0) + 1;
278
- }
279
- return acc;
280
- }, {});
281
- return selectableOptions.sort((a, b) => {
282
- if (a.group == undefined && !!b.group) {
283
- return -1;
284
- }
285
- if (a.group && b.group) {
286
- const groupA = groupCounts[a.group];
287
- const groupB = groupCounts[b.group];
288
- if (groupA && groupB && groupA < groupB) {
289
- return -1;
290
- } else if (groupCounts[a.group] === groupCounts[b.group]) {
291
- if (b.label > a.label) {
292
- return -1;
293
- }
294
- return 1;
295
- }
296
- return 1;
297
- }
298
- if (b.label > a.label) {
299
- return -1;
300
- }
301
- return 1;
302
- });
303
- }
304
- return selectableOptions.sort((a, b) => {
305
- if (a.group == undefined && !!b.group) {
306
- return -1;
307
- }
308
- if (a.group && b.group && a.group < b.group) {
309
- return -1;
310
- }
311
- if (a.group == b.group && b.label > a.label) {
312
- return 1;
313
- }
314
- return 0;
315
- });
316
- }, [selectableOptions, sorting]);
317
- };
318
-
319
- const icon = /*#__PURE__*/jsx(CheckBoxOutlineBlank, {
320
- fontSize: "small"
321
- });
322
- const checkedIcon = /*#__PURE__*/jsx(CheckBox, {
323
- fontSize: "small"
324
- });
325
- const defaultNonMultiselectValue = "";
326
- /**
327
- * Renders a MUI autocomplete input that is embedded in a react hook form context.
328
- *
329
- * @throws Error when FormContext is null.
330
- */
331
- const InputAutocomplete = ({
332
- formField,
333
- selectableOptions,
334
- noOptions,
335
- autoCompleteProps,
336
- checkboxesForMultiselect: renderCheckboxes,
337
- groupSorting,
338
- inputTextFieldProps,
339
- unregisterOptions,
340
- isUnregisteringOnUnmount
341
- }) => {
342
- const form = useHookFormContext();
343
- if (!form) {
344
- throw Error(formContextNull);
345
- }
346
- const {
347
- register,
348
- control,
349
- setValue
350
- } = form;
351
- const hasError = useFormFieldHasError(formField.name);
352
- const muiFormControl = useFormControl();
353
- const {
354
- label,
355
- name,
356
- required,
357
- requiredErrorMessage,
358
- validate
359
- } = useMergedFormField(formField, formField.t);
360
- useEffectFieldUnregisterOnUnmount({
361
- name,
362
- unregisterOptions,
363
- isUnregisteringOnUnmount
364
- });
365
- const multiSelect = !!autoCompleteProps?.multiple;
366
- const value = useWatch({
367
- name,
368
- control,
369
- exact: true
370
- });
371
- const {
372
- value: valueToUse,
373
- hasValue
374
- } = useMemo(() => {
375
- if (value) {
376
- return {
377
- value,
378
- hasValue: true
379
- };
380
- }
381
- return {
382
- value: multiSelect ? [] : defaultNonMultiselectValue,
383
- hasValue: false
384
- };
385
- }, [multiSelect, value]);
386
- const adjustedSelectableOptions = useMemo(() => {
387
- if (hasValue || multiSelect) {
388
- return selectableOptions;
389
- }
390
- return [...selectableOptions, {
391
- value: defaultNonMultiselectValue,
392
- label: ""
393
- }];
394
- }, [hasValue, multiSelect, selectableOptions]);
395
- const sortedOptions = useSortedOptionsWithGroup$1(adjustedSelectableOptions, groupSorting);
396
- assertTruthy(["string", "number", "object"].includes(typeof valueToUse), `Value (Field: ${name}, value: ${valueToUse?.toString() || "undefined"}) for select input has unexpected type`);
397
- const isRequired = required || muiFormControl?.required;
398
- const isDisabled = muiFormControl?.disabled || autoCompleteProps?.disabled;
399
- const props = register(name, {
400
- required: isRequired ? requiredErrorMessage : false,
401
- validate,
402
- disabled: isDisabled
403
- });
404
- const currentValue = useMemo(() => {
405
- return multiSelect ? adjustedSelectableOptions.filter(o => {
406
- if (Array.isArray(valueToUse)) {
407
- return valueToUse.includes(o.value);
408
- }
409
- return adjustedSelectableOptions.find(option => option.value === valueToUse);
410
- }) : adjustedSelectableOptions.find(option => option.value === valueToUse);
411
- }, [multiSelect, adjustedSelectableOptions, valueToUse]);
412
- const renderOption = useMemo(() => {
413
- if (autoCompleteProps?.renderOption) {
414
- return autoCompleteProps.renderOption;
415
- }
416
- return multiSelect && renderCheckboxes ? (liProps, option) => {
417
- return /*#__PURE__*/jsxs("li", {
418
- ...liProps,
419
- children: [/*#__PURE__*/jsx(Checkbox, {
420
- icon: icon,
421
- checkedIcon: checkedIcon,
422
- sx: {
423
- mr: 2
424
- },
425
- checked: Array.isArray(currentValue) ? !!currentValue.find(item => item.value === option.value) : false
426
- }), option.label]
427
- });
428
- } : undefined;
429
- }, [autoCompleteProps?.renderOption, currentValue, multiSelect, renderCheckboxes]);
430
- return /*#__PURE__*/jsxs(FormControl, {
431
- error: hasError,
432
- required: isRequired,
433
- disabled: isDisabled,
434
- children: [/*#__PURE__*/jsx(Autocomplete, {
435
- options: sortedOptions,
436
- value: currentValue,
437
- ...props,
438
- required: isRequired,
439
- label: label,
440
- renderOption: renderOption,
441
- multiple: multiSelect,
442
- getOptionLabel: o => {
443
- if (objectHasKey(o, "label")) {
444
- return o.label;
445
- }
446
- return "";
447
- },
448
- onChange: (e, selectedOption) => {
449
- if (Array.isArray(selectedOption)) {
450
- setValue(name, selectedOption.map(o => o.value), {
451
- shouldDirty: true,
452
- shouldValidate: true,
453
- shouldTouch: true
454
- });
455
- } else if (selectedOption) {
456
- setValue(name, selectedOption.value, {
457
- shouldDirty: true,
458
- shouldValidate: true,
459
- shouldTouch: true
460
- });
461
- }
462
- },
463
- noOptionsText: noOptions,
464
- filterOptions: (options, {
465
- inputValue
466
- }) => {
467
- return options.filter(o => {
468
- // Filter out the default empty option
469
- if (o.value === defaultNonMultiselectValue) {
470
- return false;
471
- }
472
- // If no input, show all non-default options
473
- if (!inputValue) {
474
- return true;
475
- }
476
- // Filter based on input text (case-insensitive)
477
- return o.label.toLowerCase().includes(inputValue.toLowerCase());
478
- });
479
- },
480
- renderInput: params => {
481
- return /*#__PURE__*/jsx(TextField, {
482
- ...params,
483
- label: label,
484
- variant: "outlined",
485
- ...inputTextFieldProps,
486
- required: isRequired,
487
- disabled: isDisabled,
488
- error: hasError
489
- });
490
- },
491
- groupBy: option => option.group || "Choose"
492
- // need to parse this as any in order to get no typing errors
493
- // for multiselect
494
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
495
- ,
496
- ...autoCompleteProps
497
- }), /*#__PURE__*/jsx(FormFieldError, {
498
- fieldName: formField.name
499
- })]
500
- });
501
- };
502
-
503
- const InputCheckbox = ({
504
- formField,
505
- jsxLabel,
506
- checkboxProps,
507
- formControlLabelProps,
508
- unregisterOptions,
509
- isUnregisteringOnUnmount
510
- }) => {
511
- const {
512
- control,
513
- setValue
514
- } = useHookFormContext();
515
- const hasError = useFormFieldHasError(formField.name);
516
- const muiFormControl = useFormControl();
517
- const {
518
- label,
519
- name,
520
- required,
521
- requiredErrorMessage,
522
- validate
523
- } = useMergedFormField(formField);
524
- useEffectFieldUnregisterOnUnmount({
525
- name,
526
- unregisterOptions,
527
- isUnregisteringOnUnmount
528
- });
529
- const id = `hook-form-input-checkbox-${name}`;
530
- const disabled = muiFormControl?.disabled || checkboxProps?.disabled;
531
- const isRequired = required || muiFormControl?.required;
532
- return /*#__PURE__*/jsxs(FormControl, {
533
- error: hasError,
534
- disabled: disabled,
535
- required: required,
536
- children: [/*#__PURE__*/jsx(FormControlLabel, {
537
- required: jsxLabel ? false : isRequired // If jsxLabel is set, we don't want to show the asterisk.
538
- ,
539
- disabled: disabled,
540
- label: jsxLabel ?? label,
541
- sx: {
542
- color: t => hasError ? t.palette.error.main : undefined
543
- },
544
- control: /*#__PURE__*/jsx(Controller, {
545
- name: name,
546
- control: control,
547
- rules: {
548
- required: isRequired ? requiredErrorMessage : false,
549
- validate
550
- },
551
- render: ({
552
- field: {
553
- value
554
- }
555
- }) => {
556
- return /*#__PURE__*/jsx(Checkbox, {
557
- checked: !!value,
558
- "aria-labelledby": id,
559
- onChange: (e, val) => {
560
- setValue(name, val, {
561
- shouldValidate: true,
562
- shouldDirty: true,
563
- shouldTouch: true
564
- });
565
- },
566
- ...checkboxProps,
567
- disabled: disabled
568
- });
569
- }
570
- }),
571
- ...formControlLabelProps
572
- }), /*#__PURE__*/jsx(FormFieldError, {
573
- fieldName: formField.name
574
- })]
575
- });
576
- };
577
-
578
- const InputDatePicker = ({
579
- formField,
580
- datePickerProps,
581
- unregisterOptions,
582
- isUnregisteringOnUnmount
583
- }) => {
584
- const {
585
- control
586
- } = useHookFormContext();
587
- const hasError = useFormFieldHasError(formField.name);
588
- const muiFormControl = useFormControl();
589
- const {
590
- label,
591
- name,
592
- required,
593
- requiredErrorMessage
594
- } = useMergedFormField(formField);
595
- useEffectFieldUnregisterOnUnmount({
596
- name,
597
- unregisterOptions,
598
- isUnregisteringOnUnmount
599
- });
600
- const [date, setDate] = useState(dayjs());
601
- const isRequired = required || muiFormControl?.required;
602
- const isDisabled = muiFormControl?.disabled || datePickerProps?.disabled;
603
- return /*#__PURE__*/jsx(Box, {
604
- children: /*#__PURE__*/jsxs(FormControl, {
605
- error: hasError,
606
- required: isRequired,
607
- disabled: isDisabled,
608
- children: [/*#__PURE__*/jsx(Controller, {
609
- name: name,
610
- defaultValue: date,
611
- control: control,
612
- rules: {
613
- required: isRequired ? requiredErrorMessage : false
614
- },
615
- render: ({
616
- field: {
617
- onChange,
618
- ...restField
619
- }
620
- }) => /*#__PURE__*/jsx(DatePicker, {
621
- label: label,
622
- onChange: event => {
623
- onChange(event);
624
- if (event) {
625
- setDate(event);
626
- }
627
- },
628
- disabled: isDisabled,
629
- slotProps: {
630
- textField: {
631
- required: isRequired,
632
- disabled: isDisabled,
633
- error: hasError
634
- }
635
- },
636
- ...restField,
637
- ...datePickerProps
638
- })
639
- }), /*#__PURE__*/jsx(FormFieldError, {
640
- fieldName: formField.name
641
- })]
642
- })
643
- });
644
- };
645
-
646
- const InputDateTimePicker = ({
647
- formField,
648
- dateTimePickerProps,
649
- unregisterOptions,
650
- isUnregisteringOnUnmount
651
- }) => {
652
- const {
653
- control
654
- } = useHookFormContext();
655
- const hasError = useFormFieldHasError(formField.name);
656
- const muiFormControl = useFormControl();
657
- const {
658
- label,
659
- name,
660
- required,
661
- requiredErrorMessage
662
- } = useMergedFormField(formField);
663
- useEffectFieldUnregisterOnUnmount({
664
- name,
665
- unregisterOptions,
666
- isUnregisteringOnUnmount
667
- });
668
- const [date, setDate] = useState(dayjs());
669
- const isRequired = required || muiFormControl?.required;
670
- const isDisabled = muiFormControl?.disabled || dateTimePickerProps?.disabled;
671
- return /*#__PURE__*/jsx(Box, {
672
- children: /*#__PURE__*/jsxs(FormControl, {
673
- error: hasError,
674
- required: isRequired,
675
- disabled: isDisabled,
676
- children: [/*#__PURE__*/jsx(Controller, {
677
- name: name,
678
- defaultValue: date,
679
- control: control,
680
- rules: {
681
- required: isRequired ? requiredErrorMessage : false
682
- },
683
- render: ({
684
- field: {
685
- onChange,
686
- ...restField
687
- }
688
- }) => /*#__PURE__*/jsx(DateTimePicker, {
689
- label: label,
690
- ampm: dateTimePickerProps?.ampm ? dateTimePickerProps.ampm : false,
691
- onChange: event => {
692
- onChange(event);
693
- if (event) {
694
- setDate(event);
695
- }
696
- },
697
- disabled: isDisabled,
698
- required: isRequired,
699
- slotProps: {
700
- textField: {
701
- required: isRequired,
702
- disabled: isDisabled,
703
- error: hasError
704
- }
705
- },
706
- ...restField,
707
- ...dateTimePickerProps
708
- })
709
- }), /*#__PURE__*/jsx(FormFieldError, {
710
- fieldName: formField.name
711
- })]
712
- })
713
- });
714
- };
715
-
716
- const InputNumber = ({
717
- formField,
718
- textFieldProps,
719
- numericFormatProps,
720
- unregisterOptions,
721
- isUnregisteringOnUnmount
722
- }) => {
723
- const form = useHookFormContext();
724
- const {
725
- control
726
- } = form;
727
- const muiFormControl = useFormControl();
728
- const {
729
- label,
730
- name,
731
- required,
732
- requiredErrorMessage,
733
- validate
734
- } = useMergedFormField(formField, formField.t);
735
- useEffectFieldUnregisterOnUnmount({
736
- name,
737
- unregisterOptions,
738
- isUnregisteringOnUnmount
739
- });
740
- if (!form) {
741
- throw Error(formContextNull);
742
- }
743
- const hasError = useFormFieldHasError(formField.name);
744
- const isRequired = required || muiFormControl?.required;
745
- const isDisabled = muiFormControl?.disabled || textFieldProps?.disabled;
746
- return /*#__PURE__*/jsxs(FormControl, {
747
- error: hasError,
748
- required: required,
749
- disabled: isDisabled,
750
- children: [/*#__PURE__*/jsx(Controller, {
751
- name: name,
752
- control: control,
753
- rules: {
754
- required: isRequired ? requiredErrorMessage : false,
755
- validate
756
- },
757
- render: props => {
758
- const {
759
- ref,
760
- ...rest
761
- } = props.field;
762
- return (
763
- /*#__PURE__*/
764
- // @ts-expect-error TextFieldProps is not compatible with NumberFormatBaseProps
765
- jsx(NumericFormat, {
766
- ...rest,
767
- customInput: TextField,
768
- onValueChange: target => {
769
- rest.onChange(target.value);
770
- },
771
- label: label,
772
- onChange: undefined,
773
- onBlur: props.field.onBlur,
774
- error: !!props.fieldState.error,
775
- ...textFieldProps,
776
- ...numericFormatProps,
777
- disabled: isDisabled,
778
- required: isRequired
779
- })
780
- );
781
- }
782
- }), /*#__PURE__*/jsx(FormFieldError, {
783
- fieldName: formField.name
784
- })]
785
- });
786
- };
787
-
788
- const InputOutlinedInput = ({
789
- formField,
790
- outlinedInputProps,
791
- unregisterOptions,
792
- isUnregisteringOnUnmount
793
- }) => {
794
- const form = useHookFormContext();
795
- const muiFormControl = useFormControl();
796
- const {
797
- label,
798
- name,
799
- required,
800
- requiredErrorMessage,
801
- validate
802
- } = useMergedFormField(formField, formField.t);
803
- useEffectFieldUnregisterOnUnmount({
804
- name,
805
- unregisterOptions,
806
- isUnregisteringOnUnmount
807
- });
808
- if (!form) {
809
- throw Error(formContextNull);
810
- }
811
- const {
812
- control
813
- } = form;
814
- const hasError = useFormFieldHasError(formField.name);
815
- const isRequired = required || muiFormControl?.required;
816
- const isDisabled = muiFormControl?.disabled || outlinedInputProps?.disabled;
817
- return /*#__PURE__*/jsxs(FormControl, {
818
- error: hasError,
819
- required: required,
820
- disabled: muiFormControl?.disabled,
821
- children: [/*#__PURE__*/jsx(InputLabel, {
822
- required: isRequired,
823
- disabled: isDisabled,
824
- children: label
825
- }), /*#__PURE__*/jsx(Controller, {
826
- name: name,
827
- control: control,
828
- rules: {
829
- required: isRequired ? requiredErrorMessage : false,
830
- validate
831
- },
832
- render: ({
833
- field: {
834
- value,
835
- onBlur,
836
- onChange
837
- }
838
- }) => {
839
- return /*#__PURE__*/jsx(OutlinedInput, {
840
- value: value,
841
- onChange: onChange,
842
- onBlur: onBlur,
843
- label: label,
844
- ...outlinedInputProps,
845
- required: isRequired,
846
- disabled: isDisabled
847
- });
848
- }
849
- }), /*#__PURE__*/jsx(FormFieldError, {
850
- fieldName: formField.name
851
- })]
852
- });
853
- };
854
-
855
- const InputRadio = ({
856
- formField,
857
- selectableOptions,
858
- formControlLabelProps,
859
- radioGroupProps,
860
- unregisterOptions,
861
- isUnregisteringOnUnmount
862
- }) => {
863
- const {
864
- control
865
- } = useHookFormContext();
866
- const hasError = useFormFieldHasError(formField.name);
867
- const muiFormControl = useFormControl();
868
- const {
869
- label,
870
- name,
871
- required,
872
- requiredErrorMessage,
873
- validate
874
- } = useMergedFormField(formField);
875
- useEffectFieldUnregisterOnUnmount({
876
- name,
877
- unregisterOptions,
878
- isUnregisteringOnUnmount
879
- });
880
- const id = `hook-form-input-radio-${name}`;
881
- const isRequired = required || muiFormControl?.required;
882
- const isDisabled = muiFormControl?.disabled || formControlLabelProps?.disabled;
883
- return /*#__PURE__*/jsxs(FormControl, {
884
- error: hasError,
885
- disabled: muiFormControl?.disabled,
886
- children: [/*#__PURE__*/jsx(FormLabel, {
887
- id: id,
888
- required: isRequired,
889
- disabled: isDisabled,
890
- error: hasError,
891
- sx: {
892
- color: t => hasError ? t.palette.error.main : undefined
893
- },
894
- children: label
895
- }), /*#__PURE__*/jsx(Controller, {
896
- name: name,
897
- control: control,
898
- rules: {
899
- required: isRequired ? requiredErrorMessage : false,
900
- validate
901
- },
902
- render: ({
903
- field: {
904
- onChange,
905
- value,
906
- onBlur
907
- }
908
- }) => {
909
- return /*#__PURE__*/jsx(RadioGroup, {
910
- value: value,
911
- "aria-labelledby": id,
912
- onChange: onChange,
913
- onBlur: onBlur,
914
- ...radioGroupProps,
915
- children: selectableOptions?.map(option => {
916
- return /*#__PURE__*/jsx(FormControlLabel, {
917
- value: option.value,
918
- control: /*#__PURE__*/jsx(Radio, {}),
919
- label: option.label,
920
- ...formControlLabelProps,
921
- disabled: isDisabled
922
- }, typeof option.value === "boolean" ? option.value.toString() : option.value);
923
- })
924
- });
925
- }
926
- }), /*#__PURE__*/jsx(FormFieldError, {
927
- fieldName: formField.name
928
- })]
929
- });
930
- };
931
-
932
- /**
933
- * Sorts the options by group and value.
934
- */
935
- const useSortedOptionsWithGroup = selectableOptions => {
936
- return useMemo(() => selectableOptions.sort((a, b) => {
937
- if (a.group == undefined && !!b.group) {
938
- return -1;
939
- }
940
- if (a.group && b.group && a.group < b.group) {
941
- return -1;
942
- }
943
- if (a.group == b.group && b.value > a.value) {
944
- return 1;
945
- }
946
- return 0;
947
- }), [selectableOptions]);
948
- };
949
-
950
- const InputSelect = ({
951
- formField,
952
- selectableOptions,
953
- optionsTitle,
954
- selectComponentProps,
955
- tooltipHolder,
956
- unregisterOptions,
957
- isUnregisteringOnUnmount
958
- }) => {
959
- const form = useHookFormContext();
960
- if (!form) {
961
- throw Error(formContextNull);
962
- }
963
- const {
964
- control
965
- } = form;
966
- const muiFormControl = useFormControl();
967
- const {
968
- label,
969
- name,
970
- required,
971
- requiredErrorMessage,
972
- validate
973
- } = useMergedFormField(formField, formField.t);
974
- useEffectFieldUnregisterOnUnmount({
975
- name,
976
- unregisterOptions,
977
- isUnregisteringOnUnmount
978
- });
979
- const defaultValue = useMemo(() => selectComponentProps?.multiple ? [] : "", [selectComponentProps?.multiple]);
980
- const id = `input-select-${name}`;
981
- const adjustedOptions = useMemo(() => selectComponentProps?.multiple || Array.isArray(defaultValue) ? selectableOptions : [...selectableOptions, {
982
- value: defaultValue,
983
- label: ""
984
- }], [defaultValue, selectComponentProps?.multiple, selectableOptions]);
985
- const sortedOptions = useSortedOptionsWithGroup(adjustedOptions);
986
- const hasErrors = useFormFieldHasError(formField.name);
987
- const isRequired = required || muiFormControl?.required;
988
- const isDisabled = muiFormControl?.disabled || selectComponentProps?.disabled;
989
- return /*#__PURE__*/jsxs(FormControl, {
990
- error: hasErrors,
991
- required: isRequired,
992
- disabled: isDisabled,
993
- children: [/*#__PURE__*/jsx(InputLabel, {
994
- id: id,
995
- required: isRequired,
996
- disabled: isDisabled,
997
- error: hasErrors,
998
- children: label
999
- }), /*#__PURE__*/jsx(Controller, {
1000
- name: name,
1001
- control: control,
1002
- rules: {
1003
- required: isRequired ? requiredErrorMessage : false,
1004
- validate
1005
- },
1006
- render: ({
1007
- field: {
1008
- onChange,
1009
- onBlur,
1010
- value
1011
- },
1012
- fieldState: {
1013
- error
1014
- }
1015
- }) => {
1016
- const valueToUse = value || defaultValue;
1017
- return /*#__PURE__*/jsxs(Select, {
1018
- labelId: id,
1019
- ...selectComponentProps,
1020
- label: label,
1021
- value: valueToUse,
1022
- error: !!error,
1023
- onChange: onChange,
1024
- onBlur: onBlur,
1025
- disabled: isDisabled,
1026
- required: isRequired,
1027
- children: [optionsTitle && /*#__PURE__*/jsx(MenuItem, {
1028
- value: defaultValue,
1029
- disabled: true,
1030
- children: /*#__PURE__*/jsx("em", {
1031
- children: optionsTitle
1032
- })
1033
- }), sortedOptions?.filter(o => o.value !== "").map((option, index) => {
1034
- const optionBefore = sortedOptions[index - 1];
1035
- const showGroup = (optionBefore || index == 0) && option.group && optionBefore?.group !== option.group;
1036
- const disabledText = typeof option.disabled === "string" ? option.disabled : undefined;
1037
- const isDisabledToUse = !!disabledText || !!option.disabled || isDisabled;
1038
- const menuItem = /*#__PURE__*/jsx(MenuItem, {
1039
- value: typeof option.value === "boolean" ? option.value.toString() : option.value,
1040
- disabled: isDisabledToUse,
1041
- title: typeof option.disabled === "string" ? option.disabled : undefined,
1042
- selected: typeof option.value === "boolean" ? option.value.toString() === value : value === option.value,
1043
- children: /*#__PURE__*/jsx(Typography, {
1044
- dangerouslySetInnerHTML: {
1045
- __html: option.label
1046
- }
1047
- })
1048
- }, option.label);
1049
- const wrappedMenuItem = disabledText ? /*#__PURE__*/jsxs(Box, {
1050
- sx: {
1051
- position: "relative"
1052
- },
1053
- children: [menuItem, /*#__PURE__*/jsx(Stack, {
1054
- direction: "column",
1055
- justifyContent: "center",
1056
- spacing: 1,
1057
- sx: {
1058
- position: "absolute",
1059
- right: th => th.spacing(0.5),
1060
- top: 0,
1061
- bottom: 0
1062
- },
1063
- children: tooltipHolder ? /*#__PURE__*/jsx(Tooltip, {
1064
- title: disabledText,
1065
- children: tooltipHolder
1066
- }) : null
1067
- })]
1068
- }) : menuItem;
1069
- return showGroup ? [/*#__PURE__*/jsx(ListSubheader, {
1070
- children: option.group
1071
- }, option.group), wrappedMenuItem] : wrappedMenuItem;
1072
- })]
1073
- });
1074
- }
1075
- }), /*#__PURE__*/jsx(FormFieldError, {
1076
- fieldName: formField.name
1077
- })]
1078
- });
1079
- };
1080
-
1081
- const InputSelectFromEnum = props => {
1082
- const {
1083
- enumData,
1084
- formField
1085
- } = props;
1086
- const translateFunction = formField.t;
1087
- const options = useMemo(() => {
1088
- return Object.entries(enumData.enumToUse).map(([key, value]) => {
1089
- const label = enumData.labelsForEnum[key];
1090
- assertTruthy(label, "Could not find a label for value: " + value + " in Field " + formField.name);
1091
- if (typeof label === "string") {
1092
- return {
1093
- label,
1094
- value
1095
- };
1096
- }
1097
- assertTruthy(translateFunction, `If you want to use translated labels for field (name: ${formField.name}) you need to provide a translate function in the HookFormProvider.`);
1098
- return {
1099
- label: label(translateFunction),
1100
- value
1101
- };
1102
- }).filter(option => {
1103
- if (props.limitOptions) {
1104
- return props.limitOptions.includes(option.value);
1105
- }
1106
- return true;
1107
- });
1108
- }, [enumData.enumToUse, enumData.labelsForEnum, formField.name, translateFunction, props.limitOptions]);
1109
- return /*#__PURE__*/jsx(InputSelect, {
1110
- ...props,
1111
- selectableOptions: options,
1112
- formField: formField
1113
- });
1114
- };
1115
-
1116
- const InputSlider = ({
1117
- formField,
1118
- sliderProps,
1119
- unregisterOptions,
1120
- isUnregisteringOnUnmount
1121
- }) => {
1122
- const form = useHookFormContext();
1123
- const muiFormControl = useFormControl();
1124
- const {
1125
- label,
1126
- name,
1127
- required,
1128
- requiredErrorMessage,
1129
- validate
1130
- } = useMergedFormField(formField, formField.t);
1131
- useEffectFieldUnregisterOnUnmount({
1132
- name,
1133
- unregisterOptions,
1134
- isUnregisteringOnUnmount
1135
- });
1136
- if (!form) {
1137
- throw Error(formContextNull);
1138
- }
1139
- const {
1140
- control
1141
- } = form;
1142
- const hasError = useFormFieldHasError(formField.name);
1143
- const isRequired = required || muiFormControl?.required;
1144
- const isDisabled = muiFormControl?.disabled || sliderProps?.disabled;
1145
- return /*#__PURE__*/jsxs(FormControl, {
1146
- error: hasError,
1147
- required: isRequired,
1148
- disabled: isDisabled,
1149
- children: [/*#__PURE__*/jsx(Controller, {
1150
- name: name,
1151
- control: control,
1152
- defaultValue: 0,
1153
- rules: {
1154
- required: isRequired ? requiredErrorMessage : false,
1155
- validate
1156
- },
1157
- render: ({
1158
- field: {
1159
- onChange,
1160
- value,
1161
- onBlur
1162
- }
1163
- }) => {
1164
- return /*#__PURE__*/jsx(Slider, {
1165
- value: value || 0,
1166
- onChange: onChange,
1167
- onBlur: onBlur,
1168
- required: isRequired,
1169
- label: label,
1170
- component: sliderProps?.component || "span",
1171
- max: typeof sliderProps?.max === "number" ? sliderProps.max : undefined,
1172
- min: typeof sliderProps?.min === "number" ? sliderProps.min : undefined,
1173
- ...sliderProps,
1174
- disabled: isDisabled
1175
- });
1176
- }
1177
- }), /*#__PURE__*/jsx(FormFieldError, {
1178
- fieldName: name
1179
- })]
1180
- });
1181
- };
1182
-
1183
- const InputSwitch = ({
1184
- formField,
1185
- switchProps,
1186
- formControlLabelProps,
1187
- unregisterOptions,
1188
- isUnregisteringOnUnmount
1189
- }) => {
1190
- const {
1191
- control,
1192
- setValue
1193
- } = useHookFormContext();
1194
- const hasError = useFormFieldHasError(formField.name);
1195
- const muiFormControl = useFormControl();
1196
- const {
1197
- label,
1198
- name,
1199
- required,
1200
- requiredErrorMessage,
1201
- validate
1202
- } = useMergedFormField(formField);
1203
- useEffectFieldUnregisterOnUnmount({
1204
- name,
1205
- unregisterOptions,
1206
- isUnregisteringOnUnmount
1207
- });
1208
- const isRequired = required || muiFormControl?.required;
1209
- const isDisabled = muiFormControl?.disabled || switchProps?.disabled;
1210
- return /*#__PURE__*/jsxs(FormControl, {
1211
- error: hasError,
1212
- disabled: isDisabled,
1213
- required: isRequired,
1214
- children: [/*#__PURE__*/jsx(FormControlLabel, {
1215
- label: label,
1216
- disabled: isDisabled,
1217
- required: isRequired,
1218
- sx: {
1219
- color: t => hasError ? t.palette.error.main : undefined
1220
- },
1221
- control: /*#__PURE__*/jsx(Controller, {
1222
- name: name,
1223
- control: control,
1224
- rules: {
1225
- required: isRequired ? requiredErrorMessage : false,
1226
- validate
1227
- },
1228
- render: ({
1229
- field: {
1230
- value
1231
- }
1232
- }) => {
1233
- return /*#__PURE__*/jsx(Switch, {
1234
- checked: !!value,
1235
- onChange: (e, val) => {
1236
- setValue(name, val, {
1237
- shouldValidate: true,
1238
- shouldDirty: true,
1239
- shouldTouch: true
1240
- });
1241
- },
1242
- ...switchProps
1243
- });
1244
- }
1245
- }),
1246
- ...formControlLabelProps
1247
- }), /*#__PURE__*/jsx(FormFieldError, {
1248
- fieldName: formField.name
1249
- })]
1250
- });
1251
- };
1252
-
1253
- const InputTextField = ({
1254
- formField,
1255
- textFieldProps,
1256
- unregisterOptions,
1257
- isUnregisteringOnUnmount
1258
- }) => {
1259
- const form = useHookFormContext();
1260
- const {
1261
- control
1262
- } = form;
1263
- const muiFormControl = useFormControl();
1264
- const {
1265
- label,
1266
- name,
1267
- required,
1268
- requiredErrorMessage,
1269
- validate
1270
- } = useMergedFormField(formField, formField.t);
1271
- useEffectFieldUnregisterOnUnmount({
1272
- name,
1273
- unregisterOptions,
1274
- isUnregisteringOnUnmount
1275
- });
1276
- if (!form) {
1277
- throw Error(formContextNull);
1278
- }
1279
- const hasError = useFormFieldHasError(formField.name);
1280
- const isRequired = required || muiFormControl?.required;
1281
- const isDisabled = muiFormControl?.disabled || textFieldProps?.disabled;
1282
- return /*#__PURE__*/jsxs(FormControl, {
1283
- error: hasError,
1284
- required: isRequired,
1285
- disabled: isDisabled,
1286
- children: [/*#__PURE__*/jsx(Controller, {
1287
- name: name,
1288
- control: control,
1289
- rules: {
1290
- required: isRequired ? requiredErrorMessage : false,
1291
- validate
1292
- },
1293
- render: ({
1294
- field: {
1295
- onChange,
1296
- value
1297
- },
1298
- fieldState: {
1299
- error
1300
- }
1301
- }) => {
1302
- return /*#__PURE__*/jsx(TextField, {
1303
- error: !!error,
1304
- onChange: onChange,
1305
- value: value,
1306
- label: label,
1307
- ...textFieldProps,
1308
- required: isRequired,
1309
- disabled: isDisabled
1310
- });
1311
- }
1312
- }), /*#__PURE__*/jsx(FormFieldError, {
1313
- fieldName: formField.name
1314
- })]
1315
- });
1316
- };
1317
-
1318
- const InputTimePicker = ({
1319
- formField,
1320
- timePickerProps,
1321
- unregisterOptions,
1322
- isUnregisteringOnUnmount
1323
- }) => {
1324
- const {
1325
- control
1326
- } = useHookFormContext();
1327
- const hasError = useFormFieldHasError(formField.name);
1328
- const muiFormControl = useFormControl();
1329
- const {
1330
- label,
1331
- name,
1332
- required,
1333
- requiredErrorMessage
1334
- } = useMergedFormField(formField);
1335
- useEffectFieldUnregisterOnUnmount({
1336
- name,
1337
- unregisterOptions,
1338
- isUnregisteringOnUnmount
1339
- });
1340
- const [date, setDate] = useState(dayjs());
1341
- const isRequired = required || muiFormControl?.required;
1342
- const isDisabled = muiFormControl?.disabled || timePickerProps?.disabled;
1343
- return /*#__PURE__*/jsx(Box, {
1344
- children: /*#__PURE__*/jsxs(FormControl, {
1345
- error: hasError,
1346
- required: isRequired,
1347
- disabled: isDisabled,
1348
- children: [/*#__PURE__*/jsx(Controller, {
1349
- name: name,
1350
- defaultValue: date,
1351
- control: control,
1352
- rules: {
1353
- required: isRequired ? requiredErrorMessage : false
1354
- },
1355
- render: ({
1356
- field: {
1357
- onChange,
1358
- ...restField
1359
- }
1360
- }) => /*#__PURE__*/jsx(TimePicker, {
1361
- label: label,
1362
- onChange: event => {
1363
- onChange(event);
1364
- if (event) {
1365
- setDate(event);
1366
- }
1367
- },
1368
- disabled: isDisabled,
1369
- required: isRequired,
1370
- slotProps: {
1371
- textField: {
1372
- required: isRequired,
1373
- disabled: isDisabled,
1374
- error: hasError
1375
- }
1376
- },
1377
- ...restField,
1378
- ...timePickerProps
1379
- })
1380
- }), /*#__PURE__*/jsx(FormFieldError, {
1381
- fieldName: formField.name
1382
- })]
1383
- })
1384
- });
1385
- };
1386
-
1387
- const InputToggleButton = ({
1388
- formField,
1389
- toggleButtonProps,
1390
- formControlLabelProps,
1391
- children,
1392
- unregisterOptions,
1393
- isUnregisteringOnUnmount
1394
- }) => {
1395
- const {
1396
- register,
1397
- control,
1398
- setValue
1399
- } = useHookFormContext();
1400
- const hasError = useFormFieldHasError(formField.name);
1401
- const muiFormControl = useFormControl();
1402
- const {
1403
- label,
1404
- name,
1405
- required,
1406
- requiredErrorMessage,
1407
- validate
1408
- } = useMergedFormField(formField);
1409
- useEffectFieldUnregisterOnUnmount({
1410
- name,
1411
- unregisterOptions,
1412
- isUnregisteringOnUnmount
1413
- });
1414
- const id = `hook-form-input-toggle-button-${name}`;
1415
- const valueToUse = !!useWatch({
1416
- name: name,
1417
- control: control,
1418
- exact: true
1419
- });
1420
- assertTruthy(typeof valueToUse === "boolean", `Value (Field: ${name}, value: ${valueToUse?.toString() || "undefined"}) for a InputToggleButton should be undefined or boolean`);
1421
- const onClick = useCallback(
1422
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1423
- e => {
1424
- setValue(name, !valueToUse, {
1425
- shouldValidate: true,
1426
- shouldDirty: true,
1427
- shouldTouch: true
1428
- });
1429
- }, [name, setValue, valueToUse]);
1430
- const isRequired = required || muiFormControl?.required;
1431
- const isDisabled = muiFormControl?.disabled || toggleButtonProps?.disabled;
1432
- const registered = register(name, {
1433
- required: isRequired ? requiredErrorMessage : false,
1434
- validate,
1435
- disabled: muiFormControl?.disabled
1436
- });
1437
- return /*#__PURE__*/jsxs(FormControl, {
1438
- error: hasError,
1439
- disabled: isDisabled,
1440
- required: isRequired,
1441
- children: [/*#__PURE__*/jsx(FormControlLabel, {
1442
- required: isRequired,
1443
- label: label,
1444
- labelPlacement: "top",
1445
- disabled: isDisabled,
1446
- control: /*#__PURE__*/jsx(ToggleButton, {
1447
- value: valueToUse,
1448
- selected: valueToUse,
1449
- "aria-labelledby": id,
1450
- onClick: onClick,
1451
- ...registered,
1452
- ...toggleButtonProps,
1453
- children: children
1454
- }),
1455
- sx: {
1456
- alignItems: "flex-start",
1457
- ml: 0,
1458
- color: t => hasError ? t.palette.error.main : undefined,
1459
- ...formControlLabelProps?.sx
1460
- },
1461
- ...formControlLabelProps
1462
- }), /*#__PURE__*/jsx(FormFieldError, {
1463
- fieldName: formField.name
1464
- })]
1465
- });
1466
- };
1467
-
1468
- const InputToggleButtonGroup = ({
1469
- formField,
1470
- toggleButtonGroupProps,
1471
- stackProps,
1472
- typographyProps,
1473
- buttons,
1474
- enforceValueSelected = false,
1475
- unregisterOptions,
1476
- isUnregisteringOnUnmount
1477
- }) => {
1478
- const {
1479
- register,
1480
- setValue,
1481
- control
1482
- } = useHookFormContext();
1483
- const hasError = useFormFieldHasError(formField.name);
1484
- const muiFormControl = useFormControl();
1485
- const {
1486
- label: labelText,
1487
- name,
1488
- required,
1489
- requiredErrorMessage,
1490
- validate
1491
- } = useMergedFormField(formField);
1492
- useEffectFieldUnregisterOnUnmount({
1493
- name,
1494
- unregisterOptions,
1495
- isUnregisteringOnUnmount
1496
- });
1497
- const changeEv = useCallback((_, value) => {
1498
- const onSetValue = () => setValue(name, value, {
1499
- shouldValidate: true,
1500
- shouldDirty: true,
1501
- shouldTouch: true
1502
- });
1503
- if (enforceValueSelected) {
1504
- if (toggleButtonGroupProps?.exclusive === true && value !== null) {
1505
- onSetValue();
1506
- } else if (toggleButtonGroupProps?.exclusive === false || toggleButtonGroupProps?.exclusive === undefined && value?.length) {
1507
- onSetValue();
1508
- }
1509
- } else {
1510
- onSetValue();
1511
- }
1512
- }, [enforceValueSelected, name, setValue, toggleButtonGroupProps?.exclusive]);
1513
- const id = `hook-form-input-toggle-button-group-${name}`;
1514
- const registered = register(name, {
1515
- required: required ? requiredErrorMessage : false,
1516
- validate,
1517
- disabled: muiFormControl?.disabled
1518
- });
1519
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
1520
- const valueFromForm = useWatch({
1521
- name: name,
1522
- control: control,
1523
- exact: true
1524
- });
1525
- const isRequired = required || muiFormControl?.required;
1526
- const isDisabled = muiFormControl?.disabled || toggleButtonGroupProps?.disabled;
1527
- const toggleButtonGroup = /*#__PURE__*/jsx(ToggleButtonGroup, {
1528
- ...registered,
1529
- ...toggleButtonGroupProps,
1530
- onChange: changeEv
1531
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
1532
- ,
1533
- value: valueFromForm,
1534
- children: buttons.map((button, i) => /*#__PURE__*/jsx(ToggleButton
1535
- // eslint-disable-next-line react/no-array-index-key
1536
- , {
1537
- value: button.value,
1538
- "aria-labelledby": id,
1539
- ...button.toggleButtonProps,
1540
- disabled: isDisabled,
1541
- children: button.icon
1542
- }, `${button.value.toString()}-${i}`))
1543
- });
1544
- const label = /*#__PURE__*/jsx(Typography, {
1545
- component: "span",
1546
- ...typographyProps,
1547
- sx: {
1548
- color: t => {
1549
- if (hasError) {
1550
- return t.palette.error.main;
1551
- }
1552
- return isDisabled ? t.palette.text.disabled : undefined;
1553
- }
1554
- },
1555
- children: labelText
1556
- });
1557
- return /*#__PURE__*/jsxs(FormControl, {
1558
- error: hasError,
1559
- disabled: isDisabled,
1560
- required: isRequired,
1561
- children: [formField.label ? /*#__PURE__*/jsxs(Stack, {
1562
- ...stackProps,
1563
- children: [isRequired ? /*#__PURE__*/jsxs(Stack, {
1564
- id: id,
1565
- component: "label",
1566
- sx: {
1567
- display: "block"
1568
- },
1569
- children: [label, /*#__PURE__*/jsxs(Box, {
1570
- component: "span",
1571
- "aria-hidden": true,
1572
- sx: {
1573
- color: hasError ? t => t.palette.error.main : undefined
1574
- },
1575
- children: ["\u2009", "*"]
1576
- })]
1577
- }) : label, toggleButtonGroup]
1578
- }) : toggleButtonGroup, /*#__PURE__*/jsx(FormFieldError, {
1579
- fieldName: formField.name
1580
- })]
1581
- });
1582
- };
1583
-
1584
- /**
1585
- * Turn an async submitHandler into a synchronous one.
1586
- *
1587
- * Reasoning:
1588
- * - we're often talking to the API during form submission. The onSubmit handler will be returning a Promise in this case.
1589
- * - the `form` element, per definition, always expects a synchronous function.
1590
- * - creating on inline function in every form is a bit clumsy, and does not look clean.
1591
- *
1592
- * Then/catch cases should be properly handled by the submit handler itself,
1593
- * the catch supplied here is only a last safety net against an "unhandled promise rejection" error.
1594
- */
1595
- const syncSubmit = asyncSubmitHandler => {
1596
- return e => {
1597
- asyncSubmitHandler(e).catch(rethrow);
1598
- };
1599
- };
1600
-
1601
- /**
1602
- * Wrapper around react-hook-form's useForm.
1603
- *
1604
- * Should behave like the original function, only exposing a "fieldName"
1605
- * function on top which is used to validate field names.
1606
- */
1607
- const useHookForm = props => {
1608
- const form = useForm(props);
1609
- return {
1610
- ...form,
1611
- fieldName: identity
1612
- };
1613
- };
1614
- const useHookFormFieldArray = useFieldArray;
1615
-
1616
- /**
1617
- * Reexport of FormProvider.
1618
- *
1619
- * This became necessary as context is not available when the FormProvider is initialized outside of the package. Most likely this is some kind of instance mismatch.
1620
- */
1621
- const HookFormProvider = FormProvider;
1622
-
1623
- const InputEmail = props => {
1624
- const merged = useMergedFormField(props.formField, props.formField.t, formDefaults);
1625
- const commonProps = useMemo(() => ({
1626
- textFieldProps: {
1627
- type: "email",
1628
- autoComplete: "email",
1629
- ...props.textFieldProps
1630
- },
1631
- formField: merged
1632
- }), [merged, props.textFieldProps]);
1633
- return props.isUnregisteringOnUnmount ? /*#__PURE__*/jsx(InputTextField, {
1634
- ...commonProps,
1635
- isUnregisteringOnUnmount: props.isUnregisteringOnUnmount,
1636
- unregisterOptions: props.unregisterOptions
1637
- }) : /*#__PURE__*/jsx(InputTextField, {
1638
- ...commonProps,
1639
- isUnregisteringOnUnmount: props.isUnregisteringOnUnmount
1640
- });
1641
- };
1642
- const formDefaults = {
1643
- required: true,
1644
- validate: emailInput => {
1645
- if (emailInput && emailInput.match(/.@./)) {
1646
- return true;
1647
- }
1648
- return "E-Mail address invalid";
1649
- }
1650
- };
1651
-
1652
- const InputPasswordSet = ({
1653
- passwordField,
1654
- passwordValidationField,
1655
- doNotMatchError,
1656
- passwordValidationTextFieldProps,
1657
- passwordTextFieldProps
1658
- }) => {
1659
- const {
1660
- watch
1661
- } = useHookFormContext();
1662
- const passwordFieldMerged = useMergedFormField(passwordField, passwordField.t, {
1663
- required: true
1664
- });
1665
- const validationFieldMerged = useMergedFormField(passwordValidationField, passwordValidationField.t, {
1666
- required: true
1667
- });
1668
- const validatePasswordMatch = useCallback(value => {
1669
- const passwordValue = watch(passwordFieldMerged.name);
1670
- return value === passwordValue || doNotMatchError;
1671
- }, [doNotMatchError, passwordFieldMerged.name, watch]);
1672
- return /*#__PURE__*/jsxs(Fragment, {
1673
- children: [/*#__PURE__*/jsx(InputTextField, {
1674
- formField: passwordFieldMerged,
1675
- textFieldProps: {
1676
- type: "password",
1677
- autoComplete: "new-password",
1678
- ...passwordTextFieldProps
1679
- }
1680
- }), /*#__PURE__*/jsx(InputTextField, {
1681
- formField: {
1682
- ...validationFieldMerged,
1683
- validate: validatePasswordMatch,
1684
- t: passwordValidationField.t
1685
- },
1686
- textFieldProps: {
1687
- type: "password",
1688
- autoComplete: "new-password",
1689
- ...passwordValidationTextFieldProps
1690
- }
1691
- })]
1692
- });
1693
- };
1694
-
1695
- var LoadingButtonState;
1696
- (function (LoadingButtonState) {
1697
- LoadingButtonState["Idle"] = "idle";
1698
- LoadingButtonState["Loading"] = "loading";
1699
- LoadingButtonState["Success"] = "success";
1700
- })(LoadingButtonState || (LoadingButtonState = {}));
1701
-
1702
- const LoadingButton = ({
1703
- buttonText,
1704
- buttonTextSuccess,
1705
- loadingButtonProps,
1706
- loadingButtonPropsPropsSuccess,
1707
- buttonState,
1708
- successIcon
1709
- }) => {
1710
- const isSuccess = buttonState === LoadingButtonState.Success;
1711
- const propsToSpread = isSuccess ? loadingButtonPropsPropsSuccess : loadingButtonProps;
1712
- return /*#__PURE__*/jsx(LoadingButton$1, {
1713
- loading: buttonState === LoadingButtonState.Loading,
1714
- disabled: buttonState !== LoadingButtonState.Idle,
1715
- ...propsToSpread,
1716
- children: buttonState === LoadingButtonState.Success ? /*#__PURE__*/jsxs(Fragment, {
1717
- children: [successIcon ? successIcon : null, buttonTextSuccess ? buttonTextSuccess : buttonText]
1718
- }) : buttonText
1719
- });
1720
- };
1721
-
1722
- /**
1723
- * Get loading button state from react-query mutation status.
1724
- */
1725
- const loadingButtonStateFromReactQueryMutationStatus = mutationStatus => {
1726
- const mapStatus = {
1727
- idle: LoadingButtonState.Idle,
1728
- error: LoadingButtonState.Idle,
1729
- success: LoadingButtonState.Success,
1730
- loading: LoadingButtonState.Loading
1731
- };
1732
- return mapStatus[mutationStatus];
1733
- };
1734
- /**
1735
- * Get loading button state from a react-hook-form context.
1736
- */
1737
- const useLoadingButtonStateFromFormContext = () => {
1738
- const formContext = useHookFormContext();
1739
- return loadingButtonStateFromFormState(formContext.formState);
1740
- };
1741
- /**
1742
- * Get loading button state from a react-hook-form state.
1743
- */
1744
- const loadingButtonStateFromFormState = (
1745
- // we are not interested in the value types FormState holds
1746
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1747
- formState) => {
1748
- if (formState.isSubmitting) {
1749
- return LoadingButtonState.Loading;
1750
- }
1751
- if (formState.isDirty) {
1752
- return LoadingButtonState.Idle;
1753
- }
1754
- if (formState.isSubmitSuccessful) {
1755
- return LoadingButtonState.Success;
1756
- }
1757
- return LoadingButtonState.Idle;
1758
- };
1759
-
1760
- export { FormFieldError, FormFieldErrorDisplay, HookFormProvider, InputAutocomplete, InputCheckbox, InputDatePicker, InputDateTimePicker, InputEmail, InputNumber, InputOutlinedInput, InputPasswordSet, InputRadio, InputSelect, InputSelectFromEnum, InputSlider, InputSwitch, InputOutlinedInput as InputText, InputTextField, InputTimePicker, InputToggleButton, InputToggleButtonGroup, LoadingButton, LoadingButtonState, getFormErrorForNestedKeys, loadingButtonStateFromFormState, loadingButtonStateFromReactQueryMutationStatus, syncSubmit, useFormFieldError, useFormFieldHasError, useHookForm, useHookFormContext, useHookFormFieldArray, useLoadingButtonStateFromFormContext, useMergedFormField, useSortedOptionsWithGroup, useTranslateString };
1761
- //# sourceMappingURL=packageExports.js.map