@graphcommerce/ecommerce-ui 9.0.0-canary.99 → 9.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.
Files changed (35) hide show
  1. package/CHANGELOG.md +61 -946
  2. package/Config.graphqls +6 -0
  3. package/components/ApolloError/ApolloErrorAlert.tsx +3 -3
  4. package/components/ApolloError/ApolloErrorFullPage.tsx +4 -3
  5. package/components/ApolloError/ApolloErrorSnackbar.tsx +4 -3
  6. package/components/ApolloError/maskNetworkError.tsx +1 -1
  7. package/components/ComposedSubmitButton/ComposedSubmitButton.tsx +4 -3
  8. package/components/ComposedSubmitButton/ComposedSubmitLinkOrButton.tsx +4 -3
  9. package/components/FormComponents/ActionCardListForm.tsx +25 -13
  10. package/components/FormComponents/CheckboxButtonGroup.tsx +12 -3
  11. package/components/FormComponents/CheckboxElement.tsx +12 -7
  12. package/components/FormComponents/EmailElement.tsx +5 -2
  13. package/components/FormComponents/InputBaseElement.tsx +54 -0
  14. package/components/FormComponents/MultiSelectElement.tsx +8 -4
  15. package/components/FormComponents/NumberFieldElement.tsx +21 -15
  16. package/components/FormComponents/PasswordElement.tsx +8 -4
  17. package/components/FormComponents/PasswordRepeatElement.tsx +5 -2
  18. package/components/FormComponents/RadioButtonGroup.tsx +7 -3
  19. package/components/FormComponents/SelectElement.tsx +8 -12
  20. package/components/FormComponents/SliderElement.tsx +5 -14
  21. package/components/FormComponents/SwitchElement.tsx +5 -2
  22. package/components/FormComponents/TelephoneElement.tsx +6 -3
  23. package/components/FormComponents/TextFieldElement.tsx +22 -13
  24. package/components/FormComponents/ToggleButtonGroup.tsx +7 -12
  25. package/components/FormComponents/index.ts +1 -1
  26. package/components/PreviewMode/LightTooltip.tsx +1 -1
  27. package/components/PreviewMode/PreviewMode.tsx +14 -10
  28. package/components/PreviewMode/PreviewModeActions.tsx +2 -2
  29. package/components/PreviewMode/PreviewModeToolbar.tsx +1 -1
  30. package/components/PreviewMode/previewModeDefaults.ts +1 -1
  31. package/components/PreviewMode/usePreviewModeForm.ts +1 -1
  32. package/components/WaitForQueries/WaitForQueries.tsx +3 -6
  33. package/package.json +8 -8
  34. package/route/preview.ts +2 -2
  35. package/components/FormComponents/AutoCompleteElement.tsx +0 -169
package/Config.graphqls CHANGED
@@ -4,7 +4,13 @@ enum WebsitePermissions {
4
4
  # DISABLED will be implemented later
5
5
  }
6
6
 
7
+ """
8
+ Permissions input
9
+ """
7
10
  input GraphCommercePermissions {
11
+ """
12
+ Allows the option to require login or completely disable the site.
13
+ """
8
14
  website: WebsitePermissions
9
15
  }
10
16
 
@@ -1,7 +1,7 @@
1
- import { ApolloError } from '@graphcommerce/graphql'
1
+ import type { ApolloError } from '@graphcommerce/graphql'
2
2
  import { extendableComponent } from '@graphcommerce/next-ui/Styles/extendableComponent'
3
- import { Trans } from '@lingui/react'
4
- import { AlertProps, Alert, Box, SxProps, Theme } from '@mui/material'
3
+ import type { AlertProps, SxProps, Theme } from '@mui/material'
4
+ import { Alert, Box } from '@mui/material'
5
5
  import { maskNetworkError } from './maskNetworkError'
6
6
 
7
7
  const { classes, selectors } = extendableComponent('ApolloErrorAlert', ['root', 'alert'] as const)
@@ -1,7 +1,8 @@
1
- import { ApolloError } from '@graphcommerce/graphql'
2
- import { FullPageMessage, FullPageMessageProps } from '@graphcommerce/next-ui'
1
+ import type { ApolloError } from '@graphcommerce/graphql'
2
+ import type { FullPageMessageProps } from '@graphcommerce/next-ui'
3
+ import { FullPageMessage } from '@graphcommerce/next-ui'
3
4
  import { Trans } from '@lingui/react'
