@ultraviolet/form 2.0.0-next.2 → 2.0.0-next.4

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 { Controller } 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,58 +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
- return jsx(Controller, {
29
- name: name,
30
- disabled: disabled,
31
- rules: {
32
- required,
33
- ...rules
29
+ const {
30
+ input,
31
+ meta
32
+ } = useFormField(name, {
33
+ disabled,
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
44
+ });
45
+ return jsx(Checkbox, {
46
+ name: input.name,
47
+ onChange: event => {
48
+ input.onChange(event);
49
+ onChange?.(event);
34
50
  },
35
- render: _ref2 => {
36
- let {
37
- field,
38
- fieldState: {
39
- error
40
- }
41
- } = _ref2;
42
- return jsx(Checkbox, {
43
- name: field.name,
44
- onChange: event => {
45
- field.onChange(value ? [...(field.value ?? []), value] : event.target.checked);
46
- onChange?.(event);
47
- },
48
- onBlur: event => {
49
- field.onBlur();
50
- onBlur?.(event);
51
- },
52
- onFocus: onFocus,
53
- size: size,
54
- progress: progress,
55
- disabled: field.disabled,
56
- checked: Array.isArray(field.value) ? field.value.includes(value) : !!field.value,
57
- error: getError({
58
- label: label ?? ''
59
- }, error),
60
- ref: field.ref,
61
- className: className,
62
- required: required,
63
- "data-testid": dataTestId,
64
- helper: helper,
65
- tooltip: tooltip,
66
- value: value,
67
- children: children
68
- });
69
- }
51
+ onBlur: event => {
52
+ input.onBlur(event);
53
+ onBlur?.(event);
54
+ },
55
+ onFocus: event => {
56
+ input.onFocus(event);
57
+ onFocus?.(event);
58
+ },
59
+ size: size,
60
+ progress: progress,
61
+ disabled: disabled,
62
+ checked: input.checked,
63
+ error: error,
64
+ helper: helper,
65
+ ref: ref,
66
+ className: className,
67
+ value: input.value,
68
+ required: required,
69
+ "data-testid": dataTestId,
70
+ tooltip: tooltip,
71
+ children: children
70
72
  });
71
- };
73
+ });
72
74
 
73
75
  export { CheckboxField };
@@ -1,17 +1,17 @@
1
1
  import { CheckboxGroup } from '@ultraviolet/ui';
