@graphcommerce/ecommerce-ui 1.3.3 → 1.5.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/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @graphcommerce/ecommerce-ui
2
2
 
3
+ ## 1.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#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.
8
+
9
+ Which allows you to fully compose the form on the product page without having to modify the page.
10
+
11
+ ### Patch Changes
12
+
13
+ - [#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
14
+
15
+ - Updated dependencies [[`ad63ebf4e`](https://github.com/graphcommerce-org/graphcommerce/commit/ad63ebf4e33bfb0e5c9e5e68ab69b14775f3f8a8)]:
16
+ - @graphcommerce/next-ui@4.27.0
17
+
18
+ ## 1.4.0
19
+
20
+ ### Minor Changes
21
+
22
+ - [#1645](https://github.com/graphcommerce-org/graphcommerce/pull/1645) [`fad7b6b48`](https://github.com/graphcommerce-org/graphcommerce/commit/fad7b6b48732fd631599c17abd8961de3f49c7dc) Thanks [@Jessevdpoel](https://github.com/Jessevdpoel)! - Export all react-hook-form-mui components
23
+
24
+ ### Patch Changes
25
+
26
+ - Updated dependencies [[`42e7fac75`](https://github.com/graphcommerce-org/graphcommerce/commit/42e7fac75712f9bda7a6b919ede14b3c75d07771)]:
27
+ - @graphcommerce/next-ui@4.26.0
28
+
3
29
  ## 1.3.3
4
30
 
5
31
  ### Patch Changes
@@ -0,0 +1,120 @@
1
+ import {
2
+ extendableComponent,
3
+ iconMin,
4
+ iconPlus,
5
+ IconSvg,
6
+ responsiveVal,
7
+ } from '@graphcommerce/next-ui'
8
+ import { FieldValues } from '@graphcommerce/react-hook-form'
9
+ import { i18n } from '@lingui/core'
10
+ import {
11
+ IconButton,
12
+ IconButtonProps,
13
+ SxProps,
14
+ useForkRef,
15
+ Theme,
16
+ useEventCallback,
17
+ } from '@mui/material'
18
+ import { ChangeEvent, Ref, useRef } from 'react'
19
+ import { TextFieldElement, TextFieldElementProps } from './TextFieldElement'
20
+
21
+ export type NumberFieldElementProps<T extends FieldValues = FieldValues> = Omit<
22
+ TextFieldElementProps<T>,
23
+ 'type'
24
+ > & {
25
+ DownProps?: IconButtonProps
26
+ UpProps?: IconButtonProps
27
+ sx?: SxProps<Theme>
28
+ }
29
+
30
+ type OwnerState = { size?: 'small' | 'medium' }
31
+ const name = 'TextInputNumber' as const
32
+ const parts = ['quantity', 'quantityInput', 'button'] as const
33
+ const { withState } = extendableComponent<OwnerState, typeof name, typeof parts>(name, parts)
34
+
35
+ export function NumberFieldElement<T extends FieldValues = FieldValues>(
36
+ props: NumberFieldElementProps<T>,
37
+ ) {
38
+ const {
39
+ DownProps = {},
40
+ UpProps = {},
41
+ inputProps = {},
42
+ inputRef,
43
+ sx = [],
44
+ size = 'medium',
45
+ ...textFieldProps
46
+ } = props
47
+
48
+ const classes = withState({ size })
49
+ const ref = useRef<HTMLInputElement>(null)
50
+ const forkRef = useForkRef(ref, inputRef as Ref<HTMLInputElement>)
51
+
52
+ return (
53
+ <TextFieldElement
54
+ {...textFieldProps}
55
+ size={size}
56
+ type='number'
57
+ inputRef={forkRef}
58
+ className={`${textFieldProps.className ?? ''} ${classes.quantity}`}
59
+ sx={[{ width: responsiveVal(80, 120) }, ...(Array.isArray(sx) ? sx : [sx])]}
60
+ autoComplete='off'
61
+ InputProps={{
62
+ ...textFieldProps.InputProps,
63
+ startAdornment: (
64
+ <IconButton
65
+ aria-label={i18n._(/* i18n */ 'Decrease')}
66
+ size='medium'
67
+ edge='start'
68
+ onClick={useEventCallback(() => {
69
+ if ((ref.current?.value ?? Infinity) >= inputProps.max) return
70
+
71
+ ref.current?.stepUp()
72
+ ref.current?.dispatchEvent(new Event('change', { bubbles: true }))
73
+ })}
74
+ tabIndex={-1}
75
+ color='inherit'
76
+ {...DownProps}
77
+ className={`${classes.button} ${DownProps.className ?? ''}`}
78
+ >
79
+ {DownProps.children ?? <IconSvg src={iconMin} size='small' />}
80
+ </IconButton>
81
+ ),
82
+ endAdornment: (
83
+ <IconButton
84
+ aria-label={i18n._(/* i18n */ 'Increase')}
85
+ size='medium'
86
+ edge='end'
87
+ onClick={useEventCallback(() => {
88
+ if ((ref.current?.value ?? 0) <= inputProps.min) return
89
+
90
+ ref.current?.stepDown()
91
+ ref.current?.dispatchEvent(new Event('change', { bubbles: true }))
92
+ })}
93
+ tabIndex={-1}
94
+ color='inherit'
95
+ {...UpProps}
96
+ className={`${classes.button} ${UpProps.className ?? ''}`}
97
+ >
98
+ {UpProps.children ?? <IconSvg src={iconPlus} size='small' />}
99
+ </IconButton>
100
+ ),
101
+ }}
102
+ onChange={(e: ChangeEvent<HTMLInputElement>) => {
103
+ if (textFieldProps.onChange) textFieldProps.onChange(e)
104
+ }}
105
+ inputProps={{
106
+ ...inputProps,
107
+ 'aria-label': i18n._(/* i18n */ 'Number'),
108
+ sx: [
109
+ {
110
+ textAlign: 'center',
111
+ '&::-webkit-inner-spin-button,&::-webkit-outer-spin-button': {
112
+ appearance: 'none',
113
+ },
114
+ },
115
+ ],
116
+ className: `${inputProps?.className ?? ''} ${classes.quantityInput}`,
117
+ }}
118
+ />
119
+ )
120
+ }
@@ -0,0 +1,73 @@
1
+ import {
2
+ Controller,
3
+ ControllerProps,
4
+ FieldError,
5
+ FieldValues,
6
+ } from '@graphcommerce/react-hook-form'
7
+ import { TextField, TextFieldProps } from '@mui/material'
8
+
9
+ export type TextFieldElementProps<T extends FieldValues = FieldValues> = Omit<
10
+ TextFieldProps,
11
+ 'name' | 'defaultValue'
12
+ > & {
13
+ validation?: ControllerProps['rules']
14
+ parseError?: (error: FieldError) => string
15
+ } & Pick<ControllerProps<T>, 'control' | 'defaultValue' | 'name'>
16
+
17
+ /** This is a copy of the default one, but allowing defaultValue */
18
+ export function TextFieldElement<TFieldValues extends FieldValues = FieldValues>({
19
+ validation = {},
20
+ parseError,
21
+ type,
22
+ required,
23
+ name,
24
+ control,
25
+ defaultValue,
26
+ ...rest
27
+ }: TextFieldElementProps<TFieldValues>): JSX.Element {
28
+ if (required && !validation.required) {
29
+ validation.required = 'This field is required'
30
+ }
31
+
32
+ if (type === 'email' && !validation.pattern) {
33
+ validation.pattern = {
34
+ // eslint-disable-next-line no-useless-escape
35
+ value:
36
+ /^(([^<>()\[\]\\.,;:\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,}))$/,
37
+ message: 'Please enter a valid email address',
38
+ }
39
+ }
40
+
41
+ return (
42
+ <Controller
43
+ name={name}
44
+ control={control}
45
+ rules={validation}
46
+ defaultValue={defaultValue}
47
+ render={({ field: { value, onChange, onBlur }, fieldState: { invalid, error } }) => (
48
+ <TextField
49
+ {...rest}
50
+ name={name}
51
+ value={value ?? ''}
52
+ onChange={(ev) => {
53
+ onChange(ev)
54
+ if (typeof rest.onChange === 'function') {
55
+ rest?.onChange(ev)
56
+ }
57
+ }}
58
+ onBlur={onBlur}
59
+ required={required}
60
+ type={type}
61
+ error={invalid}
62
+ helperText={
63
+ error
64
+ ? typeof parseError === 'function'
65
+ ? parseError(error)
66
+ : error.message
67
+ : rest.helperText
68
+ }
69
+ />
70
+ )}
71
+ />
72
+ )
73
+ }
@@ -1,2 +1,29 @@
1
- export { TextFieldElement, SelectElement } from 'react-hook-form-mui'
2
- export type { TextFieldElementProps, SelectElementProps } from 'react-hook-form-mui'
1
+ export {
2
+ AutocompleteElement,
3
+ CheckboxButtonGroup,
4
+ CheckboxElement,
5
+ MultiSelectElement,
6
+ PasswordElement,
7
+ PasswordRepeatElement,
8
+ RadioButtonGroup,
9
+ SelectElement,
10
+ SliderElement,
11
+ SwitchElement,
12
+ ToggleButtonGroupElement,
13
+ } from 'react-hook-form-mui'
14
+ export type {
15
+ AutocompleteElementProps,
16
+ CheckboxButtonGroupProps,
17
+ CheckboxElementProps,
18
+ MultiSelectElementProps,
19
+ PasswordElementProps,
20
+ PasswordRepeatElementProps,
21
+ RadioButtonGroupProps,
22
+ SelectElementProps,
23
+ SliderElementProps,
24
+ SwitchElementProps,
25
+ ToggleButtonGroupElementProps,
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.3.3",
5
+ "version": "1.5.0",
6
6
  "sideEffects": false,
7
7
  "prettier": "@graphcommerce/prettier-config-pwa",
8
8
  "eslintConfig": {
@@ -13,7 +13,7 @@
13
13
  },
14
14
  "dependencies": {
15
15
  "@graphcommerce/graphql": "3.4.8",
16
- "@graphcommerce/next-ui": "4.25.0",
16
+ "@graphcommerce/next-ui": "4.27.0",
17
17
  "@graphcommerce/react-hook-form": "3.3.3",
18
18
  "@mui/icons-material": "^5.10.3",
19
19
  "@mui/x-date-pickers": "^5.0.0",