4
- import { AlertProps } from '@mui/material'
5
+ import type { AlertProps } from '@mui/material'
5
6
  import { ApolloErrorAlert } from './ApolloErrorAlert'
6
7
  import { maskNetworkError } from './maskNetworkError'
7
8
 
@@ -1,5 +1,6 @@
1
- import { ApolloError } from '@graphcommerce/graphql'
2
- import { ErrorSnackbar, ErrorSnackbarProps } from '@graphcommerce/next-ui'
1
+ import type { ApolloError } from '@graphcommerce/graphql'
2
+ import type { ErrorSnackbarProps } from '@graphcommerce/next-ui'
3
+ import { ErrorSnackbar } from '@graphcommerce/next-ui'
3
4
  import { maskNetworkError } from './maskNetworkError'
4
5
 
5
6
  export type ApolloErrorSnackbarProps = {
@@ -7,7 +8,7 @@ export type ApolloErrorSnackbarProps = {
7
8
  } & Pick<ErrorSnackbarProps, 'action' | 'onClose'>
8
9
 
9
10
  export function ApolloErrorSnackbar(props: ApolloErrorSnackbarProps) {
10
- const { error, action, ...passedProps } = props
11
+ const { error, ...passedProps } = props
11
12
 
12
13
  if (!error) return null
13
14
 
@@ -1,4 +1,4 @@
1
- import { ServerError, ServerParseError } from '@graphcommerce/graphql'
1
+ import type { ServerError, ServerParseError } from '@graphcommerce/graphql'
2
2
  import { Trans } from '@lingui/react'
3
3
 
4
4
  function isServerError(error: Error | ServerParseError | ServerError | null): error is ServerError {
@@ -1,8 +1,9 @@
1
- import { iconChevronRight, IconSvg, Button, ButtonProps } from '@graphcommerce/next-ui'
2
- import { ComposedSubmitRenderComponentProps } from '@graphcommerce/react-hook-form'
1
+ import type { ButtonProps } from '@graphcommerce/next-ui'
2
+ import { Button, IconSvg, iconChevronRight } from '@graphcommerce/next-ui'
3
+ import type { ComposedSubmitRenderComponentProps } from '@graphcommerce/react-hook-form'
3
4
  import { forwardRef } from 'react'
4
5
 
5
- type ComposedSubmitButtonProps = ComposedSubmitRenderComponentProps &
6
+ export type ComposedSubmitButtonProps = ComposedSubmitRenderComponentProps &
6
7
  Omit<ButtonProps, 'loading' | 'onSubmit'>
7
8
 
8
9
  /** Makes a ComposedSubmitRenderComponent rendered as a LinkOrButton */
@@ -1,8 +1,9 @@
1
- import { iconChevronRight, LinkOrButton, LinkOrButtonProps, IconSvg } from '@graphcommerce/next-ui'
2
- import { ComposedSubmitRenderComponentProps } from '@graphcommerce/react-hook-form'
1
+ import type { LinkOrButtonProps } from '@graphcommerce/next-ui'
2
+ import { IconSvg, LinkOrButton, iconChevronRight } from '@graphcommerce/next-ui'
3
+ import type { ComposedSubmitRenderComponentProps } from '@graphcommerce/react-hook-form'
3
4
  import { forwardRef } from 'react'
4
5
 
5
- type ComposedLinkOrButtonProps = ComposedSubmitRenderComponentProps &
6
+ export type ComposedLinkOrButtonProps = ComposedSubmitRenderComponentProps &
6
7
  Omit<LinkOrButtonProps, 'loading'>
7
8
 
8
9
  /** Makes a ComposedSubmitRenderComponent rendered as a LinkOrButton */
@@ -1,6 +1,9 @@
1
- import { ActionCardList, ActionCardListProps, ActionCardProps } from '@graphcommerce/next-ui'
2
- import { ControllerProps, FieldValues, useController } from '@graphcommerce/react-hook-form'
3
- import React, { MouseEventHandler } from 'react'
1
+ import type { ActionCardListProps, ActionCardProps } from '@graphcommerce/next-ui'
2
+ import { ActionCardList } from '@graphcommerce/next-ui'
3
+ import type { ControllerProps, FieldValues } from '@graphcommerce/react-hook-form'
4
+ import { useController } from '@graphcommerce/react-hook-form'
5
+ import type { MouseEventHandler } from 'react'
6
+ import React, { useCallback } from 'react'
4
7
 
5
8
  export type ActionCardItemBase = Pick<ActionCardProps, 'value'>
6
9
 
@@ -19,6 +22,7 @@ export type ActionCardListFormProps<A, F extends FieldValues = FieldValues> = Om
19
22
  render: React.FC<ActionCardItemRenderProps<A>>
20
23
  } & ActionCardRequireOptionSelection
21
24
 
25
+ /** @public */
22
26
  export function ActionCardListForm<
23
27
  T extends ActionCardItemBase,
24
28
  F extends FieldValues = FieldValues,
@@ -40,11 +44,14 @@ export function ActionCardListForm<
40
44
  } = props
41
45
  const RenderItem = render as React.FC<ActionCardItemRenderProps<ActionCardItemBase>>
42
46
 
43
- function onSelect(itemValue: unknown, selectValues: unknown) {
44
- return multiple
45
- ? Array.isArray(selectValues) && selectValues.some((selectValue) => selectValue === itemValue)
46
- : selectValues === itemValue
47
- }
47
+ const onSelect = useCallback(
48
+ (itemValue: unknown, selectValues: unknown) =>
49
+ multiple
50
+ ? Array.isArray(selectValues) &&
51
+ selectValues.some((selectValue) => selectValue === itemValue)
52
+ : selectValues === itemValue,
53
+ [multiple],
54
+ )
48
55
 
49
56
  const {
50
57
  field: { onChange, value, ref },
@@ -60,6 +67,14 @@ export function ActionCardListForm<
60
67
  shouldUnregister,
61
68
  })
