@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.4.0",
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.26.0",
17
- "@graphcommerce/react-hook-form": "3.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"