@graphcommerce/ecommerce-ui 8.1.0-canary.9 → 9.0.0-canary.100

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,10 +1,4 @@
1
- /* eslint-disable @typescript-eslint/no-restricted-imports */
2
- import {
3
- FieldError,
4
- useController,
5
- FieldValues,
6
- UseControllerProps,
7
- } from '@graphcommerce/react-hook-form'
1
+ import { useController, FieldValues, UseControllerProps } from '@graphcommerce/react-hook-form'
8
2
  import { i18n } from '@lingui/core'
9
3
  import {
10
4
  Checkbox,
@@ -21,8 +15,6 @@ export type CheckboxButtonGroupProps<T extends FieldValues> = {
21
15
  options: { id: string | number; label: string }[] | any[]
22
16
  helperText?: string
23
17
  required?: boolean
24
- /** @deprecated Form value parsing should happen in the handleSubmit function of the form */
25
- parseError?: (error: FieldError) => string
26
18
  label?: string
27
19
  labelKey?: string
28
20
  valueKey?: string
@@ -33,22 +25,27 @@ export type CheckboxButtonGroupProps<T extends FieldValues> = {
33
25
  checkboxColor?: CheckboxProps['color']
34
26
  } & UseControllerProps<T>
35
27
 
36
- export function CheckboxButtonGroup<TFieldValues extends FieldValues>({
37
- helperText,
38
- options,
39
- label,
40
- name,
41
- parseError,
42
- required,
43
- labelKey = 'label',
44
- valueKey = 'id',
45
- returnObject,
46
- disabled,
47
- row,
48
- control,
49
- checkboxColor,
50
- ...rest
51
- }: CheckboxButtonGroupProps<TFieldValues>): JSX.Element {
28
+ export function CheckboxButtonGroup<TFieldValues extends FieldValues>(
29
+ props: CheckboxButtonGroupProps<TFieldValues>,
30
+ ): JSX.Element {
31
+ const {
32
+ helperText,
33
+ options,
34
+ label,
35
+ name,
36
+ required,
37
+ labelKey = 'label',
38
+ valueKey = 'id',
39
+ returnObject,
40
+ disabled,
41
+ row,
42
+ control,
43
+ checkboxColor,
44
+ defaultValue,
45
+ shouldUnregister,
46
+ ...rest
47
+ } = props
48
+
52
49
  const theme = useTheme()
53
50
  const {
54
51
  field: { value = [], onChange },
@@ -57,13 +54,12 @@ export function CheckboxButtonGroup<TFieldValues extends FieldValues>({
57
54
  name,
58
55
  rules: required ? { required: i18n._(/* i18n */ 'This field is required') } : undefined,
59
56
  control,
57
+ defaultValue,
58
+ disabled,
59
+ shouldUnregister,
60
60
  })
61
61
 
62
- helperText = error
63
- ? typeof parseError === 'function'
64
- ? parseError(error)
65
- : error.message
66
- : helperText
62
+ const parsedHelperText = error ? error.message : helperText
67
63
 
68
64
  const handleChange = (index: number | string) => {
69
65
  const newArray: (string | number)[] | any[] = [...value]
@@ -120,7 +116,7 @@ export function CheckboxButtonGroup<TFieldValues extends FieldValues>({
120
116
  )
121
117
  })}
122
118
  </FormGroup>
123
- {helperText && <FormHelperText>{helperText}</FormHelperText>}
119
+ {parsedHelperText && <FormHelperText>{parsedHelperText}</FormHelperText>}
124
120
  </FormControl>
125
121
  )
126
122
  }
@@ -1,9 +1,4 @@
1
- import {
2
- Controller,
3
- ControllerProps,
4
- FieldError,
5
- FieldValues,
6
- } from '@graphcommerce/react-hook-form'
1
+ import { ControllerProps, FieldValues, useController } from '@graphcommerce/react-hook-form'
7
2
  import { i18n } from '@lingui/core'
8
3
  import {
9
4
  Checkbox,
@@ -19,70 +14,71 @@ import {
19
14
  } from '@mui/material'
20
15
 
21
16
  export type CheckboxElementProps<T extends FieldValues> = Omit<CheckboxProps, 'name'> & {
22
- /** @deprecated Form value parsing should happen in the handleSubmit function of the form */
23
- parseError?: (error: FieldError) => string
24
17
  label?: FormControlLabelProps['label']
25
18
  helperText?: string
26
19
  sx?: SxProps<Theme>
27
20
  formControl?: Omit<FormControlProps<'div'>, 'required' | 'error'>
28
21
  } & Omit<ControllerProps<T>, 'render'>
29
22
 
30
- export function CheckboxElement<TFieldValues extends FieldValues>({
31
- name,
32
- rules = {},
33
- required,
34
- parseError,
35
- label,
36
- control,
37
- helperText,
38
- sx,
39
- formControl,
40
- ...rest
41
- }: CheckboxElementProps<TFieldValues>): JSX.Element {
23
+ export function CheckboxElement<TFieldValues extends FieldValues>(
24
+ props: CheckboxElementProps<TFieldValues>,
25
+ ): JSX.Element {
26
+ const {
27
+ name,
28
+ rules = {},
29
+ required,
30
+ label,
31
+ control,
32
+ helperText,
33
+ sx,
34
+ formControl,
35
+ defaultValue,
36
+ disabled,
37
+ shouldUnregister,
38
+ ...rest
39
+ } = props
40
+
42
41
  if (required && !rules.required) {
43
42
  rules.required = i18n._(/* i18n */ 'This field is required')
44
43
  }
45
44
 
45
+ const {
46
+ field: { value, onChange, ref, ...field },
47
+ fieldState: { invalid, error },
48
+ } = useController({
49
+ name,
50
+ rules,
51
+ control,
52
+ defaultValue,
53
+ disabled,
54
+ shouldUnregister,
55
+ })
56
+
57
+ const parsedHelperText = error ? error.message : helperText
58
+
46
59
  return (
47
- <Controller
48
- name={name}
49
- rules={rules}
50
- control={control}
51
- render={({ field: { value, onChange, ref, ...field }, fieldState: { invalid, error } }) => {
52
- // eslint-disable-next-line no-nested-ternary
53
- const parsedHelperText = error
54
- ? typeof parseError === 'function'
55
- ? parseError(error)
56
- : error.message
57
- : helperText
58
- return (
59
- <FormControl required={required} error={invalid} {...formControl}>
60
- <FormGroup row>
61
- <FormControlLabel
62
- label={label || ''}
63
- control={
64
- <Checkbox
65
- {...rest}
66
- {...field}
67
- inputRef={ref}
68
- color={rest.color || 'primary'}
69
- sx={{
70
- ...(Array.isArray(sx) ? sx : [sx]),
71
- color: invalid ? 'error.main' : undefined,
72
- }}
73
- value={value}
74
- checked={!!value}
75
- onChange={() => onChange(!value)}
76
- />
77
- }
78
- />
79
- </FormGroup>
80
- {parsedHelperText && (
81
- <FormHelperText error={invalid}>{parsedHelperText}</FormHelperText>
82
- )}
83
- </FormControl>
84
- )
85
- }}
86
- />
60
+ <FormControl required={required} error={invalid} {...formControl}>
61
+ <FormGroup row>
62
+ <FormControlLabel
63
+ label={label || ''}
64
+ control={
65
+ <Checkbox
66
+ {...rest}
67
+ {...field}
68
+ inputRef={ref}
69
+ color={rest.color || 'primary'}
70
+ sx={{
71
+ ...(Array.isArray(sx) ? sx : [sx]),
72
+ color: invalid ? 'error.main' : undefined,
73
+ }}
74
+ value={value}
75
+ checked={!!value}
76
+ onChange={() => onChange(!value)}
77
+ />
78
+ }
79
+ />
80
+ </FormGroup>
81
+ {parsedHelperText && <FormHelperText error={invalid}>{parsedHelperText}</FormHelperText>}
82
+ </FormControl>
87
83
  )
88
84
  }
@@ -0,0 +1,27 @@
1
+ import { emailPattern, FieldValues } from '@graphcommerce/react-hook-form'
2
+ import { i18n } from '@lingui/core'
3
+ import { Trans } from '@lingui/react'
4
+ import { TextFieldElement, TextFieldElementProps } from './TextFieldElement'
5
+
6
+ export type EmailElementProps<T extends FieldValues> = TextFieldElementProps<T>
7
+
8
+ export function EmailElement<TFieldValues extends FieldValues>(
9
+ props: EmailElementProps<TFieldValues>,
10
+ ): JSX.Element {
11
+ const { rules, ...rest } = props
12
+ return (
13
+ <TextFieldElement
14
+ type='email'
15
+ label={<Trans id='Email address' />}
16
+ autoComplete='email'
17
+ rules={{
18
+ pattern: {
19
+ value: emailPattern,
20
+ message: i18n._(/* i18n */ 'Please enter a valid email address'),
21
+ },
22
+ ...rules,
23
+ }}
24
+ {...rest}
25
+ />
26
+ )
27
+ }
@@ -1,11 +1,6 @@
1
1
  /* eslint-disable no-nested-ternary */
2
2
  import { IconSvg, iconClose } from '@graphcommerce/next-ui'
3
- import {
4
- Controller,
5
- FieldError,
6
- FieldValues,
7
- ControllerProps,
8
- } from '@graphcommerce/react-hook-form'
3
+ import { FieldValues, ControllerProps, useController } from '@graphcommerce/react-hook-form'
9
4
  import { i18n } from '@lingui/core'
10
5
  import {
11
6
  Checkbox,
@@ -27,8 +22,6 @@ export type MultiSelectElementProps<T extends FieldValues> = Omit<SelectProps, '
27
22
  itemValue?: string
28
23
  itemLabel?: string
29
24
  required?: boolean
30
- /** @deprecated Form value parsing should happen in the handleSubmit function of the form */
31
- parseError?: (error: FieldError) => string
32
25
  minWidth?: number
33
26
  menuMaxHeight?: number
34
27
  menuMaxWidth?: number
@@ -44,7 +37,7 @@ const ITEM_PADDING_TOP = 8
44
37
  export function MultiSelectElement<TFieldValues extends FieldValues>(
45
38
  props: MultiSelectElementProps<TFieldValues>,
46
39
  ): JSX.Element {
47
- let {
40
+ const {
48
41
  options,
49
42
  label = '',
50
43
  itemKey = 'id',
@@ -52,7 +45,6 @@ export function MultiSelectElement<TFieldValues extends FieldValues>(
52
45
  itemLabel = 'label',
53
46
  required = false,
54
47
  rules = {},
55
- parseError,
56
48
  name,
57
49
  menuMaxHeight = ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
58
50
  menuMaxWidth = 250,
@@ -62,114 +54,115 @@ export function MultiSelectElement<TFieldValues extends FieldValues>(
62
54
  control,
63
55
  showCheckbox,
64
56
  formControlProps,
57
+ shouldUnregister,
58
+ defaultValue,
59
+ disabled,
65
60
  ...rest
66
61
  } = props
67
62
  if (required && !rules.required) {
68
63
  rules.required = i18n._(/* i18n */ 'This field is required')
69
64
  }
70
65
 
66
+ const {
67
+ field: { value, onChange, ...field },
68
+ fieldState: { invalid, error },
69
+ } = useController({
70
+ name,
71
+ rules,
72
+ control,
73
+ defaultValue,
74
+ disabled,
75
+ shouldUnregister,
76
+ })
77
+
78
+ const parsedHelperText = error ? error.message : helperText
79
+
71
80
  return (
72
- <Controller
73
- name={name}
74
- rules={rules}
75
- control={control}
76
- render={({ field: { value, onChange, ...field }, fieldState: { invalid, error } }) => {
77
- helperText = error
78
- ? typeof parseError === 'function'
79
- ? parseError(error)
80
- : error.message
81
- : helperText
82
- return (
83
- <FormControl
84
- {...formControlProps}
85
- style={{
86
- ...formControlProps?.style,
87
- minWidth,
88
- }}
89
- variant={rest.variant}
90
- fullWidth={rest.fullWidth}
91
- error={invalid}
92
- size={rest.size}
93
- >
94
- {label && (
95
- <InputLabel
96
- size={rest.size === 'small' ? 'small' : undefined}
97
- error={invalid}
98
- htmlFor={rest.id || `select-multi-select-${name}`}
99
- required={required}
100
- >
101
- {label}
102
- </InputLabel>
103
- )}
104
- <Select
105
- {...rest}
106
- {...field}
107
- id={rest.id || `select-multi-select-${name}`}
108
- multiple
109
- label={label || undefined}
110
- error={invalid}
111
- value={value || []}
112
- required={required}
113
- onChange={onChange}
114
- MenuProps={{
115
- ...rest.MenuProps,
116
- PaperProps: {
117
- ...(rest.MenuProps?.PaperProps ?? {
118
- style: {
119
- maxHeight: menuMaxHeight,
120
- width: menuMaxWidth,
121
- ...rest.MenuProps?.PaperProps?.style,
122
- },
123
- }),
124
- },
81
+ <FormControl
82
+ {...formControlProps}
83
+ style={{
84
+ ...formControlProps?.style,
85
+ minWidth,
86
+ }}
87
+ variant={rest.variant}
88
+ fullWidth={rest.fullWidth}
89
+ error={invalid}
90
+ size={rest.size}
91
+ >
92
+ {label && (
93
+ <InputLabel
94
+ size={rest.size === 'small' ? 'small' : undefined}
95
+ error={invalid}
96
+ htmlFor={rest.id || `select-multi-select-${name}`}
97
+ required={required}
98
+ >
99
+ {label}
100
+ </InputLabel>
101
+ )}
102
+ <Select
103
+ {...rest}
104
+ {...field}
105
+ id={rest.id || `select-multi-select-${name}`}
106
+ multiple
107
+ label={label || undefined}
108
+ error={invalid}
109
+ value={value || []}
110
+ required={required}
111
+ onChange={onChange}
112
+ MenuProps={{
113
+ ...rest.MenuProps,
114
+ PaperProps: {
115
+ ...(rest.MenuProps?.PaperProps ?? {
116
+ style: {
117
+ maxHeight: menuMaxHeight,
118
+ width: menuMaxWidth,
119
+ ...rest.MenuProps?.PaperProps?.style,
120
+ },
121
+ }),
122
+ },
123
+ }}
124
+ renderValue={
125
+ typeof rest.renderValue === 'function'
126
+ ? rest.renderValue
127
+ : showChips
128
+ ? (selected) => (
129
+ <div style={{ display: 'flex', flexWrap: 'wrap' }}>
130
+ {((selected as any[]) || []).map((selectedValue) => (
131
+ <Chip
132
+ key={selectedValue}
133
+ label={selectedValue}
134
+ style={{ display: 'flex', flexWrap: 'wrap' }}
135
+ onDelete={() => {
136
+ onChange(value.filter((i: any) => i !== selectedValue))
137
+ // setValue(name, formValue.filter((i: any) => i !== value), { shouldValidate: true })
138
+ }}
139
+ deleteIcon={<IconSvg src={iconClose} />}
140
+ />
141
+ ))}
142
+ </div>
143
+ )
144
+ : (selected) => (Array.isArray(selected) ? selected.join(', ') : '')
145
+ }
146
+ >
147
+ {options.map((item) => {
148
+ const val: string | number = item[itemValue || itemKey] || item
149
+ const isChecked = Array.isArray(value) ? value.includes(val) : false
150
+ return (
151
+ <MenuItem
152
+ key={val}
153
+ value={val}
154
+ sx={{
155
+ fontWeight: (theme) =>
156
+ isChecked ? theme.typography.fontWeightBold : theme.typography.fontWeightRegular,
125
157
  }}
126
- renderValue={
127
- typeof rest.renderValue === 'function'
128
- ? rest.renderValue
129
- : showChips
130
- ? (selected) => (
131
- <div style={{ display: 'flex', flexWrap: 'wrap' }}>
132
- {((selected as any[]) || []).map((selectedValue) => (
133
- <Chip
134
- key={selectedValue}
135
- label={selectedValue}
136
- style={{ display: 'flex', flexWrap: 'wrap' }}
137
- onDelete={() => {
138
- onChange(value.filter((i: any) => i !== selectedValue))
139
- // setValue(name, formValue.filter((i: any) => i !== value), { shouldValidate: true })
140
- }}
141
- deleteIcon={<IconSvg src={iconClose} />}
142
- />
143
- ))}
144
- </div>
145
- )
146
- : (selected) => (Array.isArray(selected) ? selected.join(', ') : '')
147
- }
148
158
  >
149
- {options.map((item) => {
150
- const val: string | number = item[itemValue || itemKey] || item
151
- const isChecked = Array.isArray(value) ? value.includes(val) : false
152
- return (
153
- <MenuItem
154
- key={val}
155
- value={val}
156
- sx={{
157
- fontWeight: (theme) =>
158
- isChecked
159
- ? theme.typography.fontWeightBold
160
- : theme.typography.fontWeightRegular,
161
- }}
162
- >
163
- {showCheckbox && <Checkbox checked={isChecked} />}
164
- <ListItemText primary={item[itemLabel] || item} />
165
- </MenuItem>
166
- )
167
- })}
168
- </Select>
169
- {helperText && <FormHelperText>{helperText}</FormHelperText>}
170
- </FormControl>
171
- )
172
- }}
173
- />
159
+ {showCheckbox && <Checkbox checked={isChecked} />}
160
+ <ListItemText primary={item[itemLabel] || item} />
161
+ </MenuItem>
162
+ )
163
+ })}
164
+ </Select>
165
+ {parsedHelperText && <FormHelperText>{parsedHelperText}</FormHelperText>}
166
+ </FormControl>
174
167
  )
175
168
  }
@@ -44,6 +44,8 @@ export function NumberFieldElement<T extends FieldValues>(props: NumberFieldElem
44
44
  required,
45
45
  defaultValue,
46
46
  variant = 'outlined',
47
+ disabled,
48
+ shouldUnregister,
47
49
  ...textFieldProps
48
50
  } = props
49
51
 
@@ -61,6 +63,8 @@ export function NumberFieldElement<T extends FieldValues>(props: NumberFieldElem
61
63
  control,
62
64
  rules,
63
65
  defaultValue,
66
+ disabled,
67
+ shouldUnregister,
64
68
  })
65
69
 
66
70
  const valueAsNumber = value ? parseFloat(value) : 0
@@ -115,7 +119,11 @@ export function NumberFieldElement<T extends FieldValues>(props: NumberFieldElem
115
119
  aria-label={i18n._(/* i18n */ 'Decrease')}
116
120
  size='smaller'
117
121
  onClick={() => {
118
- if ((valueAsNumber || Infinity) <= inputProps.min) return
122
+ if (
123
+ (valueAsNumber ?? Infinity) <= inputProps.min ||
124
+ (inputProps.min === 0 && valueAsNumber <= inputProps.min)
125
+ )
126
+ return
119
127
  onChange(value - 1)
120
128
  }}
121
129
  sx={{
@@ -1,9 +1,4 @@
1
- import {
2
- FieldError,
3
- useController,
4
- FieldValues,
5
- UseControllerProps,
6
- } from '@graphcommerce/react-hook-form'
1
+ import { useController, FieldValues, UseControllerProps } from '@graphcommerce/react-hook-form'
7
2
  import { i18n } from '@lingui/core'
8
3
  import {
9
4
  FormControl,
@@ -20,8 +15,6 @@ export type RadioButtonGroupProps<T extends FieldValues> = {
20
15
  options: { label: string; id: string | number }[] | any[]
21
16
  helperText?: string
22
17
  required?: boolean
23
- /** @deprecated Form value parsing should happen in the handleSubmit function of the form */
24
- parseError?: (error: FieldError) => string
25
18
  label?: string
26
19
  labelKey?: string
27
20
  valueKey?: string
@@ -32,21 +25,27 @@ export type RadioButtonGroupProps<T extends FieldValues> = {
32
25
  row?: boolean
33
26
  } & UseControllerProps<T>
34
27
 
35
- export function RadioButtonGroup<TFieldValues extends FieldValues>({
36
- helperText,
37
- options,
38
- label,
39
- name,
40
- parseError,
41
- labelKey = 'label',
42
- valueKey = 'id',
43
- required,
44
- emptyOptionLabel,
45
- returnObject,
46
- row,
47
- control,
48
- ...rest
49
- }: RadioButtonGroupProps<TFieldValues>): JSX.Element {
28
+ export function RadioButtonGroup<TFieldValues extends FieldValues>(
29
+ props: RadioButtonGroupProps<TFieldValues>,
30
+ ): JSX.Element {
31
+ const {
32
+ helperText,
33
+ options,
34
+ label,
35
+ name,
36
+ labelKey = 'label',
37
+ valueKey = 'id',
38
+ required,
39
+ emptyOptionLabel,
40
+ returnObject,
41
+ row,
42
+ control,
43
+ defaultValue,
44
+ disabled,
45
+ shouldUnregister,
46
+ ...rest
47
+ } = props
48
+
50
49
  const theme = useTheme()
51
50
  const {
52
51
  field: { value, onChange },
@@ -55,13 +54,12 @@ export function RadioButtonGroup<TFieldValues extends FieldValues>({
55
54
  name,
56
55
  rules: required ? { required: i18n._(/* i18n */ 'This field is required') } : undefined,
57
56
  control,
57
+ defaultValue,
58
+ disabled,
59
+ shouldUnregister,
58
60
  })
59
61
 
60
- helperText = error
61
- ? typeof parseError === 'function'
62
- ? parseError(error)
63
- : error.message
64
- : helperText
62
+ const parsedHelperText = error ? error.message : helperText
65
63
 
66
64
  const onRadioChange = (event: ChangeEvent<HTMLInputElement>) => {
67
65
  const radioValue = (event.target as HTMLInputElement).value
@@ -125,7 +123,7 @@ export function RadioButtonGroup<TFieldValues extends FieldValues>({
125
123
  )
126
124
  })}
127
125
  </RadioGroup>
128
- {helperText && <FormHelperText>{helperText}</FormHelperText>}
126
+ {parsedHelperText && <FormHelperText>{parsedHelperText}</FormHelperText>}
129
127
  </FormControl>
130
128
  )
131
129
  }