@graphcommerce/ecommerce-ui 1.4.0 → 1.5.1
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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @graphcommerce/ecommerce-ui
|
|
2
2
|
|
|
3
|
+
## 1.5.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#1660](https://github.com/graphcommerce-org/graphcommerce/pull/1660) [`e5048c5ec`](https://github.com/graphcommerce-org/graphcommerce/commit/e5048c5ec52b83dbe70a246ffdcea65b55a884c6) Thanks [@paales](https://github.com/paales)! - Flatten the NumberFieldElement to use the Controller directly
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`75ae24a93`](https://github.com/graphcommerce-org/graphcommerce/commit/75ae24a93bd74e3b9b7efda21ec7ba6fbe9a3a75)]:
|
|
10
|
+
- @graphcommerce/react-hook-form@3.3.4
|
|
11
|
+
|
|
12
|
+
## 1.5.0
|
|
13
|
+
|
|
14
|
+
### Minor Changes
|
|
15
|
+
|
|
16
|
+
- [#1642](https://github.com/graphcommerce-org/graphcommerce/pull/1642) [`ad63ebf4e`](https://github.com/graphcommerce-org/graphcommerce/commit/ad63ebf4e33bfb0e5c9e5e68ab69b14775f3f8a8) Thanks [@paales](https://github.com/paales)! - Introduced `<AddProductsToCartForm/>`, which is allows for adding all product types to the cart with a single react-hook-form form.
|
|
17
|
+
|
|
18
|
+
Which allows you to fully compose the form on the product page without having to modify the page.
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- [#1642](https://github.com/graphcommerce-org/graphcommerce/pull/1642) [`9e6fd498e`](https://github.com/graphcommerce-org/graphcommerce/commit/9e6fd498e3242ab30602767ae77a8e22f80d9fd3) Thanks [@paales](https://github.com/paales)! - Support for defaultValue for TextFieldElement
|
|
23
|
+
|
|
24
|
+
- Updated dependencies [[`ad63ebf4e`](https://github.com/graphcommerce-org/graphcommerce/commit/ad63ebf4e33bfb0e5c9e5e68ab69b14775f3f8a8)]:
|
|
25
|
+
- @graphcommerce/next-ui@4.27.0
|
|
26
|
+
|
|
3
27
|
## 1.4.0
|
|
4
28
|
|
|
5
29
|
### Minor Changes
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import {
|
|
2
|
+
extendableComponent,
|
|
3
|
+
iconMin,
|
|
4
|
+
iconPlus,
|
|
5
|
+
IconSvg,
|
|
6
|
+
responsiveVal,
|
|
7
|
+
} from '@graphcommerce/next-ui'
|
|
8
|
+
import { Controller, ControllerProps, FieldValues } from '@graphcommerce/react-hook-form'
|
|
9
|
+
import { i18n } from '@lingui/core'
|
|
10
|
+
import {
|
|
11
|
+
IconButton,
|
|
12
|
+
IconButtonProps,
|
|
13
|
+
SxProps,
|
|
14
|
+
Theme,
|
|
15
|
+
TextField,
|
|
16
|
+
TextFieldProps,
|
|
17
|
+
} from '@mui/material'
|
|
18
|
+
|
|
19
|
+
export type NumberFieldElementProps<T extends FieldValues = FieldValues> = Omit<
|
|
20
|
+
TextFieldProps,
|
|
21
|
+
'type' | 'defaultValue'
|
|
22
|
+
> & {
|
|
23
|
+
DownProps?: IconButtonProps
|
|
24
|
+
UpProps?: IconButtonProps
|
|
25
|
+
sx?: SxProps<Theme>
|
|
26
|
+
} & Omit<ControllerProps<T>, 'render'>
|
|
27
|
+
|
|
28
|
+
type OwnerState = { size?: 'small' | 'medium' }
|
|
29
|
+
const componentName = 'TextInputNumber' as const
|
|
30
|
+
const parts = ['quantity', 'quantityInput', 'button'] as const
|
|
31
|
+
const { withState } = extendableComponent<OwnerState, typeof componentName, typeof parts>(
|
|
32
|
+
componentName,
|
|
33
|
+
parts,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
export function NumberFieldElement<T extends FieldValues = FieldValues>(
|
|
37
|
+
props: NumberFieldElementProps<T>,
|
|
38
|
+
) {
|
|
39
|
+
const {
|
|
40
|
+
DownProps = {},
|
|
41
|
+
UpProps = {},
|
|
42
|
+
inputProps = {},
|
|
43
|
+
sx = [],
|
|
44
|
+
size = 'medium',
|
|
45
|
+
control,
|
|
46
|
+
name,
|
|
47
|
+
rules = {},
|
|
48
|
+
required,
|
|
49
|
+
defaultValue,
|
|
50
|
+
...textFieldProps
|
|
51
|
+
} = props
|
|
52
|
+
|
|
53
|
+
const classes = withState({ size })
|
|
54
|
+
|
|
55
|
+
if (required && !rules.required) {
|
|
56
|
+
rules.required = i18n._(/* i18n */ 'This field is required')
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<Controller
|
|
61
|
+
name={name}
|
|
62
|
+
control={control}
|
|
63
|
+
rules={rules}
|
|
64
|
+
defaultValue={defaultValue}
|
|
65
|
+
render={({ field: { value, onChange, onBlur }, fieldState: { invalid, error } }) => {
|
|
66
|
+
const valueAsNumber = value ? parseFloat(value) : 0
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<TextField
|
|
70
|
+
{...textFieldProps}
|
|
71
|
+
name={name}
|
|
72
|
+
value={value ?? ''}
|
|
73
|
+
onChange={(ev) => {
|
|
74
|
+
const newValue = (ev.target as HTMLInputElement).valueAsNumber
|
|
75
|
+
onChange(Number.isNaN(newValue) ? '' : newValue)
|
|
76
|
+
textFieldProps.onChange?.(ev)
|
|
77
|
+
}}
|
|
78
|
+
onBlur={onBlur}
|
|
79
|
+
required={required}
|
|
80
|
+
error={invalid}
|
|
81
|
+
helperText={error ? error.message : textFieldProps.helperText}
|
|
82
|
+
size={size}
|
|
83
|
+
type='number'
|
|
84
|
+
className={`${textFieldProps.className ?? ''} ${classes.quantity}`}
|
|
85
|
+
sx={[{ width: responsiveVal(80, 120) }, ...(Array.isArray(sx) ? sx : [sx])]}
|
|
86
|
+
autoComplete='off'
|
|
87
|
+
InputProps={{
|
|
88
|
+
...textFieldProps.InputProps,
|
|
89
|
+
startAdornment: (
|
|
90
|
+
<IconButton
|
|
91
|
+
aria-label={i18n._(/* i18n */ 'Decrease')}
|
|
92
|
+
size='medium'
|
|
93
|
+
edge='start'
|
|
94
|
+
onClick={() => {
|
|
95
|
+
if ((valueAsNumber || Infinity) <= inputProps.min) return
|
|
96
|
+
onChange(value - 1)
|
|
97
|
+
}}
|
|
98
|
+
tabIndex={-1}
|
|
99
|
+
color='inherit'
|
|
100
|
+
{...DownProps}
|
|
101
|
+
className={`${classes.button} ${DownProps.className ?? ''}`}
|
|
102
|
+
>
|
|
103
|
+
{DownProps.children ?? <IconSvg src={iconMin} size='small' />}
|
|
104
|
+
</IconButton>
|
|
105
|
+
),
|
|
106
|
+
endAdornment: (
|
|
107
|
+
<IconButton
|
|
108
|
+
aria-label={i18n._(/* i18n */ 'Increase')}
|
|
109
|
+
size='medium'
|
|
110
|
+
edge='end'
|
|
111
|
+
onClick={() => {
|
|
112
|
+
if (valueAsNumber >= (inputProps.max ?? Infinity)) return
|
|
113
|
+
onChange(valueAsNumber + 1)
|
|
114
|
+
}}
|
|
115
|
+
tabIndex={-1}
|
|
116
|
+
color='inherit'
|
|
117
|
+
{...UpProps}
|
|
118
|
+
className={`${classes.button} ${UpProps.className ?? ''}`}
|
|
119
|
+
>
|
|
120
|
+
{UpProps.children ?? <IconSvg src={iconPlus} size='small' />}
|
|
121
|
+
</IconButton>
|
|
122
|
+
),
|
|
123
|
+
}}
|
|
124
|
+
inputProps={{
|
|
125
|
+
...inputProps,
|
|
126
|
+
'aria-label': i18n._(/* i18n */ 'Number'),
|
|
127
|
+
className: `${inputProps?.className ?? ''} ${classes.quantityInput}`,
|
|
128
|
+
sx: {
|
|
129
|
+
textAlign: 'center',
|
|
130
|
+
'&::-webkit-inner-spin-button,&::-webkit-outer-spin-button': {
|
|
131
|
+
appearance: 'none',
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
}}
|
|
135
|
+
/>
|
|
136
|
+
)
|
|
137
|
+
}}
|
|
138
|
+
/>
|
|
139
|
+
)
|
|
140
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Controller,
|
|
3
|
+
ControllerProps,
|
|
4
|
+
FieldError,
|
|
5
|
+
FieldValues,
|
|
6
|
+
} from '@graphcommerce/react-hook-form'
|
|
7
|
+
import { i18n } from '@lingui/core'
|
|
8
|
+
import { TextField, TextFieldProps } from '@mui/material'
|
|
9
|
+
|
|
10
|
+
export type TextFieldElementProps<T extends FieldValues = FieldValues> = Omit<
|
|
11
|
+
TextFieldProps,
|
|
12
|
+
'name' | 'defaultValue'
|
|
13
|
+
> & {
|
|
14
|
+
validation?: ControllerProps['rules']
|
|
15
|
+
parseError?: (error: FieldError) => string
|
|
16
|
+
} & Pick<ControllerProps<T>, 'control' | 'defaultValue' | 'name'>
|
|
17
|
+
|
|
18
|
+
/** This is a copy of the default one, but allowing defaultValue */
|
|
19
|
+
export function TextFieldElement<TFieldValues extends FieldValues = FieldValues>({
|
|
20
|
+
validation = {},
|
|
21
|
+
parseError,
|
|
22
|
+
type,
|
|
23
|
+
required,
|
|
24
|
+
name,
|
|
25
|
+
control,
|
|
26
|
+
defaultValue,
|
|
27
|
+
...rest
|
|
28
|
+
}: TextFieldElementProps<TFieldValues>): JSX.Element {
|
|
29
|
+
if (required && !validation.required) {
|
|
30
|
+
validation.required = i18n._(/* i18n */ 'This field is required')
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (type === 'email' && !validation.pattern) {
|
|
34
|
+
validation.pattern = {
|
|
35
|
+
// eslint-disable-next-line no-useless-escape
|
|
36
|
+
value:
|
|
37
|
+
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
|
|
38
|
+
message: 'Please enter a valid email address',
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<Controller
|
|
44
|
+
name={name}
|
|
45
|
+
control={control}
|
|
46
|
+
rules={validation}
|
|
47
|
+
defaultValue={defaultValue}
|
|
48
|
+
render={({ field: { value, onChange, onBlur }, fieldState: { invalid, error } }) => (
|
|
49
|
+
<TextField
|
|
50
|
+
{...rest}
|
|
51
|
+
name={name}
|
|
52
|
+
value={value ?? ''}
|
|
53
|
+
onChange={(ev) => {
|
|
54
|
+
onChange(ev)
|
|
55
|
+
if (typeof rest.onChange === 'function') {
|
|
56
|
+
rest?.onChange(ev)
|
|
57
|
+
}
|
|
58
|
+
}}
|
|
59
|
+
onBlur={onBlur}
|
|
60
|
+
required={required}
|
|
61
|
+
type={type}
|
|
62
|
+
error={invalid}
|
|
63
|
+
helperText={
|
|
64
|
+
error
|
|
65
|
+
? typeof parseError === 'function'
|
|
66
|
+
? parseError(error)
|
|
67
|
+
: error.message
|
|
68
|
+
: rest.helperText
|
|
69
|
+
}
|
|
70
|
+
/>
|
|
71
|
+
)}
|
|
72
|
+
/>
|
|
73
|
+
)
|
|
74
|
+
}
|
|
@@ -9,7 +9,6 @@ export {
|
|
|
9
9
|
SelectElement,
|
|
10
10
|
SliderElement,
|
|
11
11
|
SwitchElement,
|
|
12
|
-
TextFieldElement,
|
|
13
12
|
ToggleButtonGroupElement,
|
|
14
13
|
} from 'react-hook-form-mui'
|
|
15
14
|
export type {
|
|
@@ -23,6 +22,8 @@ export type {
|
|
|
23
22
|
SelectElementProps,
|
|
24
23
|
SliderElementProps,
|
|
25
24
|
SwitchElementProps,
|
|
26
|
-
TextFieldElementProps,
|
|
27
25
|
ToggleButtonGroupElementProps,
|
|
28
26
|
} from 'react-hook-form-mui'
|
|
27
|
+
|
|
28
|
+
export * from './TextFieldElement'
|
|
29
|
+
export * from './NumberFieldElement'
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@graphcommerce/ecommerce-ui",
|
|
3
3
|
"homepage": "https://www.graphcommerce.org/",
|
|
4
4
|
"repository": "github:graphcommerce-org/graphcommerce",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.5.1",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"prettier": "@graphcommerce/prettier-config-pwa",
|
|
8
8
|
"eslintConfig": {
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@graphcommerce/graphql": "3.4.8",
|
|
16
|
-
"@graphcommerce/next-ui": "4.
|
|
17
|
-
"@graphcommerce/react-hook-form": "3.3.
|
|
16
|
+
"@graphcommerce/next-ui": "4.27.0",
|
|
17
|
+
"@graphcommerce/react-hook-form": "3.3.4",
|
|
18
18
|
"@mui/icons-material": "^5.10.3",
|
|
19
19
|
"@mui/x-date-pickers": "^5.0.0",
|
|
20
20
|
"react-hook-form-mui": "^5.7.1"
|