62
69
 
70
+ const handleReset = useCallback(
71
+ (e: React.MouseEvent<HTMLElement>) => {
72
+ e.preventDefault()
73
+ if (!requireOptionSelection) onChange(null)
74
+ },
75
+ [onChange, requireOptionSelection],
76
+ )
77
+
63
78
  return (
64
79
  <ActionCardList
65
80
  {...other}
@@ -67,7 +82,7 @@ export function ActionCardListForm<
67
82
  required={required}
68
83
  value={value}
69
84
  ref={ref}
70
- onChange={(_, incomming) => onChange(incomming)}
85
+ onChange={(_, incoming) => onChange(incoming)}
71
86
  error={formState.isSubmitted && !!fieldState.error}
72
87
  errorMessage={fieldState.error?.message}
73
88
  >
@@ -77,10 +92,7 @@ export function ActionCardListForm<
77
92
  key={`${item.value}`}
78
93
  value={item.value}
79
94
  selected={onSelect(item.value, value)}
80
- onReset={(e) => {
81
- e.preventDefault()
82
- if (!requireOptionSelection) onChange(null)
83
- }}
95
+ onReset={handleReset}
84
96
  />
85
97
  ))}
86
98
  </ActionCardList>
@@ -1,8 +1,9 @@
1
- import { useController, FieldValues, UseControllerProps } from '@graphcommerce/react-hook-form'
1
+ import type { FieldValues, UseControllerProps } from '@graphcommerce/react-hook-form'
2
+ import { useController } from '@graphcommerce/react-hook-form'
2
3
  import { i18n } from '@lingui/core'
