@ultraviolet/form 2.0.0-next.8 → 2.0.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.
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![npm version](https://badge.fury.io/js/%40ultraviolet%2Fform.svg)](https://badge.fury.io/js/%40ultraviolet%2Fform)
4
4
 
5
5
  Ultraviolet Form is an extension of Ultraviolet UI including everything to build forms using React.
6
- It is using [React Final Form](https://final-form.org/react) under the hood.
6
+ It is using [React Hook Form](https://react-hook-form.com/) under the hood.
7
7
 
8
8
  ## Installation
9
9
 
@@ -19,11 +19,13 @@ To use the library you need to put a `ThemeProvider` from `@emotion/react` with
19
19
  import { ThemeProvider } from '@emotion/react'
20
20
  import { Form, TextInputField } from '@ultraviolet/form'
21
21
  import { theme } from '@ultraviolet/ui'
22
+ import { useForm } from '@ultraviolet/form'
22
23
 
23
24
  export default function App() {
25
+ const methods = useForm()
24
26
  return (
25
27
  <ThemeProvider theme={theme}>
26
- <Form>
28
+ <Form methods={methods}>
27
29
  <TextInputField name="example" />
28
30
  </Form>
29
31
  </ThemeProvider>
@@ -31,16 +33,6 @@ export default function App() {
31
33
  }
32
34
  ```
33
35
 
34
- ## Contribute
35
-
36
- ### Add a validator
37
-
38
- - Create a file under `src/validators/` folder
39
- - Export a default function with a type : (arg: unknown) => ValidatorObject
40
- - Export it into `src/validators/index.ts`
41
- - Add the key into the `ValidatorProps` type in `src/types.ts`
42
- - Add tests into `src/validators/__tests__` folder
43
-
44
36
  ## Documentation
45
37
 
46
38
  Checkout our [documentation website](https://storybook.ultraviolet.scaleway.com/).
@@ -3,26 +3,25 @@ import { useController } from 'react-hook-form';
3
3
  import { jsx } from '@emotion/react/jsx-runtime';
4
4
  import { useErrors } from '../../providers/ErrorContext/index.js';
5
5
 
6
- const CheckboxField = _ref => {
7
- let {
8
- name,
9
- label,
10
- size,
11
- progress,
12
- disabled,
13
- required,
14
- className,
15
- children,
16
- onChange,
17
- onBlur,
18
- onFocus,
19
- rules,
20
- helper,
21
- tooltip,
22
- 'data-testid': dataTestId,
23
- value,
24
- shouldUnregister = false
25
- } = _ref;
6
+ const CheckboxField = ({
7
+ name,
8
+ label,
9
+ size,
10
+ progress,
11
+ disabled,
12
+ required,
13
+ className,
14
+ children,
15
+ onChange,
16
+ onBlur,
17
+ onFocus,
18
+ rules,
19
+ helper,
20
+ tooltip,
21
+ 'data-testid': dataTestId,
22
+ value,
23
+ shouldUnregister = false
24
+ }) => {
26
25
  const {
27
26
  getError
28
27
  } = useErrors();
@@ -3,20 +3,19 @@ import { useController } from 'react-hook-form';
3
3
  import { jsx } from '@emotion/react/jsx-runtime';
4
4
  import { useErrors } from '../../providers/ErrorContext/index.js';
5
5
 
6
- const CheckboxGroupField = _ref => {
7
- let {
8
- legend,
9
- className,
10
- helper,
11
- direction,
12
- children,
13
- onChange,
14
- label = '',
15
- error: customError,
16
- name,
17
- required = false,
18
- shouldUnregister = false
19
- } = _ref;
6
+ const CheckboxGroupField = ({
7
+ legend,
8
+ className,
9
+ helper,
10
+ direction,
11
+ children,
12
+ onChange,
13
+ label = '',
14
+ error: customError,
15
+ name,
16
+ required = false,
17
+ shouldUnregister = false
18
+ }) => {
20
19
  const {
21
20
  getError
22
21
  } = useErrors();
@@ -7,26 +7,25 @@ import { useErrors } from '../../providers/ErrorContext/index.js';
7
7
 
8
8
  const parseDate = value => typeof value === 'string' ? new Date(value) : value;
9
9
  const isEmpty = value => typeof value === 'string' ? value === '' : value === undefined;
10
- const DateField = _ref => {
11
- let {
12
- required,
13
- name,
14
- label = '',
15
- format,
16
- locale,
17
- maxDate,
18
- minDate,
19
- disabled,
20
- onChange,
21
- onBlur,
22
- onFocus,
23
- rules,
24
- autoFocus = false,
25
- excludeDates,
26
- selectsRange,
27
- 'data-testid': dataTestId,
28
- shouldUnregister = false
29
- } = _ref;
10
+ const DateField = ({
11
+ required,
12
+ name,
13
+ label = '',
14
+ format,
15
+ locale,
16
+ maxDate,
17
+ minDate,
18
+ disabled,
19
+ onChange,
20
+ onBlur,
21
+ onFocus,
22
+ rules,
23
+ autoFocus = false,
24
+ excludeDates,
25
+ selectsRange,
26
+ 'data-testid': dataTestId,
27
+ shouldUnregister = false
28
+ }) => {
30
29
  const {
31
30
  getError
32
31
  } = useErrors();
@@ -6,15 +6,14 @@ import { jsx } from '@emotion/react/jsx-runtime';
6
6
  import { ErrorProvider } from '../../providers/ErrorContext/index.js';
7
7
 
8
8
  const FormSubmitContext = /*#__PURE__*/React.createContext({});
9
- const Form = _ref => {
10
- let {
11
- children,
12
- methods: methodsProp,
13
- initialValues,
14
- errors,
15
- onRawSubmit,
16
- name
17
- } = _ref;
9
+ const Form = ({
10
+ children,
11
+ methods: methodsProp,
12
+ initialValues,
13
+ errors,
14
+ onRawSubmit,
15
+ name
16
+ }) => {
18
17
  const methodsHook = useForm({
19
18
  defaultValues: initialValues,
20
19
  mode: 'onChange'
@@ -3,26 +3,25 @@ import { useController } from 'react-hook-form';
3
3
  import { jsx } from '@emotion/react/jsx-runtime';
4
4
  import { useErrors } from '../../providers/ErrorContext/index.js';
5
5
 
6
- const NumberInputField = _ref => {
7
- let {
8
- disabled,
9
- maxValue,
10
- minValue,
11
- name,
12
- onChange,
13
- onBlur,
14
- onFocus,
15
- onMaxCrossed,
16
- onMinCrossed,
17
- required,
18
- size,
19
- step,
20
- text,
21
- rules,
22
- className,
23
- label,
24
- shouldUnregister = false
25
- } = _ref;
6
+ const NumberInputField = ({
7
+ disabled,
8
+ maxValue,
9
+ minValue,
10
+ name,
11
+ onChange,
12
+ onBlur,
13
+ onFocus,
14
+ onMaxCrossed,
15
+ onMinCrossed,
16
+ required,
17
+ size,
18
+ step,
19
+ text,
20
+ rules,
21
+ className,
22
+ label,
23
+ shouldUnregister = false
24
+ }) => {
26
25
  const {
27
26
  getError
28
27
  } = useErrors();
@@ -3,23 +3,22 @@ import { useController } from 'react-hook-form';
3
3
  import { jsx } from '@emotion/react/jsx-runtime';
4
4
  import { useErrors } from '../../providers/ErrorContext/index.js';
5
5
 
6
- const RadioField = _ref => {
7
- let {
8
- className,
9
- 'data-testid': dataTestId,
10
- disabled,
11
- id,
12
- name,
13
- onBlur,
14
- label = '',
15
- onChange,
16
- onFocus,
17
- required,
18
- value,
19
- rules,
20
- tooltip,
21
- shouldUnregister = false
22
- } = _ref;
6
+ const RadioField = ({
7
+ className,
8
+ 'data-testid': dataTestId,
9
+ disabled,
10
+ id,
11
+ name,
12
+ onBlur,
13
+ label = '',
14
+ onChange,
15
+ onFocus,
16
+ required,
17
+ value,
18
+ rules,
19
+ tooltip,
20
+ shouldUnregister = false
21
+ }) => {
23
22
  const {
24
23
  getError
25
24
  } = useErrors();
@@ -3,21 +3,20 @@ import { useController } from 'react-hook-form';
3
3
  import { jsx } from '@emotion/react/jsx-runtime';
4
4
  import { useErrors } from '../../providers/ErrorContext/index.js';
5
5
 
6
- const RadioGroupField = _ref => {
7
- let {
8
- className,
9
- legend = '',
10
- name,
11
- onChange,
12
- required,
13
- rules,
14
- children,
15
- label = '',
16
- error: customError,
17
- helper,
18
- direction,
19
- shouldUnregister = false
20
- } = _ref;
6
+ const RadioGroupField = ({
7
+ className,
8
+ legend = '',
9
+ name,
10
+ onChange,
11
+ required,
12
+ rules,
13
+ children,
14
+ label = '',
15
+ error: customError,
16
+ helper,
17
+ direction,
18
+ shouldUnregister = false
19
+ }) => {
21
20
  const {
22
21
  getError
23
22
  } = useErrors();
@@ -7,54 +7,51 @@ import { useErrors } from '../../providers/ErrorContext/index.js';
7
7
  const identity = x => x;
8
8
  // const identity = <T,>(x: T) => x
9
9
 
10
- const SelectInputField = _ref => {
11
- let {
12
- animation,
13
- animationDuration,
14
- animationOnChange,
15
- children,
16
- className,
17
- disabled,
18
- // error: errorProp,
19
- format: formatProp = identity,
20
- // formatOnBlur,
21
- id,
22
- inputId,
23
- isClearable,
24
- isLoading,
25
- isSearchable,
26
- label = '',
27
- maxLength,
28
- menuPortalTarget,
29
- minLength,
30
- multiple,
31
- name,
32
- onBlur,
33
- onChange,
34
- onFocus,
35
- options: optionsProp,
36
- parse: parseProp = identity,
37
- placeholder,
38
- readOnly,
39
- required,
40
- rules,
41
- noTopLabel,
42
- noOptionsMessage,
43
- customStyle,
44
- shouldUnregister = false
45
- } = _ref;
46
- const options = useMemo(() => optionsProp || Children.toArray(children).flat().filter(Boolean).map(_ref2 => {
47
- let {
48
- props: {
49
- children: labelChild,
50
- ...option
51
- }
52
- } = _ref2;
53
- return {
54
- ...option,
55
- label: labelChild
56
- };
57
- }), [optionsProp, children]);
10
+ const SelectInputField = ({
11
+ animation,
12
+ animationDuration,
13
+ animationOnChange,
14
+ children,
15
+ className,
16
+ disabled,
17
+ // error: errorProp,
18
+ format: formatProp = identity,
19
+ // formatOnBlur,
20
+ id,
21
+ inputId,
22
+ isClearable,
23
+ isLoading,
24
+ isSearchable,
25
+ label = '',
26
+ maxLength,
27
+ menuPortalTarget,
28
+ minLength,
29
+ multiple,
30
+ name,
31
+ onBlur,
32
+ onChange,
33
+ onFocus,
34
+ options: optionsProp,
35
+ parse: parseProp = identity,
36
+ placeholder,
37
+ readOnly,
38
+ required,
39
+ rules,
40
+ noTopLabel,
41
+ noOptionsMessage,
42
+ customStyle,
43
+ shouldUnregister = false,
44
+ 'data-testid': dataTestId
45
+ }) => {
46
+ const options = useMemo(() => optionsProp || Children.toArray(children).flat().filter(Boolean).map(({
47
+ props: {
48
+ children: labelChild,
49
+ ...option
50
+ }
51
+ }) => ({
52
+ ...option,
53
+ label: labelChild
54
+ })), [optionsProp, children]);
58
55
  const parse = useMemo(() => multiple ? parseProp : option => parseProp(option?.value ?? null, name), [multiple, parseProp, name]);
59
56
  const format = useCallback(val => {
60
57
  if (multiple) return formatProp(val, name);
@@ -126,6 +123,7 @@ const SelectInputField = _ref => {
126
123
  required: required,
127
124
  value: format(field.value),
128
125
  noOptionsMessage: noOptionsMessage,
126
+ "data-testid": dataTestId,
129
127
  children: children
130
128
  });
131
129
  };
@@ -2,25 +2,25 @@ import { SelectableCard } from '@ultraviolet/ui';
2
2
  import { useController } from 'react-hook-form';
3
3
  import { jsx } from '@emotion/react/jsx-runtime';
4
4
 
5
- const SelectableCardField = _ref => {
6
- let {
7
- name,
8
- value,
9
- onChange,
10
- showTick,
11
- type,
12
- disabled,
13
- children,
14
- className,
15
- onFocus,
16
- onBlur,
17
- required,
18
- tooltip,
19
- id,
20
- label,
21
- rules,
22
- shouldUnregister = false
23
- } = _ref;
5
+ const SelectableCardField = ({
6
+ name,
7
+ value,
8
+ onChange,
9
+ showTick,
10
+ type,
11
+ disabled,
12
+ children,
13
+ className,
14
+ onFocus,
15
+ onBlur,
16
+ required,
17
+ tooltip,
18
+ id,
19
+ label,
20
+ rules,
21
+ shouldUnregister = false,
22
+ 'data-testid': dataTestId
23
+ }) => {
24
24
  const {
25
25
  field,
26
26
  fieldState: {
@@ -34,14 +34,24 @@ const SelectableCardField = _ref => {
34
34
  ...rules
35
35
  }
36
36
  });
37
+ const isChecked = type === 'checkbox' && Array.isArray(field.value) && value ? (field.value ?? []).includes(value) : field.value === value;
37
38
  return jsx(SelectableCard, {
38
39
  isError: !!error,
39
40
  showTick: showTick,
40
- checked: field.value === value,
41
+ checked: isChecked,
41
42
  className: className,
42
43
  disabled: disabled,
43
44
  onChange: event => {
44
- field.onChange(event);
45
+ if (type === 'checkbox') {
46
+ const fieldValue = field.value ?? [];
47
+ if (fieldValue?.includes(event.currentTarget.value)) {
48
+ field.onChange(fieldValue?.filter(currentValue => currentValue !== event.currentTarget.value));
49
+ } else {
50
+ field.onChange([...fieldValue, event.currentTarget.value]);
51
+ }
52
+ } else {
53
+ field.onChange(event);
54
+ }
45
55
  onChange?.(event);
46
56
  },
47
57
  onBlur: event => {
@@ -57,6 +67,7 @@ const SelectableCardField = _ref => {
57
67
  label: label,
58
68
  value: value ?? '',
59
69
  name: field.name,
70
+ "data-testid": dataTestId,
60
71
  children: children
61
72
  });
62
73
  };
@@ -2,20 +2,19 @@ import { Button } from '@ultraviolet/ui';
2
2
  import { useFormState } from 'react-hook-form';
3
3
  import { jsx } from '@emotion/react/jsx-runtime';
4
4
 
5
- const Submit = _ref => {
6
- let {
7
- children,
8
- className,
9
- disabled = false,
10
- icon,
11
- iconPosition,
12
- size,
13
- variant = 'filled',
14
- sentiment = 'primary',
15
- tooltip,
16
- fullWidth,
17
- onClick
18
- } = _ref;
5
+ const Submit = ({
6
+ children,
7
+ className,
8
+ disabled = false,
9
+ icon,
10
+ iconPosition,
11
+ size,
12
+ variant = 'filled',
13
+ sentiment = 'primary',
14
+ tooltip,
15
+ fullWidth,
16
+ onClick
17
+ }) => {
19
18
  const {
20
19
  isSubmitting,
21
20
  isValid
@@ -2,10 +2,9 @@ import { Alert } from '@ultraviolet/ui';
2
2
  import { useFormState } from 'react-hook-form';
3
3
  import { jsx } from '@emotion/react/jsx-runtime';
4
4
 
5
- const SubmitErrorAlert = _ref => {
6
- let {
7
- className
8
- } = _ref;
5
+ const SubmitErrorAlert = ({
6
+ className
7
+ }) => {
9
8
  const {
10
9
  errors
11
10
  } = useFormState();
@@ -2,19 +2,19 @@ import { TagInput } from '@ultraviolet/ui';
2
2
  import { useController } from 'react-hook-form';
3
3
  import { jsx } from '@emotion/react/jsx-runtime';
4
4
 
5
- const TagInputField = _ref => {
6
- let {
7
- className,
8
- disabled,
9
- id,
10
- name,
11
- onChange,
12
- placeholder,
13
- required,
14
- rules,
15
- variant,
16
- shouldUnregister = false
17
- } = _ref;
5
+ const TagInputField = ({
6
+ className,
7
+ disabled,
8
+ id,
9
+ name,
10
+ onChange,
11
+ placeholder,
12
+ required,
13
+ rules,
14
+ variant,
15
+ shouldUnregister = false,
16
+ 'data-testid': dataTestId
17
+ }) => {
18
18
  const {
19
19
  field
20
20
  } = useController({
@@ -36,7 +36,8 @@ const TagInputField = _ref => {
36
36
  },
37
37
  placeholder: placeholder,
38
38
  variant: variant,
39
- tags: field.value
39
+ tags: field.value,
40
+ "data-testid": dataTestId
40
41
  });
41
42
  };
42
43