@graphcommerce/next-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.
- package/ActionCard/ActionCard.tsx +219 -203
- package/ActionCard/ActionCardAccordion.tsx +4 -2
- package/ActionCard/ActionCardLayout.tsx +3 -2
- package/ActionCard/ActionCardList.tsx +6 -5
- package/Blog/BlogAuthor/BlogAuthor.tsx +5 -4
- package/Blog/BlogContent/BlogContent.tsx +3 -2
- package/Blog/BlogHeader/BlogHeader.tsx +4 -3
- package/Blog/BlogList/BlogList.tsx +3 -3
- package/Blog/BlogListItem/BlogListItem.tsx +6 -5
- package/Blog/BlogTags/BlogTag.tsx +3 -2
- package/Blog/BlogTags/BlogTags.tsx +1 -1
- package/Breadcrumbs/Breadcrumbs.tsx +25 -19
- package/Breadcrumbs/BreadcrumbsList.tsx +3 -2
- package/Breadcrumbs/jsonLdBreadcrumb.tsx +1 -1
- package/Breadcrumbs/types.ts +1 -2
- package/Button/Button.tsx +2 -1
- package/Button/LinkOrButton.tsx +4 -2
- package/CHANGELOG.md +294 -1344
- package/ChipMenu/ChipMenu.tsx +3 -2
- package/Config.graphqls +28 -10
- package/Container/Container.tsx +90 -0
- package/ContainerWithHeader/ContainerWithHeader.tsx +2 -1
- package/Document/DocumentBodyEnd.tsx +1 -1
- package/Document/DocumentBodyStart.tsx +1 -1
- package/Document/DocumentHeadEnd.tsx +1 -1
- package/Document/DocumentHeadStart.tsx +1 -1
- package/Fab/Fab.tsx +15 -17
- package/FlagAvatar/FlagAvatar.tsx +2 -1
- package/Footer/Footer.tsx +14 -10
- package/Form/Form.tsx +2 -1
- package/Form/FormHeader.tsx +1 -1
- package/Form/FormRow.tsx +1 -1
- package/Form/InputCheckmark.tsx +2 -1
- package/FramerScroller/ItemScroller.tsx +5 -8
- package/FramerScroller/SidebarGallery.tsx +23 -30
- package/FramerScroller/SidebarSlider.tsx +8 -7
- package/FullPageMessage/FullPageMessage.tsx +2 -1
- package/IconHeader/IconHeader.tsx +5 -3
- package/IconSvg/IconSvg.tsx +8 -7
- package/Intl/DateTimeFormat/DateFormat.tsx +6 -4
- package/Intl/DateTimeFormat/DateTimeFormat.tsx +10 -14
- package/Intl/DateTimeFormat/TimeFormat.tsx +6 -4
- package/Intl/DateTimeFormat/index.ts +1 -0
- package/Intl/DateTimeFormat/useIntlDateTimeFormat.ts +13 -0
- package/Intl/DisplayNames/DisplayNames.tsx +5 -13
- package/Intl/DisplayNames/index.ts +1 -0
- package/Intl/DisplayNames/useIntlDisplayNames.ts +12 -0
- package/Intl/{ListFormat.tsx → ListFormat/ListFormat.tsx} +8 -13
- package/Intl/ListFormat/index.ts +2 -0
- package/Intl/ListFormat/useIntlListFormat.ts +15 -0
- package/Intl/NumberFormat/CurrencyFormat.tsx +4 -2
- package/Intl/NumberFormat/NumberFormat.tsx +15 -17
- package/Intl/NumberFormat/PercentFormat.tsx +6 -2
- package/Intl/NumberFormat/UnitFormat.tsx +5 -5
- package/Intl/NumberFormat/index.ts +1 -0
- package/Intl/NumberFormat/useIntlNumberFormat.ts +17 -0
- package/Intl/RelativeTimeFormat/RelativeTimeFormat.tsx +6 -13
- package/Intl/RelativeTimeFormat/RelativeToTimeFormat.tsx +4 -2
- package/Intl/RelativeTimeFormat/index.ts +1 -0
- package/Intl/RelativeTimeFormat/useIntlRelativeTimeFormat.ts +15 -0
- package/Intl/useIntlLocalesArgument.ts +16 -0
- package/Layout/components/LayoutHeader.tsx +7 -4
- package/Layout/components/LayoutHeaderBack.tsx +6 -4
- package/Layout/components/LayoutHeaderClose.tsx +1 -1
- package/Layout/components/LayoutHeaderContent.tsx +11 -12
- package/Layout/components/LayoutProvider.tsx +1 -1
- package/Layout/components/LayoutTitle.tsx +5 -3
- package/Layout/context/layoutContext.tsx +1 -1
- package/Layout/types.ts +1 -1
- package/LayoutDefault/components/LayoutDefault.tsx +12 -10
- package/LayoutOverlay/components/LayoutOverlay.tsx +3 -2
- package/LayoutOverlay/components/LayoutOverlayHeader.tsx +2 -1
- package/LayoutOverlay/test/LayoutOverlayDemo.tsx +4 -1
- package/LayoutParts/DesktopHeaderBadge.tsx +2 -1
- package/LayoutParts/DesktopNavBar.tsx +26 -22
- package/LayoutParts/DesktopNavBarItem.tsx +11 -7
- package/LayoutParts/Logo.tsx +5 -5
- package/LayoutParts/MenuFab.tsx +7 -13
- package/LayoutParts/MenuFabItem.tsx +6 -1
- package/LayoutParts/MenuFabSecondaryItem.tsx +11 -7
- package/LayoutParts/MobileTopRight.tsx +24 -0
- package/LayoutParts/PlaceholderFab.tsx +2 -1
- package/LayoutParts/StickyBelowHeader.tsx +2 -1
- package/LayoutParts/index.ts +1 -0
- package/LazyHydrate/LazyHydrate.tsx +18 -21
- package/MediaQuery/MediaQuery.tsx +111 -0
- package/MediaQuery/index.ts +1 -0
- package/Navigation/components/NavigationFab.tsx +3 -2
- package/Navigation/components/NavigationItem.tsx +3 -3
- package/Navigation/components/NavigationList.tsx +4 -3
- package/Navigation/components/NavigationOverlay.tsx +18 -11
- package/Navigation/components/NavigationProvider.tsx +9 -8
- package/Navigation/components/NavigationTitle.tsx +5 -5
- package/Navigation/hooks/useNavigation.ts +4 -2
- package/Overlay/components/Overlay.tsx +3 -2
- package/Overlay/components/OverlayBase.tsx +71 -30
- package/Overlay/components/OverlayContainer.tsx +2 -2
- package/Overlay/components/OverlayHeader.tsx +7 -4
- package/Overlay/components/OverlaySsr.tsx +2 -1
- package/Overlay/components/OverlayStickyBottom.tsx +2 -1
- package/Overlay/utils/variantsToScrollSnapType.ts +2 -2
- package/OverlayOrPopperChip/OverlayOrPopperChip.tsx +5 -12
- package/OverlayOrPopperChip/OverlayOrPopperPanel.tsx +3 -3
- package/OverlayOrPopperChip/OverlayPanel.tsx +13 -7
- package/OverlayOrPopperChip/OverlayPanelActions.tsx +2 -2
- package/OverlayOrPopperChip/PopperPanel.tsx +3 -2
- package/OverlayOrPopperChip/PopperPanelActions.tsx +2 -2
- package/OverlayOrPopperChip/types.ts +2 -2
- package/OverlayOrPopperChip/useHandleClickNotDrag.ts +3 -1
- package/Page/CssAndFramerMotionProvider.tsx +2 -1
- package/Page/types.ts +5 -5
- package/PageLoadIndicator/PageLoadIndicator.tsx +3 -2
- package/PageMeta/PageMeta.tsx +3 -2
- package/PageMeta/canonicalize.ts +7 -3
- package/Pagination/Pagination.tsx +4 -2
- package/Pagination/PaginationExtended.tsx +2 -9
- package/RenderType/RenderType.tsx +6 -0
- package/Row/ButtonLinkList/ButtonLinkList.tsx +4 -7
- package/Row/ButtonLinkList/ButtonLinkListItem.tsx +2 -1
- package/Row/ColumnOne/variant/VariantMessage.tsx +2 -4
- package/Row/ColumnOneBoxed/ColumnOneBoxed.tsx +4 -2
- package/Row/ColumnOneCentered/ColumnOneCentered.tsx +4 -2
- package/Row/ColumnThree/ColumnThree.tsx +6 -5
- package/Row/ColumnTwo/ColumnTwo.tsx +8 -7
- package/Row/ColumnTwoSpread/ColumnTwoSpread.tsx +7 -5
- package/Row/ColumnTwoWithTop/ColumnTwoWithTop.tsx +5 -4
- package/Row/ContentLinks/ContentLinks.tsx +4 -3
- package/Row/HeroBanner/HeroBanner.tsx +3 -2
- package/Row/IconBlocks/IconBlock.tsx +3 -2
- package/Row/IconBlocks/IconBlocks.tsx +3 -2
- package/Row/ImageText/ImageText.tsx +3 -2
- package/Row/ImageTextBoxed/ImageTextBoxed.tsx +4 -3
- package/Row/ParagraphWithSidebarSlide/ParagraphWithSidebarSlide.tsx +3 -2
- package/Row/Quote/Quote.tsx +1 -1
- package/Row/Row.tsx +2 -1
- package/Row/RowLinks/RowLinks.tsx +36 -34
- package/Row/RowLinks/variant/VariantImageLabelSwiper.tsx +6 -2
- package/Row/RowLinks/variant/VariantInline.tsx +6 -2
- package/Row/RowLinks/variant/VariantLogoSwiper.tsx +2 -1
- package/Row/RowLinks/variant/VariantUsps.tsx +2 -1
- package/Row/SpecialBanner/SpecialBanner.tsx +3 -2
- package/SectionContainer/SectionContainer.tsx +3 -2
- package/SectionHeader/SectionHeader.tsx +2 -1
- package/Separator/Separator.tsx +3 -2
- package/Snackbar/DismissibleSnackbar.tsx +1 -1
- package/Snackbar/ErrorSnackbar.tsx +1 -1
- package/Snackbar/MessageSnackbarImpl.tsx +7 -16
- package/StarRatingField/StarRatingField.tsx +3 -2
- package/Stepper/Stepper.tsx +3 -2
- package/Styles/__tests__/spreadVal.test.ts +4 -4
- package/Styles/extendableComponent.ts +4 -3
- package/Styles/withEmotionCache.tsx +2 -2
- package/Styles/withTheme.tsx +4 -1
- package/TextInputNumber/TextInputNumber.tsx +5 -8
- package/Theme/DarkLightModeThemeProvider.tsx +10 -7
- package/Theme/MuiButton.ts +2 -1
- package/Theme/MuiChip.ts +2 -1
- package/Theme/MuiFab.ts +2 -1
- package/Theme/MuiSlider.ts +3 -3
- package/Theme/MuiSnackbar.ts +1 -1
- package/Theme/NextLink.tsx +35 -15
- package/Theme/createTheme.ts +6 -0
- package/Theme/index.ts +1 -0
- package/Theme/themeDefaults.ts +10 -10
- package/Theme/useContainerSizing.ts +20 -0
- package/TimeAgo/TimeAgo.tsx +3 -3
- package/ToggleButton/ToggleButton.tsx +6 -4
- package/ToggleButtonGroup/ToggleButtonGroup.tsx +99 -94
- package/UspList/UspList.tsx +3 -2
- package/UspList/UspListItem.tsx +3 -2
- package/hooks/memoDeep.ts +3 -2
- package/hooks/useDateTimeFormat.ts +3 -1
- package/hooks/useMatchMedia.ts +2 -1
- package/hooks/useMemoDeep.ts +2 -1
- package/hooks/useNumberFormat.ts +3 -1
- package/index.ts +3 -1
- package/package.json +17 -18
- package/utils/cookie.ts +4 -3
- package/utils/robots.ts +1 -1
- package/utils/sitemap.ts +3 -2
- package/utils/sxx.ts +16 -0
- package/AnimatedRow/AnimatedRow.tsx +0 -23
- package/docs/building-components.mdx +0 -3
- package/docs/components/ComponentBasic.tsx +0 -26
- package/docs/components/ComponentChild.tsx +0 -49
- package/docs/components/ComponentChildVariant.tsx +0 -55
- package/docs/components/ComponentChildVariantExtendable.tsx +0 -63
- package/docs/components/ComponentStylable.tsx +0 -32
- package/docs/pages/building-components.tsx +0 -62
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useUrlQuery } from '../../hooks/useUrlQuery'
|
|
2
|
-
import {
|
|
2
|
+
import type { LayoutOverlayProps } from '../components/LayoutOverlay'
|
|
3
|
+
import { LayoutOverlay } from '../components/LayoutOverlay'
|
|
3
4
|
|
|
4
5
|
export type LayoutOverlayState = Omit<
|
|
5
6
|
LayoutOverlayProps,
|
|
@@ -12,6 +13,8 @@ export type LayoutOverlayState = Omit<
|
|
|
12
13
|
| 'disableInert'
|
|
13
14
|
| 'widthMd'
|
|
14
15
|
| 'widthSm'
|
|
16
|
+
| 'disableAnimation'
|
|
17
|
+
| 'disableDrag'
|
|
15
18
|
>
|
|
16
19
|
|
|
17
20
|
export function useLayoutState() {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { BadgeProps } from '@mui/material'
|
|
2
|
+
import { Badge } from '@mui/material'
|
|
2
3
|
|
|
3
4
|
/** Note: This should _only_ be used on the Desktop, use a standard Badge for other usecases. */
|
|
4
5
|
export function DesktopHeaderBadge(props: BadgeProps) {
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Scroller, ScrollerButton, ScrollerProvider } from '@graphcommerce/framer-scroller'
|
|
2
|
-
import {
|
|
2
|
+
import type { BoxProps } from '@mui/material'
|
|
3
3
|
import React from 'react'
|
|
4
|
-
import {
|
|
4
|
+
import type { IconSvgProps } from '../IconSvg'
|
|
5
|
+
import { IconSvg } from '../IconSvg'
|
|
6
|
+
import { MediaQuery } from '../MediaQuery'
|
|
5
7
|
import { extendableComponent } from '../Styles/extendableComponent'
|
|
6
8
|
import { iconChevronLeft, iconChevronRight } from '../icons'
|
|
7
9
|
|
|
@@ -23,25 +25,27 @@ export function DesktopNavBar(props: MenuTabsProps) {
|
|
|
23
25
|
const { children, iconLeft, iconRight, sx = [] } = props
|
|
24
26
|
|
|
25
27
|
return (
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
]
|
|
40
|
-
|
|
28
|
+
<MediaQuery
|
|
29
|
+
component='span'
|
|
30
|
+
query={(theme) => theme.breakpoints.up('md')}
|
|
31
|
+
display='grid'
|
|
32
|
+
className={classes.root}
|
|
33
|
+
sx={[
|
|
34
|
+
{
|
|
35
|
+
width: '100%',
|
|
36
|
+
alignItems: 'center',
|
|
37
|
+
position: 'relative',
|
|
38
|
+
pointerEvents: 'all',
|
|
39
|
+
gridTemplateColumns: 'auto 1fr auto',
|
|
40
|
+
},
|
|
41
|
+
...(Array.isArray(sx) ? sx : [sx]),
|
|
42
|
+
]}
|
|
43
|
+
>
|
|
44
|
+
<ScrollerProvider scrollSnapAlign='none'>
|
|
41
45
|
<Scroller
|
|
42
46
|
hideScrollbar
|
|
43
47
|
sx={(theme) => ({
|
|
44
|
-
gridArea:
|
|
48
|
+
gridArea: '1 / 1 / 1 / 4',
|
|
45
49
|
columnGap: theme.spacings.md,
|
|
46
50
|
padding: `0 ${theme.spacings.md}`,
|
|
47
51
|
gridAutoColumns: 'min-content',
|
|
@@ -53,7 +57,7 @@ export function DesktopNavBar(props: MenuTabsProps) {
|
|
|
53
57
|
|
|
54
58
|
<ScrollerButton
|
|
55
59
|
sxContainer={{
|
|
56
|
-
gridArea:
|
|
60
|
+
gridArea: '1 / 1 / 1 / 2',
|
|
57
61
|
pointerEvents: 'none',
|
|
58
62
|
'& > *': { pointerEvents: 'all' },
|
|
59
63
|
}}
|
|
@@ -77,7 +81,7 @@ export function DesktopNavBar(props: MenuTabsProps) {
|
|
|
77
81
|
|
|
78
82
|
<ScrollerButton
|
|
79
83
|
sxContainer={{
|
|
80
|
-
gridArea:
|
|
84
|
+
gridArea: '1 / 3 / 1 / 4',
|
|
81
85
|
pointerEvents: 'none',
|
|
82
86
|
'& > *': {
|
|
83
87
|
pointerEvents: 'all',
|
|
@@ -100,8 +104,8 @@ export function DesktopNavBar(props: MenuTabsProps) {
|
|
|
100
104
|
>
|
|
101
105
|
<IconSvg src={iconRight ?? iconChevronRight} />
|
|
102
106
|
</ScrollerButton>
|
|
103
|
-
</
|
|
104
|
-
</
|
|
107
|
+
</ScrollerProvider>
|
|
108
|
+
</MediaQuery>
|
|
105
109
|
)
|
|
106
110
|
}
|
|
107
111
|
DesktopNavBar.selectors = selectors
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { LinkProps } from '@mui/material'
|
|
2
|
+
import { Box, Link } from '@mui/material'
|
|
2
3
|
import { useRouter } from 'next/router'
|
|
3
4
|
import { extendableComponent } from '../Styles/extendableComponent'
|
|
4
5
|
|
|
5
6
|
const { classes, selectors } = extendableComponent('DesktopNavItem', ['root', 'line'] as const)
|
|
6
7
|
|
|
7
|
-
export type DesktopNavItemLinkProps = LinkProps<'a'>
|
|
8
|
+
export type DesktopNavItemLinkProps = LinkProps<'a'> & {
|
|
9
|
+
active?: boolean
|
|
10
|
+
}
|
|
8
11
|
export type DesktopNavItemButtonProps = LinkProps<'div'> & {
|
|
9
12
|
onClick: LinkProps<'button'>['onClick']
|
|
13
|
+
active?: boolean
|
|
10
14
|
}
|
|
11
15
|
|
|
12
16
|
function isLinkProps(
|
|
@@ -19,7 +23,7 @@ export function DesktopNavItem(props: DesktopNavItemLinkProps | DesktopNavItemBu
|
|
|
19
23
|
const router = useRouter()
|
|
20
24
|
|
|
21
25
|
if (!isLinkProps(props)) {
|
|
22
|
-
const { onClick, children, sx = [], ...linkProps } = props
|
|
26
|
+
const { onClick, children, sx = [], active, ...linkProps } = props
|
|
23
27
|
|
|
24
28
|
return (
|
|
25
29
|
<Link
|
|
@@ -40,9 +44,9 @@ export function DesktopNavItem(props: DesktopNavItemLinkProps | DesktopNavItemBu
|
|
|
40
44
|
)
|
|
41
45
|
}
|
|
42
46
|
|
|
43
|
-
const { href, children, sx = [], ...linkProps } = props
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
const { href, children, sx = [], active, ...linkProps } = props
|
|
48
|
+
const activeValue =
|
|
49
|
+
typeof active === 'undefined' ? router.asPath.startsWith((href ?? '').toString()) : active
|
|
46
50
|
|
|
47
51
|
return (
|
|
48
52
|
<Link
|
|
@@ -67,7 +71,7 @@ export function DesktopNavItem(props: DesktopNavItemLinkProps | DesktopNavItemBu
|
|
|
67
71
|
background: (theme) => theme.palette.primary.main,
|
|
68
72
|
margin: '0 auto',
|
|
69
73
|
marginTop: '6px',
|
|
70
|
-
opacity:
|
|
74
|
+
opacity: activeValue ? 1 : 0,
|
|
71
75
|
}}
|
|
72
76
|
/>
|
|
73
77
|
</Link>
|
package/LayoutParts/Logo.tsx
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ImageProps } from '@graphcommerce/image'
|
|
2
|
+
import { Image } from '@graphcommerce/image'
|
|
3
|
+
import type { SxProps, Theme } from '@mui/material'
|
|
2
4
|
import {
|
|
5
|
+
Box,
|
|
6
|
+
unstable_composeClasses as composeClasses,
|
|
3
7
|
generateUtilityClass,
|
|
4
8
|
styled,
|
|
5
|
-
SxProps,
|
|
6
|
-
Theme,
|
|
7
|
-
unstable_composeClasses as composeClasses,
|
|
8
|
-
Box,
|
|
9
9
|
} from '@mui/material'
|
|
10
10
|
import { useRouter } from 'next/router'
|
|
11
11
|
import { forwardRef } from 'react'
|
package/LayoutParts/MenuFab.tsx
CHANGED
|
@@ -1,25 +1,15 @@
|
|
|
1
1
|
import { useMotionValueValue } from '@graphcommerce/framer-utils'
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
Fab,
|
|
5
|
-
ListItem,
|
|
6
|
-
Menu,
|
|
7
|
-
styled,
|
|
8
|
-
Box,
|
|
9
|
-
SxProps,
|
|
10
|
-
Theme,
|
|
11
|
-
FabProps,
|
|
12
|
-
MenuProps as MenuPropsType,
|
|
13
|
-
} from '@mui/material'
|
|
2
|
+
import type { FabProps, MenuProps as MenuPropsType, SxProps, Theme } from '@mui/material'
|
|
3
|
+
import { Box, Divider, Fab, ListItem, Menu, styled } from '@mui/material'
|
|
14
4
|
import { m } from 'framer-motion'
|
|
15
5
|
import { useRouter } from 'next/router'
|
|
16
6
|
import React, { useEffect } from 'react'
|
|
7
|
+
import { iconClose, iconMenu } from '../icons'
|
|
17
8
|
import { IconSvg } from '../IconSvg'
|
|
18
9
|
import { useScrollY } from '../Layout/hooks/useScrollY'
|
|
19
10
|
import { extendableComponent } from '../Styles/extendableComponent'
|
|
20
11
|
import { responsiveVal } from '../Styles/responsiveVal'
|
|
21
12
|
import { useFabSize } from '../Theme'
|
|
22
|
-
import { iconMenu, iconClose } from '../icons'
|
|
23
13
|
import { useFabAnimation } from './useFabAnimation'
|
|
24
14
|
|
|
25
15
|
const MotionDiv = styled(m.div)({})
|
|
@@ -42,6 +32,10 @@ type OwnerState = {
|
|
|
42
32
|
|
|
43
33
|
const { withState } = extendableComponent<OwnerState, typeof name, typeof parts>(name, parts)
|
|
44
34
|
|
|
35
|
+
/**
|
|
36
|
+
* @deprecated Will be removed
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
45
39
|
export function MenuFab(props: MenuFabProps) {
|
|
46
40
|
const {
|
|
47
41
|
children,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ListItemButtonProps } from '@mui/material'
|
|
2
|
+
import { ListItemButton, ListItemText } from '@mui/material'
|
|
2
3
|
import { useRouter } from 'next/router'
|
|
3
4
|
import { NextLink } from '../Theme'
|
|
4
5
|
|
|
@@ -6,6 +7,10 @@ export type MenuFabItemProps = Omit<ListItemButtonProps<'a'>, 'href' | 'button'>
|
|
|
6
7
|
href: NonNullable<ListItemButtonProps<'a'>['href']>
|
|
7
8
|
}
|
|
8
9
|
|
|
10
|
+
/**
|
|
11
|
+
* @deprecated Will be removed
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
9
14
|
export function MenuFabItem(props: MenuFabItemProps) {
|
|
10
15
|
const { href, children, sx = [], ...listItemProps } = props
|
|
11
16
|
const hrefString = href.toString()
|
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { SxProps, Theme } from '@mui/material'
|
|
2
|
+
import { ListItemButton, ListItemIcon, ListItemText } from '@mui/material'
|
|
2
3
|
import { useRouter } from 'next/router'
|
|
3
|
-
import
|
|
4
|
+
import type { MouseEventHandler } from 'react'
|
|
5
|
+
import React from 'react'
|
|
4
6
|
import { extendableComponent } from '../Styles'
|
|
5
7
|
import { NextLink } from '../Theme'
|
|
6
8
|
|
|
7
9
|
export type FabMenuSecondaryItemProps = {
|
|
8
10
|
href: string
|
|
9
11
|
children: React.ReactNode
|
|
10
|
-
icon
|
|
12
|
+
icon?: React.ReactNode
|
|
11
13
|
sx?: SxProps<Theme>
|
|
12
14
|
onClick?: MouseEventHandler<HTMLElement>
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
const compName = 'MenuFabSecondaryItem'
|
|
17
|
+
const compName = 'MenuFabSecondaryItem'
|
|
16
18
|
const parts = ['root', 'icon', 'text'] as const
|
|
17
19
|
const { classes } = extendableComponent(compName, parts)
|
|
18
20
|
|
|
@@ -35,9 +37,11 @@ export function MenuFabSecondaryItem(props: FabMenuSecondaryItemProps) {
|
|
|
35
37
|
dense
|
|
36
38
|
selected={router.asPath.startsWith(href)}
|
|
37
39
|
>
|
|
38
|
-
|
|
39
|
-
{
|
|
40
|
-
|
|
40
|
+
{icon && (
|
|
41
|
+
<ListItemIcon className={classes.text} sx={{ paddingRight: '8px', minWidth: 'unset' }}>
|
|
42
|
+
{icon}
|
|
43
|
+
</ListItemIcon>
|
|
44
|
+
)}
|
|
41
45
|
<ListItemText className={classes.icon}>{children}</ListItemText>
|
|
42
46
|
</ListItemButton>
|
|
43
47
|
)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { MediaQueryProps } from '../MediaQuery'
|
|
2
|
+
import { MediaQuery } from '../MediaQuery'
|
|
3
|
+
import { sxx } from '../utils/sxx'
|
|
4
|
+
|
|
5
|
+
export function MobileTopRight(props: Omit<MediaQueryProps, 'query'>) {
|
|
6
|
+
const { sx, ...rest } = props
|
|
7
|
+
return (
|
|
8
|
+
<MediaQuery
|
|
9
|
+
query={(theme) => theme.breakpoints.down('md')}
|
|
10
|
+
display='flex'
|
|
11
|
+
{...rest}
|
|
12
|
+
sx={sxx(
|
|
13
|
+
(theme) => ({
|
|
14
|
+
position: 'absolute',
|
|
15
|
+
right: theme.page.horizontal,
|
|
16
|
+
top: 0,
|
|
17
|
+
height: theme.appShell.headerHeightSm,
|
|
18
|
+
alignItems: 'center',
|
|
19
|
+
}),
|
|
20
|
+
sx,
|
|
21
|
+
)}
|
|
22
|
+
/>
|
|
23
|
+
)
|
|
24
|
+
}
|
package/LayoutParts/index.ts
CHANGED
|
@@ -1,34 +1,32 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
useLayoutEffect,
|
|
7
|
-
useEffect,
|
|
8
|
-
CSSProperties,
|
|
9
|
-
} from 'react'
|
|
10
|
-
|
|
11
|
-
// Make sure the server doesn't choke on the useLayoutEffect
|
|
12
|
-
export const useLayoutEffect2 = typeof window !== 'undefined' ? useLayoutEffect : useEffect
|
|
1
|
+
import { useIsomorphicLayoutEffect } from '@graphcommerce/framer-utils'
|
|
2
|
+
import type { BoxProps } from '@mui/material'
|
|
3
|
+
import { Box } from '@mui/material'
|
|
4
|
+
import type { CSSProperties } from 'react'
|
|
5
|
+
import React, { startTransition, useRef, useState } from 'react'
|
|
13
6
|
|
|
14
7
|
export type LazyHydrateProps = BoxProps<'div'> & {
|
|
15
8
|
/**
|
|
16
|
-
* The content is always rendered on the server and on the client it uses the server rendered HTML
|
|
9
|
+
* The content is always rendered on the server and on the client it uses the server rendered HTML
|
|
10
|
+
* until it is hydrated.
|
|
17
11
|
*/
|
|
18
12
|
children: React.ReactNode
|
|
19
13
|
|
|
20
14
|
/**
|
|
21
|
-
* When a boolean is provided, the IntersectionObserver is disabled and hydrates the component
|
|
15
|
+
* When a boolean is provided, the IntersectionObserver is disabled and hydrates the component
|
|
16
|
+
* when the value becomes true.
|
|
22
17
|
*
|
|
23
18
|
* For example:
|
|
19
|
+
*
|
|
24
20
|
* - Disable the hydration functionality completely: `<LazyHydrate hydrated={true}>`
|
|
25
|
-
* - Hydrate the component on some state `<LazyHydrate hydrated={someState}>` where someState
|
|
21
|
+
* - Hydrate the component on some state `<LazyHydrate hydrated={someState}>` where someState
|
|
22
|
+
* initially is false and later becomes true.
|
|
26
23
|
*/
|
|
27
24
|
hydrated?: boolean
|
|
28
25
|
|
|
29
26
|
/**
|
|
30
27
|
* By default LazyHydrate does not defer the rendering of components when they are rendered client
|
|
31
|
-
* side, because using an IntersectionObserver on an element with no height, will cause all
|
|
28
|
+
* side, because using an IntersectionObserver on an element with no height, will cause all
|
|
29
|
+
* siblings to render at once.
|
|
32
30
|
*
|
|
33
31
|
* By proving a height, we can use the IntersectionObserver on the client as well.
|
|
34
32
|
*/
|
|
@@ -36,9 +34,8 @@ export type LazyHydrateProps = BoxProps<'div'> & {
|
|
|
36
34
|
}
|
|
37
35
|
|
|
38
36
|
/**
|
|
39
|
-
* LazyHydrate can defer the hydration of a component until it becomes visible.
|
|
40
|
-
*
|
|
41
|
-
* This can be a way to improve the TBT of a page.
|
|
37
|
+
* LazyHydrate can defer the hydration of a component until it becomes visible. OR manually by using
|
|
38
|
+
* the hydrated prop. This can be a way to improve the TBT of a page.
|
|
42
39
|
*/
|
|
43
40
|
export function LazyHydrate(props: LazyHydrateProps) {
|
|
44
41
|
const { hydrated, children, height, ...elementProps } = props
|
|
@@ -47,7 +44,7 @@ export function LazyHydrate(props: LazyHydrateProps) {
|
|
|
47
44
|
const [isHydrated, setIsHydrated] = useState(hydrated || false)
|
|
48
45
|
if (!isHydrated && hydrated) setIsHydrated(true)
|
|
49
46
|
|
|
50
|
-
|
|
47
|
+
useIsomorphicLayoutEffect(() => {
|
|
51
48
|
// If we are manually hydrating, we watch that value and do not use the IntersectionObserver
|
|
52
49
|
if (isHydrated || !rootRef.current) return undefined
|
|
53
50
|
|
|
@@ -71,7 +68,7 @@ export function LazyHydrate(props: LazyHydrateProps) {
|
|
|
71
68
|
observer.observe(rootRef.current)
|
|
72
69
|
|
|
73
70
|
return () => observer.disconnect()
|
|
74
|
-
}, [hydrated, isHydrated])
|
|
71
|
+
}, [height, hydrated, isHydrated])
|
|
75
72
|
|
|
76
73
|
if (isHydrated) {
|
|
77
74
|
return <Box {...elementProps}>{children}</Box>
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { BoxProps, Theme } from '@mui/material'
|
|
2
|
+
import { Box, useTheme } from '@mui/material'
|
|
3
|
+
import type { CSSProperties } from 'react'
|
|
4
|
+
import { useEffect, useMemo, useState } from 'react'
|
|
5
|
+
|
|
6
|
+
export type MediaQueryProps<C extends React.ElementType = 'div'> = BoxProps<C> & {
|
|
7
|
+
/** The media query to match. */
|
|
8
|
+
query: string | ((theme: Theme) => string)
|
|
9
|
+
/**
|
|
10
|
+
* The display style to apply when the media query matches.
|
|
11
|
+
*
|
|
12
|
+
* @default 'contents'
|
|
13
|
+
*/
|
|
14
|
+
display?: CSSProperties['display']
|
|
15
|
+
/**
|
|
16
|
+
* The content to render when the media query matches.
|
|
17
|
+
*
|
|
18
|
+
* It doesn't matter if the children are actual compontents or if they are forwarded from some
|
|
19
|
+
* other location.
|
|
20
|
+
*/
|
|
21
|
+
children: React.ReactNode
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* MediaQuery: Render (and hydrate) a Component based on a media query given.
|
|
26
|
+
*
|
|
27
|
+
* Example:
|
|
28
|
+
*
|
|
29
|
+
* ```tsx
|
|
30
|
+
* ;<MediaQuery query={(theme) => theme.breakpoints.up('md')}>
|
|
31
|
+
* <MyExpensiveDesktopComponent>Only visisble on desktop</MyExpensiveDesktopComponent>
|
|
32
|
+
* </MediaQuery>
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* Forwarded props also work:
|
|
36
|
+
*
|
|
37
|
+
* ```tsx
|
|
38
|
+
* function MyComponent(props: { children: React.ReactNode }) {
|
|
39
|
+
* const { children } = props
|
|
40
|
+
* return <MediaQuery query={(theme) => theme.breakpoints.up('md')}>{children}</MediaQuery>
|
|
41
|
+
* }
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* When to use:
|
|
45
|
+
*
|
|
46
|
+
* 1. UseMediaQuery: When you are now using useMediaQuery to conditionally render content for mobile or
|
|
47
|
+
* desktop. a. Is very slow as it has to wait for the JS to initialize on pageload. b. Can cause
|
|
48
|
+
* CLS problems if the useMediaQuery is used to render elements in the viewport. c. Can cause LCP
|
|
49
|
+
* issues if useMediaQuery is used to render the LCP element. d. Causes TBT problems as a
|
|
50
|
+
* component always needs to be rerendered. (And bad TBT can cause INP problems) e. HTML isn't
|
|
51
|
+
* present in the DOM, which can cause SEO issues.
|
|
52
|
+
* 2. CSS Media query: When you are using CSS to show or hide content based on media queries. a. Causes
|
|
53
|
+
* TBT problems as both code paths need to be rendered. (And bad TBT can cause INP problems)
|
|
54
|
+
*
|
|
55
|
+
* How does it work? It wraps the component in a div that has 'display: contents;' when shown and
|
|
56
|
+
* 'display: none;' when hidden so it should not interfere with other styling. It conditionally
|
|
57
|
+
* hydrates the component if the query matches. If it doesn't match, it will NOT render the
|
|
58
|
+
* component (and thus not execute the JS).
|
|
59
|
+
*/
|
|
60
|
+
export function MediaQuery<Component extends React.ElementType = 'div'>(
|
|
61
|
+
props: MediaQueryProps<Component>,
|
|
62
|
+
) {
|
|
63
|
+
const { query, sx, children, display = 'contents', ...elementProps } = props
|
|
64
|
+
|
|
65
|
+
const theme = useTheme()
|
|
66
|
+
const queryString = typeof query === 'function' ? query(theme) : query
|
|
67
|
+
|
|
68
|
+
const matchMedia = useMemo(
|
|
69
|
+
() => globalThis.matchMedia?.(queryString.replace(/^@media( ?)/m, '')),
|
|
70
|
+
[queryString],
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
const [matches, setMatches] = useState(matchMedia?.matches || false)
|
|
74
|
+
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
if (matchMedia.matches) setMatches(true)
|
|
77
|
+
|
|
78
|
+
const controller = new AbortController()
|
|
79
|
+
matchMedia.addEventListener(
|
|
80
|
+
'change',
|
|
81
|
+
(e) => {
|
|
82
|
+
if (e.matches) setMatches(true)
|
|
83
|
+
},
|
|
84
|
+
{ signal: controller.signal, once: true },
|
|
85
|
+
)
|
|
86
|
+
return () => controller.abort()
|
|
87
|
+
}, [matchMedia])
|
|
88
|
+
|
|
89
|
+
const sxVal = [
|
|
90
|
+
{ display: 'none', [queryString]: { display } },
|
|
91
|
+
...(Array.isArray(sx) ? sx : [sx]),
|
|
92
|
+
]
|
|
93
|
+
|
|
94
|
+
if (typeof window === 'undefined' || matches) {
|
|
95
|
+
return (
|
|
96
|
+
<Box {...elementProps} sx={sxVal}>
|
|
97
|
+
{children}
|
|
98
|
+
</Box>
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<Box
|
|
104
|
+
// eslint-disable-next-line react/no-danger
|
|
105
|
+
dangerouslySetInnerHTML={{ __html: '' }}
|
|
106
|
+
suppressHydrationWarning
|
|
107
|
+
{...elementProps}
|
|
108
|
+
sx={sxVal}
|
|
109
|
+
/>
|
|
110
|
+
)
|
|
111
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './MediaQuery'
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useMotionValueValue } from '@graphcommerce/framer-utils'
|
|
2
|
-
import {
|
|
2
|
+
import type { FabProps, SxProps, Theme } from '@mui/material'
|
|
3
|
+
import { Box, Fab, styled, useTheme } from '@mui/material'
|
|
3
4
|
import { m } from 'framer-motion'
|
|
4
5
|
import { useRouter } from 'next/router'
|
|
5
6
|
import React, { useEffect } from 'react'
|
|
@@ -8,7 +9,7 @@ import { useScrollY } from '../../Layout/hooks/useScrollY'
|
|
|
8
9
|
import { useFabAnimation } from '../../LayoutParts/useFabAnimation'
|
|
9
10
|
import { extendableComponent } from '../../Styles/extendableComponent'
|
|
10
11
|
import { useFabSize } from '../../Theme'
|
|
11
|
-
import {
|
|
12
|
+
import { iconClose, iconMenu } from '../../icons'
|
|
12
13
|
|
|
13
14
|
const MotionDiv = styled(m.div)({})
|
|
14
15
|
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
2
2
|
import { useMotionValueValue } from '@graphcommerce/framer-utils'
|
|
3
|
-
import {
|
|
3
|
+
import { Box, ListItemButton, alpha, styled, useEventCallback } from '@mui/material'
|
|
4
4
|
import React from 'react'
|
|
5
5
|
import { IconSvg } from '../../IconSvg'
|
|
6
6
|
import { extendableComponent } from '../../Styles/extendableComponent'
|
|
7
7
|
import { NextLink } from '../../Theme'
|
|
8
8
|
import { useMatchMedia } from '../../hooks'
|
|
9
9
|
import { iconChevronRight } from '../../icons'
|
|
10
|
+
import type { NavigationNode } from '../hooks/useNavigation'
|
|
10
11
|
import {
|
|
11
12
|
isNavigationButton,
|
|
12
13
|
isNavigationComponent,
|
|
13
14
|
isNavigationHref,
|
|
14
|
-
NavigationNode,
|
|
15
15
|
useNavigation,
|
|
16
16
|
} from '../hooks/useNavigation'
|
|
17
17
|
import type { NavigationList } from './NavigationList'
|
|
@@ -24,7 +24,7 @@ type OwnerState = {
|
|
|
24
24
|
column: number
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
type NavigationItemProps = NavigationNode & {
|
|
27
|
+
export type NavigationItemProps = NavigationNode & {
|
|
28
28
|
parentPath: string
|
|
29
29
|
idx: number
|
|
30
30
|
NavigationList: typeof NavigationList
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { styled } from '@mui/material'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
import { extendableComponent } from '../../Styles/extendableComponent'
|
|
4
|
-
import { NavigationNode } from '../hooks/useNavigation'
|
|
5
|
-
import {
|
|
4
|
+
import type { NavigationNode } from '../hooks/useNavigation'
|
|
5
|
+
import type { mouseEventPref } from './NavigationItem'
|
|
6
|
+
import { NavigationItem } from './NavigationItem'
|
|
6
7
|
|
|
7
8
|
const NavigationUList = styled('ul')({
|
|
8
9
|
display: 'block',
|
|
@@ -14,7 +15,7 @@ const NavigationUList = styled('ul')({
|
|
|
14
15
|
},
|
|
15
16
|
})
|
|
16
17
|
|
|
17
|
-
type NavigationItemsProps = {
|
|
18
|
+
export type NavigationItemsProps = {
|
|
18
19
|
parentPath?: string
|
|
19
20
|
items: NavigationNode[]
|
|
20
21
|
selected?: boolean
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { dvw, useMotionSelector, useMotionValueValue } from '@graphcommerce/framer-utils'
|
|
2
2
|
import { i18n } from '@lingui/core'
|
|
3
|
-
import {
|
|
3
|
+
import type { SxProps, Theme } from '@mui/material'
|
|
4
|
+
import { Box, Fab, styled, useEventCallback, useTheme } from '@mui/material'
|
|
4
5
|
import { m } from 'framer-motion'
|
|
5
6
|
import React, { useEffect, useRef } from 'react'
|
|
6
7
|
import type { LiteralUnion } from 'type-fest'
|
|
@@ -11,9 +12,9 @@ import { OverlaySsr } from '../../Overlay/components/OverlaySsr'
|
|
|
11
12
|
import { extendableComponent } from '../../Styles/extendableComponent'
|
|
12
13
|
import { useFabSize } from '../../Theme'
|
|
13
14
|
import { useMatchMedia } from '../../hooks'
|
|
14
|
-
import {
|
|
15
|
+
import { iconChevronLeft, iconClose } from '../../icons'
|
|
15
16
|
import { useNavigation } from '../hooks/useNavigation'
|
|
16
|
-
import { mouseEventPref } from './NavigationItem'
|
|
17
|
+
import type { mouseEventPref } from './NavigationItem'
|
|
17
18
|
import { NavigationList } from './NavigationList'
|
|
18
19
|
import { NavigationTitle } from './NavigationTitle'
|
|
19
20
|
|
|
@@ -22,8 +23,9 @@ type LayoutOverlaySize = 'floating' | 'minimal' | 'full'
|
|
|
22
23
|
type LayoutOverlayAlign = 'start' | 'end' | 'center' | 'stretch'
|
|
23
24
|
type ItemPadding = LiteralUnion<keyof Theme['spacings'], string | number>
|
|
24
25
|
|
|
25
|
-
type NavigationOverlayProps = {
|
|
26
|
+
export type NavigationOverlayProps = {
|
|
26
27
|
sx?: SxProps<Theme>
|
|
28
|
+
overlaySx?: SxProps<Theme>
|
|
27
29
|
stretchColumns?: boolean
|
|
28
30
|
variantSm: LayoutOverlayVariant
|
|
29
31
|
variantMd: LayoutOverlayVariant
|
|
@@ -39,12 +41,13 @@ type NavigationOverlayProps = {
|
|
|
39
41
|
const MotionDiv = styled(m.div)({})
|
|
40
42
|
|
|
41
43
|
const componentName = 'Navigation'
|
|
42
|
-
const parts = ['root', 'navigation', 'header', 'column'] as const
|
|
44
|
+
const parts = ['root', 'navigation', 'header', 'column', 'wrapper'] as const
|
|
43
45
|
const { classes } = extendableComponent(componentName, parts)
|
|
44
46
|
|
|
45
47
|
export const NavigationOverlay = React.memo((props: NavigationOverlayProps) => {
|
|
46
48
|
const {
|
|
47
49
|
sx,
|
|
50
|
+
overlaySx,
|
|
48
51
|
stretchColumns,
|
|
49
52
|
variantMd,
|
|
50
53
|
variantSm,
|
|
@@ -124,12 +127,15 @@ export const NavigationOverlay = React.memo((props: NavigationOverlayProps) => {
|
|
|
124
127
|
animating.set(false)
|
|
125
128
|
},
|
|
126
129
|
}}
|
|
127
|
-
sx={
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
130
|
+
sx={[
|
|
131
|
+
{
|
|
132
|
+
zIndex: 'drawer',
|
|
133
|
+
'& .LayoutOverlayBase-overlayPane': {
|
|
134
|
+
minWidth: itemWidthMd,
|
|
135
|
+
},
|
|
131
136
|
},
|
|
132
|
-
|
|
137
|
+
...(Array.isArray(overlaySx) ? overlaySx : [overlaySx]),
|
|
138
|
+
]}
|
|
133
139
|
>
|
|
134
140
|
<MotionDiv layout layoutDependency={selectionValue} sx={{ display: 'grid' }}>
|
|
135
141
|
<Box
|
|
@@ -182,6 +188,7 @@ export const NavigationOverlay = React.memo((props: NavigationOverlayProps) => {
|
|
|
182
188
|
</MotionDiv>
|
|
183
189
|
<MotionDiv layout='position' layoutDependency={selectionValue} sx={{ display: 'grid' }}>
|
|
184
190
|
<Box
|
|
191
|
+
className={classes.wrapper}
|
|
185
192
|
sx={[
|
|
186
193
|
(theme) => ({
|
|
187
194
|
display: 'grid',
|