@graphcommerce/next-ui 9.1.0-canary.54 → 10.0.0-canary.56
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/ActionCardList.tsx +2 -2
- package/Breadcrumbs/Breadcrumbs.tsx +4 -4
- package/Breadcrumbs/BreadcrumbsList.tsx +2 -2
- package/CHANGELOG.md +96 -0
- package/FramerScroller/SidebarGallery.tsx +5 -4
- package/Intl/DateTimeFormat/DateTimeFormat.tsx +3 -2
- package/Layout/components/LayoutHeaderBack.tsx +2 -2
- package/Layout/components/LayoutHeaderClose.tsx +11 -8
- package/LayoutOverlay/components/LayoutOverlayHeader2.tsx +213 -0
- package/LayoutOverlay/index.ts +1 -0
- package/Navigation/components/NavigationList.tsx +1 -1
- package/Navigation/components/NavigationOverlay.tsx +3 -3
- package/Navigation/components/NavigationTitle.tsx +2 -2
- package/Overlay/components/OverlayBase.tsx +3 -3
- package/Overlay/components/OverlayCloseButton.tsx +25 -0
- package/Overlay/components/OverlayHeader2.tsx +26 -0
- package/Overlay/components/index.ts +4 -2
- package/OverlayOrPopperChip/OverlayPanelActions.tsx +5 -5
- package/OverlayOrPopperChip/PopperPanelActions.tsx +5 -5
- package/Page/types.ts +1 -1
- package/PageMeta/canonicalize.ts +2 -1
- package/Pagination/Pagination.tsx +5 -2
- package/SkipLink/SkipLink.tsx +2 -2
- package/Snackbar/ErrorSnackbar.tsx +2 -2
- package/Snackbar/MessageSnackbarImpl.tsx +2 -2
- package/Styles/withEmotionCache.tsx +1 -3
- package/Tabs/TabItem.tsx +134 -0
- package/Tabs/Tabs.tsx +124 -0
- package/TextInputNumber/TextInputNumber.tsx +4 -4
- package/Theme/DarkLightModeThemeProvider.tsx +2 -2
- package/Theme/NextLink.tsx +4 -4
- package/hooks/memoDeep.ts +1 -1
- package/index.ts +2 -0
- package/package.json +34 -16
- package/po.d.ts +6 -0
- package/{types.d.ts → types.ts} +0 -9
- package/utils/storefrontConfig.ts +5 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Trans } from '@lingui/react'
|
|
1
|
+
import { t } from '@lingui/core/macro'
|
|
2
|
+
import { Trans } from '@lingui/react/macro'
|
|
3
3
|
import { Box, Button, Fab, Typography } from '@mui/material'
|
|
4
4
|
import { iconClose } from '../icons'
|
|
5
5
|
import { IconSvg, useIconSvgSize } from '../IconSvg'
|
|
@@ -30,7 +30,7 @@ export function OverlayPanelActions(props: PanelActionsProps) {
|
|
|
30
30
|
primary={
|
|
31
31
|
onReset && (
|
|
32
32
|
<Button variant='inline' color='primary' onClick={onReset}>
|
|
33
|
-
<Trans
|
|
33
|
+
<Trans>Reset</Trans>
|
|
34
34
|
</Button>
|
|
35
35
|
)
|
|
36
36
|
}
|
|
@@ -43,7 +43,7 @@ export function OverlayPanelActions(props: PanelActionsProps) {
|
|
|
43
43
|
ml: `calc((${fabSize} - ${svgSize}) * -0.5)`,
|
|
44
44
|
}}
|
|
45
45
|
size='small'
|
|
46
|
-
aria-label={
|
|
46
|
+
aria-label={t`Close`}
|
|
47
47
|
>
|
|
48
48
|
<IconSvg src={iconClose} size='large' aria-hidden />
|
|
49
49
|
</Fab>
|
|
@@ -68,7 +68,7 @@ export function OverlayPanelActions(props: PanelActionsProps) {
|
|
|
68
68
|
fullWidth
|
|
69
69
|
// sx={(theme) => ({ mt: theme.spacings.md })}
|
|
70
70
|
>
|
|
71
|
-
<Trans
|
|
71
|
+
<Trans>Apply</Trans>
|
|
72
72
|
</Button>
|
|
73
73
|
</OverlayStickyBottom>
|
|
74
74
|
</>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Trans } from '@lingui/react'
|
|
1
|
+
import { t } from '@lingui/core/macro'
|
|
2
|
+
import { Trans } from '@lingui/react/macro'
|
|
3
3
|
import { Box, Button, Fab, Typography } from '@mui/material'
|
|
4
4
|
import { iconClose } from '../icons'
|
|
5
5
|
import { IconSvg, useIconSvgSize } from '../IconSvg'
|
|
@@ -24,7 +24,7 @@ export function PopperPanelActions(props: PanelActionsProps) {
|
|
|
24
24
|
primary={
|
|
25
25
|
onReset && (
|
|
26
26
|
<Button variant='text' color='primary' size='medium' onClick={onReset}>
|
|
27
|
-
<Trans
|
|
27
|
+
<Trans>Reset</Trans>
|
|
28
28
|
</Button>
|
|
29
29
|
)
|
|
30
30
|
}
|
|
@@ -37,7 +37,7 @@ export function PopperPanelActions(props: PanelActionsProps) {
|
|
|
37
37
|
ml: `calc((${fabSize} - ${svgSize}) * -0.5)`,
|
|
38
38
|
}}
|
|
39
39
|
size='small'
|
|
40
|
-
aria-label={
|
|
40
|
+
aria-label={t`Close`}
|
|
41
41
|
>
|
|
42
42
|
<IconSvg src={iconClose} size='large' aria-hidden />
|
|
43
43
|
</Fab>
|
|
@@ -68,7 +68,7 @@ export function PopperPanelActions(props: PanelActionsProps) {
|
|
|
68
68
|
color='primary'
|
|
69
69
|
fullWidth
|
|
70
70
|
>
|
|
71
|
-
<Trans
|
|
71
|
+
<Trans>Apply</Trans>
|
|
72
72
|
</Button>
|
|
73
73
|
</OverlayStickyBottom>
|
|
74
74
|
</>
|
package/Page/types.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ParsedUrlQuery } from 'querystring'
|
|
2
|
-
import type { UpPage } from '@graphcommerce/framer-next-pages
|
|
2
|
+
import type { UpPage } from '@graphcommerce/framer-next-pages'
|
|
3
3
|
// todo: remove references to GraphQL
|
|
4
4
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
5
5
|
import type { NormalizedCacheObject } from '@graphcommerce/graphql'
|
package/PageMeta/canonicalize.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {} from '@graphcommerce/next-config'
|
|
2
|
+
import { canonicalBaseUrl } from '@graphcommerce/next-config/config'
|
|
2
3
|
import { addBasePath } from 'next/dist/client/add-base-path'
|
|
3
4
|
import { addLocale } from 'next/dist/client/add-locale'
|
|
4
5
|
import { getDomainLocale } from 'next/dist/client/get-domain-locale'
|
|
@@ -49,7 +50,7 @@ export function canonicalize(router: PartialNextRouter, incoming?: Canonical) {
|
|
|
49
50
|
addLocale(as, curLocale, conf?.domain ? conf.locale : router.defaultLocale),
|
|
50
51
|
)
|
|
51
52
|
|
|
52
|
-
let siteUrl = conf?.canonicalBaseUrl ||
|
|
53
|
+
let siteUrl = conf?.canonicalBaseUrl || canonicalBaseUrl
|
|
53
54
|
|
|
54
55
|
if (conf?.domain && !conf?.canonicalBaseUrl) siteUrl = `https://${conf.domain}`
|
|
55
56
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Trans } from '@lingui/react'
|
|
1
|
+
import { Trans } from '@lingui/react/macro'
|
|
2
2
|
import type { PaginationProps, SxProps, Theme } from '@mui/material'
|
|
3
3
|
import { Box, IconButton } from '@mui/material'
|
|
4
4
|
import type { UsePaginationItem } from '@mui/material/usePagination'
|
|
@@ -59,6 +59,7 @@ export function Pagination(props: PagePaginationProps) {
|
|
|
59
59
|
<IconSvg src={iconChevronRight} className={classes.icon} size='medium' />
|
|
60
60
|
</IconButton>
|
|
61
61
|
)
|
|
62
|
+
const max = Math.max(1, count)
|
|
62
63
|
|
|
63
64
|
return (
|
|
64
65
|
<Box
|
|
@@ -82,7 +83,9 @@ export function Pagination(props: PagePaginationProps) {
|
|
|
82
83
|
{page === 1 ? chevronLeft : renderLink(page - 1, chevronLeft, prevBtnProps)}
|
|
83
84
|
|
|
84
85
|
<Box typography='body1'>
|
|
85
|
-
<Trans
|
|
86
|
+
<Trans>
|
|
87
|
+
Page {page} of {max}
|
|
88
|
+
</Trans>
|
|
86
89
|
</Box>
|
|
87
90
|
|
|
88
91
|
{page === count ? chevronRight : renderLink(page + 1, chevronRight, nextBtnProps)}
|
package/SkipLink/SkipLink.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Trans } from '@lingui/react'
|
|
1
|
+
import { Trans } from '@lingui/react/macro'
|
|
2
2
|
import { Link } from '@mui/material'
|
|
3
3
|
|
|
4
4
|
export function SkipLink() {
|
|
@@ -32,7 +32,7 @@ export function SkipLink() {
|
|
|
32
32
|
},
|
|
33
33
|
})}
|
|
34
34
|
>
|
|
35
|
-
<Trans
|
|
35
|
+
<Trans>Skip to main content</Trans>
|
|
36
36
|
</Link>
|
|
37
37
|
)
|
|
38
38
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Trans } from '@lingui/react'
|
|
1
|
+
import { Trans } from '@lingui/react/macro'
|
|
2
2
|
import { Button } from '@mui/material'
|
|
3
3
|
import { MessageSnackbar } from './MessageSnackbar'
|
|
4
4
|
import type { MessageSnackbarProps } from './MessageSnackbarImpl'
|
|
@@ -15,7 +15,7 @@ export function ErrorSnackbar(props: ErrorSnackbarProps) {
|
|
|
15
15
|
action={
|
|
16
16
|
action ?? (
|
|
17
17
|
<Button size='medium' variant='pill' color='secondary' fullWidth>
|
|
18
|
-
<Trans
|
|
18
|
+
<Trans>Ok</Trans>
|
|
19
19
|
</Button>
|
|
20
20
|
)
|
|
21
21
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { t } from '@lingui/core/macro'
|
|
2
2
|
import type { SnackbarProps, SxProps, Theme } from '@mui/material'
|
|
3
3
|
import { Box, Fab, lighten, Portal, Snackbar, SnackbarContent } from '@mui/material'
|
|
4
4
|
import React, { useEffect, useState } from 'react'
|
|
@@ -190,7 +190,7 @@ export default function MessageSnackbarImpl(props: MessageSnackbarProps) {
|
|
|
190
190
|
{!disableClose && (
|
|
191
191
|
<Fab
|
|
192
192
|
className={classes.close}
|
|
193
|
-
aria-label={
|
|
193
|
+
aria-label={t`Close`}
|
|
194
194
|
size='small'
|
|
195
195
|
onClick={hideSnackbar}
|
|
196
196
|
onMouseDown={preventAnimationBubble}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'
|
|
2
1
|
import createEmotionServer from '@emotion/server/create-instance'
|
|
3
2
|
import type { AppType } from 'next/app'
|
|
4
3
|
// eslint-disable-next-line @next/next/no-document-import-in-page
|
|
@@ -8,7 +7,7 @@ import type { DocumentContext } from 'next/document'
|
|
|
8
7
|
import { createEmotionCache } from './createEmotionCache'
|
|
9
8
|
import type { EmotionProviderProps } from './EmotionProvider'
|
|
10
9
|
|
|
11
|
-
export type EmotionCacheProps = { emotionStyleTags:
|
|
10
|
+
export type EmotionCacheProps = { emotionStyleTags: React.ReactNode[] }
|
|
12
11
|
|
|
13
12
|
export function withEmotionCache(Document: typeof NextDocument): typeof NextDocument {
|
|
14
13
|
return class DocumentWithEmotionCache extends Document {
|
|
@@ -32,7 +31,6 @@ export function withEmotionCache(Document: typeof NextDocument): typeof NextDocu
|
|
|
32
31
|
<style
|
|
33
32
|
data-emotion={`${style.key} ${style.ids.join(' ')}`}
|
|
34
33
|
key={style.key}
|
|
35
|
-
// eslint-disable-next-line react/no-danger
|
|
36
34
|
dangerouslySetInnerHTML={{ __html: style.css }}
|
|
37
35
|
/>
|
|
38
36
|
))
|
package/Tabs/TabItem.tsx
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { Box, ButtonBase, type SxProps, type Theme } from '@mui/material'
|
|
2
|
+
import { alpha, useTheme } from '@mui/material/styles'
|
|
3
|
+
import { forwardRef } from 'react'
|
|
4
|
+
import { extendableComponent } from '../Styles/extendableComponent'
|
|
5
|
+
import { responsiveVal } from '../Styles/responsiveVal'
|
|
6
|
+
import { sxx } from '../utils/sxx'
|
|
7
|
+
|
|
8
|
+
export type TabItemVariant = 'chrome'
|
|
9
|
+
|
|
10
|
+
export type TabItemProps = {
|
|
11
|
+
/** Whether this tab is selected */
|
|
12
|
+
selected: boolean
|
|
13
|
+
/** Content to display inside the tab */
|
|
14
|
+
children: React.ReactNode
|
|
15
|
+
/** Click handler */
|
|
16
|
+
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void
|
|
17
|
+
|
|
18
|
+
/** Spacing for the tab */
|
|
19
|
+
spacing?: string
|
|
20
|
+
/** Custom styling */
|
|
21
|
+
sx?: SxProps<Theme>
|
|
22
|
+
/** Whether to disable ripple effect */
|
|
23
|
+
disableRipple?: boolean
|
|
24
|
+
/** Additional className */
|
|
25
|
+
className?: string
|
|
26
|
+
|
|
27
|
+
color: (theme: Theme) => string
|
|
28
|
+
variant?: 'chrome'
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
type State = {
|
|
32
|
+
selected: boolean
|
|
33
|
+
variant: 'chrome'
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const name = 'TabItem'
|
|
37
|
+
const parts = ['root', 'content'] as const
|
|
38
|
+
const { withState } = extendableComponent<State, typeof name, typeof parts>(name, parts)
|
|
39
|
+
|
|
40
|
+
export const TabItem = forwardRef<HTMLButtonElement, TabItemProps>((props, ref) => {
|
|
41
|
+
const {
|
|
42
|
+
selected,
|
|
43
|
+
children,
|
|
44
|
+
onClick,
|
|
45
|
+
spacing = responsiveVal(4, 20),
|
|
46
|
+
sx,
|
|
47
|
+
disableRipple = true,
|
|
48
|
+
className,
|
|
49
|
+
color = (theme) => theme.palette.background.default,
|
|
50
|
+
variant = 'chrome',
|
|
51
|
+
...other
|
|
52
|
+
} = props
|
|
53
|
+
|
|
54
|
+
const classes = withState({ selected, variant })
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<Box
|
|
58
|
+
ref={ref}
|
|
59
|
+
component={ButtonBase}
|
|
60
|
+
onClick={selected ? undefined : onClick}
|
|
61
|
+
className={`${classes.root} ${className ?? ''}`}
|
|
62
|
+
disableRipple={selected || disableRipple}
|
|
63
|
+
role='tab'
|
|
64
|
+
aria-selected={selected}
|
|
65
|
+
// tabindex={0}
|
|
66
|
+
sx={sxx(
|
|
67
|
+
(theme) => ({
|
|
68
|
+
position: 'relative',
|
|
69
|
+
textDecoration: 'none',
|
|
70
|
+
color: 'text.primary',
|
|
71
|
+
typography: 'subtitle1',
|
|
72
|
+
mt: spacing,
|
|
73
|
+
height: `calc(100% - ${spacing})`,
|
|
74
|
+
pb: spacing,
|
|
75
|
+
mx: `calc(${spacing} / 2)`,
|
|
76
|
+
transition: 'background-color 0.2s ease-in-out',
|
|
77
|
+
|
|
78
|
+
'&:hover:not(.selected) .TabItem-content': {
|
|
79
|
+
bgcolor: alpha(color(theme), 0.5),
|
|
80
|
+
},
|
|
81
|
+
'&:focus:not(.selected) .TabItem-content': {
|
|
82
|
+
bgcolor: alpha(color(theme), 0.5),
|
|
83
|
+
},
|
|
84
|
+
'&::before': {
|
|
85
|
+
opacity: 0,
|
|
86
|
+
transition: 'opacity 0.2s ease-in-out',
|
|
87
|
+
content: '""',
|
|
88
|
+
position: 'absolute',
|
|
89
|
+
bottom: 0,
|
|
90
|
+
left: '-10px',
|
|
91
|
+
width: '10px',
|
|
92
|
+
height: '10px',
|
|
93
|
+
background: `radial-gradient(circle at top left, transparent 10px, ${color(theme)} 10px)`,
|
|
94
|
+
},
|
|
95
|
+
'&::after': {
|
|
96
|
+
opacity: 0,
|
|
97
|
+
transition: 'opacity 0.2s ease-in-out',
|
|
98
|
+
content: '""',
|
|
99
|
+
position: 'absolute',
|
|
100
|
+
bottom: 0,
|
|
101
|
+
right: '-10px',
|
|
102
|
+
width: '10px',
|
|
103
|
+
height: '10px',
|
|
104
|
+
background: `radial-gradient(circle at top right, transparent 10px, ${color(theme)} 10px)`,
|
|
105
|
+
},
|
|
106
|
+
borderStartStartRadius: '0.5em',
|
|
107
|
+
borderStartEndRadius: '0.5em',
|
|
108
|
+
'&.selected': {
|
|
109
|
+
bgcolor: color(theme),
|
|
110
|
+
'&::before': { opacity: 1 },
|
|
111
|
+
'&::after': { opacity: 1 },
|
|
112
|
+
},
|
|
113
|
+
}),
|
|
114
|
+
sx,
|
|
115
|
+
)}
|
|
116
|
+
{...other}
|
|
117
|
+
>
|
|
118
|
+
<Box
|
|
119
|
+
className={classes.content}
|
|
120
|
+
sx={{
|
|
121
|
+
display: 'flex',
|
|
122
|
+
alignItems: 'center',
|
|
123
|
+
height: '100%',
|
|
124
|
+
px: spacing,
|
|
125
|
+
gap: `calc(${spacing} / 2)`,
|
|
126
|
+
borderRadius: '0.5em',
|
|
127
|
+
transition: 'background-color 0.2s ease-in-out',
|
|
128
|
+
}}
|
|
129
|
+
>
|
|
130
|
+
{children}
|
|
131
|
+
</Box>
|
|
132
|
+
</Box>
|
|
133
|
+
)
|
|
134
|
+
})
|
package/Tabs/Tabs.tsx
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { Scroller, ScrollerButton, ScrollerProvider } from '@graphcommerce/framer-scroller'
|
|
2
|
+
import { Box, type SxProps, type Theme } from '@mui/material'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { iconChevronLeft, iconChevronRight } from '../icons'
|
|
5
|
+
import { IconSvg } from '../IconSvg'
|
|
6
|
+
import { extendableComponent } from '../Styles/extendableComponent'
|
|
7
|
+
import { sxx } from '../utils/sxx'
|
|
8
|
+
|
|
9
|
+
export type TabsProps = {
|
|
10
|
+
children: React.ReactNode
|
|
11
|
+
sx?: SxProps<Theme>
|
|
12
|
+
/** Additional content to show before tabs */
|
|
13
|
+
startContent?: React.ReactNode
|
|
14
|
+
/** Additional content to show after tabs */
|
|
15
|
+
endContent?: React.ReactNode
|
|
16
|
+
/** Whether to show separators between tabs */
|
|
17
|
+
showSeparators?: boolean
|
|
18
|
+
/** Custom separator component */
|
|
19
|
+
separator?: React.ReactNode
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const { classes } = extendableComponent('Tabs', ['root', 'scroller', 'left', 'right', 'button'])
|
|
23
|
+
|
|
24
|
+
export function Tabs(props: TabsProps) {
|
|
25
|
+
const { children, sx, startContent, endContent, showSeparators = true, separator } = props
|
|
26
|
+
|
|
27
|
+
const defaultSeparator = (
|
|
28
|
+
<Box
|
|
29
|
+
className='separator'
|
|
30
|
+
sx={{ width: '2px', height: '1em', bgcolor: 'divider', mx: '-1px' }}
|
|
31
|
+
/>
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
const separatorElement = separator ?? defaultSeparator
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<Box
|
|
38
|
+
className={classes.root}
|
|
39
|
+
sx={sxx(
|
|
40
|
+
{
|
|
41
|
+
alignItems: 'stretch',
|
|
42
|
+
position: 'relative',
|
|
43
|
+
pointerEvents: 'all',
|
|
44
|
+
gridTemplateColumns: 'auto 1fr auto',
|
|
45
|
+
display: 'grid',
|
|
46
|
+
gridAutoFlow: 'column',
|
|
47
|
+
},
|
|
48
|
+
sx,
|
|
49
|
+
)}
|
|
50
|
+
>
|
|
51
|
+
<ScrollerProvider scrollSnapAlign='none'>
|
|
52
|
+
<Scroller
|
|
53
|
+
hideScrollbar
|
|
54
|
+
sx={{
|
|
55
|
+
gridArea: '1 / 1 / 1 / 4',
|
|
56
|
+
gridAutoColumns: 'min-content',
|
|
57
|
+
alignItems: 'center',
|
|
58
|
+
// Hide the Separator that comes before or after the selected tab.
|
|
59
|
+
'& .separator': { transition: 'opacity 0.2s ease-in-out' },
|
|
60
|
+
'& .TabItem-root.selected + .separator': { opacity: 0 },
|
|
61
|
+
'& .separator:has(+ .TabItem-root.selected)': { opacity: 0 },
|
|
62
|
+
// Same for hover:
|
|
63
|
+
'& .TabItem-root:hover + .separator': { opacity: 0 },
|
|
64
|
+
'& .separator:has(+ .TabItem-root:hover)': { opacity: 0 },
|
|
65
|
+
}}
|
|
66
|
+
className={classes.scroller}
|
|
67
|
+
role='tablist'
|
|
68
|
+
>
|
|
69
|
+
{startContent}
|
|
70
|
+
|
|
71
|
+
{showSeparators && startContent && separatorElement}
|
|
72
|
+
|
|
73
|
+
{React.Children.map(children, (child, index) => (
|
|
74
|
+
// eslint-disable-next-line react/no-array-index-key
|
|
75
|
+
<React.Fragment key={index}>
|
|
76
|
+
{showSeparators && index > 0 && separatorElement}
|
|
77
|
+
{child}
|
|
78
|
+
</React.Fragment>
|
|
79
|
+
))}
|
|
80
|
+
|
|
81
|
+
{showSeparators && endContent && separatorElement}
|
|
82
|
+
|
|
83
|
+
{endContent}
|
|
84
|
+
</Scroller>
|
|
85
|
+
|
|
86
|
+
<ScrollerButton
|
|
87
|
+
sxContainer={{
|
|
88
|
+
gridArea: '1 / 1 / 1 / 2',
|
|
89
|
+
display: 'flex',
|
|
90
|
+
alignItems: 'center',
|
|
91
|
+
justifyContent: 'center',
|
|
92
|
+
pointerEvents: 'none',
|
|
93
|
+
'& > *': { pointerEvents: 'all' },
|
|
94
|
+
}}
|
|
95
|
+
sx={{ pointerEvents: 'all' }}
|
|
96
|
+
direction='left'
|
|
97
|
+
size='small'
|
|
98
|
+
tabIndex={-1}
|
|
99
|
+
className={`${classes.left} ${classes.button}`}
|
|
100
|
+
>
|
|
101
|
+
<IconSvg src={iconChevronLeft} />
|
|
102
|
+
</ScrollerButton>
|
|
103
|
+
|
|
104
|
+
<ScrollerButton
|
|
105
|
+
sxContainer={{
|
|
106
|
+
gridArea: '1 / 3 / 1 / 4',
|
|
107
|
+
display: 'flex',
|
|
108
|
+
alignItems: 'center',
|
|
109
|
+
justifyContent: 'center',
|
|
110
|
+
pointerEvents: 'none',
|
|
111
|
+
'& > *': { pointerEvents: 'all' },
|
|
112
|
+
}}
|
|
113
|
+
sx={{ pointerEvents: 'all' }}
|
|
114
|
+
direction='right'
|
|
115
|
+
size='small'
|
|
116
|
+
tabIndex={-1}
|
|
117
|
+
className={`${classes.right} ${classes.button}`}
|
|
118
|
+
>
|
|
119
|
+
<IconSvg src={iconChevronRight} />
|
|
120
|
+
</ScrollerButton>
|
|
121
|
+
</ScrollerProvider>
|
|
122
|
+
</Box>
|
|
123
|
+
)
|
|
124
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { t } from '@lingui/core/macro'
|
|
2
2
|
import type { IconButtonProps, SxProps, TextFieldProps, Theme } from '@mui/material'
|
|
3
3
|
import {
|
|
4
4
|
Box,
|
|
@@ -125,7 +125,7 @@ export function TextInputNumber(props: TextInputNumberProps) {
|
|
|
125
125
|
startAdornment: (
|
|
126
126
|
<Box>
|
|
127
127
|
<Fab
|
|
128
|
-
aria-label={
|
|
128
|
+
aria-label={t`Decrease`}
|
|
129
129
|
size='smaller'
|
|
130
130
|
sx={{ boxShadow: variant === 'standard' ? 4 : 0, minHeight: '30px' }}
|
|
131
131
|
onPointerDown={() => setDirection('down')}
|
|
@@ -141,7 +141,7 @@ export function TextInputNumber(props: TextInputNumberProps) {
|
|
|
141
141
|
endAdornment: (
|
|
142
142
|
<Box>
|
|
143
143
|
<Fab
|
|
144
|
-
aria-label={
|
|
144
|
+
aria-label={t`Increase`}
|
|
145
145
|
size='smaller'
|
|
146
146
|
sx={{ boxShadow: variant === 'standard' ? 4 : 0, minHeight: '30px' }}
|
|
147
147
|
onPointerDown={() => setDirection('up')}
|
|
@@ -160,7 +160,7 @@ export function TextInputNumber(props: TextInputNumberProps) {
|
|
|
160
160
|
updateDisabled(e.target)
|
|
161
161
|
}}
|
|
162
162
|
inputProps={{
|
|
163
|
-
'aria-label':
|
|
163
|
+
'aria-label': t`Number`,
|
|
164
164
|
...inputProps,
|
|
165
165
|
sx: [
|
|
166
166
|
{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Trans } from '@lingui/react'
|
|
1
|
+
import { Trans } from '@lingui/react/macro'
|
|
2
2
|
import type { FabProps, ListItemButtonProps, Theme } from '@mui/material'
|
|
3
3
|
import {
|
|
4
4
|
Fab,
|
|
@@ -133,7 +133,7 @@ export function DarkLightModeMenuSecondaryItem(props: ListItemButtonProps) {
|
|
|
133
133
|
<IconSvg src={currentMode === 'light' ? iconMoon : iconSun} size='medium' />
|
|
134
134
|
</ListItemIcon>
|
|
135
135
|
<ListItemText>
|
|
136
|
-
{currentMode === 'light' ? <Trans
|
|
136
|
+
{currentMode === 'light' ? <Trans>Dark Mode</Trans> : <Trans>Light Mode</Trans>}
|
|
137
137
|
</ListItemText>
|
|
138
138
|
</ListItemButton>
|
|
139
139
|
)
|
package/Theme/NextLink.tsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { canonicalBaseUrl } from '@graphcommerce/next-config/config'
|
|
1
2
|
import type { LinkProps as NextLinkProps } from 'next/link'
|
|
2
3
|
import Link from 'next/link'
|
|
3
4
|
import { useRouter } from 'next/router'
|
|
@@ -30,8 +31,7 @@ export const NextLink = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) =>
|
|
|
30
31
|
let { href, target, relative, locale, ...rest } = props
|
|
31
32
|
|
|
32
33
|
const router = useRouter()
|
|
33
|
-
const canonicalBaseUrl
|
|
34
|
-
useStorefrontConfig().canonicalBaseUrl ?? import.meta.graphCommerce.canonicalBaseUrl
|
|
34
|
+
const canonical = useStorefrontConfig().canonicalBaseUrl ?? canonicalBaseUrl
|
|
35
35
|
|
|
36
36
|
// The href is optional in a MUI link, but required in a Next.js link
|
|
37
37
|
// When the href is not a string, we pass it through directly
|
|
@@ -44,14 +44,14 @@ export const NextLink = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) =>
|
|
|
44
44
|
* and make the URL relative without the locale. Prevents Next.js prefixing again with the current
|
|
45
45
|
* locale.
|
|
46
46
|
*/
|
|
47
|
-
if (!locale && isFullUrl && href.startsWith(
|
|
47
|
+
if (!locale && isFullUrl && href.startsWith(canonical)) {
|
|
48
48
|
const url = new URL(href)
|
|
49
49
|
locale = router.locales?.find((l) => url.pathname.startsWith(`/${l}/`))
|
|
50
50
|
href = locale ? url.pathname.replace(`/${locale}/`, '/') : url.pathname
|
|
51
51
|
href += url.search
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
const isExternal = isFullUrl && !href.startsWith(
|
|
54
|
+
const isExternal = isFullUrl && !href.startsWith(canonical)
|
|
55
55
|
if (isExternal) target = target || '_blank'
|
|
56
56
|
|
|
57
57
|
// Relative URL's cause more pain than they're worth
|
package/hooks/memoDeep.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
|
-
import diff from '@graphcommerce/react-hook-form
|
|
2
|
+
import { diff } from '@graphcommerce/react-hook-form'
|
|
3
3
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
4
4
|
import { equal } from '@wry/equality'
|
|
5
5
|
import type { FunctionComponent, NamedExoticComponent } from 'react'
|
package/index.ts
CHANGED
|
@@ -59,6 +59,8 @@ export * from './Stepper/Stepper'
|
|
|
59
59
|
export * from './Styles'
|
|
60
60
|
export * from './TextInputNumber/TextInputNumber'
|
|
61
61
|
export * from './Theme'
|
|
62
|
+
export * from './Tabs/TabItem'
|
|
63
|
+
export * from './Tabs/Tabs'
|
|
62
64
|
export * from './TimeAgo/TimeAgo'
|
|
63
65
|
export * from './ToggleButton/ToggleButton'
|
|
64
66
|
export * from './ToggleButtonGroup/ToggleButtonGroup'
|
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": "
|
|
5
|
+
"version": "10.0.0-canary.56",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"prettier": "@graphcommerce/prettier-config-pwa",
|
|
8
8
|
"eslintConfig": {
|
|
@@ -11,35 +11,53 @@
|
|
|
11
11
|
"project": "./tsconfig.json"
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
|
+
"exports": {
|
|
15
|
+
".": "./index.ts",
|
|
16
|
+
"./types": "./types.ts",
|
|
17
|
+
"./server": "./server.ts",
|
|
18
|
+
"./Layout/components/LayoutHeaderClose": "./Layout/components/LayoutHeaderClose.tsx",
|
|
19
|
+
"./LayoutOverlay/test/LayoutOverlayDemo": "./LayoutOverlay/test/LayoutOverlayDemo.tsx",
|
|
20
|
+
"./Styles/extendableComponent": "./Styles/extendableComponent.ts",
|
|
21
|
+
"./Styles": "./Styles/index.ts",
|
|
22
|
+
"./hooks/useMatchMedia": "./hooks/useMatchMedia.ts",
|
|
23
|
+
"./hooks/useStorefrontConfig": "./hooks/useStorefrontConfig.ts",
|
|
24
|
+
"./hooks/useIsSsr": "./hooks/useIsSsr.ts",
|
|
25
|
+
"./hooks/useMemoObject": "./hooks/useMemoObject.ts",
|
|
26
|
+
"./utils/cssFlags": "./utils/cssFlags.tsx",
|
|
27
|
+
"./Intl/DateTimeFormat/toDate": "./Intl/DateTimeFormat/toDate.ts",
|
|
28
|
+
"./Breadcrumbs/BreadcrumbsJsonLd": "./Breadcrumbs/BreadcrumbsJsonLd.tsx",
|
|
29
|
+
"./Breadcrumbs/jsonLdBreadcrumb": "./Breadcrumbs/jsonLdBreadcrumb.tsx",
|
|
30
|
+
"./RenderType/filterNonNullableKeys": "./RenderType/filterNonNullableKeys.ts"
|
|
31
|
+
},
|
|
14
32
|
"dependencies": {
|
|
15
33
|
"cookie": "^1.0.2",
|
|
16
|
-
"react-is": "^
|
|
34
|
+
"react-is": "^19.2.0"
|
|
17
35
|
},
|
|
18
36
|
"devDependencies": {
|
|
19
|
-
"@types/react-is": "^
|
|
20
|
-
"typescript": "5.
|
|
37
|
+
"@types/react-is": "^19.2.0",
|
|
38
|
+
"typescript": "5.9.3"
|
|
21
39
|
},
|
|
22
40
|
"peerDependencies": {
|
|
23
41
|
"@emotion/cache": "^11",
|
|
24
42
|
"@emotion/react": "^11",
|
|
25
43
|
"@emotion/server": "^11",
|
|
26
44
|
"@emotion/styled": "^11",
|
|
27
|
-
"@graphcommerce/eslint-config-pwa": "^
|
|
28
|
-
"@graphcommerce/framer-next-pages": "^
|
|
29
|
-
"@graphcommerce/framer-scroller": "^
|
|
30
|
-
"@graphcommerce/framer-utils": "^
|
|
31
|
-
"@graphcommerce/image": "^
|
|
32
|
-
"@graphcommerce/prettier-config-pwa": "^
|
|
33
|
-
"@graphcommerce/typescript-config-pwa": "^
|
|
34
|
-
"@lingui/core": "^
|
|
35
|
-
"@lingui/macro": "^
|
|
36
|
-
"@lingui/react": "^
|
|
45
|
+
"@graphcommerce/eslint-config-pwa": "^10.0.0-canary.56",
|
|
46
|
+
"@graphcommerce/framer-next-pages": "^10.0.0-canary.56",
|
|
47
|
+
"@graphcommerce/framer-scroller": "^10.0.0-canary.56",
|
|
48
|
+
"@graphcommerce/framer-utils": "^10.0.0-canary.56",
|
|
49
|
+
"@graphcommerce/image": "^10.0.0-canary.56",
|
|
50
|
+
"@graphcommerce/prettier-config-pwa": "^10.0.0-canary.56",
|
|
51
|
+
"@graphcommerce/typescript-config-pwa": "^10.0.0-canary.56",
|
|
52
|
+
"@lingui/core": "^5",
|
|
53
|
+
"@lingui/macro": "^5",
|
|
54
|
+
"@lingui/react": "^5",
|
|
37
55
|
"@mui/lab": "^5.0.0-alpha.68",
|
|
38
56
|
"@mui/material": "^5.10.16",
|
|
39
57
|
"framer-motion": "^11.0.0",
|
|
40
58
|
"next": "*",
|
|
41
59
|
"next-sitemap": "4.2.3",
|
|
42
|
-
"react": "^
|
|
43
|
-
"react-dom": "^
|
|
60
|
+
"react": "^19.2.0",
|
|
61
|
+
"react-dom": "^19.2.0"
|
|
44
62
|
}
|
|
45
63
|
}
|
package/po.d.ts
ADDED
package/{types.d.ts → types.ts}
RENAMED
|
@@ -5,12 +5,3 @@
|
|
|
5
5
|
import './Theme/createTheme'
|
|
6
6
|
// eslint-disable-next-line react/no-typos
|
|
7
7
|
import 'react'
|
|
8
|
-
|
|
9
|
-
declare module '*.po' {
|
|
10
|
-
const messages: Record<
|
|
11
|
-
string,
|
|
12
|
-
string | Array<string | Array<string | (string | undefined) | Record<string, unknown>>>
|
|
13
|
-
>
|
|
14
|
-
|
|
15
|
-
export const messages
|
|
16
|
-
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import { storefront } from '@graphcommerce/next-config/config'
|
|
2
|
+
|
|
3
|
+
export const storefrontAll = storefront
|
|
2
4
|
|
|
3
5
|
/** Get the current storefront config based on the provided locale */
|
|
4
6
|
export const storefrontConfig = (locale?: string | undefined) =>
|
|
5
|
-
|
|
7
|
+
storefront.find((l) => l.locale === locale)
|
|
6
8
|
|
|
7
9
|
export const storefrontConfigDefault = () =>
|
|
8
|
-
|
|
10
|
+
storefront.find((l) => l.defaultLocale) ?? storefrontAll[0]
|