4
+ import type { CheckboxProps } from '@mui/material'
3
5
  import {
4
6
  Checkbox,
5
- CheckboxProps,
6
7
  FormControl,
7
8
  FormControlLabel,
8
9
  FormGroup,
@@ -12,12 +13,14 @@ import {
12
13
  } from '@mui/material'
13
14
 
14
15
  export type CheckboxButtonGroupProps<T extends FieldValues> = {
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
17
  options: { id: string | number; label: string }[] | any[]
16
18
  helperText?: string
17
19
  required?: boolean
18
20
  label?: string
19
21
  labelKey?: string
20
22
  valueKey?: string
23
+ // eslint-disable-next-line @typescript-eslint/ban-types
21
24
  onChange?: Function
22
25
  returnObject?: boolean
23
26
  disabled?: boolean
@@ -25,6 +28,7 @@ export type CheckboxButtonGroupProps<T extends FieldValues> = {
25
28
  checkboxColor?: CheckboxProps['color']
26
29
  } & UseControllerProps<T>
27
30
 
31
+ /** @public */
28
32
  export function CheckboxButtonGroup<TFieldValues extends FieldValues>(
29
33
  props: CheckboxButtonGroupProps<TFieldValues>,
30
34
  ): JSX.Element {
@@ -62,13 +66,17 @@ export function CheckboxButtonGroup<TFieldValues extends FieldValues>(
62
66
  const parsedHelperText = error ? error.message : helperText
63
67
 
64
68
  const handleChange = (index: number | string) => {
69
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
65
70
  const newArray: (string | number)[] | any[] = [...value]
66
71
  const exists =
72
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
67
73
  value.findIndex((i: any) => (returnObject ? i[valueKey] === index : i === index)) === -1
68
74
  if (exists) {
75
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
69
76
  newArray.push(returnObject ? options.find((i) => i[valueKey] === index) : index)
70
77
  } else {
71
78
  newArray.splice(
79
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
72
80
  value.findIndex((i: any) => (returnObject ? i[valueKey] === index : i === index)),
73
81
  1,
74
82
  )
@@ -93,7 +101,7 @@ export function CheckboxButtonGroup<TFieldValues extends FieldValues>(
93
101
  )
94
102
  }
95
103
  const isChecked =
96
- value.findIndex((item: any) =>
104
+ value.findIndex((item) =>
97
105
  returnObject ? item[valueKey] === optionKey : item === optionKey,
98
106
  ) !== -1
99
107
  return (
@@ -107,6 +115,7 @@ export function CheckboxButtonGroup<TFieldValues extends FieldValues>(
107
115
  value={optionKey}
108
116
  checked={isChecked}
109
117
  disabled={disabled}
118
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
110
119
  onChange={() => handleChange(optionKey)}
111
120
  />
112
121
  }
@@ -1,16 +1,20 @@
1
- import { ControllerProps, FieldValues, useController } from '@graphcommerce/react-hook-form'
1
+ import type { ControllerProps, FieldValues } from '@graphcommerce/react-hook-form'
2
+ import { useController } from '@graphcommerce/react-hook-form'
2
3
  import { i18n } from '@lingui/core'
4
+ import type {
5
+ CheckboxProps,
6
+ FormControlLabelProps,
7
+ FormControlProps,
8
+ SxProps,
9
+ Theme,
10
+ } from '@mui/material'
3
11
  import {
4
12
  Checkbox,
5
- CheckboxProps,
6
13
  FormControl,
7
14
  FormControlLabel,
8
- FormControlLabelProps,
9
- FormControlProps,
10
15
  FormGroup,
11
16
  FormHelperText,
12
- SxProps,
13
- Theme,
17
+ useForkRef,
14
18
  } from '@mui/material'
15
19
 
16
20
  export type CheckboxElementProps<T extends FieldValues> = Omit<CheckboxProps, 'name'> & {
@@ -20,6 +24,7 @@ export type CheckboxElementProps<T extends FieldValues> = Omit<CheckboxProps, 'n
20
24
  formControl?: Omit<FormControlProps<'div'>, 'required' | 'error'>
21
25
  } & Omit<ControllerProps<T>, 'render'>
22
26
 
27
+ /** @public */
23
28
  export function CheckboxElement<TFieldValues extends FieldValues>(
24
29
  props: CheckboxElementProps<TFieldValues>,
25
30
  ): JSX.Element {
@@ -65,7 +70,7 @@ export function CheckboxElement<TFieldValues extends FieldValues>(
65
70
  <Checkbox
66
71
  {...rest}
67
72
  {...field}
68
- inputRef={ref}
73
+ inputRef={useForkRef(ref, rest.inputRef)}
69
74
  color={rest.color || 'primary'}
70
75
  sx={{
71
76
  ...(Array.isArray(sx) ? sx : [sx]),
@@ -1,10 +1,13 @@
1
- import { emailPattern, FieldValues } from '@graphcommerce/react-hook-form'
1
+ import type { FieldValues } from '@graphcommerce/react-hook-form'
2
+ import { emailPattern } from '@graphcommerce/react-hook-form'
2
3
  import { i18n } from '@lingui/core'
3
4
  import { Trans } from '@lingui/react'
4
- import { TextFieldElement, TextFieldElementProps } from './TextFieldElement'
5
+ import type { TextFieldElementProps } from './TextFieldElement'
6
+ import { TextFieldElement } from './TextFieldElement'
5
7
 
6
8
  export type EmailElementProps<T extends FieldValues> = TextFieldElementProps<T>
7
9
 
10
+ /** @public */
8
11
  export function EmailElement<TFieldValues extends FieldValues>(
9
12
  props: EmailElementProps<TFieldValues>,
10
13
  ): JSX.Element {
@@ -0,0 +1,54 @@
1
+ /* eslint-disable no-nested-ternary */
2
+ import { FieldValues, UseControllerProps, useController } from '@graphcommerce/react-hook-form'
3
+ import { i18n } from '@lingui/core'
4
+ import { InputBase, InputBaseProps } from '@mui/material'
5
+ import React from 'react'
6
+
7
+ export type InputBaseElementProps<T extends FieldValues = FieldValues> = Omit<
8
+ InputBaseProps,
9
+ 'name' | 'defaultValue'
10
+ > & {
11
+ showValid?: boolean
12
+ } & UseControllerProps<T>
13
+
14
+ type InputBaseElementComponent = <TFieldValues extends FieldValues>(
15
+ props: InputBaseElementProps<TFieldValues> & { ref?: React.Ref<HTMLInputElement> },
16
+ ) => JSX.Element
17
+
18
+ export const InputBaseElement = React.forwardRef<
19
+ HTMLInputElement,
20
+ InputBaseElementProps<FieldValues>
21
+ >((props: InputBaseElementProps<FieldValues>, ref: React.Ref<HTMLInputElement>): JSX.Element => {
22
+ const {
23
+ type,
24
+ required,
25
+ name,
26
+ control,
27
+ defaultValue,
28
+ rules = {},
29
+ shouldUnregister,
30
+ showValid,
31
+ disabled,
32
+ ...rest
33
+ } = props
34
+
35
+ if (required && !rules?.required) {
36
+ rules.required = i18n._(/* i18n */ 'This field is required')
37
+ }
38
+
39
+ const {
40
+ field,
41
+ fieldState: { error },
42
+ } = useController({ name, control, rules, defaultValue, shouldUnregister, disabled })
43
+
44
+ return (
45
+ <InputBase
46
+ {...rest}
47
+ {...field}
48
+ ref={ref}
49
+ required={required}
50
+ type={type}
51
+ error={Boolean(error) || rest.error}
52
+ />
53
+ )
54
+ }) as InputBaseElementComponent
@@ -1,21 +1,22 @@
1
1
  /* eslint-disable no-nested-ternary */
2
- import { IconSvg, iconClose } from '@graphcommerce/next-ui'
3
- import { FieldValues, ControllerProps, useController } from '@graphcommerce/react-hook-form'
2
+ import { iconClose, IconSvg } from '@graphcommerce/next-ui'
3
+ import type { ControllerProps, FieldValues } from '@graphcommerce/react-hook-form'
4
+ import { useController } from '@graphcommerce/react-hook-form'
4
5
  import { i18n } from '@lingui/core'
6
+ import type { FormControlProps, SelectProps } from '@mui/material'
5
7
  import {
6
8
  Checkbox,
7
9
  Chip,
8
10
  FormControl,
9
- FormControlProps,
10
11
  FormHelperText,
11
12
  InputLabel,
12
13
  ListItemText,
13
14
  MenuItem,
14
15
  Select,
15
- SelectProps,
16
16
  } from '@mui/material'
17
17
 
18
18
  export type MultiSelectElementProps<T extends FieldValues> = Omit<SelectProps, 'value'> & {
19
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
20
  options: { id: string | number; label: string }[] | any[]
20
21
  label?: string
21
22
  itemKey?: string
@@ -34,6 +35,7 @@ export type MultiSelectElementProps<T extends FieldValues> = Omit<SelectProps, '
34
35
  const ITEM_HEIGHT = 48
35
36
  const ITEM_PADDING_TOP = 8
36
37
 
38
+ /** @public */
37
39
  export function MultiSelectElement<TFieldValues extends FieldValues>(
38
40
  props: MultiSelectElementProps<TFieldValues>,
39
41
  ): JSX.Element {
@@ -127,12 +129,14 @@ export function MultiSelectElement<TFieldValues extends FieldValues>(
127
129
  : showChips
128
130
  ? (selected) => (
129
131
  <div style={{ display: 'flex', flexWrap: 'wrap' }}>
132
+ {/* eslint-disable-next-line @typescript-eslint/no-explicit-any */}
130
133
  {((selected as any[]) || []).map((selectedValue) => (
131
134
  <Chip
132
135
  key={selectedValue}
133
136
  label={selectedValue}
134
137
  style={{ display: 'flex', flexWrap: 'wrap' }}
135
138
  onDelete={() => {
139
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
136
140
  onChange(value.filter((i: any) => i !== selectedValue))
137
141
  // setValue(name, formValue.filter((i: any) => i !== value), { shouldValidate: true })
138
142
  }}
@@ -5,14 +5,11 @@ import {
5
5
  IconSvg,
6
6
  responsiveVal,
7
7
  } from '@graphcommerce/next-ui'
8
- import {
9
- Controller,
10
- ControllerProps,
11
- FieldValues,
12
- useController,
13
- } from '@graphcommerce/react-hook-form'
8
+ import type { ControllerProps, FieldValues } from '@graphcommerce/react-hook-form'
9
+ import { Controller, useController } from '@graphcommerce/react-hook-form'
14
10
  import { i18n } from '@lingui/core'
15
- import { IconButtonProps, SxProps, Theme, TextField, TextFieldProps, Fab } from '@mui/material'
11
+ import type { IconButtonProps, SxProps, TextFieldProps, Theme } from '@mui/material'
12
+ import { Fab, TextField, useForkRef } from '@mui/material'
16
13
 
17
14
  export type NumberFieldElementProps<T extends FieldValues = FieldValues> = Omit<
18
15
  TextFieldProps,
@@ -24,18 +21,20 @@ export type NumberFieldElementProps<T extends FieldValues = FieldValues> = Omit<
24
21
  } & Omit<ControllerProps<T>, 'render'>
25
22
 
26
23
  type OwnerState = { size?: 'small' | 'medium' }
27
- const componentName = 'TextInputNumber' as const
24
+ const componentName = 'TextInputNumber'
28
25
  const parts = ['quantity', 'quantityInput', 'button'] as const
29
26
  const { withState } = extendableComponent<OwnerState, typeof componentName, typeof parts>(
30
27
  componentName,
31
28
  parts,
32
29
  )
33
30
 
31
+ /** @public */
34
32
  export function NumberFieldElement<T extends FieldValues>(props: NumberFieldElementProps<T>) {
35
33
  const {
36
34
  DownProps = {},
37
35
  UpProps = {},
38
36
  inputProps = {},
37
+ InputProps = {},
39
38
  sx = [],
40
39
  size = 'medium',
41
40
  control,
@@ -46,11 +45,18 @@ export function NumberFieldElement<T extends FieldValues>(props: NumberFieldElem
46
45
  variant = 'outlined',
47
46
  disabled,
48
47
  shouldUnregister,
49
- ...textFieldProps
48
+ ...rest
50
49
  } = props
51
50
 
52
51
  const classes = withState({ size })
53
52
 
53
+ let InputPropsFiltered = InputProps
54
+
55
+ if (variant === 'outlined' && 'disableUnderline' in InputPropsFiltered) {
56
+ const { disableUnderline, ...filteredInputProps } = InputPropsFiltered
57
+ InputPropsFiltered = filteredInputProps
58
+ }
59
+
54
60
  if (required && !rules.required) {
55
61
  rules.required = i18n._(/* i18n */ 'This field is required')
56
62
  }
@@ -71,22 +77,22 @@ export function NumberFieldElement<T extends FieldValues>(props: NumberFieldElem
71
77
 
72
78
  return (
73
79
  <TextField
74
- {...textFieldProps}
80
+ {...rest}
75
81
  {...field}
76
- inputRef={ref}
82
+ inputRef={useForkRef(ref, rest.inputRef)}
77
83
  value={value ?? ''}
78
84
  onChange={(ev) => {
79
85
  const newValue = (ev.target as HTMLInputElement).valueAsNumber
80
86
  onChange(Number.isNaN(newValue) ? '' : newValue)
81
- textFieldProps.onChange?.(ev)
87
+ rest.onChange?.(ev)
82
88
  }}
83
89
  variant={variant}
84
90
  required={required}
85
91
  error={invalid}
86
- helperText={error ? error.message : textFieldProps.helperText}
92
+ helperText={error ? error.message : rest.helperText}
87
93
  size={size}
88
94
  type='number'
89
- className={`${textFieldProps.className ?? ''} ${classes.quantity}`}
95
+ className={`${rest.className ?? ''} ${classes.quantity}`}
90
96
  sx={[
91
97
  {
92
98
  width: responsiveVal(90, 120),
@@ -113,7 +119,7 @@ export function NumberFieldElement<T extends FieldValues>(props: NumberFieldElem
113
119
  ]}
114
120
  autoComplete='off'
115
121
  InputProps={{
116
- ...textFieldProps.InputProps,
122
+ ...InputPropsFiltered,
117
123
  startAdornment: (
118
124
  <Fab
119
125
  aria-label={i18n._(/* i18n */ 'Decrease')}
@@ -1,13 +1,17 @@
1
1
  import { iconEye, iconEyeCrossed, IconSvg } from '@graphcommerce/next-ui'
2
- import { FieldValues } from '@graphcommerce/react-hook-form'
3
- import { IconButton, IconButtonProps, InputAdornment } from '@mui/material'
4
- import { MouseEvent, useState } from 'react'
5
- import { TextFieldElement, TextFieldElementProps } from './TextFieldElement'
2
+ import type { FieldValues } from '@graphcommerce/react-hook-form'
3
+ import type { IconButtonProps } from '@mui/material'
4
+ import { IconButton, InputAdornment } from '@mui/material'
5
+ import type { MouseEvent } from 'react'
6
+ import { useState } from 'react'
7
+ import type { TextFieldElementProps } from './TextFieldElement'
8
+ import { TextFieldElement } from './TextFieldElement'
6
9
 
7
10
  export type PasswordElementProps<T extends FieldValues> = TextFieldElementProps<T> & {
8
11
  iconColor?: IconButtonProps['color']
9
12
  }
10
13
 
14
+ /** @public */
11
15
  export function PasswordElement<TFieldValues extends FieldValues>(
12
16
  props: PasswordElementProps<TFieldValues>,
13
17
  ): JSX.Element {
@@ -1,11 +1,14 @@
1
- import { useWatch, FieldValues } from '@graphcommerce/react-hook-form'
1
+ import type { FieldValues } from '@graphcommerce/react-hook-form'
2
+ import { useWatch } from '@graphcommerce/react-hook-form'
2
3
  import { i18n } from '@lingui/core'
3
- import { PasswordElement, PasswordElementProps } from './PasswordElement'
4
+ import type { PasswordElementProps } from './PasswordElement'
5
+ import { PasswordElement } from './PasswordElement'
4
6
 
5
7
  export type PasswordRepeatElementProps<T extends FieldValues> = PasswordElementProps<T> & {
6
8
  passwordFieldName: PasswordElementProps<T>['name']
7
9
  }
8
10
 
11
+ /** @public */
9
12
  export function PasswordRepeatElement<TFieldValues extends FieldValues>({
10
13
  passwordFieldName,
11
14
  ...rest
@@ -1,4 +1,5 @@
1
- import { useController, FieldValues, UseControllerProps } from '@graphcommerce/react-hook-form'
1
+ import type { FieldValues, UseControllerProps } from '@graphcommerce/react-hook-form'
2
+ import { useController } from '@graphcommerce/react-hook-form'
2
3
  import { i18n } from '@lingui/core'
3
4
  import {
4
5
  FormControl,
@@ -9,9 +10,10 @@ import {
9
10
  RadioGroup,
10
11
  useTheme,
11
12
  } from '@mui/material'
12
- import { ChangeEvent } from 'react'
13
+ import type { ChangeEvent } from 'react'
13
14
 
14
15
  export type RadioButtonGroupProps<T extends FieldValues> = {
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
17
  options: { label: string; id: string | number }[] | any[]
16
18
  helperText?: string
17
19
  required?: boolean
@@ -20,11 +22,13 @@ export type RadioButtonGroupProps<T extends FieldValues> = {
20
22
  valueKey?: string
21
23
  type?: 'number' | 'string'
22
24
  emptyOptionLabel?: 'string'
25
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
26
  onChange?: (value: any) => void
24
27
  returnObject?: boolean
25
28
  row?: boolean
26
29
  } & UseControllerProps<T>
27
30
 
31
+ /** @public */
28
32
  export function RadioButtonGroup<TFieldValues extends FieldValues>(
29
33
  props: RadioButtonGroupProps<TFieldValues>,
30
34
  ): JSX.Element {
@@ -95,7 +99,7 @@ export function RadioButtonGroup<TFieldValues extends FieldValues>(
95
99
  value=''
96
100
  />
97
101
  )}
98
- {options.map((option: any) => {
102
+ {options.map((option) => {
99
103
  const optionKey = option[valueKey]
100
104
  if (!optionKey) {
101
105
  console.error(
@@ -1,12 +1,9 @@
1
1
  import { InputCheckmark } from '@graphcommerce/next-ui'
2
- import {
3
- Controller,
4
- ControllerProps,
5
- FieldValues,
6
- useController,
7
- } from '@graphcommerce/react-hook-form'
2
+ import type { ControllerProps, FieldValues } from '@graphcommerce/react-hook-form'
3
+ import { useController } from '@graphcommerce/react-hook-form'
8
4
  import { i18n } from '@lingui/core'
9
- import { MenuItem, TextField, TextFieldProps } from '@mui/material'
5
+ import type { TextFieldProps } from '@mui/material'
6
+ import { MenuItem, TextField, useForkRef } from '@mui/material'
10
7
 
11
8
  type OptionBase = { id: string | number; label: string | number }
12
9
 
@@ -14,23 +11,21 @@ export type SelectElementProps<T extends FieldValues, O extends OptionBase> = Om
14
11
  TextFieldProps,
15
12
  'name' | 'type' | 'onChange' | 'defaultValue'
16
13
  > & {
17
- /** @deprecated Please use the rules props instead */
18
- validation?: ControllerProps<T>['rules']
19
14
  options?: O[]
20
15
  type?: 'string' | 'number'
21
16
  onChange?: (value: string | number) => void
22
17
  showValid?: boolean
23
18
  } & Omit<ControllerProps<T>, 'render'>
24
19
 
20
+ /** @public */
25
21
  export function SelectElement<TFieldValues extends FieldValues, O extends OptionBase>({
26
22
  name,
27
23
  required,
28
24
  options = [],
29
25
  type,
30
- validation,
31
26
  control,
32
27
  defaultValue,
33
- rules = validation ?? {},
28
+ rules = {},
34
29
  showValid,
35
30
  disabled,
36
31
  shouldUnregister,
@@ -66,7 +61,7 @@ export function SelectElement<TFieldValues extends FieldValues, O extends Option
66
61
  {...rest}
67
62
  value={value ?? ''}
68
63
  {...field}
69
- inputRef={ref}
64
+ inputRef={useForkRef(ref, rest.inputRef)}
70
65
  onChange={(event) => {
71
66
  let item: number | string | O | undefined = event.target.value
72
67
  if (type === 'number') item = Number(item)
@@ -87,6 +82,7 @@ export function SelectElement<TFieldValues extends FieldValues, O extends Option
87
82
  ),
88
83
  }}
89
84
  >
85
+ {/* eslint-disable-next-line jsx-a11y/control-has-associated-label */}
90
86
  {isNativeSelect && <option />}
91
87
  {options.map((item) => (
92
88
  <ChildComponent key={item.id} value={item.id}>