2
- import { Controller } 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
@@ -19,38 +19,38 @@ const CheckboxGroupField = _ref => {
19
19
  const {
20
20
  getError
21
21
  } = useErrors();
22
- return jsx(Controller, {
23
- name: name,
24
- render: _ref2 => {
25
- let {
26
- field,
27
- fieldState: {
28
- error
29
- }
30
- } = _ref2;
31
- return jsx(CheckboxGroup, {
32
- legend: legend,
33
- name: name,
34
- value: field.value,
35
- onChange: event => {
36
- const fieldValue = field.value;
37
- if (fieldValue?.includes(event.currentTarget.value)) {
38
- field.onChange(fieldValue?.filter(currentValue => currentValue !== event.currentTarget.value));
39
- } else {
40
- field.onChange([...field.value, event.currentTarget.value]);
41
- }
42
- onChange?.(event);
43
- },
44
- error: getError({
45
- label
46
- }, error) ?? customError,
47
- className: className,
48
- direction: direction,
49
- helper: helper,
50
- required: required,
51
- children: children
52
- });
53
- }
22
+ const {
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,
34
+ name
35
+ });
36
+ return jsx(CheckboxGroup, {
37
+ legend: legend,
38
+ name: fields.name,
39
+ value: fields.value,
40
+ onChange: event => {
41
+ if (fields.value?.includes(event.currentTarget.value)) {
42
+ fields.remove(fields.value.indexOf(event.currentTarget?.value));
43
+ } else {
44
+ fields.push(event.currentTarget.value);
45
+ }
46
+ onChange?.(event);
47
+ },
48
+ error: error ?? customError,
49
+ className: className,
50
+ direction: direction,
51
+ helper: helper,
52
+ required: required,
53
+ children: children
54
54
  });
55
55
  };
56
56
  CheckboxGroupField.Checkbox = CheckboxGroup.Checkbox;
@@ -1,9 +1,7 @@
1
1
  import { DateInput } from '@ultraviolet/ui';
2
- import { Controller } 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,
@@ -29,64 +30,67 @@ const DateField = _ref => {
29
30
  const {
30
31
  getError
31
32
  } = useErrors();
32
- return jsx(Controller, {
33
- name: name,
34
- rules: {
35
- ...rules,
36
- validate: {
37
- ...rules?.validate,
38
- minDate: minDateValidator(minDate),
39
- maxDate: maxDateValidator(maxDate)
40
- },
41
- required
42
- },
43
- render: _ref2 => {
44
- let {
45
- field,
46
- fieldState: {
47
- error
33
+ const {
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,
51
+ name,
52
+ value: input.value
53
+ });
54
+ return jsx(DateInput, {
55
+ label: label,
56
+ format: format || (value => value ? parseDate(value).toLocaleDateString() : ''),
57
+ locale: locale,
58
+ required: required,
59
+ value: input.value,
60
+ onChange: val => {
61
+ if (val && val instanceof Date) {
62
+ onChange?.(val);
63
+ const newDate = parseDate(val);
64
+ if (isEmpty(input.value)) {
65
+ input.onChange(newDate);
66
+ return;
48
67
  }
49
- } = _ref2;
50
- return jsx(DateInput, {
51
- name: field.name,
52
- label: label,
53
- value: field.value,
54
- format: format || (value => value ? parseDate(value).toLocaleDateString() : ''),
55
- locale: locale,
56
- required: required,
57
- onChange: val => {
58
- if (val && val instanceof Date) {
59
- onChange?.(val);
60
- const newDate = parseDate(val);
61
- if (isEmpty(field.value)) {
62
- field.onChange(newDate);
63
- return;
64
- }
65
- const currentDate = parseDate(field.value);
66
- newDate.setHours(currentDate.getHours(), currentDate.getMinutes());
67
- field.onChange(newDate);
68
- }
69
- },
70
- onBlur: e => {
71
- field.onBlur();
72
- onBlur?.(e);
73
- },
74
- onFocus: onFocus,
75
- maxDate: maxDate,
76
- minDate: minDate,
77
- error: getError({
78
- minDate,
79
- maxDate,
80
- label
81
- }, error),
82
- disabled: disabled,
83
- autoFocus: autoFocus,
84
- excludeDates: excludeDates,
85
- "data-testid": dataTestId,
86
- startDate: selectsRange ? field.value[0] : undefined,
87
- endDate: selectsRange ? field.value[1] : undefined
88
- });
89
- }
68
+ const currentDate = parseDate(input.value);
69
+ newDate.setHours(currentDate.getHours(), currentDate.getMinutes());
70
+ input.onChange(newDate);
71
+ } else if (Array.isArray(val)) {
72
+ input.onChange(val);
73
+ }
74
+ },
75
+ onBlur: e => {
76
+ input.onBlur(e);
77
+ onBlur?.(e);
78
+ },
79
+ onFocus: e => {
80
+ input.onFocus(e);
81
+ onFocus?.(e);
82
+ },
83
+ maxDate: maxDate,
84
+ minDate: minDate,
85
+ startDate: selectsRange ? input.value[0] : undefined,
86
+ endDate: selectsRange ? input.value[1] : undefined,
87
+ error: error,
88
+ disabled: disabled,
89
+ autoFocus: autoFocus,
90
+ name: input.name,
91
+ "data-testid": dataTestId,
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 { Controller } 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,58 +17,48 @@ 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
- return jsx(Controller, {
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
36
+ });
37
+ return jsx(NumberInput, {
29
38
  name: name,
30
- rules: {
31
- required,
32
- max: maxValue,
33
- min: minValue,
34
- ...rules
39
+ disabled: disabled,
40
+ onBlur: event => {
41
+ input.onBlur(event);
42
+ onBlur?.(event);
43
+ },
44
+ onChange: event => {
45
+ input.onChange(event);
46
+ onChange?.(event);
47
+ },
48
+ onFocus: event => {
49
+ input.onFocus(event);
50
+ onFocus?.(event);
35
51
  },
36
- render: _ref2 => {
37
- let {
38
- field,
39
- fieldState: {
40
- error
41
- }
42
- } = _ref2;
43
- return jsx(NumberInput, {
44
- name: field.name,
45
- value: field.value,
46
- disabled: disabled,
47
- onBlur: event => {
48
- field.onBlur();
49
- onBlur?.(event);
50
- },
51
- onChange: event => {
52
- // React hook form doesnt allow undefined values after definition https://react-hook-form.com/docs/usecontroller/controller (that make sense)
53
- field.onChange(event ?? null);
54
- onChange?.(event);
55
- },
56
- onFocus: onFocus,
57
- maxValue: maxValue,
58
- minValue: minValue,
59
- onMinCrossed: onMinCrossed,
60
- onMaxCrossed: onMaxCrossed,
61
- size: size,
62
- step: step,
63
- text: text,
64
- className: className,
65
- label: label,
66
- error: getError({
67
- label: label ?? '',
68
- max: maxValue,
69
- min: minValue
70
- }, error)
71
- });
72
- }
52
+ maxValue: maxValue,
53
+ minValue: minValue,
54
+ onMinCrossed: onMinCrossed,
55
+ onMaxCrossed: onMaxCrossed,
56
+ size: size,
57
+ step: step,
58
+ text: text,
59
+ value: input.value,
60
+ className: className,
61
+ "data-testid": dataTestId
73
62
  });
74
63
  };
75
64