@graphcommerce/next-ui 4.21.0 → 4.22.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/ActionCard/ActionCard.tsx +46 -12
- package/ActionCard/ActionCardList.tsx +17 -15
- package/ActionCard/ActionCardListForm.tsx +1 -2
- package/AnimatedRow/AnimatedRow.tsx +1 -0
- package/Blog/BlogHeader/BlogHeader.tsx +7 -1
- package/Blog/BlogListItem/BlogListItem.tsx +5 -1
- package/Blog/BlogTags/BlogTag.tsx +2 -3
- package/CHANGELOG.md +30 -0
- package/Footer/Footer.tsx +3 -2
- package/Form/Form.tsx +7 -1
- package/Form/FormActions.tsx +1 -1
- package/FramerScroller/SidebarGallery.tsx +1 -5
- package/IconSvg/IconSvg.tsx +4 -4
- package/Layout/components/LayoutHeaderClose.tsx +2 -0
- package/Layout/components/LayoutHeaderContent.tsx +3 -1
- package/LayoutDefault/components/LayoutDefault.tsx +3 -3
- package/LayoutOverlay/components/LayoutOverlay.tsx +2 -1
- package/LayoutParts/DesktopHeaderBadge.tsx +3 -3
- package/Navigation/components/NavigationItem.tsx +31 -17
- package/Navigation/components/NavigationList.tsx +21 -15
- package/Navigation/components/NavigationOverlay.tsx +47 -27
- package/Navigation/components/NavigationProvider.tsx +12 -30
- package/Navigation/hooks/useNavigation.ts +33 -6
- package/Overlay/components/Overlay.tsx +1 -2
- package/Overlay/components/OverlayBase.tsx +19 -19
- package/Overlay/hooks/useOverlayPosition.ts +6 -1
- package/Row/HeroBanner/HeroBanner.tsx +7 -2
- package/Row/ImageText/ImageText.tsx +10 -3
- package/Row/ImageTextBoxed/ImageTextBoxed.tsx +7 -1
- package/Row/ParagraphWithSidebarSlide/ParagraphWithSidebarSlide.tsx +4 -2
- package/Row/SpecialBanner/SpecialBanner.tsx +10 -2
- package/Snackbar/MessageSnackbarImpl.tsx +9 -5
- package/Stepper/Stepper.tsx +1 -1
- package/Styles/breakpointVal.tsx +1 -1
- package/TextInputNumber/TextInputNumber.tsx +5 -4
- package/Theme/MuiButton.ts +12 -3
- package/Theme/MuiFab.ts +2 -2
- package/ToggleButton/ToggleButton.tsx +15 -5
- package/hooks/index.ts +1 -0
- package/hooks/useMemoDeep.ts +15 -0
- package/package.json +5 -5
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import styled from '@emotion/styled'
|
|
2
|
+
import { useMotionValueValue, useMotionSelector } from '@graphcommerce/framer-utils'
|
|
2
3
|
import { i18n } from '@lingui/core'
|
|
3
4
|
import { Trans } from '@lingui/react'
|
|
4
5
|
import { Box, Fab, SxProps, Theme, useEventCallback, useMediaQuery } from '@mui/material'
|
|
5
|
-
import { m } from 'framer-motion'
|
|
6
|
-
import { useEffect, useState } from 'react'
|
|
6
|
+
import { m, useMotionValue } from 'framer-motion'
|
|
7
|
+
import React, { startTransition, useEffect, useRef, useState } from 'react'
|
|
7
8
|
import { IconSvg, useIconSvgSize } from '../../IconSvg'
|
|
8
9
|
import { LayoutHeaderContent } from '../../Layout/components/LayoutHeaderContent'
|
|
9
10
|
import { LayoutTitle } from '../../Layout/components/LayoutTitle'
|
|
@@ -17,6 +18,7 @@ import {
|
|
|
17
18
|
NavigationContextType,
|
|
18
19
|
NavigationNodeButton,
|
|
19
20
|
NavigationNodeHref,
|
|
21
|
+
NavigationPath,
|
|
20
22
|
useNavigation,
|
|
21
23
|
} from '../hooks/useNavigation'
|
|
22
24
|
import { mouseEventPref } from './NavigationItem'
|
|
@@ -27,7 +29,6 @@ type LayoutOverlaySize = 'floating' | 'minimal' | 'full'
|
|
|
27
29
|
type LayoutOverlayAlign = 'start' | 'end' | 'center' | 'stretch'
|
|
28
30
|
|
|
29
31
|
type NavigationOverlayProps = {
|
|
30
|
-
active: boolean
|
|
31
32
|
sx?: SxProps<Theme>
|
|
32
33
|
stretchColumns?: boolean
|
|
33
34
|
variantSm: LayoutOverlayVariant
|
|
@@ -42,8 +43,9 @@ type NavigationOverlayProps = {
|
|
|
42
43
|
|
|
43
44
|
function findCurrent(
|
|
44
45
|
items: NavigationContextType['items'],
|
|
45
|
-
selected:
|
|
46
|
+
selected: NavigationPath | false,
|
|
46
47
|
): NavigationNodeHref | NavigationNodeButton | undefined {
|
|
48
|
+
if (selected === false) return undefined
|
|
47
49
|
const lastItem = selected.slice(-1)[0]
|
|
48
50
|
|
|
49
51
|
if (!lastItem) return undefined
|
|
@@ -67,9 +69,8 @@ const componentName = 'Navigation'
|
|
|
67
69
|
const parts = ['root', 'navigation', 'header', 'column'] as const
|
|
68
70
|
const { classes } = extendableComponent(componentName, parts)
|
|
69
71
|
|
|
70
|
-
export
|
|
72
|
+
export const NavigationOverlay = React.memo<NavigationOverlayProps>((props) => {
|
|
71
73
|
const {
|
|
72
|
-
active,
|
|
73
74
|
sx,
|
|
74
75
|
stretchColumns,
|
|
75
76
|
variantMd,
|
|
@@ -82,28 +83,42 @@ export function NavigationOverlay(props: NavigationOverlayProps) {
|
|
|
82
83
|
itemWidthMd,
|
|
83
84
|
mouseEvent,
|
|
84
85
|
} = props
|
|
85
|
-
const {
|
|
86
|
+
const { selection, items, animating, closing } = useNavigation()
|
|
86
87
|
|
|
87
88
|
const fabSize = useFabSize('responsive')
|
|
88
89
|
const svgSize = useIconSvgSize('large')
|
|
89
90
|
|
|
90
91
|
const isMobile = useMediaQuery<Theme>((theme) => theme.breakpoints.down('md'))
|
|
91
92
|
const handleOnBack = useEventCallback(() => {
|
|
92
|
-
if (isMobile)
|
|
93
|
-
|
|
93
|
+
if (isMobile) {
|
|
94
|
+
const current = selection.get()
|
|
95
|
+
selection.set(current !== false ? current.slice(0, -1) : false)
|
|
96
|
+
} else selection.set([])
|
|
94
97
|
})
|
|
95
98
|
|
|
99
|
+
const selectedLevel = useMotionValueValue(selection, (s) => (s === false ? -1 : s.length))
|
|
100
|
+
const activeAndNotClosing = useMotionSelector([selection, closing], ([s, c]) =>
|
|
101
|
+
c ? false : s !== false,
|
|
102
|
+
)
|
|
103
|
+
|
|
96
104
|
useEffect(() => {
|
|
97
|
-
animating.
|
|
98
|
-
}, [
|
|
105
|
+
animating.set(false)
|
|
106
|
+
}, [activeAndNotClosing, animating])
|
|
107
|
+
|
|
108
|
+
const afterClose = useEventCallback(() => {
|
|
109
|
+
if (!closing.get()) return
|
|
110
|
+
closing.set(false)
|
|
111
|
+
selection.set(false)
|
|
112
|
+
})
|
|
99
113
|
|
|
100
|
-
const
|
|
114
|
+
const handleClose = useEventCallback(() => closing.set(true))
|
|
101
115
|
|
|
102
116
|
return (
|
|
103
117
|
<Overlay
|
|
104
118
|
className={classes.root}
|
|
105
|
-
active={
|
|
106
|
-
|
|
119
|
+
active={activeAndNotClosing}
|
|
120
|
+
safeToRemove={afterClose}
|
|
121
|
+
onClosed={handleClose}
|
|
107
122
|
variantSm={variantSm}
|
|
108
123
|
sizeSm={sizeSm}
|
|
109
124
|
justifySm={justifySm}
|
|
@@ -111,13 +126,14 @@ export function NavigationOverlay(props: NavigationOverlayProps) {
|
|
|
111
126
|
sizeMd={sizeMd}
|
|
112
127
|
justifyMd={justifyMd}
|
|
113
128
|
overlayPaneProps={{
|
|
129
|
+
layout: true,
|
|
130
|
+
initial: false,
|
|
114
131
|
onLayoutAnimationStart: () => {
|
|
115
|
-
animating.
|
|
132
|
+
animating.set(true)
|
|
116
133
|
},
|
|
117
134
|
onLayoutAnimationComplete: () => {
|
|
118
|
-
animating.
|
|
135
|
+
animating.set(false)
|
|
119
136
|
},
|
|
120
|
-
layout: true,
|
|
121
137
|
}}
|
|
122
138
|
sx={{
|
|
123
139
|
zIndex: 'drawer',
|
|
@@ -146,7 +162,7 @@ export function NavigationOverlay(props: NavigationOverlayProps) {
|
|
|
146
162
|
switchPoint={0}
|
|
147
163
|
layout='position'
|
|
148
164
|
left={
|
|
149
|
-
|
|
165
|
+
selectedLevel > 0 && (
|
|
150
166
|
<Fab
|
|
151
167
|
color='inherit'
|
|
152
168
|
onClick={handleOnBack}
|
|
@@ -165,7 +181,7 @@ export function NavigationOverlay(props: NavigationOverlayProps) {
|
|
|
165
181
|
right={
|
|
166
182
|
<Fab
|
|
167
183
|
color='inherit'
|
|
168
|
-
onClick={
|
|
184
|
+
onClick={handleClose}
|
|
169
185
|
sx={{
|
|
170
186
|
boxShadow: 'none',
|
|
171
187
|
marginLeft: `calc((${fabSize} - ${svgSize}) * -0.5)`,
|
|
@@ -179,7 +195,7 @@ export function NavigationOverlay(props: NavigationOverlayProps) {
|
|
|
179
195
|
}
|
|
180
196
|
>
|
|
181
197
|
<LayoutTitle size='small' component='span'>
|
|
182
|
-
{findCurrent(items,
|
|
198
|
+
{findCurrent(items, selection.get())?.name ?? <Trans id='Menu' />}
|
|
183
199
|
</LayoutTitle>
|
|
184
200
|
</LayoutHeaderContent>
|
|
185
201
|
</Box>
|
|
@@ -193,7 +209,7 @@ export function NavigationOverlay(props: NavigationOverlayProps) {
|
|
|
193
209
|
'& .NavigationItem-item': {
|
|
194
210
|
// eslint-disable-next-line no-nested-ternary
|
|
195
211
|
width: itemWidthMd
|
|
196
|
-
?
|
|
212
|
+
? selectedLevel >= 1
|
|
197
213
|
? `calc(${itemWidthMd} + 1px)`
|
|
198
214
|
: itemWidthMd
|
|
199
215
|
: 'stretch',
|
|
@@ -201,7 +217,7 @@ export function NavigationOverlay(props: NavigationOverlayProps) {
|
|
|
201
217
|
[theme.breakpoints.down('md')]: {
|
|
202
218
|
width:
|
|
203
219
|
sizeSm !== 'floating'
|
|
204
|
-
? `calc(${itemWidthSm || '100vw'} + ${
|
|
220
|
+
? `calc(${itemWidthSm || '100vw'} + ${selectedLevel}px)`
|
|
205
221
|
: `calc(${itemWidthSm || '100vw'} - ${theme.page.horizontal} - ${
|
|
206
222
|
theme.page.horizontal
|
|
207
223
|
})`,
|
|
@@ -213,7 +229,7 @@ export function NavigationOverlay(props: NavigationOverlayProps) {
|
|
|
213
229
|
sizeSm !== 'floating'
|
|
214
230
|
? `calc(${itemWidthSm || '100vw'} - ${theme.spacings.md} - ${
|
|
215
231
|
theme.spacings.md
|
|
216
|
-
} + ${
|
|
232
|
+
} + ${selectedLevel}px)`
|
|
217
233
|
: `calc(${itemWidthSm || '100vw'} - ${theme.spacings.md} - ${
|
|
218
234
|
theme.spacings.md
|
|
219
235
|
} - ${theme.page.horizontal} - ${theme.page.horizontal})`,
|
|
@@ -251,7 +267,7 @@ export function NavigationOverlay(props: NavigationOverlayProps) {
|
|
|
251
267
|
...(Array.isArray(sx) ? sx : [sx]),
|
|
252
268
|
]}
|
|
253
269
|
>
|
|
254
|
-
{
|
|
270
|
+
{selectedLevel >= 0 && (
|
|
255
271
|
<Box
|
|
256
272
|
sx={(theme) => ({
|
|
257
273
|
gridArea: '1 / 1 / 999 / 2',
|
|
@@ -260,7 +276,7 @@ export function NavigationOverlay(props: NavigationOverlayProps) {
|
|
|
260
276
|
className={classes.column}
|
|
261
277
|
/>
|
|
262
278
|
)}
|
|
263
|
-
{
|
|
279
|
+
{selectedLevel >= 1 && (
|
|
264
280
|
<Box
|
|
265
281
|
sx={(theme) => ({
|
|
266
282
|
gridArea: '1 / 2 / 999 / 3',
|
|
@@ -269,7 +285,7 @@ export function NavigationOverlay(props: NavigationOverlayProps) {
|
|
|
269
285
|
className={classes.column}
|
|
270
286
|
/>
|
|
271
287
|
)}
|
|
272
|
-
{
|
|
288
|
+
{selectedLevel >= 2 && (
|
|
273
289
|
<Box
|
|
274
290
|
sx={(theme) => ({
|
|
275
291
|
gridArea: '1 / 3 / 999 / 4',
|
|
@@ -278,7 +294,7 @@ export function NavigationOverlay(props: NavigationOverlayProps) {
|
|
|
278
294
|
className={classes.column}
|
|
279
295
|
/>
|
|
280
296
|
)}
|
|
281
|
-
{
|
|
297
|
+
{selectedLevel >= 3 && (
|
|
282
298
|
<Box
|
|
283
299
|
sx={(theme) => ({
|
|
284
300
|
gridArea: '1 / 4 / 999 / 5',
|
|
@@ -294,4 +310,8 @@ export function NavigationOverlay(props: NavigationOverlayProps) {
|
|
|
294
310
|
</MotionDiv>
|
|
295
311
|
</Overlay>
|
|
296
312
|
)
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
316
|
+
NavigationOverlay.displayName = 'NavigationOverlay'
|
|
297
317
|
}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { useState, useMemo, SetStateAction, useRef } from 'react'
|
|
1
|
+
import { MotionConfig, useMotionValue } from 'framer-motion'
|
|
2
|
+
import React, { useMemo, useRef } from 'react'
|
|
4
3
|
import { isElement } from 'react-is'
|
|
5
4
|
import {
|
|
6
5
|
NavigationNode,
|
|
7
|
-
NavigationPath,
|
|
8
6
|
NavigationContextType,
|
|
9
7
|
NavigationContext,
|
|
10
|
-
|
|
8
|
+
UseNavigationSelection,
|
|
11
9
|
} from '../hooks/useNavigation'
|
|
12
10
|
|
|
13
11
|
export type NavigationProviderProps = {
|
|
@@ -16,51 +14,35 @@ export type NavigationProviderProps = {
|
|
|
16
14
|
closeAfterNavigate?: boolean
|
|
17
15
|
children?: React.ReactNode
|
|
18
16
|
animationDuration?: number
|
|
19
|
-
|
|
20
|
-
setSelected: (value: SetStateAction<NavigationPath>) => void
|
|
21
|
-
onChange?: NavigationSelect
|
|
22
|
-
onClose?: NavigationContextType['onClose']
|
|
17
|
+
selection: UseNavigationSelection
|
|
23
18
|
}
|
|
24
19
|
|
|
25
20
|
const nonNullable = <T,>(value: T): value is NonNullable<T> => value !== null && value !== undefined
|
|
26
21
|
|
|
27
|
-
export
|
|
22
|
+
export const NavigationProvider = React.memo<NavigationProviderProps>((props) => {
|
|
28
23
|
const {
|
|
29
24
|
items,
|
|
30
|
-
onChange,
|
|
31
25
|
hideRootOnNavigate = true,
|
|
32
26
|
closeAfterNavigate = false,
|
|
33
27
|
animationDuration = 0.275,
|
|
34
28
|
children,
|
|
35
|
-
|
|
36
|
-
selected,
|
|
37
|
-
setSelected,
|
|
29
|
+
selection,
|
|
38
30
|
} = props
|
|
39
31
|
|
|
40
|
-
const animating =
|
|
41
|
-
|
|
42
|
-
const select = useEventCallback((incomming: NavigationPath) => {
|
|
43
|
-
setSelected(incomming)
|
|
44
|
-
onChange?.(incomming)
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
const onClose: NavigationContextType['onClose'] = useEventCallback((e, href) => {
|
|
48
|
-
onCloseUnstable?.(e, href)
|
|
49
|
-
setTimeout(() => select([]), animationDuration * 1000)
|
|
50
|
-
})
|
|
32
|
+
const animating = useMotionValue(false)
|
|
33
|
+
const closing = useMotionValue(false)
|
|
51
34
|
|
|
52
35
|
const value = useMemo<NavigationContextType>(
|
|
53
36
|
() => ({
|
|
54
37
|
hideRootOnNavigate,
|
|
55
|
-
|
|
56
|
-
select,
|
|
38
|
+
selection,
|
|
57
39
|
animating,
|
|
40
|
+
closing,
|
|
58
41
|
items: items
|
|
59
42
|
.map((item, index) => (isElement(item) ? { id: item.key ?? index, component: item } : item))
|
|
60
43
|
.filter(nonNullable),
|
|
61
|
-
onClose,
|
|
62
44
|
}),
|
|
63
|
-
[hideRootOnNavigate,
|
|
45
|
+
[hideRootOnNavigate, selection, animating, closing, items],
|
|
64
46
|
)
|
|
65
47
|
|
|
66
48
|
return (
|
|
@@ -68,4 +50,4 @@ export function NavigationProvider(props: NavigationProviderProps) {
|
|
|
68
50
|
<NavigationContext.Provider value={value}>{children}</NavigationContext.Provider>
|
|
69
51
|
</MotionConfig>
|
|
70
52
|
)
|
|
71
|
-
}
|
|
53
|
+
})
|
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MotionValue, useMotionValue } from 'framer-motion'
|
|
2
|
+
import { createContext, MutableRefObject, useContext } from 'react'
|
|
2
3
|
|
|
3
4
|
export type NavigationId = string | number
|
|
4
5
|
export type NavigationPath = NavigationId[]
|
|
5
|
-
export type NavigationSelect = (selected: NavigationPath) => void
|
|
6
6
|
export type NavigationRender = React.FC<
|
|
7
7
|
(NavigationNodeComponent | NavigationNodeHref) & { children?: React.ReactNode }
|
|
8
8
|
>
|
|
9
9
|
|
|
10
|
+
export type UseNavigationSelection = MotionValue<NavigationPath | false>
|
|
11
|
+
|
|
10
12
|
export type NavigationOnClose = (
|
|
11
13
|
event?: React.MouseEvent<HTMLAnchorElement>,
|
|
12
14
|
href?: string | undefined,
|
|
13
15
|
) => void
|
|
14
16
|
export type NavigationContextType = {
|
|
15
|
-
|
|
16
|
-
select: NavigationSelect
|
|
17
|
+
selection: UseNavigationSelection
|
|
17
18
|
items: NavigationNode[]
|
|
18
19
|
hideRootOnNavigate: boolean
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
animating: MotionValue<boolean>
|
|
21
|
+
closing: MotionValue<boolean>
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
type NavigationNodeBase = {
|
|
@@ -57,3 +58,29 @@ export const NavigationContext = createContext(undefined as unknown as Navigatio
|
|
|
57
58
|
export function useNavigation() {
|
|
58
59
|
return useContext(NavigationContext)
|
|
59
60
|
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* To prevent excessive rerenders we're not using plain React useState, but we're using a reactive
|
|
64
|
+
* motion value (could easily be any other reactive variable like Zustand, MobX, etc).
|
|
65
|
+
*
|
|
66
|
+
* Usage:
|
|
67
|
+
*
|
|
68
|
+
* ```tsx
|
|
69
|
+
* const selection = useNavigationSelection()
|
|
70
|
+
*
|
|
71
|
+
* function onClose() {
|
|
72
|
+
* selection.set(false)
|
|
73
|
+
* }
|
|
74
|
+
*
|
|
75
|
+
* function openRoot() {
|
|
76
|
+
* selection.set([])
|
|
77
|
+
* }
|
|
78
|
+
*
|
|
79
|
+
* function openPath() {
|
|
80
|
+
* selection.set(['my-path'])
|
|
81
|
+
* }
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export function useNavigationSelection(): UseNavigationSelection {
|
|
85
|
+
return useMotionValue<NavigationPath | false>(false)
|
|
86
|
+
}
|
|
@@ -6,7 +6,7 @@ import { OverlayBase, LayoutOverlayBaseProps } from './OverlayBase'
|
|
|
6
6
|
|
|
7
7
|
export type OverlayProps = Omit<
|
|
8
8
|
SetOptional<LayoutOverlayBaseProps, 'variantSm' | 'variantMd'>,
|
|
9
|
-
'direction' | 'offsetPageY' | 'isPresent'
|
|
9
|
+
'direction' | 'offsetPageY' | 'isPresent'
|
|
10
10
|
>
|
|
11
11
|
|
|
12
12
|
export function Overlay(props: OverlayProps) {
|
|
@@ -50,7 +50,6 @@ export function Overlay(props: OverlayProps) {
|
|
|
50
50
|
direction={1}
|
|
51
51
|
active={active}
|
|
52
52
|
isPresent={active}
|
|
53
|
-
safeToRemove={undefined}
|
|
54
53
|
{...otherProps}
|
|
55
54
|
>
|
|
56
55
|
{children}
|
|
@@ -39,7 +39,7 @@ export type LayoutOverlayBaseProps = {
|
|
|
39
39
|
onClosed: () => void
|
|
40
40
|
offsetPageY: number
|
|
41
41
|
isPresent: boolean
|
|
42
|
-
safeToRemove
|
|
42
|
+
safeToRemove?: (() => void) | null | undefined
|
|
43
43
|
overlayPaneProps?: MotionProps
|
|
44
44
|
} & StyleProps &
|
|
45
45
|
OverridableProps
|
|
@@ -115,14 +115,7 @@ export function OverlayBase(incommingProps: LayoutOverlayBaseProps) {
|
|
|
115
115
|
useIsomorphicLayoutEffect(() => {
|
|
116
116
|
const scroller = scrollerRef.current
|
|
117
117
|
|
|
118
|
-
if (!scroller) return undefined
|
|
119
|
-
|
|
120
|
-
if (!isPresent && position.get() === OverlayPosition.UNOPENED) {
|
|
121
|
-
scroller.scrollLeft = positions.closed.x.get()
|
|
122
|
-
scroller.scrollTop = positions.closed.y.get()
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (!isPresent) return undefined
|
|
118
|
+
if (!scroller || !isPresent) return undefined
|
|
126
119
|
|
|
127
120
|
const open = { x: positions.open.x.get(), y: positions.open.y.get() }
|
|
128
121
|
|
|
@@ -170,16 +163,23 @@ export function OverlayBase(incommingProps: LayoutOverlayBaseProps) {
|
|
|
170
163
|
|
|
171
164
|
// When the overlay is closed by navigating away, we're closing the overlay.
|
|
172
165
|
useEffect(() => {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
clearScrollLock()
|
|
166
|
+
const scroller = scrollerRef.current
|
|
167
|
+
if (isPresent || !scroller) return
|
|
176
168
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
169
|
+
if (position.get() === OverlayPosition.UNOPENED) {
|
|
170
|
+
position.set(OverlayPosition.CLOSED)
|
|
171
|
+
clearScrollLock()
|
|
172
|
+
scroller.scrollLeft = positions.closed.x.get()
|
|
173
|
+
scroller.scrollTop = positions.closed.y.get()
|
|
174
|
+
safeToRemove?.()
|
|
175
|
+
} else {
|
|
176
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
177
|
+
scrollTo({
|
|
178
|
+
x: positions.closed.x.get(),
|
|
179
|
+
y: positions.closed.y.get(),
|
|
180
|
+
}).then(() => safeToRemove?.())
|
|
181
|
+
}
|
|
182
|
+
}, [isPresent, position, positions, safeToRemove, scrollTo, scrollerRef])
|
|
183
183
|
|
|
184
184
|
// Only go back to a previous page if the overlay isn't closed.
|
|
185
185
|
const closeOverlay = useCallback(() => {
|
|
@@ -384,7 +384,7 @@ export function OverlayBase(incommingProps: LayoutOverlayBaseProps) {
|
|
|
384
384
|
[theme.breakpoints.down('md')]: {
|
|
385
385
|
minWidth: '80vw',
|
|
386
386
|
'&:not(.sizeMdFull)': {
|
|
387
|
-
width: '
|
|
387
|
+
width: 'auto',
|
|
388
388
|
},
|
|
389
389
|
|
|
390
390
|
'&.variantSmBottom.sizeSmFull': {
|
|
@@ -26,6 +26,7 @@ export function useOverlayPosition() {
|
|
|
26
26
|
|
|
27
27
|
const measure = () => {
|
|
28
28
|
const positions = getScrollSnapPositions()
|
|
29
|
+
|
|
29
30
|
state.open.x.set(positions.x[1] ?? 0)
|
|
30
31
|
state.closed.x.set(positions.x[0])
|
|
31
32
|
state.open.y.set(positions.y[1] ?? 0)
|
|
@@ -50,10 +51,14 @@ export function useOverlayPosition() {
|
|
|
50
51
|
|
|
51
52
|
const xC = state.closed.x.get()
|
|
52
53
|
const xO = state.open.x.get()
|
|
54
|
+
|
|
53
55
|
const visX = xO === xC ? 1 : Math.max(0, Math.min(1, (x - xC) / (xO - xC)))
|
|
54
56
|
|
|
57
|
+
let vis = visY * visX
|
|
58
|
+
if (xC === 0 && xO === 0 && yC === 0 && yO === 0) vis = 0
|
|
59
|
+
|
|
55
60
|
// todo: visibility sometimes flickers
|
|
56
|
-
state.open.visible.set(
|
|
61
|
+
state.open.visible.set(vis)
|
|
57
62
|
}
|
|
58
63
|
|
|
59
64
|
const cancelY = scroll.y.onChange(calc)
|
|
@@ -3,6 +3,7 @@ import { m, useTransform } from 'framer-motion'
|
|
|
3
3
|
import React from 'react'
|
|
4
4
|
import { useScrollY } from '../../Layout/hooks/useScrollY'
|
|
5
5
|
import { extendableComponent } from '../../Styles'
|
|
6
|
+
import { breakpointVal } from '../../Styles/breakpointVal'
|
|
6
7
|
import { responsiveVal } from '../../Styles/responsiveVal'
|
|
7
8
|
import { Row } from '../Row'
|
|
8
9
|
|
|
@@ -84,9 +85,11 @@ export function HeroBanner(props: HeroBannerProps) {
|
|
|
84
85
|
width: '100%',
|
|
85
86
|
height: '100%',
|
|
86
87
|
[theme.breakpoints.down('md')]: {
|
|
87
|
-
|
|
88
|
+
...breakpointVal(
|
|
89
|
+
'borderRadius',
|
|
88
90
|
theme.shape.borderRadius * 2,
|
|
89
91
|
theme.shape.borderRadius * 3,
|
|
92
|
+
theme.breakpoints.values,
|
|
90
93
|
),
|
|
91
94
|
},
|
|
92
95
|
},
|
|
@@ -99,9 +102,11 @@ export function HeroBanner(props: HeroBannerProps) {
|
|
|
99
102
|
style={{ width: !matches ? width : 0, borderRadius }}
|
|
100
103
|
className={classes.animated}
|
|
101
104
|
sx={(theme) => ({
|
|
102
|
-
|
|
105
|
+
...breakpointVal(
|
|
106
|
+
'borderRadius',
|
|
103
107
|
theme.shape.borderRadius * 2,
|
|
104
108
|
theme.shape.borderRadius * 3,
|
|
109
|
+
theme.breakpoints.values,
|
|
105
110
|
),
|
|
106
111
|
overflow: 'hidden',
|
|
107
112
|
transform: 'translateZ(0)',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Box, SxProps, Theme } from '@mui/material'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
import { extendableComponent } from '../../Styles'
|
|
4
|
-
import {
|
|
4
|
+
import { breakpointVal } from '../../Styles/breakpointVal'
|
|
5
5
|
import { Row } from '../Row'
|
|
6
6
|
|
|
7
7
|
export type ImageTextProps = {
|
|
@@ -37,7 +37,12 @@ export function ImageText(props: ImageTextProps) {
|
|
|
37
37
|
background: 'none',
|
|
38
38
|
gridTemplateColumns: '1fr 1fr',
|
|
39
39
|
},
|
|
40
|
-
|
|
40
|
+
...breakpointVal(
|
|
41
|
+
'borderRadius',
|
|
42
|
+
theme.shape.borderRadius * 2,
|
|
43
|
+
theme.shape.borderRadius * 3,
|
|
44
|
+
theme.breakpoints.values,
|
|
45
|
+
),
|
|
41
46
|
})}
|
|
42
47
|
>
|
|
43
48
|
<Box
|
|
@@ -49,9 +54,11 @@ export function ImageText(props: ImageTextProps) {
|
|
|
49
54
|
height: '100%',
|
|
50
55
|
width: '100%',
|
|
51
56
|
objectFit: 'cover',
|
|
52
|
-
|
|
57
|
+
...breakpointVal(
|
|
58
|
+
'borderRadius',
|
|
53
59
|
theme.shape.borderRadius * 2,
|
|
54
60
|
theme.shape.borderRadius * 3,
|
|
61
|
+
theme.breakpoints.values,
|
|
55
62
|
),
|
|
56
63
|
},
|
|
57
64
|
})}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Box, SxProps, Theme } from '@mui/material'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
import { extendableComponent } from '../../Styles'
|
|
4
|
+
import { breakpointVal } from '../../Styles/breakpointVal'
|
|
4
5
|
import { responsiveVal } from '../../Styles/responsiveVal'
|
|
5
6
|
import { Row } from '../Row'
|
|
6
7
|
|
|
@@ -32,7 +33,12 @@ export function ImageTextBoxed(props: ImageTextBoxedProps) {
|
|
|
32
33
|
gridTemplateColumns: '1fr auto',
|
|
33
34
|
columnGap: `${theme.spacings.lg}`,
|
|
34
35
|
},
|
|
35
|
-
|
|
36
|
+
...breakpointVal(
|
|
37
|
+
'borderRadius',
|
|
38
|
+
theme.shape.borderRadius * 2,
|
|
39
|
+
theme.shape.borderRadius * 3,
|
|
40
|
+
theme.breakpoints.values,
|
|
41
|
+
),
|
|
36
42
|
overflow: 'hidden',
|
|
37
43
|
})}
|
|
38
44
|
>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Box, ContainerProps } from '@mui/material'
|
|
2
2
|
import { extendableComponent } from '../../Styles'
|
|
3
|
-
import {
|
|
3
|
+
import { breakpointVal } from '../../Styles/breakpointVal'
|
|
4
4
|
import { Row } from '../Row'
|
|
5
5
|
|
|
6
6
|
export type ParagraphWithSidebarSlideProps = ContainerProps & {
|
|
@@ -46,9 +46,11 @@ export function ParagraphWithSidebarSlide(props: ParagraphWithSidebarSlideProps)
|
|
|
46
46
|
filter: 'brightness(100%)',
|
|
47
47
|
height: '100%',
|
|
48
48
|
},
|
|
49
|
-
|
|
49
|
+
...breakpointVal(
|
|
50
|
+
'borderRadius',
|
|
50
51
|
theme.shape.borderRadius * 2,
|
|
51
52
|
theme.shape.borderRadius * 3,
|
|
53
|
+
theme.breakpoints.values,
|
|
52
54
|
),
|
|
53
55
|
},
|
|
54
56
|
})}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Box, ContainerProps, Typography } from '@mui/material'
|
|
2
2
|
import { extendableComponent } from '../../Styles'
|
|
3
|
+
import { breakpointVal } from '../../Styles/breakpointVal'
|
|
3
4
|
import { responsiveVal } from '../../Styles/responsiveVal'
|
|
4
5
|
import { Row } from '../Row'
|
|
5
6
|
|
|
@@ -31,7 +32,12 @@ export function SpecialBanner(props: SpecialBannerProps) {
|
|
|
31
32
|
paddingTop: theme.spacings.lg,
|
|
32
33
|
paddingBottom: theme.spacings.lg,
|
|
33
34
|
justifySelf: 'start',
|
|
34
|
-
|
|
35
|
+
...breakpointVal(
|
|
36
|
+
'borderRadius',
|
|
37
|
+
theme.shape.borderRadius * 2,
|
|
38
|
+
theme.shape.borderRadius * 3,
|
|
39
|
+
theme.breakpoints.values,
|
|
40
|
+
),
|
|
35
41
|
[theme.breakpoints.up('md')]: {
|
|
36
42
|
padding: 0,
|
|
37
43
|
background: 'none',
|
|
@@ -51,9 +57,11 @@ export function SpecialBanner(props: SpecialBannerProps) {
|
|
|
51
57
|
width: responsiveVal(200, 900),
|
|
52
58
|
height: 'auto',
|
|
53
59
|
objectFit: 'cover',
|
|
54
|
-
|
|
60
|
+
...breakpointVal(
|
|
61
|
+
'borderRadius',
|
|
55
62
|
theme.shape.borderRadius * 2,
|
|
56
63
|
theme.shape.borderRadius * 3,
|
|
64
|
+
theme.breakpoints.values,
|
|
57
65
|
),
|
|
58
66
|
},
|
|
59
67
|
[theme.breakpoints.up('lg')]: {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { breakpointVal } from '@graphcommerce/next-ui'
|
|
1
2
|
import {
|
|
2
3
|
Fab,
|
|
3
4
|
Snackbar,
|
|
@@ -65,8 +66,6 @@ export default function MessageSnackbarImpl(props: MessageSnackbarImplProps) {
|
|
|
65
66
|
}, [open])
|
|
66
67
|
|
|
67
68
|
const hideSnackbar = (e) => {
|
|
68
|
-
e.preventDefault()
|
|
69
|
-
|
|
70
69
|
setShowSnackbar(false)
|
|
71
70
|
onClose?.()
|
|
72
71
|
}
|
|
@@ -86,20 +85,25 @@ export default function MessageSnackbarImpl(props: MessageSnackbarImplProps) {
|
|
|
86
85
|
message={message}
|
|
87
86
|
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
|
|
88
87
|
open={showSnackbar}
|
|
89
|
-
autoHideDuration={autoHide ?
|
|
88
|
+
autoHideDuration={autoHide ? 5000 : null}
|
|
90
89
|
className={classes.root}
|
|
91
90
|
sx={sx}
|
|
92
91
|
onClose={hideSnackbar}
|
|
93
92
|
>
|
|
94
93
|
<SnackbarContent
|
|
95
|
-
elevation={
|
|
94
|
+
elevation={16}
|
|
96
95
|
className={classes.content}
|
|
97
96
|
sx={(theme) => ({
|
|
98
97
|
'&.variantPill': {
|
|
99
98
|
backgroundColor: theme.palette.background.paper,
|
|
100
99
|
color: theme.palette.text.primary,
|
|
101
100
|
[theme.breakpoints.up('md')]: {
|
|
102
|
-
|
|
101
|
+
...breakpointVal(
|
|
102
|
+
'borderRadius',
|
|
103
|
+
theme.shape.borderRadius * 3,
|
|
104
|
+
theme.shape.borderRadius * 4,
|
|
105
|
+
theme.breakpoints.values,
|
|
106
|
+
),
|
|
103
107
|
},
|
|
104
108
|
padding: theme.spacings.xxs,
|
|
105
109
|
},
|
package/Stepper/Stepper.tsx
CHANGED
package/Styles/breakpointVal.tsx
CHANGED