@graphcommerce/next-ui 7.1.0-canary.9 → 8.0.0-canary.100
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 +2 -0
- package/CHANGELOG.md +255 -8
- package/Config.graphqls +24 -0
- package/Footer/Footer.tsx +97 -94
- package/FramerScroller/ItemScroller.tsx +3 -3
- package/FramerScroller/SidebarGallery.tsx +181 -162
- package/JsonLd/JsonLd.tsx +0 -2
- package/LayoutDefault/components/LayoutDefault.tsx +6 -1
- package/LayoutParts/DesktopNavBar.tsx +2 -0
- package/LayoutParts/Logo.tsx +20 -20
- package/LazyHydrate/LazyHydrate.tsx +72 -0
- package/LazyHydrate/index.ts +1 -0
- package/Navigation/components/NavigationFab.tsx +9 -7
- package/Navigation/components/NavigationOverlay.tsx +9 -1
- package/Navigation/components/NavigationProvider.tsx +18 -4
- package/Overlay/components/OverlayBase.tsx +1 -1
- package/Overlay/components/index.ts +1 -0
- package/Page/CssAndFramerMotionProvider.tsx +20 -18
- package/PageMeta/PageMeta.tsx +20 -13
- package/RenderType/filterNonNullableKeys.ts +11 -14
- package/Row/ColumnOne/variant/VariantMessage.tsx +12 -0
- package/Row/ColumnOne/variant/index.ts +1 -0
- package/Row/index.ts +1 -0
- package/SkipLink/SkipLink.tsx +38 -0
- package/Snackbar/DismissibleSnackbar.tsx +28 -0
- package/Snackbar/MessageSnackbarImpl.tsx +19 -2
- package/Styles/EmotionProvider.tsx +8 -8
- package/Styles/createEmotionCache.ts +14 -0
- package/Styles/withEmotionCache.tsx +26 -16
- package/TextInputNumber/TextInputNumber.tsx +7 -1
- package/Theme/MuiButton.ts +2 -2
- package/Theme/MuiChip.ts +2 -2
- package/Theme/MuiFab.ts +1 -1
- package/Theme/MuiSlider.ts +2 -2
- package/Theme/MuiSnackbar.ts +6 -4
- package/hooks/useDateTimeFormat.ts +3 -5
- package/hooks/useNumberFormat.ts +3 -5
- package/index.ts +4 -2
- package/package.json +16 -18
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useMotionValueValue } from '@graphcommerce/framer-utils'
|
|
2
|
-
import { Fab, styled, Box, SxProps, Theme, FabProps } from '@mui/material'
|
|
2
|
+
import { Fab, styled, Box, SxProps, Theme, FabProps, useTheme } from '@mui/material'
|
|
3
3
|
import { m } from 'framer-motion'
|
|
4
4
|
import { useRouter } from 'next/router'
|
|
5
5
|
import React, { useEffect } from 'react'
|
|
@@ -35,6 +35,8 @@ export function NavigationFab(props: NavigationFabProps) {
|
|
|
35
35
|
const scrollY = useScrollY()
|
|
36
36
|
const scrolled = useMotionValueValue(scrollY, (y) => y > 10)
|
|
37
37
|
|
|
38
|
+
const theme = useTheme()
|
|
39
|
+
|
|
38
40
|
useEffect(() => {
|
|
39
41
|
const clear = () => setOpenEl(null)
|
|
40
42
|
router.events.on('routeChangeStart', clear)
|
|
@@ -54,19 +56,19 @@ export function NavigationFab(props: NavigationFabProps) {
|
|
|
54
56
|
>
|
|
55
57
|
<MotionDiv
|
|
56
58
|
className={classes.wrapper}
|
|
57
|
-
sx={
|
|
59
|
+
sx={{
|
|
58
60
|
[theme.breakpoints.down('md')]: {
|
|
59
61
|
opacity: '1 !important',
|
|
60
62
|
transform: 'none !important',
|
|
61
63
|
},
|
|
62
|
-
}
|
|
64
|
+
}}
|
|
63
65
|
style={{ opacity }}
|
|
64
66
|
>
|
|
65
67
|
<Fab
|
|
66
68
|
color='inherit'
|
|
67
69
|
aria-label='Open Menu'
|
|
68
70
|
size='responsive'
|
|
69
|
-
sx={
|
|
71
|
+
sx={{
|
|
70
72
|
boxShadow: 'none',
|
|
71
73
|
'&:hover, &:focus': {
|
|
72
74
|
boxShadow: 'none',
|
|
@@ -75,7 +77,7 @@ export function NavigationFab(props: NavigationFabProps) {
|
|
|
75
77
|
background: theme.palette.text.primary,
|
|
76
78
|
pointerEvents: 'all',
|
|
77
79
|
color: theme.palette.background.paper,
|
|
78
|
-
}
|
|
80
|
+
}}
|
|
79
81
|
className={classes.fab}
|
|
80
82
|
{...fabProps}
|
|
81
83
|
>
|
|
@@ -87,7 +89,7 @@ export function NavigationFab(props: NavigationFabProps) {
|
|
|
87
89
|
)}
|
|
88
90
|
</Fab>
|
|
89
91
|
<MotionDiv
|
|
90
|
-
sx={
|
|
92
|
+
sx={{
|
|
91
93
|
pointerEvents: 'none',
|
|
92
94
|
borderRadius: '99em',
|
|
93
95
|
position: 'absolute',
|
|
@@ -96,7 +98,7 @@ export function NavigationFab(props: NavigationFabProps) {
|
|
|
96
98
|
boxShadow: theme.shadows[6],
|
|
97
99
|
top: 0,
|
|
98
100
|
[theme.breakpoints.down('md')]: { opacity: '1 !important' },
|
|
99
|
-
}
|
|
101
|
+
}}
|
|
100
102
|
className={classes.shadow}
|
|
101
103
|
style={{ opacity: shadowOpacity }}
|
|
102
104
|
/>
|
|
@@ -2,7 +2,7 @@ import { useMotionValueValue, useMotionSelector, dvw } from '@graphcommerce/fram
|
|
|
2
2
|
import { i18n } from '@lingui/core'
|
|
3
3
|
import { useTheme, Box, Fab, SxProps, Theme, useEventCallback, styled } from '@mui/material'
|
|
4
4
|
import { m } from 'framer-motion'
|
|
5
|
-
import React, { useEffect } from 'react'
|
|
5
|
+
import React, { useEffect, useRef } from 'react'
|
|
6
6
|
import type { LiteralUnion } from 'type-fest'
|
|
7
7
|
import { IconSvg, useIconSvgSize } from '../../IconSvg'
|
|
8
8
|
import { LayoutHeaderContent } from '../../Layout/components/LayoutHeaderContent'
|
|
@@ -71,6 +71,8 @@ export const NavigationOverlay = React.memo((props: NavigationOverlayProps) => {
|
|
|
71
71
|
} else selection.set([])
|
|
72
72
|
})
|
|
73
73
|
|
|
74
|
+
const a11yFocusRef = useRef<HTMLButtonElement | null>(null)
|
|
75
|
+
|
|
74
76
|
const selectedLevel = useMotionValueValue(selection, (s) => (s === false ? -1 : s.length))
|
|
75
77
|
const selectionValue = useMotionValueValue(selection, (s) => (s ? s.join('') : s))
|
|
76
78
|
const activeAndNotClosing = useMotionSelector([selection, closing], ([s, c]) =>
|
|
@@ -79,6 +81,10 @@ export const NavigationOverlay = React.memo((props: NavigationOverlayProps) => {
|
|
|
79
81
|
|
|
80
82
|
useEffect(() => {
|
|
81
83
|
animating.set(true)
|
|
84
|
+
|
|
85
|
+
if (activeAndNotClosing) {
|
|
86
|
+
a11yFocusRef.current?.focus()
|
|
87
|
+
}
|
|
82
88
|
}, [activeAndNotClosing, animating])
|
|
83
89
|
|
|
84
90
|
const afterClose = useEventCallback(() => {
|
|
@@ -161,6 +167,7 @@ export const NavigationOverlay = React.memo((props: NavigationOverlayProps) => {
|
|
|
161
167
|
sx={{ boxShadow: 'none', my: fabMarginY }}
|
|
162
168
|
size='responsive'
|
|
163
169
|
aria-label={i18n._(/* i18n */ 'Close')}
|
|
170
|
+
ref={a11yFocusRef}
|
|
164
171
|
>
|
|
165
172
|
<IconSvg src={iconClose} size='large' aria-hidden />
|
|
166
173
|
</Fab>
|
|
@@ -178,6 +185,7 @@ export const NavigationOverlay = React.memo((props: NavigationOverlayProps) => {
|
|
|
178
185
|
(theme) => ({
|
|
179
186
|
display: 'grid',
|
|
180
187
|
alignItems: !stretchColumns ? 'start' : undefined,
|
|
188
|
+
justifyContent: 'end',
|
|
181
189
|
[theme.breakpoints.down('md')]: {
|
|
182
190
|
width:
|
|
183
191
|
sizeSm !== 'floating'
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { MotionConfig, useMotionValue } from 'framer-motion'
|
|
1
|
+
import { MotionConfig, useMotionValue, useTransform } from 'framer-motion'
|
|
2
2
|
import React, { useMemo } from 'react'
|
|
3
3
|
import { isElement } from 'react-is'
|
|
4
|
+
import { LazyHydrate } from '../../LazyHydrate'
|
|
5
|
+
import { nonNullable } from '../../RenderType/nonNullable'
|
|
4
6
|
import {
|
|
5
7
|
NavigationNode,
|
|
6
8
|
NavigationContextType,
|
|
@@ -9,8 +11,9 @@ import {
|
|
|
9
11
|
NavigationNodeType,
|
|
10
12
|
NavigationNodeComponent,
|
|
11
13
|
} from '../hooks/useNavigation'
|
|
14
|
+
import { useMotionValueValue } from '@graphcommerce/framer-utils'
|
|
12
15
|
|
|
13
|
-
export type
|
|
16
|
+
export type NavigationProviderBaseProps = {
|
|
14
17
|
items: (NavigationNode | React.ReactElement)[]
|
|
15
18
|
hideRootOnNavigate?: boolean
|
|
16
19
|
closeAfterNavigate?: boolean
|
|
@@ -20,9 +23,9 @@ export type NavigationProviderProps = {
|
|
|
20
23
|
serverRenderDepth?: number
|
|
21
24
|
}
|
|
22
25
|
|
|
23
|
-
|
|
26
|
+
export type NavigationProviderProps = NavigationProviderBaseProps & { hold?: boolean }
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
const NavigationProviderBase = React.memo<NavigationProviderBaseProps>((props) => {
|
|
26
29
|
const {
|
|
27
30
|
items,
|
|
28
31
|
hideRootOnNavigate = true,
|
|
@@ -73,3 +76,14 @@ export const NavigationProvider = React.memo<NavigationProviderProps>((props) =>
|
|
|
73
76
|
</MotionConfig>
|
|
74
77
|
)
|
|
75
78
|
})
|
|
79
|
+
|
|
80
|
+
export function NavigationProvider(props: NavigationProviderProps) {
|
|
81
|
+
const { selection } = props
|
|
82
|
+
const hydrateManually = useMotionValueValue(selection, (s) => s !== false)
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<LazyHydrate hydrated={hydrateManually}>
|
|
86
|
+
<NavigationProviderBase {...props} />
|
|
87
|
+
</LazyHydrate>
|
|
88
|
+
)
|
|
89
|
+
}
|
|
@@ -311,7 +311,7 @@ export function OverlayBase(incomingProps: LayoutOverlayBaseProps) {
|
|
|
311
311
|
const handleEscape = (e: KeyboardEvent | Event) => {
|
|
312
312
|
if (active && (e as KeyboardEvent)?.key === 'Escape') closeOverlay()
|
|
313
313
|
}
|
|
314
|
-
useDomEvent(windowRef, '
|
|
314
|
+
useDomEvent(windowRef, 'keydown', handleEscape, { passive: true })
|
|
315
315
|
|
|
316
316
|
const dragging = useMotionValue(false)
|
|
317
317
|
const scrollerElementRef = scrollerRef as React.RefObject<HTMLElement>
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { GlobalStyles } from '@mui/material'
|
|
2
2
|
import { LazyMotion } from 'framer-motion'
|
|
3
|
+
import { EmotionProvider, EmotionProviderProps } from '../Styles/EmotionProvider'
|
|
3
4
|
|
|
4
|
-
export type
|
|
5
|
-
children: React.ReactNode
|
|
6
|
-
}
|
|
5
|
+
export type CssAndFramerMotionProviderProps = EmotionProviderProps
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* For [@emotion/core](https://emotion.sh/docs/introduction) and
|
|
@@ -12,22 +11,25 @@ export type GraphCommerceProviderProps = {
|
|
|
12
11
|
* - Wrapps the app to lazily load framer-motion.
|
|
13
12
|
* - Wrapps the app to have Emotion CSS styles
|
|
14
13
|
*/
|
|
15
|
-
export function CssAndFramerMotionProvider(
|
|
14
|
+
export function CssAndFramerMotionProvider(props: CssAndFramerMotionProviderProps) {
|
|
15
|
+
const { children, emotionCache } = props
|
|
16
16
|
return (
|
|
17
|
-
<
|
|
18
|
-
{
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
'
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
'
|
|
26
|
-
|
|
17
|
+
<EmotionProvider emotionCache={emotionCache}>
|
|
18
|
+
<LazyMotion features={async () => (await import('./framerFeatures')).default} strict>
|
|
19
|
+
{children}
|
|
20
|
+
<GlobalStyles
|
|
21
|
+
styles={{
|
|
22
|
+
':root': {
|
|
23
|
+
'--client-size-y': '100vh',
|
|
24
|
+
'--client-size-x': '100vw',
|
|
25
|
+
'@supports(height: 100dvh)': {
|
|
26
|
+
'--client-size-y': '100dvh',
|
|
27
|
+
'--client-size-x': '100dvw',
|
|
28
|
+
},
|
|
27
29
|
},
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
</
|
|
30
|
+
}}
|
|
31
|
+
/>
|
|
32
|
+
</LazyMotion>
|
|
33
|
+
</EmotionProvider>
|
|
32
34
|
)
|
|
33
35
|
}
|
package/PageMeta/PageMeta.tsx
CHANGED
|
@@ -2,8 +2,8 @@ import { usePageContext } from '@graphcommerce/framer-next-pages'
|
|
|
2
2
|
import { addBasePath } from 'next/dist/client/add-base-path'
|
|
3
3
|
import { addLocale } from 'next/dist/client/add-locale'
|
|
4
4
|
import { getDomainLocale } from 'next/dist/client/get-domain-locale'
|
|
5
|
+
import { resolveHref } from 'next/dist/client/resolve-href'
|
|
5
6
|
import { NextRouter } from 'next/dist/shared/lib/router/router'
|
|
6
|
-
import { resolveHref } from 'next/dist/shared/lib/router/utils/resolve-href'
|
|
7
7
|
import Head from 'next/head'
|
|
8
8
|
import { useRouter } from 'next/router'
|
|
9
9
|
import type {} from '@graphcommerce/next-config'
|
|
@@ -60,18 +60,25 @@ export function canonicalize(router: PartialNextRouter, incoming?: Canonical) {
|
|
|
60
60
|
const curLocale = router.locale
|
|
61
61
|
|
|
62
62
|
// Copied from here https://github.com/vercel/next.js/blob/213c42f446874d29d07fa2cca6e6b11fc9c3b711/packages/next/client/link.tsx#L512
|
|
63
|
-
const localeDomain =
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
63
|
+
const localeDomain = getDomainLocale(
|
|
64
|
+
as,
|
|
65
|
+
curLocale,
|
|
66
|
+
router && router.locales,
|
|
67
|
+
router.domainLocales,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
if (localeDomain) {
|
|
71
|
+
canonical = localeDomain
|
|
72
|
+
} else {
|
|
73
|
+
href = addBasePath(addLocale(as, curLocale, router.defaultLocale))
|
|
74
|
+
|
|
75
|
+
let siteUrl =
|
|
76
|
+
storefrontConfig(router.locale)?.canonicalBaseUrl ||
|
|
77
|
+
import.meta.graphCommerce.canonicalBaseUrl
|
|
78
|
+
if (siteUrl.endsWith('/')) siteUrl = siteUrl.slice(0, -1)
|
|
79
|
+
|
|
80
|
+
canonical = `${siteUrl}${href}`
|
|
81
|
+
}
|
|
75
82
|
}
|
|
76
83
|
|
|
77
84
|
if (!canonical.startsWith('http')) {
|
|
@@ -1,26 +1,23 @@
|
|
|
1
|
-
import type { OptionalKeysOf
|
|
1
|
+
import type { OptionalKeysOf } from 'type-fest'
|
|
2
2
|
|
|
3
|
-
export type RequiredKeys<
|
|
4
|
-
T
|
|
5
|
-
Keys
|
|
6
|
-
>
|
|
7
|
-
Omit<T, Keys> & {
|
|
8
|
-
[K in Keys]: NonNullable<T[K]>
|
|
9
|
-
}
|
|
10
|
-
>
|
|
3
|
+
export type RequiredKeys<T extends Record<string, unknown>, Keys extends OptionalKeysOf<T>> = Omit<
|
|
4
|
+
T,
|
|
5
|
+
Keys
|
|
6
|
+
> & { [K in Keys]: NonNullable<T[K]> }
|
|
11
7
|
|
|
12
8
|
export function filterNonNullableKeys<
|
|
13
9
|
T extends Record<string, unknown>,
|
|
14
10
|
Keys extends OptionalKeysOf<T>,
|
|
15
|
-
>(
|
|
11
|
+
>(
|
|
12
|
+
items: (T | null | undefined)[] | null | undefined,
|
|
13
|
+
values: Keys[] = [],
|
|
14
|
+
): RequiredKeys<T, Keys>[] {
|
|
16
15
|
if (!items) return []
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
return items.filter(
|
|
19
18
|
(item) =>
|
|
20
19
|
item !== null &&
|
|
21
20
|
typeof item !== 'undefined' &&
|
|
22
21
|
values.every((v) => item?.[v] !== null && typeof item?.[v] !== 'undefined'),
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
return result as RequiredKeys<T, Keys>[]
|
|
22
|
+
) as RequiredKeys<T, Keys>[]
|
|
26
23
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DismissibleSnackbar,
|
|
3
|
+
DismissibleSnackbarProps,
|
|
4
|
+
} from '../../../Snackbar/DismissibleSnackbar'
|
|
5
|
+
|
|
6
|
+
export type VariantMessageProps = DismissibleSnackbarProps
|
|
7
|
+
|
|
8
|
+
export function VariantMessage(props: VariantMessageProps) {
|
|
9
|
+
const { ...rest } = props
|
|
10
|
+
|
|
11
|
+
return <DismissibleSnackbar variant='pill' severity='info' disableBackdropClick {...rest} />
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './VariantMessage'
|
package/Row/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from './Row'
|
|
2
2
|
export * from './ButtonLinkList'
|
|
3
3
|
export * from './ColumnOne/ColumnOne'
|
|
4
|
+
export * from './ColumnOne/variant'
|
|
4
5
|
export * from './ColumnOneBoxed/ColumnOneBoxed'
|
|
5
6
|
export * from './ColumnOneCentered/ColumnOneCentered'
|
|
6
7
|
export * from './ColumnThree/ColumnThree'
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Trans } from '@lingui/react'
|
|
2
|
+
import { Link } from '@mui/material'
|
|
3
|
+
|
|
4
|
+
export function SkipLink() {
|
|
5
|
+
const setFocus = (e) => {
|
|
6
|
+
e.preventDefault()
|
|
7
|
+
globalThis.document.querySelector<HTMLDivElement>('#skip-nav')?.focus()
|
|
8
|
+
globalThis.document.querySelector<HTMLDivElement>('#skip-nav')?.scrollIntoView()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<Link
|
|
13
|
+
href='#skip-nav'
|
|
14
|
+
tabIndex={0}
|
|
15
|
+
onClick={setFocus}
|
|
16
|
+
onKeyDown={(e) => {
|
|
17
|
+
if (e.key === 'Enter') {
|
|
18
|
+
setFocus(e)
|
|
19
|
+
}
|
|
20
|
+
}}
|
|
21
|
+
sx={(theme) => ({
|
|
22
|
+
position: 'absolute',
|
|
23
|
+
top: theme.page.vertical,
|
|
24
|
+
zIndex: '-1',
|
|
25
|
+
marginLeft: theme.page.horizontal,
|
|
26
|
+
padding: theme.spacings.xxs,
|
|
27
|
+
backgroundColor: theme.palette.background.paper,
|
|
28
|
+
border: theme.palette.text.primary,
|
|
29
|
+
borderRadius: theme.shape.borderRadius,
|
|
30
|
+
'&:focus': {
|
|
31
|
+
zIndex: 9999,
|
|
32
|
+
},
|
|
33
|
+
})}
|
|
34
|
+
>
|
|
35
|
+
<Trans id='Skip to main content' />
|
|
36
|
+
</Link>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react'
|
|
2
|
+
import { MessageSnackbar } from './MessageSnackbar'
|
|
3
|
+
import { MessageSnackbarProps } from './MessageSnackbarImpl'
|
|
4
|
+
|
|
5
|
+
export type DismissibleSnackbarProps = MessageSnackbarProps & {
|
|
6
|
+
id: string
|
|
7
|
+
storageType?: 'localStorage' | 'sessionStorage'
|
|
8
|
+
}
|
|
9
|
+
export function DismissibleSnackbar(props: DismissibleSnackbarProps) {
|
|
10
|
+
const { storageType = 'localStorage', id, onClose, ...rest } = props
|
|
11
|
+
const messageId = `DismissibleSnackbar_${id}`
|
|
12
|
+
const [open, setOpen] = useState(false)
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
setOpen(!globalThis[storageType]?.getItem(messageId))
|
|
16
|
+
}, [messageId, storageType])
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<MessageSnackbar
|
|
20
|
+
{...rest}
|
|
21
|
+
open={open}
|
|
22
|
+
onClose={() => {
|
|
23
|
+
globalThis[storageType]?.setItem(messageId, `${Date.now()}`)
|
|
24
|
+
onClose?.()
|
|
25
|
+
}}
|
|
26
|
+
/>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
@@ -14,6 +14,7 @@ import React, { useEffect, useState } from 'react'
|
|
|
14
14
|
import { IconSvg } from '../IconSvg'
|
|
15
15
|
import { extendableComponent, breakpointVal } from '../Styles'
|
|
16
16
|
import { iconClose, iconCheckmark, iconSadFace } from '../icons'
|
|
17
|
+
import iconInfo from '../icons/info.svg'
|
|
17
18
|
|
|
18
19
|
type Size = 'normal' | 'wide'
|
|
19
20
|
type Variant = 'contained' | 'pill'
|
|
@@ -34,6 +35,10 @@ type OwnerState = {
|
|
|
34
35
|
size?: Size
|
|
35
36
|
severity?: 'success' | 'info' | 'warning' | 'error'
|
|
36
37
|
variant?: Variant
|
|
38
|
+
/**
|
|
39
|
+
* Setting this to true allows interaction with the rest of the page without closing the Snackbar
|
|
40
|
+
*/
|
|
41
|
+
disableBackdropClick?: boolean
|
|
37
42
|
}
|
|
38
43
|
|
|
39
44
|
const name = 'MessageSnackbarImpl' as const
|
|
@@ -56,6 +61,7 @@ export default function MessageSnackbarImpl(props: MessageSnackbarProps) {
|
|
|
56
61
|
onClose,
|
|
57
62
|
severity = 'info',
|
|
58
63
|
sx,
|
|
64
|
+
disableBackdropClick,
|
|
59
65
|
...snackbarProps
|
|
60
66
|
} = props
|
|
61
67
|
|
|
@@ -65,7 +71,11 @@ export default function MessageSnackbarImpl(props: MessageSnackbarProps) {
|
|
|
65
71
|
setShowSnackbar(!!open)
|
|
66
72
|
}, [open])
|
|
67
73
|
|
|
68
|
-
const hideSnackbar = () => {
|
|
74
|
+
const hideSnackbar = (event: React.SyntheticEvent | Event, reason?: string) => {
|
|
75
|
+
if (disableBackdropClick && reason === 'clickaway') {
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
|
|
69
79
|
setShowSnackbar(false)
|
|
70
80
|
onClose?.()
|
|
71
81
|
}
|
|
@@ -80,6 +90,7 @@ export default function MessageSnackbarImpl(props: MessageSnackbarProps) {
|
|
|
80
90
|
}
|
|
81
91
|
|
|
82
92
|
let icon = iconCheckmark
|
|
93
|
+
if (severity === 'info') icon = iconInfo
|
|
83
94
|
if (severity === 'error') icon = iconSadFace
|
|
84
95
|
|
|
85
96
|
return (
|
|
@@ -91,7 +102,13 @@ export default function MessageSnackbarImpl(props: MessageSnackbarProps) {
|
|
|
91
102
|
open={showSnackbar}
|
|
92
103
|
autoHideDuration={autoHide ? 5000 : null}
|
|
93
104
|
className={classes.root}
|
|
94
|
-
sx={
|
|
105
|
+
sx={[
|
|
106
|
+
{
|
|
107
|
+
pointerEvents: 'none',
|
|
108
|
+
'& > *': { pointerEvents: 'auto' },
|
|
109
|
+
},
|
|
110
|
+
...(Array.isArray(sx) ? sx : [sx]),
|
|
111
|
+
]}
|
|
95
112
|
onClose={hideSnackbar}
|
|
96
113
|
>
|
|
97
114
|
<SnackbarContent
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import createCache from '@emotion/cache'
|
|
2
1
|
import type { EmotionCache } from '@emotion/cache'
|
|
3
2
|
import { CacheProvider } from '@emotion/react'
|
|
3
|
+
import { createEmotionCache } from './createEmotionCache'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
return muiCache
|
|
9
|
-
}
|
|
5
|
+
export type EmotionProviderProps = { children?: React.ReactNode; emotionCache?: EmotionCache }
|
|
6
|
+
|
|
7
|
+
const clientSideEmotionCache = createEmotionCache()
|
|
10
8
|
|
|
11
9
|
/** Provider that is supposed to be used in your `pages/_app.tsx` */
|
|
12
|
-
export function EmotionProvider(
|
|
13
|
-
|
|
10
|
+
export function EmotionProvider(props: EmotionProviderProps) {
|
|
11
|
+
const { children, emotionCache = clientSideEmotionCache } = props
|
|
12
|
+
|
|
13
|
+
return <CacheProvider value={emotionCache}>{children}</CacheProvider>
|
|
14
14
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import createCache from '@emotion/cache'
|
|
2
|
+
|
|
3
|
+
export const createEmotionCache = () => {
|
|
4
|
+
let insertionPoint: HTMLElement | undefined
|
|
5
|
+
|
|
6
|
+
if (typeof window !== 'undefined') {
|
|
7
|
+
const emotionInsertionPoint = document.querySelector<HTMLMetaElement>(
|
|
8
|
+
'meta[name="emotion-insertion-point"]',
|
|
9
|
+
)
|
|
10
|
+
insertionPoint = emotionInsertionPoint ?? undefined
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return createCache({ key: 'mui-style', insertionPoint })
|
|
14
|
+
}
|
|
@@ -1,36 +1,46 @@
|
|
|
1
1
|
import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'
|
|
2
2
|
import createEmotionServer from '@emotion/server/create-instance'
|
|
3
3
|
// eslint-disable-next-line @next/next/no-document-import-in-page
|
|
4
|
+
import { AppType } from 'next/app'
|
|
4
5
|
import type NextDocument from 'next/document'
|
|
5
6
|
// eslint-disable-next-line @next/next/no-document-import-in-page
|
|
6
7
|
import type { DocumentContext, DocumentInitialProps } from 'next/document'
|
|
7
|
-
import {
|
|
8
|
+
import { EmotionProviderProps } from './EmotionProvider'
|
|
9
|
+
import { createEmotionCache } from './createEmotionCache'
|
|
8
10
|
|
|
9
11
|
export type EmotionCacheProps = { emotionStyleTags: EmotionJSX.Element[] }
|
|
10
12
|
|
|
11
13
|
export function withEmotionCache(Document: typeof NextDocument): typeof NextDocument {
|
|
12
14
|
return class DocumentWithEmotionCache extends Document {
|
|
13
15
|
static async getInitialProps(ctx: DocumentContext) {
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
+
const cache = createEmotionCache()
|
|
17
|
+
const emotionServer = createEmotionServer(cache)
|
|
18
|
+
|
|
19
|
+
const originalRenderPage = ctx.renderPage
|
|
20
|
+
ctx.renderPage = () =>
|
|
21
|
+
originalRenderPage({
|
|
22
|
+
enhanceApp:
|
|
23
|
+
(App: React.ComponentType<React.ComponentProps<AppType> & EmotionProviderProps>) =>
|
|
24
|
+
(props) => <App emotionCache={cache} {...props} />,
|
|
25
|
+
})
|
|
16
26
|
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
const initialProps = await Document.getInitialProps(ctx)
|
|
28
|
+
// This is important. It prevents Emotion to render invalid HTML.
|
|
29
|
+
// See https://github.com/mui/material-ui/issues/26561#issuecomment-855286153
|
|
30
|
+
const emotionStyles = emotionServer.extractCriticalToChunks(initialProps.html)
|
|
31
|
+
const emotionStyleTags = emotionStyles.styles.map((style) => (
|
|
32
|
+
<style
|
|
33
|
+
data-emotion={`${style.key} ${style.ids.join(' ')}`}
|
|
34
|
+
key={style.key}
|
|
35
|
+
// eslint-disable-next-line react/no-danger
|
|
36
|
+
dangerouslySetInnerHTML={{ __html: style.css }}
|
|
37
|
+
/>
|
|
38
|
+
))
|
|
28
39
|
|
|
29
|
-
|
|
40
|
+
return {
|
|
30
41
|
...initialProps,
|
|
31
42
|
emotionStyleTags,
|
|
32
43
|
}
|
|
33
|
-
return props
|
|
34
44
|
}
|
|
35
45
|
}
|
|
36
46
|
}
|
|
@@ -32,6 +32,9 @@ const name = 'TextInputNumber' as const
|
|
|
32
32
|
const parts = ['quantity', 'quantityInput', 'button'] as const
|
|
33
33
|
const { withState } = extendableComponent<OwnerState, typeof name, typeof parts>(name, parts)
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* @deprecated Please us NumberFieldElement
|
|
37
|
+
*/
|
|
35
38
|
export function TextInputNumber(props: TextInputNumberProps) {
|
|
36
39
|
const {
|
|
37
40
|
DownProps = {},
|
|
@@ -102,6 +105,9 @@ export function TextInputNumber(props: TextInputNumberProps) {
|
|
|
102
105
|
width: responsiveVal(90, 120),
|
|
103
106
|
},
|
|
104
107
|
{
|
|
108
|
+
'& input[type=number]': {
|
|
109
|
+
MozAppearance: 'textfield',
|
|
110
|
+
},
|
|
105
111
|
'& .MuiOutlinedInput-root': {
|
|
106
112
|
px: '3px',
|
|
107
113
|
display: 'grid',
|
|
@@ -159,8 +165,8 @@ export function TextInputNumber(props: TextInputNumberProps) {
|
|
|
159
165
|
updateDisabled(e.target)
|
|
160
166
|
}}
|
|
161
167
|
inputProps={{
|
|
162
|
-
...inputProps,
|
|
163
168
|
'aria-label': i18n._(/* i18n */ 'Number'),
|
|
169
|
+
...inputProps,
|
|
164
170
|
sx: [
|
|
165
171
|
{
|
|
166
172
|
typography: 'body1',
|
package/Theme/MuiButton.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ComponentsVariants } from '@mui/material'
|
|
1
|
+
import { ComponentsVariants, Theme } from '@mui/material'
|
|
2
2
|
import { responsiveVal } from '../Styles/responsiveVal'
|
|
3
3
|
|
|
4
4
|
declare module '@mui/material/Button/Button' {
|
|
@@ -8,7 +8,7 @@ declare module '@mui/material/Button/Button' {
|
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
type ButtonVariants = NonNullable<ComponentsVariants['MuiButton']>
|
|
11
|
+
type ButtonVariants = NonNullable<ComponentsVariants<Theme>['MuiButton']>
|
|
12
12
|
|
|
13
13
|
export const MuiButtonResponsive: ButtonVariants = [
|
|
14
14
|
{
|
package/Theme/MuiChip.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ComponentsVariants, darken } from '@mui/material'
|
|
1
|
+
import { ComponentsVariants, Theme, darken } from '@mui/material'
|
|
2
2
|
import { responsiveVal } from '../Styles'
|
|
3
3
|
|
|
4
4
|
declare module '@mui/material/Chip/Chip' {
|
|
@@ -10,7 +10,7 @@ declare module '@mui/material/Chip/Chip' {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
type ChipVariants = NonNullable<ComponentsVariants['MuiChip']>
|
|
13
|
+
type ChipVariants = NonNullable<ComponentsVariants<Theme>['MuiChip']>
|
|
14
14
|
|
|
15
15
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
16
16
|
export const MuiChip: ChipVariants = [
|
package/Theme/MuiFab.ts
CHANGED
package/Theme/MuiSlider.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { ComponentsVariants } from '@mui/material'
|
|
1
|
+
import { ComponentsVariants, Theme } from '@mui/material'
|
|
2
2
|
|
|
3
3
|
declare module '@mui/material/Slider/Slider' {
|
|
4
4
|
interface SliderPropsSizeOverrides {
|
|
5
5
|
large: true
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
|
-
type SliderVariants = NonNullable<ComponentsVariants['MuiSlider']>
|
|
8
|
+
type SliderVariants = NonNullable<ComponentsVariants<Theme>['MuiSlider']>
|
|
9
9
|
|
|
10
10
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
11
11
|
export const MuiSlider: SliderVariants = [
|