@ultraviolet/form 2.0.0-next.6 → 2.0.0-next.7

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.
@@ -1,12 +1,14 @@
1
1
  import { Checkbox } from '@ultraviolet/ui';
2
- import { useController } from 'react-hook-form';
2
+ import { forwardRef } from 'react';
3
3
  import { jsx } from '@emotion/react/jsx-runtime';
4
4
  import { useErrors } from '../../providers/ErrorContext/index.js';
5
+ import { useFormField } from '../../hooks/useFormField.js';
5
6
 
6
- const CheckboxField = _ref => {
7
+ const CheckboxField = /*#__PURE__*/forwardRef((_ref, ref) => {
7
8
  let {
9
+ validate,
8
10
  name,
9
- label,
11
+ label = '',
10
12
  size,
11
13
  progress,
12
14
  disabled,
@@ -16,55 +18,58 @@ const CheckboxField = _ref => {
16
18
  onChange,
17
19
  onBlur,
18
20
  onFocus,
19
- rules,
21
+ value,
20
22
  helper,
21
23
  tooltip,
22
- 'data-testid': dataTestId,
23
- value
24
+ 'data-testid': dataTestId
24
25
  } = _ref;
25
26
  const {
26
27
  getError
27
28
  } = useErrors();
28
29
  const {
29
- field,
30
- fieldState: {
31
- error
32
- }
33
- } = useController({
34
- name,
30
+ input,
31
+ meta
32
+ } = useFormField(name, {
35
33
  disabled,
36
- rules: {
37
- required,
38
- ...rules
39
- }
34
+ required,
35
+ type: 'checkbox',
36
+ validate,
37
+ value
38
+ });
39
+ const error = getError({
40
+ label,
41
+ meta: meta,
42
+ name,
43
+ value: input.value ?? input.checked
40
44
  });
41
45
  return jsx(Checkbox, {
42
- name: field.name,
46
+ name: input.name,
43
47
  onChange: event => {
44
- field.onChange(value ? [...(field.value ?? []), value] : event.target.checked);
45
- onChange?.(event.target.checked);
48
+ input.onChange(event);
49
+ onChange?.(event);
46
50
  },
47
51
  onBlur: event => {
48
- field.onBlur();
52
+ input.onBlur(event);
49
53
  onBlur?.(event);
50
54
  },
51
- onFocus: onFocus,
55
+ onFocus: event => {
56
+ input.onFocus(event);
57
+ onFocus?.(event);
58
+ },
52
59
  size: size,
53
60
  progress: progress,
54
- disabled: field.disabled,
55
- checked: Array.isArray(field.value) ? field.value.includes(value) : !!field.value,
56
- error: getError({
57
- label: label ?? ''
58
- }, error),
59
- ref: field.ref,
61
+ disabled: disabled,
62
+ checked: input.checked,
63
+ error: error,
64
+ helper: helper,
65
+ ref: ref,
60
66
  className: className,
67
+ value: input.value,
61
68
  required: required,
62
69
  "data-testid": dataTestId,
63
- helper: helper,
64
70
  tooltip: tooltip,
65
- value: value,
66
71
  children: children
67
72
  });
68
- };
73
+ });
69
74
 
70
75
  export { CheckboxField };
@@ -1,17 +1,17 @@
1
1
  import { CheckboxGroup } from '@ultraviolet/ui';
2
- import { useController } from 'react-hook-form';
2
+ import { useFieldArray } from 'react-final-form-arrays';
3
3
  import { jsx } from '@emotion/react/jsx-runtime';
4
4
  import { useErrors } from '../../providers/ErrorContext/index.js';
5
5
 
6
6
  const CheckboxGroupField = _ref => {
7
7
  let {
8
8
  legend,
9
+ value,
9
10
  className,
10
11
  helper,
11
12
  direction,
12
13
  children,
13
14
  onChange,
14
- label = '',
15
15
  error: customError,
16
16
  name,
17
17
  required = false
@@ -20,29 +20,32 @@ const CheckboxGroupField = _ref => {
20
20
  getError
21
21
  } = useErrors();
22
22
  const {
23
- field,
24
- fieldState: {
25
- error
26
- }
27
- } = useController({
23
+ fields,
24
+ meta
25
+ } = useFieldArray(name, {
26
+ type: 'checkbox',
27
+ value,
28
+ validate: localValue => required && localValue?.length === 0 ? 'Required' : undefined
29
+ });
30
+ const error = getError({
31
+ label: legend,
32
+ meta,
33
+ value: fields.value,
28
34
  name
29
35
  });
30
36
  return jsx(CheckboxGroup, {
31
37
  legend: legend,
32
- name: name,
33
- value: field.value,
38
+ name: fields.name,
39
+ value: fields.value,
34
40
  onChange: event => {
35
- const fieldValue = field.value;
36
- if (fieldValue?.includes(event.currentTarget.value)) {
37
- field.onChange(fieldValue?.filter(currentValue => currentValue !== event.currentTarget.value));
41
+ if (fields.value?.includes(event.currentTarget.value)) {
42
+ fields.remove(fields.value.indexOf(event.currentTarget?.value));
38
43
  } else {
39
- field.onChange([...field.value, event.currentTarget.value]);
44
+ fields.push(event.currentTarget.value);
40
45
  }
41
- onChange?.(event.currentTarget.value);
46
+ onChange?.(event);
42
47
  },
43
- error: getError({
44
- label
45
- }, error) ?? customError,
48
+ error: error ?? customError,
46
49
  className: className,
47
50
  direction: direction,
48
51
  helper: helper,
@@ -1,9 +1,7 @@
1
1
  import { DateInput } from '@ultraviolet/ui';
2
- import { useController } from 'react-hook-form';
3
- import { maxDateValidator } from '../../validators/maxDate.js';
4
- import { minDateValidator } from '../../validators/minDate.js';
5
2
  import { jsx } from '@emotion/react/jsx-runtime';
6
3
  import { useErrors } from '../../providers/ErrorContext/index.js';
4
+ import { useFormField } from '../../hooks/useFormField.js';
7
5
 
8
6
  const parseDate = value => typeof value === 'string' ? new Date(value) : value;
9
7
  const isEmpty = value => typeof value === 'string' ? value === '' : value === undefined;
@@ -12,15 +10,18 @@ const DateField = _ref => {
12
10
  required,
13
11
  name,
14
12
  label = '',
13
+ validate,
15
14
  format,
16
15
  locale,
17
16
  maxDate,
18
17
  minDate,
18
+ initialValue,
19
19
  disabled,
20
+ value: inputVal,
20
21
  onChange,
21
22
  onBlur,
22
23
  onFocus,
23
- rules,
24
+ formatOnBlur,
24
25
  autoFocus = false,
25
26
  excludeDates,
26
27
  selectsRange,
@@ -30,63 +31,66 @@ const DateField = _ref => {
30
31
  getError
31
32
  } = useErrors();
32
33
  const {
33
- field,
34
- fieldState: {
35
- error
36
- }
37
- } = useController({
34
+ input,
35
+ meta
36
+ } = useFormField(name, {
37
+ disabled,
38
+ formatOnBlur,
39
+ initialValue,
40
+ maxDate,
41
+ minDate,
42
+ required,
43
+ validate,
44
+ value: inputVal
45
+ });
46
+ const error = getError({
47
+ label,
48
+ maxDate,
49
+ meta: meta,
50
+ minDate,
38
51
  name,
39
- rules: {
40
- ...rules,
41
- validate: {
42
- ...rules?.validate,
43
- minDate: minDateValidator(minDate),
44
- maxDate: maxDateValidator(maxDate)
45
- },
46
- required
47
- }
52
+ value: input.value
48
53
  });
49
54
  return jsx(DateInput, {
50
- name: field.name,
51
55
  label: label,
52
- value: field.value,
53
56
  format: format || (value => value ? parseDate(value).toLocaleDateString() : ''),
54
57
  locale: locale,
55
58
  required: required,
59
+ value: input.value,
56
60
  onChange: val => {
57
61
  if (val && val instanceof Date) {
58
62
  onChange?.(val);
59
63
  const newDate = parseDate(val);
60
- if (isEmpty(field.value)) {
61
- field.onChange(newDate);
64
+ if (isEmpty(input.value)) {
65
+ input.onChange(newDate);
62
66
  return;
63
67
  }
64
- const currentDate = parseDate(field.value);
68
+ const currentDate = parseDate(input.value);
65
69
  newDate.setHours(currentDate.getHours(), currentDate.getMinutes());
66
- field.onChange(newDate);
70
+ input.onChange(newDate);
67
71
  } else if (Array.isArray(val)) {
68
- field.onChange(val);
72
+ input.onChange(val);
69
73
  }
70
74
  },
71
75
  onBlur: e => {
72
- field.onBlur();
76
+ input.onBlur(e);
73
77
  onBlur?.(e);
74
78
  },
75
- onFocus: onFocus,
79
+ onFocus: e => {
80
+ input.onFocus(e);
81
+ onFocus?.(e);
82
+ },
76
83
  maxDate: maxDate,
77
84
  minDate: minDate,
78
- error: getError({
79
- minDate,
80
- maxDate,
81
- label
82
- }, error),
85
+ startDate: selectsRange ? input.value[0] : undefined,
86
+ endDate: selectsRange ? input.value[1] : undefined,
87
+ error: error,
83
88
  disabled: disabled,
84
89
  autoFocus: autoFocus,
85
- excludeDates: excludeDates,
86
- selectsRange: selectsRange,
90
+ name: input.name,
87
91
  "data-testid": dataTestId,
88
- startDate: selectsRange && Array.isArray(field.value) ? field.value[0] : undefined,
89
- endDate: selectsRange && Array.isArray(field.value) ? field.value[1] : undefined
92
+ excludeDates: excludeDates,
93
+ selectsRange: selectsRange
90
94
  });
91
95
  };
92
96
 
@@ -1,83 +1,43 @@
1
- import React, { useMemo } from 'react';
2
- import { useForm, FormProvider } from 'react-hook-form';
3
- import { FORM_ERROR } from '../../constants.js';
4
- import { defaultErrors } from './defaultErrors.js';
1
+ import arrayMutators from 'final-form-arrays';
2
+ import { Form as Form$1 } from 'react-final-form';
5
3
  import { jsx } from '@emotion/react/jsx-runtime';
6
4
  import { ErrorProvider } from '../../providers/ErrorContext/index.js';
7
5
 
8
- const FormSubmitContext = /*#__PURE__*/React.createContext({});
9
6
  const Form = _ref => {
10
7
  let {
11
8
  children,
12
- methods: methodsProp,
13
- initialValues,
14
- errors,
15
9
  onRawSubmit,
16
- name
10
+ errors,
11
+ initialValues,
12
+ validateOnBlur,
13
+ validate,
14
+ name,
15
+ render,
16
+ mutators,
17
+ keepDirtyOnReinitialize,
18
+ className
17
19
  } = _ref;
18
- const methodsHook = useForm({
19
- defaultValues: initialValues,
20
- mode: 'onChange'
21
- });
22
- const methods = !methodsProp ? methodsHook : methodsProp;
23
- const handleSubmit = methods.handleSubmit(async values => {
24
- const result = await onRawSubmit(values, {
25
- reset: methods.reset,
26
- resetFieldState: methods.resetField,
27
- restart: () => methods.reset(initialValues),
28
- change: methods.setValue
29
- });
30
- if (result === null) {
31
- methods.setError('root.submit', {
32
- type: 'custom'
33
- });
34
- return;
35
- }
36
- if (result && typeof result !== 'boolean' && typeof result !== 'number') {
37
- methods.setError('root.submit', {
38
- type: 'custom',
39
- message: typeof result === 'object' ? result[FORM_ERROR] : result
40
- });
41
- }
42
- });
43
- const formSubmitContextValue = useMemo(() => ({
44
- handleSubmit
45
- }), [handleSubmit]);
46
- return jsx(FormProvider, {
47
- ...methods,
48
- children: jsx(FormSubmitContext.Provider, {
49
- value: formSubmitContextValue,
50
- children: jsx(ErrorProvider, {
51
- errors: {
52
- ...defaultErrors,
53
- ...errors
54
- },
55
- children: jsx("form", {
56
- onSubmit: async e => {
57
- e.preventDefault();
58
- e.stopPropagation();
59
- await handleSubmit(e);
60
- },
61
- name: name,
62
- children: typeof children === 'function' ? children({
63
- values: methods.watch(),
64
- hasValidationErrors: !methods.formState.isValid,
65
- errors: methods.formState.errors,
66
- submitting: methods.formState.isSubmitting,
67
- pristine: !methods.formState.isDirty,
68
- handleSubmit,
69
- submitError: !!methods.formState.errors?.root?.['submit'],
70
- valid: methods.formState.isValid,
71
- form: {
72
- change: methods.setValue,
73
- reset: methods.reset,
74
- submit: handleSubmit
75
- }
76
- }) : children
77
- })
20
+ return jsx(Form$1, {
21
+ initialValues: initialValues,
22
+ validateOnBlur: validateOnBlur,
23
+ validate: validate,
24
+ mutators: {
25
+ ...arrayMutators,
26
+ ...mutators
27
+ },
28
+ onSubmit: onRawSubmit,
29
+ render: render ?? (renderProps => jsx(ErrorProvider, {
30
+ errors: errors,
31
+ children: jsx("form", {
32
+ noValidate: true,
33
+ name: name,
34
+ onSubmit: renderProps.handleSubmit,
35
+ className: className,
36
+ children: typeof children === 'function' ? children(renderProps) : children
78
37
  })
79
- })
38
+ })),
39
+ keepDirtyOnReinitialize: keepDirtyOnReinitialize
80
40
  });
81
41
  };
82
42
 
83
- export { Form, FormSubmitContext };
43
+ export { Form };
@@ -1,7 +1,6 @@
1
1
  import { NumberInput } from '@ultraviolet/ui';
2
- import { useController } from 'react-hook-form';
3
2
  import { jsx } from '@emotion/react/jsx-runtime';
4
- import { useErrors } from '../../providers/ErrorContext/index.js';
3
+ import { useFormField } from '../../hooks/useFormField.js';
5
4
 
6
5
  const NumberInputField = _ref => {
7
6
  let {
@@ -18,41 +17,38 @@ const NumberInputField = _ref => {
18
17
  size,
19
18
  step,
20
19
  text,
21
- rules,
20
+ validate,
21
+ value,
22
22
  className,
23
- label
23
+ 'data-testid': dataTestId
24
24
  } = _ref;
25
25
  const {
26
- getError
27
- } = useErrors();
28
- const {
29
- field,
30
- fieldState: {
31
- error
32
- }
33
- } = useController({
34
- name,
35
- rules: {
36
- max: maxValue,
37
- min: minValue,
38
- required,
39
- ...rules
40
- }
26
+ input
27
+ } = useFormField(name, {
28
+ disabled,
29
+ required,
30
+ type: 'number',
31
+ validate,
32
+ value,
33
+ defaultValue: 0,
34
+ max: maxValue,
35
+ min: minValue
41
36
  });
42
37
  return jsx(NumberInput, {
43
- name: field.name,
44
- value: field.value,
38
+ name: name,
45
39
  disabled: disabled,
46
40
  onBlur: event => {
47
- field.onBlur();
41
+ input.onBlur(event);
48
42
  onBlur?.(event);
49
43
  },
50
44
  onChange: event => {
51
- // React hook form doesnt allow undefined values after definition https://react-hook-form.com/docs/usecontroller/controller (that make sense)
52
- field.onChange(event ?? null);
45
+ input.onChange(event);
53
46
  onChange?.(event);
54
47
  },
55
- onFocus: onFocus,
48
+ onFocus: event => {
49
+ input.onFocus(event);
50
+ onFocus?.(event);
51
+ },
56
52
  maxValue: maxValue,
57
53
  minValue: minValue,
58
54
  onMinCrossed: onMinCrossed,
@@ -60,13 +56,9 @@ const NumberInputField = _ref => {
60
56
  size: size,
61
57
  step: step,
62
58
  text: text,
59
+ value: input.value,
63
60
  className: className,
64
- label: label,
65
- error: getError({
66
- label: label ?? '',
67
- max: maxValue,
68
- min: minValue
69
- }, error)
61
+ "data-testid": dataTestId
70
62
  });
71
63
  };
72
64
 
@@ -1,7 +1,7 @@
1
1
  import { Radio } from '@ultraviolet/ui';
2
- import { useController } from 'react-hook-form';
3
2
  import { jsx } from '@emotion/react/jsx-runtime';
4
3
  import { useErrors } from '../../providers/ErrorContext/index.js';
4
+ import { useFormField } from '../../hooks/useFormField.js';
5
5
 
6
6
  const RadioField = _ref => {
7
7
  let {
@@ -9,52 +9,57 @@ const RadioField = _ref => {
9
9
  'data-testid': dataTestId,
10
10
  disabled,
11
11
  id,
12
+ label = '',
12
13
  name,
13
14
  onBlur,
14
- label = '',
15
15
  onChange,
16
16
  onFocus,
17
17
  required,
18
+ validate,
18
19
  value,
19
- rules,
20
20
  tooltip
21
21
  } = _ref;
22
22
  const {
23
23
  getError
24
24
  } = useErrors();
25
25
  const {
26
- field,
27
- fieldState: {
28
- error
29
- }
30
- } = useController({
26
+ input,
27
+ meta
28
+ } = useFormField(name, {
29
+ required,
30
+ type: 'radio',
31
+ validate,
32
+ value
33
+ });
34
+ const error = getError({
35
+ disabled,
36
+ label: label,
37
+ meta: meta,
31
38
  name,
32
- rules: {
33
- required,
34
- ...rules
35
- }
39
+ value: input.value
36
40
  });
37
41
  return jsx(Radio, {
38
- name: field.name,
39
- checked: field.value === value,
42
+ checked: input.checked,
40
43
  className: className,
41
44
  "data-testid": dataTestId,
42
45
  disabled: disabled,
43
- error: getError({
44
- label: typeof label === 'string' ? label : ''
45
- }, error),
46
+ error: error,
46
47
  id: id,
47
- onChange: () => {
48
- field.onChange(value);
49
- onChange?.(value);
48
+ name: input.name,
49
+ onChange: event => {
50
+ input.onChange(event);
51
+ onChange?.(event);
50
52
  },
51
53
  onBlur: event => {
52
- field.onBlur();
54
+ input.onBlur(event);
53
55
  onBlur?.(event);
54
56
  },
55
- onFocus: onFocus,
57
+ onFocus: event => {
58
+ input.onFocus(event);
59
+ onFocus?.(event);
60
+ },
56
61
  required: required,
57
- value: value ?? '',
62
+ value: input.value,
58
63
  label: label,
59
64
  tooltip: tooltip
60
65
  });
@@ -1,7 +1,7 @@
1
1
  import { RadioGroup } from '@ultraviolet/ui';
2
- import { useController } from 'react-hook-form';
3
2
  import { jsx } from '@emotion/react/jsx-runtime';
4
3
  import { useErrors } from '../../providers/ErrorContext/index.js';
4
+ import { useFormField } from '../../hooks/useFormField.js';
5
5
 
6
6
  const RadioGroupField = _ref => {
7
7
  let {
@@ -10,9 +10,9 @@ const RadioGroupField = _ref => {
10
10
  name,
11
11
  onChange,
12
12
  required,
13
- rules,
13
+ validate,
14
+ value,
14
15
  children,
15
- label = '',
16
16
  error: customError,
17
17
  helper,
18
18
  direction
@@ -21,27 +21,30 @@ const RadioGroupField = _ref => {
21
21
  getError
22
22
  } = useErrors();
23
23
  const {
24
- field,
25
- fieldState: {
26
- error
27
- }
28
- } = useController({
24
+ input,
25
+ meta
26
+ } = useFormField(name, {
27
+ required,
28
+ validate,
29
+ value
30
+ });
31
+ const error = getError({
32
+ label: legend,
33
+ meta: meta,
29
34
  name,
30
- rules
35
+ value: input.value
31
36
  });
32
37
  return jsx(RadioGroup, {
33
38
  className: className,
34
- name: field.name,
39
+ name: input.name,
35
40
  onChange: event => {
36
- field.onChange(event);
37
- onChange?.(event.target.value);
41
+ input.onChange(event);
42
+ onChange?.(event);
38
43
  },
39
44
  required: required,
40
- value: field.value,
45
+ value: input.value,
41
46
  legend: legend,
42
- error: getError({
43
- label
44
- }, error) ?? customError,
47
+ error: error ?? customError,
45
48
  helper: helper,
46
49
  direction: direction,
47
50
  children: children