@graphcommerce/next-ui 4.8.0 → 4.8.3

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.
@@ -2,21 +2,32 @@ import { Theme } from '@emotion/react'
2
2
  import { SxProps, ButtonBase, Box } from '@mui/material'
3
3
  import React, { FormEvent } from 'react'
4
4
 
5
- type ActionCardProps = {
5
+ export type ActionCardProps = {
6
6
  sx?: SxProps<Theme>
7
7
  title?: string | React.ReactNode
8
8
  image?: React.ReactNode
9
9
  action?: React.ReactNode
10
10
  details?: React.ReactNode
11
11
  secondaryAction?: React.ReactNode
12
- onClick?: (e: FormEvent<HTMLButtonElement>, v: string) => void
13
- onChange?: (e: FormEvent<HTMLButtonElement>, v: string) => void
12
+ onClick?: (e: FormEvent<HTMLElement>, v: string | number) => void
14
13
  selected?: boolean
15
14
  hidden?: boolean | (() => boolean)
16
- value: string
15
+ value: string | number
17
16
  reset?: React.ReactNode
18
17
  }
19
18
 
19
+ const actionButtonStyles: SxProps = {
20
+ '& .MuiButton-root': {
21
+ '&.MuiButton-textSecondary': {
22
+ padding: '5px',
23
+ margin: '-5px',
24
+ '&:hover': {
25
+ background: 'none',
26
+ },
27
+ },
28
+ },
29
+ }
30
+
20
31
  export function ActionCard(props: ActionCardProps) {
21
32
  const {
22
33
  title,
@@ -25,7 +36,6 @@ export function ActionCard(props: ActionCardProps) {
25
36
  details,
26
37
  secondaryAction,
27
38
  sx = [],
28
- onChange,
29
39
  onClick,
30
40
  value,
31
41
  selected,
@@ -33,52 +43,31 @@ export function ActionCard(props: ActionCardProps) {
33
43
  reset,
34
44
  } = props
35
45
 
36
- const handleChange = (event: FormEvent<HTMLButtonElement>) => onChange?.(event, value)
37
- const handleClick = (event: FormEvent<HTMLButtonElement>) => {
38
- if (onClick) {
39
- onClick(event, value)
40
- if (event.isDefaultPrevented()) return
41
- }
42
- handleChange(event)
43
- }
44
-
45
- const actionButtonStyles: SxProps = {
46
- '& .MuiButton-root': {
47
- '&.MuiButton-textSecondary': {
48
- padding: '5px',
49
- margin: '-5px',
50
- '&:hover': {
51
- background: 'none',
52
- },
53
- },
54
- },
55
- }
46
+ const handleClick = (event: FormEvent<HTMLElement>) => onClick?.(event, value)
56
47
 
57
48
  return (
58
49
  <ButtonBase
59
- component='button'
50
+ component='div'
60
51
  className='ActionCard-root'
61
52
  onClick={handleClick}
62
- onChange={handleChange}
63
- value={value}
64
53
  sx={[
65
- {
54
+ (theme) => ({
66
55
  display: 'grid',
67
56
  width: '100%',
68
57
  gridTemplateColumns: 'min-content',
69
- gridTemplateAreas: `
70
- "image title action"
71
- "image details secondaryDetails"
72
- "image secondaryAction additionalDetails"
73
- "additionalContent additionalContent additionalContent"
74
- `,
58
+ gridTemplateAreas: {
59
+ xs: `
60
+ "image title action"
61
+ "image details details"
62
+ "image secondaryAction additionalDetails"
63
+ "additionalContent additionalContent additionalContent"
64
+ `,
65
+ },
75
66
  justifyContent: 'unset',
76
- },
77
- (theme) => ({
78
67
  typography: 'body1',
79
- textAlign: 'left',
68
+ // textAlign: 'left',
80
69
  background: theme.palette.background.paper,
81
- padding: `calc(${theme.spacings.xs} + 1px)`,
70
+ padding: `calc(${theme.spacings.xxs} + 1px) calc(${theme.spacings.xs} + 1px)`,
82
71
  columnGap: theme.spacings.xxs,
83
72
  border: `1px solid ${theme.palette.divider}`,
84
73
  borderBottomColor: `transparent`,
@@ -102,7 +91,7 @@ export function ActionCard(props: ActionCardProps) {
102
91
  borderTopRightRadius: theme.shape.borderRadius,
103
92
  borderBottomLeftRadius: theme.shape.borderRadius,
104
93
  borderBottomRightRadius: theme.shape.borderRadius,
105
- padding: theme.spacings.xs,
94
+ padding: `${theme.spacings.xxs} ${theme.spacings.xs}`,
106
95
  })),
107
96
  ...(Array.isArray(sx) ? sx : [sx]),
108
97
  ]}
@@ -1,6 +1,8 @@
1
- import { Box } from '@mui/material'
1
+ import { Alert, Box, FormHelperText } from '@mui/material'
2
+ import { AnimatePresence } from 'framer-motion'
2
3
  import React from 'react'
3
4
  import { isFragment } from 'react-is'
5
+ import { AnimatedRow } from '../AnimatedRow/AnimatedRow'
4
6
 
5
7
  type MultiSelect = {
6
8
  multiple: true
@@ -16,10 +18,11 @@ type Select = {
16
18
  onChange?: (event: React.MouseEvent<HTMLElement>, value: string | null) => void
17
19
  }
18
20
 
19
- type ActionCardListProps<SelectOrMulti = MultiSelect | Select> = {
21
+ export type ActionCardListProps<SelectOrMulti = MultiSelect | Select> = {
20
22
  children?: React.ReactNode
21
23
  required?: boolean
22
24
  error?: boolean
25
+ errorMessage?: string
23
26
  } & SelectOrMulti
24
27
 
25
28
  function isMulti(props: ActionCardListProps): props is ActionCardListProps<MultiSelect> {
@@ -33,7 +36,7 @@ function isValueSelected(value: string, candidate: string | string[]) {
33
36
  }
34
37
 
35
38
  export function ActionCardList(props: ActionCardListProps) {
36
- const { children, required, value, error = false } = props
39
+ const { children, required, value, error = false, errorMessage } = props
37
40
 
38
41
  const handleChange = isMulti(props)
39
42
  ? (event: React.MouseEvent<HTMLElement, MouseEvent>, buttonValue: string) => {
@@ -70,15 +73,15 @@ export function ActionCardList(props: ActionCardListProps) {
70
73
  paddingLeft: theme.spacings.xs,
71
74
  paddingRight: theme.spacings.xs,
72
75
  },
73
- '& .ActionCard-root:first-of-type': {
76
+ '& > div:first-of-type.ActionCard-root': {
74
77
  borderTop: 2,
75
78
  borderTopColor: 'error.main',
76
- paddingTop: theme.spacings.xs,
79
+ paddingTop: theme.spacings.xxs,
77
80
  },
78
- '& .ActionCard-root:last-of-type': {
81
+ '& > div:last-of-type.ActionCard-root': {
79
82
  borderBottom: 2,
80
83
  borderBottomColor: 'error.main',
81
- paddingBottom: theme.spacings.xs,
84
+ paddingBottom: theme.spacings.xxs,
82
85
  },
83
86
  })),
84
87
  ]}
@@ -105,6 +108,15 @@ export function ActionCardList(props: ActionCardListProps) {
105
108
  : child.props.selected,
106
109
  })
107
110
  })}
111
+ {error && (
112
+ <Alert
113
+ severity='error'
114
+ variant='filled'
115
+ sx={{ borderStartStartRadius: 0, borderStartEndRadius: 0 }}
116
+ >
117
+ {errorMessage}
118
+ </Alert>
119
+ )}
108
120
  </Box>
109
121
  )
110
122
  }
@@ -0,0 +1,63 @@
1
+ /* eslint-disable import/no-extraneous-dependencies */
2
+ import { Controller, ControllerProps } from '@graphcommerce/react-hook-form'
3
+ import React from 'react'
4
+ import { ActionCardProps } from './ActionCard'
5
+ import { ActionCardList, ActionCardListProps } from './ActionCardList'
6
+
7
+ export type ActionCardItemBase = Pick<ActionCardProps, 'value'>
8
+
9
+ export type ActionCardItemRenderer<T> = Pick<ActionCardProps, 'selected' | 'hidden' | 'value'> & {
10
+ onReset: React.MouseEventHandler<HTMLButtonElement>
11
+ } & T
12
+
13
+ export type ActionCardListFormProps<T extends ActionCardItemBase> = Omit<
14
+ ActionCardListProps,
15
+ 'value'
16
+ > &
17
+ Omit<ControllerProps<any>, 'render'> & {
18
+ items: T[]
19
+ render: React.VFC<ActionCardItemRenderer<T>>
20
+ }
21
+
22
+ export function ActionCardListForm<T extends ActionCardItemBase>(
23
+ props: ActionCardListFormProps<T>,
24
+ ) {
25
+ const { required, rules, items, render, control, name, errorMessage } = props
26
+ const RenderItem = render as React.VFC<ActionCardItemRenderer<ActionCardItemBase>>
27
+
28
+ return (
29
+ <Controller
30
+ {...props}
31
+ control={control}
32
+ name={name}
33
+ rules={{
34
+ required,
35
+ ...rules,
36
+ validate: (v) => (v ? true : 'Please select a shipping address'),
37
+ }}
38
+ render={({ field: { onChange, value }, fieldState, formState }) => (
39
+ <ActionCardList
40
+ required
41
+ value={value}
42
+ onChange={(_, incomming) => onChange(incomming)}
43
+ error={formState.isSubmitted && !!fieldState.error}
44
+ errorMessage={errorMessage}
45
+ >
46
+ {items.map((item) => (
47
+ <RenderItem
48
+ {...item}
49
+ key={item.value}
50
+ value={item.value}
51
+ selected={value === item.value}
52
+ hidden={!!value && value !== item.value}
53
+ onReset={(e) => {
54
+ e.preventDefault()
55
+ onChange(null)
56
+ }}
57
+ />
58
+ ))}
59
+ </ActionCardList>
60
+ )}
61
+ />
62
+ )
63
+ }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # Change Log
2
2
 
3
+ ## 4.8.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1487](https://github.com/graphcommerce-org/graphcommerce/pull/1487) [`afc67103d`](https://github.com/graphcommerce-org/graphcommerce/commit/afc67103d0e00583e274465036fd287537f95e79) Thanks [@paales](https://github.com/paales)! - When additing an additional breakpoint it would throw a typescript error
8
+
9
+ - Updated dependencies []:
10
+ - @graphcommerce/framer-scroller@2.1.14
11
+
12
+ ## 4.8.2
13
+
14
+ ### Patch Changes
15
+
16
+ - [#1485](https://github.com/graphcommerce-org/graphcommerce/pull/1485) [`c8c246b8a`](https://github.com/graphcommerce-org/graphcommerce/commit/c8c246b8aaab0621b68a2fca2a1c529a56fad962) Thanks [@paales](https://github.com/paales)! - TextInputNumber: when adding a label it should be displayed properly
17
+
18
+ - Updated dependencies []:
19
+ - @graphcommerce/framer-scroller@2.1.13
20
+
21
+ ## 4.8.1
22
+
23
+ ### Patch Changes
24
+
25
+ - [#1477](https://github.com/graphcommerce-org/graphcommerce/pull/1477) [`a9df81310`](https://github.com/graphcommerce-org/graphcommerce/commit/a9df81310c051876dd82fb2819105dece47cc213) Thanks [@paales](https://github.com/paales)! - Revert faulty background color on LayoutDefault
26
+
27
+ * [#1477](https://github.com/graphcommerce-org/graphcommerce/pull/1477) [`f167f9963`](https://github.com/graphcommerce-org/graphcommerce/commit/f167f99630966a7de43717937d43669e66132494) Thanks [@paales](https://github.com/paales)! - LayoutOverlay performance improvements
28
+
29
+ * Updated dependencies [[`55c2dcde7`](https://github.com/graphcommerce-org/graphcommerce/commit/55c2dcde7869ee51b84494af653b3edfd43904a4), [`597e2f413`](https://github.com/graphcommerce-org/graphcommerce/commit/597e2f413bdb5b76793b40ab631ce61390e26e81), [`f167f9963`](https://github.com/graphcommerce-org/graphcommerce/commit/f167f99630966a7de43717937d43669e66132494)]:
30
+ - @graphcommerce/framer-scroller@2.1.12
31
+ - @graphcommerce/framer-next-pages@3.2.2
32
+ - @graphcommerce/framer-utils@3.1.3
33
+ - @graphcommerce/image@3.1.6
34
+
3
35
  ## 4.8.0
4
36
 
5
37
  ### Minor Changes
@@ -58,7 +58,7 @@ export function LayoutDefault(props: LayoutDefaultProps) {
58
58
  display: 'grid',
59
59
  gridTemplateRows: `auto auto 1fr auto`,
60
60
  gridTemplateColumns: '100%',
61
- background: theme.palette.background.paper,
61
+ background: theme.palette.background.default,
62
62
  }),
63
63
  ...(Array.isArray(sx) ? sx : [sx]),
64
64
  ]}
@@ -177,7 +177,6 @@ export function LayoutOverlayBase(incommingProps: LayoutOverlayBaseProps) {
177
177
  useEffect(() => positions.open.visible.onChange((o) => o === 0 && closeOverlay()))
178
178
 
179
179
  // Measure the offset of the overlay in the scroller.
180
-
181
180
  const offsetY = useMotionValue(0)
182
181
  useEffect(() => {
183
182
  if (!overlayRef.current) return () => {}
@@ -195,21 +194,20 @@ export function LayoutOverlayBase(incommingProps: LayoutOverlayBaseProps) {
195
194
 
196
195
  const onClickAway = useCallback(
197
196
  (event: React.MouseEvent<HTMLDivElement>) => {
198
- const isTarget = event.target === scrollerRef.current || event.target === beforeRef.current
197
+ const isTarget =
198
+ event.target === scrollerRef.current ||
199
+ event.target === beforeRef.current ||
200
+ event.target === overlayRef.current
199
201
  if (isTarget && snap.get()) closeOverlay()
200
202
  },
201
203
  [closeOverlay, scrollerRef, snap],
202
204
  )
203
205
 
204
- const pointerEvents = useTransform(position, (p) =>
205
- p === OverlayPosition.CLOSED ? 'none' : 'auto',
206
- )
207
-
208
206
  return (
209
207
  <>
210
208
  <MotionDiv
211
209
  className={classes.backdrop}
212
- style={{ opacity: positions.open.visible, pointerEvents }}
210
+ style={{ opacity: positions.open.visible }}
213
211
  sx={[
214
212
  {
215
213
  zIndex: -1,
@@ -233,7 +231,6 @@ export function LayoutOverlayBase(incommingProps: LayoutOverlayBaseProps) {
233
231
  grid={false}
234
232
  hideScrollbar
235
233
  onClick={onClickAway}
236
- style={{ pointerEvents }}
237
234
  sx={[
238
235
  (theme) => ({
239
236
  overscrollBehavior: 'contain',
@@ -320,9 +317,9 @@ export function LayoutOverlayBase(incommingProps: LayoutOverlayBaseProps) {
320
317
  <Box
321
318
  className={classes.overlay}
322
319
  ref={overlayRef}
320
+ onClick={onClickAway}
323
321
  sx={(theme) => ({
324
322
  display: 'grid',
325
- pointerEvents: 'none',
326
323
  gridArea: 'overlay',
327
324
  scrollSnapAlign: 'start',
328
325
  scrollSnapStop: 'always',
@@ -97,13 +97,10 @@ export function TextInputNumber(props: TextInputNumberProps) {
97
97
  width: responsiveVal(80, 120),
98
98
  backgroundColor: 'inherit',
99
99
  },
100
-
101
100
  ...(Array.isArray(sx) ? sx : [sx]),
102
101
  ]}
103
102
  autoComplete='off'
104
- label={' '}
105
103
  id='quantity-input'
106
- InputLabelProps={{ shrink: false }}
107
104
  InputProps={{
108
105
  ...textFieldProps.InputProps,
109
106
  startAdornment: (
@@ -1,10 +1,9 @@
1
- import { BreakpointsOptions, experimental_sx, SxProps, Theme } from '@mui/material'
1
+ import { experimental_sx, SxProps, Theme } from '@mui/material'
2
2
  import { Shadows } from '@mui/material/styles/shadows'
3
- import type { SetRequired } from 'type-fest'
4
3
 
5
4
  // https://material.io/design/environment/elevation.html#default-elevations
6
5
 
7
- const breakpoints: SetRequired<BreakpointsOptions, 'values'> = {
6
+ const breakpoints = {
8
7
  values: {
9
8
  xs: 0,
10
9
  sm: 600,
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@graphcommerce/next-ui",
3
3
  "homepage": "https://www.graphcommerce.org/",
4
4
  "repository": "github:graphcommerce-org/graphcommerce",
5
- "version": "4.8.0",
5
+ "version": "4.8.3",
6
6
  "author": "",
7
7
  "license": "MIT",
8
8
  "sideEffects": false,
@@ -19,10 +19,10 @@
19
19
  "@emotion/react": "^11.9.0",
20
20
  "@emotion/server": "^11.4.0",
21
21
  "@emotion/styled": "^11.6.0",
22
- "@graphcommerce/framer-next-pages": "3.2.1",
23
- "@graphcommerce/framer-scroller": "2.1.11",
24
- "@graphcommerce/framer-utils": "3.1.2",
25
- "@graphcommerce/image": "3.1.5",
22
+ "@graphcommerce/framer-next-pages": "3.2.2",
23
+ "@graphcommerce/framer-scroller": "2.1.14",
24
+ "@graphcommerce/framer-utils": "3.1.3",
25
+ "@graphcommerce/image": "3.1.6",
26
26
  "react-is": "^17.0.0",
27
27
  "react-schemaorg": "^2.0.0",
28
28
  "schema-dts": "^1.1.0"