@graphcommerce/next-ui 4.9.0 → 4.10.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.
@@ -1,6 +1,6 @@
1
- import { Theme } from '@emotion/react'
2
- import { SxProps, ButtonBase, Box } from '@mui/material'
1
+ import { SxProps, ButtonBase, Box, Theme } from '@mui/material'
3
2
  import React, { FormEvent } from 'react'
3
+ import { extendableComponent } from '../Styles'
4
4
 
5
5
  export type ActionCardProps = {
6
6
  sx?: SxProps<Theme>
@@ -8,64 +8,83 @@ export type ActionCardProps = {
8
8
  image?: React.ReactNode
9
9
  action?: React.ReactNode
10
10
  details?: React.ReactNode
11
+ price?: React.ReactNode
12
+ after?: React.ReactNode
11
13
  secondaryAction?: React.ReactNode
12
14
  onClick?: (e: FormEvent<HTMLElement>, v: string | number) => void
13
15
  selected?: boolean
14
- hidden?: boolean | (() => boolean)
16
+ hidden?: boolean
15
17
  value: string | number
16
18
  reset?: React.ReactNode
17
19
  disabled?: boolean
18
20
  }
19
21
 
20
- const actionButtonStyles: SxProps = {
21
- '& .MuiButton-root': {
22
- '&.MuiButton-textSecondary': {
23
- padding: '5px',
24
- margin: '-5px',
25
- '&:hover': {
26
- background: 'none',
27
- },
28
- },
29
- },
22
+ const parts = [
23
+ 'root',
24
+ 'image',
25
+ 'title',
26
+ 'action',
27
+ 'details',
28
+ 'price',
29
+ 'after',
30
+ 'secondaryAction',
31
+ 'reset',
32
+ ] as const
33
+ const name = 'ActionCard'
34
+
35
+ type StateProps = {
36
+ selected?: boolean
37
+ hidden?: boolean
38
+ disabled?: boolean
39
+ image?: boolean
30
40
  }
31
41
 
42
+ const { withState, selectors } = extendableComponent<StateProps, typeof name, typeof parts>(
43
+ name,
44
+ parts,
45
+ )
46
+
47
+ export const actionCardSelectors = selectors
48
+
32
49
  export function ActionCard(props: ActionCardProps) {
33
50
  const {
34
51
  title,
35
52
  image,
36
53
  action,
37
54
  details,
55
+ price,
56
+ after,
38
57
  secondaryAction,
39
58
  sx = [],
40
59
  onClick,
41
60
  value,
42
- selected,
43
- hidden,
61
+ selected = false,
62
+ hidden = false,
44
63
  reset,
45
- disabled,
64
+ disabled = false,
46
65
  } = props
47
66
 
67
+ const classes = withState({ hidden, disabled, selected, image: Boolean(image) })
68
+
48
69
  const handleClick = (event: FormEvent<HTMLElement>) => onClick?.(event, value)
49
70
 
50
71
  return (
51
72
  <ButtonBase
52
73
  component='div'
53
- className='ActionCard-root'
74
+ className={classes.root}
54
75
  onClick={handleClick}
55
76
  disabled={disabled}
56
77
  sx={[
57
78
  (theme) => ({
58
79
  display: 'grid',
59
80
  width: '100%',
60
- gridTemplateColumns: 'min-content',
61
- gridTemplateAreas: {
62
- xs: `
63
- "image title action"
64
- "image details details"
65
- "image secondaryAction additionalDetails"
66
- "additionalContent additionalContent additionalContent"
67
- `,
68
- },
81
+ gridTemplateColumns: 'min-content auto auto',
82
+ gridTemplateAreas: `
83
+ "image title action"
84
+ "image details ${price ? 'price' : 'details'}"
85
+ "image secondaryActio additionalDetails"
86
+ "after after after"
87
+ `,
69
88
  justifyContent: 'unset',
70
89
  typography: 'body1',
71
90
  // textAlign: 'left',
@@ -84,10 +103,19 @@ export function ActionCard(props: ActionCardProps) {
84
103
  borderBottom: `1px solid ${theme.palette.divider}`,
85
104
  },
86
105
  }),
87
- !!hidden && {
106
+ !image && {
107
+ gridTemplateColumns: 'auto auto',
108
+ gridTemplateAreas: `
109
+ "title action"
110
+ "details ${price ? 'price' : 'details'}"
111
+ "secondaryAction additionalDetails"
112
+ "after after"
113
+ `,
114
+ },
115
+ hidden && {
88
116
  display: 'none',
89
117
  },
90
- !!selected &&
118
+ selected &&
91
119
  ((theme) => ({
92
120
  border: `2px solid ${theme.palette.secondary.main} !important`,
93
121
  borderTopLeftRadius: theme.shape.borderRadius,
@@ -96,7 +124,7 @@ export function ActionCard(props: ActionCardProps) {
96
124
  borderBottomRightRadius: theme.shape.borderRadius,
97
125
  padding: `${theme.spacings.xxs} ${theme.spacings.xs}`,
98
126
  })),
99
- !!disabled &&
127
+ disabled &&
100
128
  ((theme) => ({
101
129
  background: theme.palette.background.default,
102
130
  })),
@@ -104,32 +132,57 @@ export function ActionCard(props: ActionCardProps) {
104
132
  ...(Array.isArray(sx) ? sx : [sx]),
105
133
  ]}
106
134
  >
107
- {image && <Box sx={{ gridArea: 'image', justifySelf: 'center', padding: 1 }}>{image}</Box>}
135
+ {image && (
136
+ <Box
137
+ className={classes.image}
138
+ sx={{
139
+ gridArea: 'image',
140
+ display: 'flex',
141
+ }}
142
+ >
143
+ {image}
144
+ </Box>
145
+ )}
108
146
  {title && (
109
- <Box sx={{ gridArea: 'title', fontWeight: 'bold', marginLeft: !image ? -2 : undefined }}>
147
+ <Box className={classes.title} sx={{ gridArea: 'title', display: 'flex' }}>
110
148
  {title}
111
149
  </Box>
112
150
  )}
113
151
  {action && (
152
+ <Box className={classes.action} sx={{ gridArea: 'action', textAlign: 'right' }}>
153
+ {!selected ? action : reset}
154
+ </Box>
155
+ )}
156
+ {details && (
114
157
  <Box
158
+ className={classes.details}
115
159
  sx={{
116
- gridArea: 'action',
117
- textAlign: 'right',
118
- ...actionButtonStyles,
160
+ gridArea: 'details',
161
+ color: 'text.secondary',
119
162
  }}
120
163
  >
121
- {!selected ? action : reset}
164
+ {details}
122
165
  </Box>
123
166
  )}
124
- {details && (
167
+
168
+ {price && !disabled && (
125
169
  <Box
126
- sx={{ gridArea: 'details', color: 'text.secondary', marginLeft: !image ? -2 : undefined }}
170
+ className={classes.price}
171
+ sx={{ gridArea: 'price', textAlign: 'right', typography: 'h5' }}
127
172
  >
128
- {details}
173
+ {price}
129
174
  </Box>
130
175
  )}
176
+
131
177
  {secondaryAction && (
132
- <Box sx={{ gridArea: 'secondaryAction', ...actionButtonStyles }}>{secondaryAction}</Box>
178
+ <Box className={classes.secondaryAction} sx={{ gridArea: 'secondaryAction' }}>
179
+ {secondaryAction}
180
+ </Box>
181
+ )}
182
+ {after && (
183
+ <Box className={classes.after} sx={{ gridArea: 'after' }}>
184
+ {after}
185
+ </Box>
133
186
  )}
134
187
  </ButtonBase>
135
188
  )
@@ -1,13 +1,16 @@
1
1
  /* eslint-disable import/no-extraneous-dependencies */
2
2
  import { Controller, ControllerProps } from '@graphcommerce/react-hook-form'
3
- import React from 'react'
3
+ import React, { MouseEventHandler } from 'react'
4
4
  import { ActionCardProps } from './ActionCard'
5
5
  import { ActionCardList, ActionCardListProps } from './ActionCardList'
6
6
 
7
7
  export type ActionCardItemBase = Pick<ActionCardProps, 'value'>
8
8
 
9
- export type ActionCardItemRenderer<T> = Pick<ActionCardProps, 'selected' | 'hidden' | 'value'> & {
10
- onReset: React.MouseEventHandler<HTMLButtonElement>
9
+ export type ActionCardItemRenderProps<T> = Pick<
10
+ ActionCardProps,
11
+ 'selected' | 'hidden' | 'value'
12
+ > & {
13
+ onReset: MouseEventHandler<HTMLAnchorElement> & MouseEventHandler<HTMLSpanElement>
11
14
  } & T
12
15
 
13
16
  export type ActionCardListFormProps<T extends ActionCardItemBase> = Omit<
@@ -16,14 +19,14 @@ export type ActionCardListFormProps<T extends ActionCardItemBase> = Omit<
16
19
  > &
17
20
  Omit<ControllerProps<any>, 'render'> & {
18
21
  items: T[]
19
- render: React.VFC<ActionCardItemRenderer<T>>
22
+ render: React.VFC<ActionCardItemRenderProps<T>>
20
23
  }
21
24
 
22
25
  export function ActionCardListForm<T extends ActionCardItemBase>(
23
26
  props: ActionCardListFormProps<T>,
24
27
  ) {
25
28
  const { required, rules, items, render, control, name, errorMessage } = props
26
- const RenderItem = render as React.VFC<ActionCardItemRenderer<ActionCardItemBase>>
29
+ const RenderItem = render as React.VFC<ActionCardItemRenderProps<ActionCardItemBase>>
27
30
 
28
31
  return (
29
32
  <Controller
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Change Log
2
2
 
3
+ ## 4.10.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#1515](https://github.com/graphcommerce-org/graphcommerce/pull/1515) [`371e6cf52`](https://github.com/graphcommerce-org/graphcommerce/commit/371e6cf52916a3b6c44192bd40cc8271bd608832) Thanks [@mikekeehnen](https://github.com/mikekeehnen)! - - Shipping method UI improvements in checkout, like working ripple effect, auto select and other styling changes.
8
+ - Added new inline button variant
9
+
10
+ * [#1518](https://github.com/graphcommerce-org/graphcommerce/pull/1518) [`4143483f3`](https://github.com/graphcommerce-org/graphcommerce/commit/4143483f37c038d2bbf218be2685e27a31a35745) Thanks [@mikekeehnen](https://github.com/mikekeehnen)! - New ActionCardListForm implementation for Payment Methods
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies []:
15
+ - @graphcommerce/framer-scroller@2.1.17
16
+
3
17
  ## 4.9.0
4
18
 
5
19
  ### Minor Changes
@@ -4,6 +4,7 @@ import { responsiveVal } from '../Styles/responsiveVal'
4
4
  declare module '@mui/material/Button/Button' {
5
5
  interface ButtonPropsVariantOverrides {
6
6
  pill: true
7
+ inline: true
7
8
  }
8
9
  }
9
10
 
@@ -126,3 +127,64 @@ export const MuiButtonPill: ButtonVariants = [
126
127
  }),
127
128
  },
128
129
  ]
130
+
131
+ export const MuiButtonInline: ButtonVariants = [
132
+ {
133
+ props: { variant: 'inline', color: 'primary' },
134
+ style: ({ theme }) => ({
135
+ color: theme.palette.primary.main,
136
+ '&:hover:not(.Mui-disabled)': { backgroundColor: `${theme.palette.primary.main}30` },
137
+ }),
138
+ },
139
+ {
140
+ props: { variant: 'inline', color: 'secondary' },
141
+ style: ({ theme }) => ({
142
+ color: theme.palette.secondary.main,
143
+ '&:hover:not(.Mui-disabled)': {
144
+ backgroundColor: theme.palette.secondary.light,
145
+ },
146
+ }),
147
+ },
148
+ {
149
+ props: { variant: 'inline' },
150
+ style: { textTransform: 'none', fontWeight: 500 },
151
+ },
152
+ {
153
+ props: { variant: 'inline', size: 'small' },
154
+ style: ({ theme }) => ({
155
+ margin: `calc(${theme.spacings.xxs} / 2 * -1 )`,
156
+ padding: '3px 9px',
157
+
158
+ '& .MuiLoadingButton-loadingIndicatorEnd': { right: 3 },
159
+ '& .MuiLoadingButton-loadingIndicatorStart': { left: 9 },
160
+ }),
161
+ },
162
+ {
163
+ props: { variant: 'inline', size: 'medium' },
164
+ style: ({ theme }) => ({
165
+ margin: `calc(${theme.spacings.xxs} * -1 )`,
166
+ padding: `${responsiveVal(3, 5)} ${responsiveVal(9, 15)}`,
167
+
168
+ '& .MuiLoadingButton-loadingIndicatorEnd': { right: responsiveVal(9, 15) },
169
+ '& .MuiLoadingButton-loadingIndicatorStart': { left: responsiveVal(9, 15) },
170
+ }),
171
+ },
172
+ {
173
+ props: { variant: 'inline', size: 'large' },
174
+ style: ({ theme }) => ({
175
+ margin: `calc(${theme.spacings.xs} * -1)`,
176
+ padding: `${responsiveVal(8, 10)} ${responsiveVal(12, 22)}`,
177
+
178
+ '& .MuiLoadingButton-loadingIndicatorEnd': { right: responsiveVal(16, 24) },
179
+ '& .MuiLoadingButton-loadingIndicatorStart': { left: responsiveVal(16, 24) },
180
+ }),
181
+ },
182
+ {
183
+ props: { variant: 'inline', disableRipple: true },
184
+ style: {
185
+ '&:hover:not(.Mui-disabled)': {
186
+ backgroundColor: 'transparent',
187
+ },
188
+ },
189
+ },
190
+ ]
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.9.0",
5
+ "version": "4.10.0",
6
6
  "author": "",
7
7
  "license": "MIT",
8
8
  "sideEffects": false,
@@ -20,7 +20,7 @@
20
20
  "@emotion/server": "^11.4.0",
21
21
  "@emotion/styled": "^11.6.0",
22
22
  "@graphcommerce/framer-next-pages": "3.2.3",
23
- "@graphcommerce/framer-scroller": "2.1.16",
23
+ "@graphcommerce/framer-scroller": "2.1.17",
24
24
  "@graphcommerce/framer-utils": "3.1.4",
25
25
  "@graphcommerce/image": "3.1.7",
26
26
  "react-is": "^18.1.0",