@graphcommerce/next-ui 7.0.0-canary.21 → 7.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.
- package/ActionCard/ActionCard.tsx +7 -8
- package/ActionCard/ActionCardAccordion.tsx +58 -0
- package/ActionCard/ActionCardLayout.tsx +6 -6
- package/ActionCard/ActionCardList.tsx +32 -4
- package/ActionCard/ActionCardListForm.tsx +1 -1
- package/ActionCard/index.ts +1 -0
- package/Blog/BlogListItem/BlogListItem.tsx +15 -14
- package/Button/LinkOrButton.tsx +5 -4
- package/CHANGELOG.md +263 -1
- package/Footer/Footer.tsx +65 -57
- package/FramerScroller/SidebarGallery.tsx +22 -11
- package/IconSvg/IconSvg.tsx +28 -30
- package/Layout/components/LayoutHeader.tsx +4 -1
- package/LayoutOverlay/components/LayoutOverlayHeader.tsx +2 -1
- package/LayoutParts/StickyBelowHeader.tsx +19 -10
- package/Navigation/hooks/useNavigation.ts +1 -0
- package/Overlay/components/OverlayBase.tsx +33 -8
- package/OverlayOrPopperChip/OverlayPanelActions.tsx +1 -1
- package/OverlayOrPopperChip/PopperPanel.tsx +1 -1
- package/OverlayOrPopperChip/PopperPanelActions.tsx +2 -2
- package/PageMeta/PageMeta.tsx +24 -2
- package/Pagination/Pagination.tsx +16 -13
- package/RenderType/RenderType.tsx +1 -1
- package/Row/IconBlocks/IconBlock.tsx +36 -33
- package/Styles/__tests__/spreadVal.test.ts +1 -1
- package/TextInputNumber/TextInputNumber.tsx +50 -30
- package/Theme/MuiButton.ts +4 -4
- package/Theme/MuiFab.ts +15 -1
- package/hooks/useDateTimeFormat.ts +8 -1
- package/hooks/useNumberFormat.ts +8 -1
- package/package.json +17 -16
package/Footer/Footer.tsx
CHANGED
|
@@ -65,63 +65,71 @@ export function Footer(props: FooterProps) {
|
|
|
65
65
|
className={classes.root}
|
|
66
66
|
{...containerProps}
|
|
67
67
|
>
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
68
|
+
{socialLinks && (
|
|
69
|
+
<Box
|
|
70
|
+
sx={(theme) => ({
|
|
71
|
+
display: 'grid',
|
|
72
|
+
justifyContent: 'start',
|
|
73
|
+
gridAutoFlow: 'column',
|
|
74
|
+
gridArea: 'social',
|
|
75
|
+
gap: { xs: `0 ${theme.spacings.xs}`, md: `0 ${theme.spacings.xs}` },
|
|
76
|
+
'& > *': {
|
|
77
|
+
minWidth: 'min-content',
|
|
78
|
+
},
|
|
79
|
+
})}
|
|
80
|
+
className={classes.social}
|
|
81
|
+
>
|
|
82
|
+
{socialLinks}
|
|
83
|
+
</Box>
|
|
84
|
+
)}
|
|
85
|
+
{storeSwitcher && (
|
|
86
|
+
<Box
|
|
87
|
+
sx={(theme) => ({
|
|
88
|
+
gridArea: 'switcher',
|
|
89
|
+
justifySelf: 'end',
|
|
90
|
+
[theme.breakpoints.down('md')]: {
|
|
91
|
+
justifySelf: 'center',
|
|
92
|
+
},
|
|
93
|
+
})}
|
|
94
|
+
className={classes.storeSwitcher}
|
|
95
|
+
>
|
|
96
|
+
{storeSwitcher}
|
|
97
|
+
</Box>
|
|
98
|
+
)}
|
|
99
|
+
{customerService && (
|
|
100
|
+
<Box
|
|
101
|
+
sx={(theme) => ({
|
|
102
|
+
gridArea: 'support',
|
|
103
|
+
justifySelf: 'flex-end',
|
|
104
|
+
[theme.breakpoints.down('md')]: {
|
|
105
|
+
justifySelf: 'center',
|
|
106
|
+
},
|
|
107
|
+
})}
|
|
108
|
+
className={classes.support}
|
|
109
|
+
>
|
|
110
|
+
{customerService}
|
|
111
|
+
</Box>
|
|
112
|
+
)}
|
|
113
|
+
{copyright && (
|
|
114
|
+
<Box
|
|
115
|
+
sx={(theme) => ({
|
|
116
|
+
typography: 'body2',
|
|
117
|
+
display: 'grid',
|
|
118
|
+
gridAutoFlow: 'column',
|
|
119
|
+
alignContent: 'center',
|
|
120
|
+
gridArea: 'links',
|
|
121
|
+
gap: theme.spacings.sm,
|
|
122
|
+
[theme.breakpoints.down('md')]: {
|
|
123
|
+
gridAutoFlow: 'row',
|
|
124
|
+
textAlign: 'center',
|
|
125
|
+
gap: `8px`,
|
|
126
|
+
},
|
|
127
|
+
})}
|
|
128
|
+
className={classes.copyright}
|
|
129
|
+
>
|
|
130
|
+
{copyright}
|
|
131
|
+
</Box>
|
|
132
|
+
)}
|
|
125
133
|
</Container>
|
|
126
134
|
)
|
|
127
135
|
}
|
|
@@ -48,6 +48,7 @@ export type SidebarGalleryProps = {
|
|
|
48
48
|
aspectRatio?: [number, number]
|
|
49
49
|
routeHash?: string
|
|
50
50
|
sx?: SxProps<Theme>
|
|
51
|
+
disableZoom?: boolean
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
export function SidebarGallery(props: SidebarGalleryProps) {
|
|
@@ -57,6 +58,7 @@ export function SidebarGallery(props: SidebarGalleryProps) {
|
|
|
57
58
|
aspectRatio: [width, height] = [1, 1],
|
|
58
59
|
sx,
|
|
59
60
|
routeHash = 'gallery',
|
|
61
|
+
disableZoom,
|
|
60
62
|
} = props
|
|
61
63
|
|
|
62
64
|
const router = useRouter()
|
|
@@ -76,6 +78,9 @@ export function SidebarGallery(props: SidebarGalleryProps) {
|
|
|
76
78
|
}, [prevRoute?.pathname, route, router, zoomed])
|
|
77
79
|
|
|
78
80
|
const toggle = () => {
|
|
81
|
+
if (disableZoom) {
|
|
82
|
+
return
|
|
83
|
+
}
|
|
79
84
|
if (!zoomed) {
|
|
80
85
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
81
86
|
router.push(route, undefined, { shallow: true })
|
|
@@ -192,7 +197,7 @@ export function SidebarGallery(props: SidebarGalleryProps) {
|
|
|
192
197
|
height: '100%',
|
|
193
198
|
gridAutoColumns: `100%`,
|
|
194
199
|
gridTemplateRows: `100%`,
|
|
195
|
-
cursor: 'zoom-in',
|
|
200
|
+
cursor: disableZoom ? 'auto' : 'zoom-in',
|
|
196
201
|
},
|
|
197
202
|
zoomed && {
|
|
198
203
|
height: `var(--client-size-y)`,
|
|
@@ -232,16 +237,22 @@ export function SidebarGallery(props: SidebarGalleryProps) {
|
|
|
232
237
|
right: theme.spacings.sm,
|
|
233
238
|
}}
|
|
234
239
|
>
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
240
|
+
{!disableZoom && (
|
|
241
|
+
<Fab
|
|
242
|
+
size='small'
|
|
243
|
+
className={classes.toggleIcon}
|
|
244
|
+
disabled={!hasImages}
|
|
245
|
+
onMouseUp={toggle}
|
|
246
|
+
aria-label='Toggle Fullscreen'
|
|
247
|
+
sx={{ boxShadow: 6 }}
|
|
248
|
+
>
|
|
249
|
+
{!zoomed ? (
|
|
250
|
+
<IconSvg src={iconFullscreen} />
|
|
251
|
+
) : (
|
|
252
|
+
<IconSvg src={iconFullscreenExit} />
|
|
253
|
+
)}
|
|
254
|
+
</Fab>
|
|
255
|
+
)}
|
|
245
256
|
</MotionBox>
|
|
246
257
|
<Box
|
|
247
258
|
className={classes.centerLeft}
|
package/IconSvg/IconSvg.tsx
CHANGED
|
@@ -53,37 +53,35 @@ export function useIconSvgSize(size: keyof typeof sizes) {
|
|
|
53
53
|
return sizes[size]
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
const Svg = styled('svg', { name, target: name })(() =>
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
'
|
|
82
|
-
|
|
83
|
-
stroke: 'none',
|
|
84
|
-
},
|
|
56
|
+
const Svg = styled('svg', { name, target: name })(() => ({
|
|
57
|
+
userSelect: 'none',
|
|
58
|
+
width: '1em',
|
|
59
|
+
height: '1em',
|
|
60
|
+
display: 'inline-block',
|
|
61
|
+
|
|
62
|
+
strokeLinecap: 'square',
|
|
63
|
+
strokeLinejoin: 'miter',
|
|
64
|
+
strokeMiterlimit: 4,
|
|
65
|
+
|
|
66
|
+
fill: 'none',
|
|
67
|
+
stroke: 'currentColor',
|
|
68
|
+
|
|
69
|
+
fontSize: '1.3em',
|
|
70
|
+
|
|
71
|
+
strokeWidth: svgIconStrokeWidth(28, 148, 1.4, 0.8),
|
|
72
|
+
|
|
73
|
+
'&.sizeXs': { fontSize: sizes.xs },
|
|
74
|
+
'&.sizeSmall': { fontSize: sizes.small },
|
|
75
|
+
'&.sizeMedium': { fontSize: sizes.medium },
|
|
76
|
+
'&.sizeLarge': { fontSize: sizes.large },
|
|
77
|
+
'&.sizeXl': { fontSize: sizes.xl },
|
|
78
|
+
'&.sizeXxl': { fontSize: sizes.xxl },
|
|
79
|
+
|
|
80
|
+
'&.fillIcon': {
|
|
81
|
+
fill: 'currentColor',
|
|
82
|
+
stroke: 'none',
|
|
85
83
|
},
|
|
86
|
-
|
|
84
|
+
}))
|
|
87
85
|
|
|
88
86
|
/**
|
|
89
87
|
* IconSvg component is supposed to be used in combination with `icons`
|
|
@@ -26,6 +26,8 @@ export type LayoutHeaderProps = FloatingProps &
|
|
|
26
26
|
noAlign?: boolean
|
|
27
27
|
|
|
28
28
|
sx?: SxProps<Theme>
|
|
29
|
+
|
|
30
|
+
hideBackButton?: boolean
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
type ComponentStyleProps = {
|
|
@@ -46,6 +48,7 @@ export function LayoutHeader(props: LayoutHeaderProps) {
|
|
|
46
48
|
const {
|
|
47
49
|
children,
|
|
48
50
|
divider,
|
|
51
|
+
hideBackButton = false,
|
|
49
52
|
primary,
|
|
50
53
|
secondary,
|
|
51
54
|
noAlign = false,
|
|
@@ -54,7 +57,7 @@ export function LayoutHeader(props: LayoutHeaderProps) {
|
|
|
54
57
|
sx = [],
|
|
55
58
|
bgColor,
|
|
56
59
|
} = props
|
|
57
|
-
const showBack = useShowBack()
|
|
60
|
+
const showBack = useShowBack() && !hideBackButton
|
|
58
61
|
const showClose = useShowClose()
|
|
59
62
|
|
|
60
63
|
const floatFallback = !children
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { LayoutHeaderProps, LayoutHeader } from '../../Layout'
|
|
2
2
|
|
|
3
3
|
export function LayoutOverlayHeader(props: LayoutHeaderProps) {
|
|
4
|
-
const { sx } = props
|
|
4
|
+
const { sx, switchPoint } = props
|
|
5
5
|
return (
|
|
6
6
|
<LayoutHeader
|
|
7
7
|
{...props}
|
|
8
8
|
noAlign
|
|
9
|
+
switchPoint={switchPoint !== 0 ? switchPoint : -1000}
|
|
9
10
|
sx={[
|
|
10
11
|
(theme) => ({
|
|
11
12
|
[theme.breakpoints.down('md')]: {
|
|
@@ -1,25 +1,34 @@
|
|
|
1
|
-
import { Container } from '@mui/material'
|
|
1
|
+
import { Container, SxProps, Theme } from '@mui/material'
|
|
2
2
|
import React from 'react'
|
|
3
|
+
import { extendableComponent } from '../Styles'
|
|
3
4
|
|
|
4
5
|
export type StickyBelowHeaderProps = {
|
|
5
6
|
children: React.ReactNode
|
|
7
|
+
sx?: SxProps<Theme>
|
|
6
8
|
}
|
|
7
9
|
|
|
10
|
+
const { classes } = extendableComponent('StickyBelowHeader', ['root'])
|
|
11
|
+
|
|
8
12
|
/** - Makes the children sticky to the parent container */
|
|
9
13
|
export function StickyBelowHeader(props: StickyBelowHeaderProps) {
|
|
14
|
+
const { sx = [] } = props
|
|
10
15
|
return (
|
|
11
16
|
<Container
|
|
12
|
-
|
|
13
|
-
position: 'sticky',
|
|
14
|
-
top: { xs: theme.appShell.headerHeightSm, md: `${theme.page.vertical} !important` },
|
|
15
|
-
zIndex: 96,
|
|
16
|
-
pointerEvents: 'none',
|
|
17
|
-
'& > *': {
|
|
18
|
-
pointerEvents: 'auto',
|
|
19
|
-
},
|
|
20
|
-
})}
|
|
17
|
+
className={classes.root}
|
|
21
18
|
maxWidth={false}
|
|
22
19
|
{...props}
|
|
20
|
+
sx={[
|
|
21
|
+
(theme) => ({
|
|
22
|
+
position: 'sticky',
|
|
23
|
+
top: { xs: theme.appShell.headerHeightSm, md: `${theme.page.vertical} !important` },
|
|
24
|
+
zIndex: 96,
|
|
25
|
+
pointerEvents: 'none',
|
|
26
|
+
'& > *': {
|
|
27
|
+
pointerEvents: 'auto',
|
|
28
|
+
},
|
|
29
|
+
}),
|
|
30
|
+
...(Array.isArray(sx) ? sx : [sx]),
|
|
31
|
+
]}
|
|
23
32
|
/>
|
|
24
33
|
)
|
|
25
34
|
}
|
|
@@ -13,9 +13,9 @@ import {
|
|
|
13
13
|
motionValue,
|
|
14
14
|
useDomEvent,
|
|
15
15
|
useMotionValue,
|
|
16
|
+
useMotionValueEvent,
|
|
16
17
|
useTransform,
|
|
17
18
|
} from 'framer-motion'
|
|
18
|
-
import framesync from 'framesync'
|
|
19
19
|
import React, { useCallback, useEffect, useRef } from 'react'
|
|
20
20
|
import { LayoutProvider } from '../../Layout/components/LayoutProvider'
|
|
21
21
|
import { ExtendableComponent, extendableComponent } from '../../Styles'
|
|
@@ -196,7 +196,7 @@ export function OverlayBase(incomingProps: LayoutOverlayBaseProps) {
|
|
|
196
196
|
scroller.scrollLeft = scroll.x.getPrevious()
|
|
197
197
|
scroller.scrollTop = scroll.y.getPrevious()
|
|
198
198
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
199
|
-
scrollTo(openClosePositions().open)
|
|
199
|
+
scrollTo(openClosePositions().open, { stopAnimationOnScroll: false })
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
202
|
|
|
@@ -281,7 +281,9 @@ export function OverlayBase(incomingProps: LayoutOverlayBaseProps) {
|
|
|
281
281
|
|
|
282
282
|
if (position.get() !== OverlayPosition.OPENED && !scroll.animating.get()) {
|
|
283
283
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
284
|
-
scrollTo(openClosePositions().open).then(() =>
|
|
284
|
+
scrollTo(openClosePositions().open, { stopAnimationOnScroll: false }).then(() =>
|
|
285
|
+
position.set(OverlayPosition.OPENED),
|
|
286
|
+
)
|
|
285
287
|
}
|
|
286
288
|
}, [isPresent, openClosePositions, position, scroll.animating, scrollTo, scrollerRef, variant])
|
|
287
289
|
|
|
@@ -291,7 +293,7 @@ export function OverlayBase(incomingProps: LayoutOverlayBaseProps) {
|
|
|
291
293
|
if (isPresent || !scroller) return
|
|
292
294
|
|
|
293
295
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
294
|
-
scrollTo(openClosePositions().closed).then(() => {
|
|
296
|
+
scrollTo(openClosePositions().closed, { stopAnimationOnScroll: false }).then(() => {
|
|
295
297
|
safeToRemove?.()
|
|
296
298
|
document.body.style.overflow = ''
|
|
297
299
|
})
|
|
@@ -311,10 +313,28 @@ export function OverlayBase(incomingProps: LayoutOverlayBaseProps) {
|
|
|
311
313
|
}
|
|
312
314
|
useDomEvent(windowRef, 'keyup', handleEscape, { passive: true })
|
|
313
315
|
|
|
316
|
+
const dragging = useMotionValue(false)
|
|
317
|
+
const scrollerElementRef = scrollerRef as React.RefObject<HTMLElement>
|
|
318
|
+
|
|
319
|
+
const handleDragStart = () => {
|
|
320
|
+
dragging.set(true)
|
|
321
|
+
}
|
|
322
|
+
const handleDragEnd = () => {
|
|
323
|
+
dragging.set(false)
|
|
324
|
+
// When releasing pointer and visibility 0 (overlay is dragged offscreen), close the overlay
|
|
325
|
+
if (positions.open.visible.get() === 0) closeOverlay()
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
useDomEvent(scrollerElementRef, 'pointerdown', handleDragStart, { passive: true })
|
|
329
|
+
useDomEvent(scrollerElementRef, 'pointerup', handleDragEnd, { passive: true })
|
|
330
|
+
// We use touchend as well as pointerup, because scrolling (dragging the overlay) on mobile causes pointercancel to fire, preventing pointerup from ever firing
|
|
331
|
+
useDomEvent(scrollerElementRef, 'touchend', handleDragEnd, { passive: true })
|
|
332
|
+
|
|
314
333
|
// When the overlay isn't visible anymore, we navigate back.
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
334
|
+
useMotionValueEvent(
|
|
335
|
+
positions.open.visible,
|
|
336
|
+
'change',
|
|
337
|
+
(o) => o === 0 && !dragging.get() && closeOverlay(),
|
|
318
338
|
)
|
|
319
339
|
|
|
320
340
|
// Measure the offset of the overlay in the scroller.
|
|
@@ -469,9 +489,14 @@ export function OverlayBase(incomingProps: LayoutOverlayBaseProps) {
|
|
|
469
489
|
sx={(theme) => ({
|
|
470
490
|
display: 'grid',
|
|
471
491
|
gridArea: 'overlay',
|
|
472
|
-
scrollSnapAlign: 'start',
|
|
473
492
|
scrollSnapStop: 'always',
|
|
474
493
|
pointerEvents: 'none',
|
|
494
|
+
'&.variantMdBottom, &.variantMdRight': {
|
|
495
|
+
scrollSnapAlign: 'end',
|
|
496
|
+
},
|
|
497
|
+
'&.variantMdLeft': {
|
|
498
|
+
scrollSnapAlign: 'start',
|
|
499
|
+
},
|
|
475
500
|
[theme.breakpoints.down('md')]: {
|
|
476
501
|
justifyContent: justifySm,
|
|
477
502
|
alignItems: justifySm,
|
|
@@ -24,7 +24,7 @@ export const OverlayPanelActions = (props: PanelActionsProps) => {
|
|
|
24
24
|
<>
|
|
25
25
|
<LayoutOverlayHeader
|
|
26
26
|
noAlign
|
|
27
|
-
sx={{ '&.noAlign': { mb: 0 } }}
|
|
27
|
+
sx={[{ '&.noAlign': { mb: 0 } }, ...(Array.isArray(sx) ? sx : [sx])]}
|
|
28
28
|
switchPoint={-10000}
|
|
29
29
|
size='small'
|
|
30
30
|
primary={
|
|
@@ -10,7 +10,7 @@ export type PopperPanelProps = PanelProps & {
|
|
|
10
10
|
|
|
11
11
|
export function PopperPanel(props: PopperPanelProps) {
|
|
12
12
|
const { activeEl, children, ...actionsProps } = props
|
|
13
|
-
const ref = useRef(null)
|
|
13
|
+
const ref = useRef<HTMLDivElement>(null)
|
|
14
14
|
const movement = useHandleClickNotDrag(ref)
|
|
15
15
|
const handleClickAway = () => {
|
|
16
16
|
if (movement.get() === 'drag') return
|
|
@@ -9,7 +9,7 @@ import { iconClose } from '../icons'
|
|
|
9
9
|
import { PanelActionsProps } from './types'
|
|
10
10
|
|
|
11
11
|
export function PopperPanelActions(props: PanelActionsProps) {
|
|
12
|
-
const { title, children, onReset, onClose, onApply, sx } = props
|
|
12
|
+
const { title, children, onReset, onClose, onApply, sx = [] } = props
|
|
13
13
|
|
|
14
14
|
const fabSize = useFabSize('small')
|
|
15
15
|
const svgSize = useIconSvgSize('large')
|
|
@@ -18,7 +18,7 @@ export function PopperPanelActions(props: PanelActionsProps) {
|
|
|
18
18
|
<>
|
|
19
19
|
<LayoutHeader
|
|
20
20
|
noAlign
|
|
21
|
-
sx={{ '&.noAlign': { mb: 0 } }}
|
|
21
|
+
sx={[{ '&.noAlign': { mb: 0 } }, ...(Array.isArray(sx) ? sx : [sx])]}
|
|
22
22
|
switchPoint={-10000}
|
|
23
23
|
size='small'
|
|
24
24
|
primary={
|
package/PageMeta/PageMeta.tsx
CHANGED
|
@@ -31,6 +31,9 @@ export type PageMetaProps = {
|
|
|
31
31
|
metaDescription?: string
|
|
32
32
|
metaRobots?: MetaRobotsAll | MetaRobots[]
|
|
33
33
|
children?: React.ReactNode
|
|
34
|
+
ogImage?: string | null
|
|
35
|
+
ogImageUseFallback?: boolean
|
|
36
|
+
ogType?: string | null
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
type PartialNextRouter = Pick<
|
|
@@ -90,7 +93,16 @@ export function useCanonical(incoming?: Canonical) {
|
|
|
90
93
|
|
|
91
94
|
export function PageMeta(props: PageMetaProps) {
|
|
92
95
|
const { active } = usePageContext()
|
|
93
|
-
const {
|
|
96
|
+
const {
|
|
97
|
+
children,
|
|
98
|
+
title,
|
|
99
|
+
canonical: canonicalBare,
|
|
100
|
+
metaDescription,
|
|
101
|
+
ogImage,
|
|
102
|
+
ogType,
|
|
103
|
+
ogImageUseFallback = false,
|
|
104
|
+
metaRobots = ['all'],
|
|
105
|
+
} = props
|
|
94
106
|
|
|
95
107
|
const canonical = useCanonical(canonicalBare)
|
|
96
108
|
|
|
@@ -99,10 +111,20 @@ export function PageMeta(props: PageMetaProps) {
|
|
|
99
111
|
<Head>
|
|
100
112
|
<title>{title.trim()}</title>
|
|
101
113
|
{metaDescription && (
|
|
102
|
-
|
|
114
|
+
<>
|
|
115
|
+
<meta name='description' content={metaDescription.trim()} key='meta-description' />
|
|
116
|
+
<meta property='og:description' content={metaDescription.trim()} key='og-description' />
|
|
117
|
+
</>
|
|
103
118
|
)}
|
|
104
119
|
<meta name='robots' content={metaRobots.join(',')} key='meta-robots' />
|
|
105
120
|
{canonical && <link rel='canonical' href={canonical} key='canonical' />}
|
|
121
|
+
<meta property='og:title' content={title.trim()} key='og-title' />
|
|
122
|
+
<meta property='og:type' content={ogType ?? 'website'} key='og-type' />
|
|
123
|
+
<meta property='og:url' content={canonical} key='og-url' />
|
|
124
|
+
{(ogImage || ogImageUseFallback) && (
|
|
125
|
+
<meta property='og:image' content={ogImage ?? '/open-graph-image.jpg'} key='og-image' />
|
|
126
|
+
)}
|
|
127
|
+
|
|
106
128
|
{children}
|
|
107
129
|
</Head>
|
|
108
130
|
)
|
|
@@ -22,7 +22,7 @@ const { classes } = extendableComponent('Pagination', parts)
|
|
|
22
22
|
* Read more: https://ahrefs.com/blog/rel-prev-next-pagination/
|
|
23
23
|
*/
|
|
24
24
|
export function Pagination(props: PagePaginationProps) {
|
|
25
|
-
const { count, page, renderLink, classes: styles, ...paginationProps } = props
|
|
25
|
+
const { count, page, renderLink, classes: styles, sx = [], ...paginationProps } = props
|
|
26
26
|
|
|
27
27
|
const { items } = usePagination({
|
|
28
28
|
count,
|
|
@@ -61,18 +61,21 @@ export function Pagination(props: PagePaginationProps) {
|
|
|
61
61
|
return (
|
|
62
62
|
<Box
|
|
63
63
|
className={classes.root}
|
|
64
|
-
sx={
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
64
|
+
sx={[
|
|
65
|
+
(theme) => ({
|
|
66
|
+
margin: '0 auto',
|
|
67
|
+
marginTop: theme.spacings.lg,
|
|
68
|
+
marginBottom: theme.spacings.lg,
|
|
69
|
+
display: 'flex',
|
|
70
|
+
alignItems: 'center',
|
|
71
|
+
justifyContent: 'center',
|
|
72
|
+
gap: '6px',
|
|
73
|
+
'& .Mui-disabled': {
|
|
74
|
+
background: 'none',
|
|
75
|
+
},
|
|
76
|
+
}),
|
|
77
|
+
...(Array.isArray(sx) ? sx : [sx]),
|
|
78
|
+
]}
|
|
76
79
|
>
|
|
77
80
|
{page === 1 ? chevronLeft : renderLink(page - 1, chevronLeft, prevBtnProps)}
|
|
78
81
|
|
|
@@ -8,7 +8,7 @@ type FilterTypeByTypename<A extends TypeObject, Typename extends string> = A ext
|
|
|
8
8
|
: never
|
|
9
9
|
: never
|
|
10
10
|
|
|
11
|
-
type TypeRenderMethod<P> = (props: P) => React.
|
|
11
|
+
type TypeRenderMethod<P> = (props: P) => React.ReactNode
|
|
12
12
|
|
|
13
13
|
type TypeRenderMap<
|
|
14
14
|
T extends TypeObject,
|
|
@@ -14,37 +14,40 @@ const name = 'IconBlock' as const
|
|
|
14
14
|
const parts = ['block', 'link', 'title'] as const
|
|
15
15
|
const { classes } = extendableComponent(name, parts)
|
|
16
16
|
|
|
17
|
-
export const IconBlock = React.forwardRef<HTMLAnchorElement, IconBlockProps>(
|
|
18
|
-
|
|
17
|
+
export const IconBlock = React.forwardRef<HTMLAnchorElement & HTMLButtonElement, IconBlockProps>(
|
|
18
|
+
(props, ref) => {
|
|
19
|
+
const { title, children, icon, href = '#', sx = [], ...buttonProps } = props
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
{title}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
21
|
+
return (
|
|
22
|
+
<Button
|
|
23
|
+
ref={ref}
|
|
24
|
+
href={href}
|
|
25
|
+
variant='outlined'
|
|
26
|
+
color='primary'
|
|
27
|
+
className={classes.block}
|
|
28
|
+
{...buttonProps}
|
|
29
|
+
sx={[
|
|
30
|
+
(theme) => ({
|
|
31
|
+
padding: `${theme.spacings.sm}`,
|
|
32
|
+
textAlign: 'center',
|
|
33
|
+
'& > *': {
|
|
34
|
+
display: 'grid',
|
|
35
|
+
gridAutoFlow: 'row',
|
|
36
|
+
justifyItems: 'center',
|
|
37
|
+
gap: `${theme.spacings.xxs}`,
|
|
38
|
+
},
|
|
39
|
+
}),
|
|
40
|
+
...(Array.isArray(sx) ? sx : [sx]),
|
|
41
|
+
]}
|
|
42
|
+
>
|
|
43
|
+
<Box>
|
|
44
|
+
{icon}
|
|
45
|
+
<Typography variant='subtitle1' className={classes.title} component='span'>
|
|
46
|
+
{title}
|
|
47
|
+
</Typography>
|
|
48
|
+
{children}
|
|
49
|
+
</Box>
|
|
50
|
+
</Button>
|
|
51
|
+
)
|
|
52
|
+
},
|
|
53
|
+
)
|