Some checks failed
No response / noResponse (push) Has been cancelled
CI / Continuous releases (push) Has been cancelled
CI / test-dev (macos-latest) (push) Has been cancelled
CI / test-dev (ubuntu-latest) (push) Has been cancelled
CI / test-dev (windows-latest) (push) Has been cancelled
Maintenance / main (push) Has been cancelled
Scorecards supply-chain security / Scorecards analysis (push) Has been cancelled
CodeQL / Analyze (push) Has been cancelled
423 lines
14 KiB
JavaScript
423 lines
14 KiB
JavaScript
import 'docs/src/modules/components/bootstrap';
|
||
// --- Post bootstrap -----
|
||
import * as React from 'react';
|
||
import { loadCSS } from 'fg-loadcss';
|
||
import NextHead from 'next/head';
|
||
import PropTypes from 'prop-types';
|
||
import { useRouter } from 'next/router';
|
||
import { LicenseInfo } from '@mui/x-license';
|
||
import materialPkgJson from '@mui/material/package.json';
|
||
import joyPkgJson from '@mui/joy/package.json';
|
||
import systemPkgJson from '@mui/system/package.json';
|
||
import generalDocsPages from 'docs/data/docs/pages';
|
||
import docsInfraPages from 'docs/data/docs-infra/pages';
|
||
import materialPages from 'docs/data/material/pages';
|
||
import joyPages from 'docs/data/joy/pages';
|
||
import systemPages from 'docs/data/system/pages';
|
||
import PageContext from 'docs/src/modules/components/PageContext';
|
||
import GoogleAnalytics from 'docs/src/modules/components/GoogleAnalytics';
|
||
import { CodeCopyProvider } from '@mui/docs/CodeCopy';
|
||
import { ThemeProvider } from 'docs/src/modules/components/ThemeContext';
|
||
import { CodeVariantProvider } from 'docs/src/modules/utils/codeVariant';
|
||
import DocsStyledEngineProvider from 'docs/src/modules/utils/StyledEngineProvider';
|
||
import createEmotionCache from 'docs/src/createEmotionCache';
|
||
import findActivePage from 'docs/src/modules/utils/findActivePage';
|
||
import getProductInfoFromUrl from 'docs/src/modules/utils/getProductInfoFromUrl';
|
||
import { DocsProvider } from '@mui/docs/DocsProvider';
|
||
import { mapTranslations } from '@mui/docs/i18n';
|
||
import SvgMuiLogomark, {
|
||
muiSvgLogoString,
|
||
muiSvgWordmarkString,
|
||
} from 'docs/src/icons/SvgMuiLogomark';
|
||
import './global.css';
|
||
import '../public/static/components-gallery/base-theme.css';
|
||
import { Inter, Roboto } from 'next/font/google';
|
||
import localFont from 'next/font/local';
|
||
import * as config from '../config';
|
||
|
||
const inter = Inter({
|
||
weight: ['300', '400', '500', '600', '700'],
|
||
subsets: ['latin'],
|
||
});
|
||
|
||
const roboto = Roboto({
|
||
weight: ['300', '400', '500', '700'],
|
||
style: ['normal', 'italic'],
|
||
subsets: ['latin'],
|
||
});
|
||
|
||
const generalSans = localFont({
|
||
declarations: [{ prop: 'font-family', value: 'General Sans' }],
|
||
src: [
|
||
{ path: '../public/static/fonts/GeneralSans-Regular.woff2', weight: '400', style: 'normal' },
|
||
{ path: '../public/static/fonts/GeneralSans-Medium.woff2', weight: '500', style: 'normal' },
|
||
{ path: '../public/static/fonts/GeneralSans-Semibold.woff2', weight: '600', style: 'normal' },
|
||
{ path: '../public/static/fonts/GeneralSans-Bold.woff2', weight: '700', style: 'normal' },
|
||
],
|
||
});
|
||
|
||
const ibmPlexSans = localFont({
|
||
declarations: [{ prop: 'font-family', value: 'IBM Plex Sans' }],
|
||
src: [
|
||
{ path: '../public/static/fonts/IBMPlexSans-Regular.woff2', weight: '400', style: 'normal' },
|
||
{ path: '../public/static/fonts/IBMPlexSans-Medium.woff2', weight: '500', style: 'normal' },
|
||
{ path: '../public/static/fonts/IBMPlexSans-SemiBold.woff2', weight: '600', style: 'normal' },
|
||
{ path: '../public/static/fonts/IBMPlexSans-Bold.woff2', weight: '700', style: 'normal' },
|
||
],
|
||
});
|
||
|
||
export const fontClasses = `${inter.className} ${roboto.className} ${generalSans.className} ${ibmPlexSans.className}`;
|
||
|
||
// Remove the license warning from demonstration purposes
|
||
LicenseInfo.setLicenseKey(process.env.NEXT_PUBLIC_MUI_LICENSE);
|
||
|
||
// Client-side cache, shared for the whole session of the user in the browser.
|
||
const clientSideEmotionCache = createEmotionCache();
|
||
|
||
let reloadInterval;
|
||
|
||
// Avoid infinite loop when "Upload on reload" is set in the Chrome sw dev tools.
|
||
function lazyReload() {
|
||
clearInterval(reloadInterval);
|
||
reloadInterval = setInterval(() => {
|
||
if (document.hasFocus()) {
|
||
window.location.reload();
|
||
}
|
||
}, 100);
|
||
}
|
||
|
||
// Inspired by
|
||
// https://developers.google.com/web/tools/workbox/guides/advanced-recipes#offer_a_page_reload_for_users
|
||
function forcePageReload(registration) {
|
||
// console.log('already controlled?', Boolean(navigator.serviceWorker.controller));
|
||
|
||
if (!navigator.serviceWorker.controller) {
|
||
// The window client isn't currently controlled so it's a new service
|
||
// worker that will activate immediately.
|
||
return;
|
||
}
|
||
|
||
// console.log('registration waiting?', Boolean(registration.waiting));
|
||
if (registration.waiting) {
|
||
// SW is waiting to activate. Can occur if multiple clients open and
|
||
// one of the clients is refreshed.
|
||
registration.waiting.postMessage('skipWaiting');
|
||
return;
|
||
}
|
||
|
||
function listenInstalledStateChange() {
|
||
registration.installing.addEventListener('statechange', (event) => {
|
||
// console.log('statechange', event.target.state);
|
||
if (event.target.state === 'installed' && registration.waiting) {
|
||
// A new service worker is available, inform the user
|
||
registration.waiting.postMessage('skipWaiting');
|
||
} else if (event.target.state === 'activated') {
|
||
// Force the control of the page by the activated service worker.
|
||
lazyReload();
|
||
}
|
||
});
|
||
}
|
||
|
||
if (registration.installing) {
|
||
listenInstalledStateChange();
|
||
return;
|
||
}
|
||
|
||
// We are currently controlled so a new SW may be found...
|
||
// Add a listener in case a new SW is found,
|
||
registration.addEventListener('updatefound', listenInstalledStateChange);
|
||
}
|
||
|
||
async function registerServiceWorker() {
|
||
if (
|
||
'serviceWorker' in navigator &&
|
||
process.env.NODE_ENV === 'production' &&
|
||
window.location.host.includes('mui.com')
|
||
) {
|
||
// register() automatically attempts to refresh the sw.js.
|
||
const registration = await navigator.serviceWorker.register('/sw.js');
|
||
// Force the page reload for users.
|
||
forcePageReload(registration);
|
||
}
|
||
}
|
||
|
||
let dependenciesLoaded = false;
|
||
|
||
function loadDependencies() {
|
||
if (dependenciesLoaded) {
|
||
return;
|
||
}
|
||
|
||
dependenciesLoaded = true;
|
||
|
||
loadCSS(
|
||
'https://fonts.googleapis.com/icon?family=Material+Icons|Material+Icons+Two+Tone',
|
||
document.querySelector('#material-icon-font'),
|
||
);
|
||
}
|
||
|
||
if (typeof window !== 'undefined' && process.env.NODE_ENV === 'production') {
|
||
// eslint-disable-next-line no-console
|
||
console.log(
|
||
`%c
|
||
|
||
███╗ ███╗ ██╗ ██╗ ██████╗
|
||
████╗ ████║ ██║ ██║ ██╔═╝
|
||
██╔████╔██║ ██║ ██║ ██║
|
||
██║╚██╔╝██║ ██║ ██║ ██║
|
||
██║ ╚═╝ ██║ ╚██████╔╝ ██████╗
|
||
╚═╝ ╚═╝ ╚═════╝ ╚═════╝
|
||
|
||
Tip: you can access the documentation \`theme\` object directly in the console.
|
||
`,
|
||
'font-family:monospace;color:#1976d2;font-size:12px;',
|
||
);
|
||
}
|
||
function AppWrapper(props) {
|
||
const { children, emotionCache, pageProps } = props;
|
||
|
||
const router = useRouter();
|
||
// TODO move productId & productCategoryId resolution to page layout.
|
||
// We should use the productId field from the markdown and fallback to getProductInfoFromUrl()
|
||
// if not present
|
||
const { productId, productCategoryId } = getProductInfoFromUrl(router.asPath);
|
||
|
||
React.useEffect(() => {
|
||
loadDependencies();
|
||
registerServiceWorker();
|
||
|
||
// Remove the server-side injected CSS.
|
||
const jssStyles = document.querySelector('#jss-server-side');
|
||
if (jssStyles) {
|
||
jssStyles.parentElement.removeChild(jssStyles);
|
||
}
|
||
}, []);
|
||
|
||
const productIdentifier = React.useMemo(() => {
|
||
const languagePrefix = pageProps.userLanguage === 'en' ? '' : `/${pageProps.userLanguage}`;
|
||
|
||
if (productId === 'material-ui') {
|
||
return {
|
||
metadata: '',
|
||
name: 'Material UI',
|
||
logo: SvgMuiLogomark,
|
||
logoSvg: muiSvgLogoString,
|
||
wordmarkSvg: muiSvgWordmarkString,
|
||
versions: [
|
||
{ text: `v${materialPkgJson.version}`, current: true },
|
||
{
|
||
text: 'v6',
|
||
href: `https://v6.mui.com${languagePrefix}/material-ui/getting-started/`,
|
||
},
|
||
{
|
||
text: 'v5',
|
||
href: `https://v5.mui.com${languagePrefix}/getting-started/installation/`,
|
||
},
|
||
{
|
||
text: 'v4',
|
||
href: `https://v4.mui.com${languagePrefix}/getting-started/installation/`,
|
||
},
|
||
{
|
||
text: 'View all versions',
|
||
href: `https://mui.com${languagePrefix}/versions/`,
|
||
},
|
||
],
|
||
};
|
||
}
|
||
|
||
if (productId === 'joy-ui') {
|
||
return {
|
||
metadata: '',
|
||
name: 'Joy UI',
|
||
logo: SvgMuiLogomark,
|
||
logoSvg: muiSvgLogoString,
|
||
wordmarkSvg: muiSvgWordmarkString,
|
||
versions: [{ text: `v${joyPkgJson.version}`, current: true }],
|
||
};
|
||
}
|
||
|
||
if (productId === 'system') {
|
||
return {
|
||
metadata: '',
|
||
name: 'MUI System',
|
||
logo: SvgMuiLogomark,
|
||
logoSvg: muiSvgLogoString,
|
||
wordmarkSvg: muiSvgWordmarkString,
|
||
versions: [
|
||
{ text: `v${systemPkgJson.version}`, current: true },
|
||
{ text: 'v6', href: `https://v6.mui.com${languagePrefix}/system/getting-started/` },
|
||
{ text: 'v5', href: `https://v5.mui.com${languagePrefix}/system/getting-started/` },
|
||
{ text: 'v4', href: `https://v4.mui.com${languagePrefix}/system/basics/` },
|
||
{
|
||
text: 'View all versions',
|
||
href: `https://mui.com${languagePrefix}/versions/`,
|
||
},
|
||
],
|
||
};
|
||
}
|
||
|
||
if (productId === 'core') {
|
||
return {
|
||
metadata: '',
|
||
name: 'MUI Core',
|
||
logo: SvgMuiLogomark,
|
||
logoSvg: muiSvgLogoString,
|
||
wordmarkSvg: muiSvgWordmarkString,
|
||
versions: [
|
||
{ text: `v${materialPkgJson.version}`, current: true },
|
||
{
|
||
text: 'View all versions',
|
||
href: `https://mui.com${languagePrefix}/versions/`,
|
||
},
|
||
],
|
||
};
|
||
}
|
||
|
||
if (productId === 'docs-infra') {
|
||
return {
|
||
metadata: '',
|
||
name: 'Docs-infra',
|
||
logo: SvgMuiLogomark,
|
||
logoSvg: muiSvgLogoString,
|
||
wordmarkSvg: muiSvgWordmarkString,
|
||
versions: [
|
||
{
|
||
text: 'v0.0.0',
|
||
href: `https://mui.com${languagePrefix}/versions/`,
|
||
},
|
||
],
|
||
};
|
||
}
|
||
|
||
if (productId === 'docs') {
|
||
return {
|
||
metadata: '',
|
||
name: 'Home docs',
|
||
logo: SvgMuiLogomark,
|
||
logoSvg: muiSvgLogoString,
|
||
wordmarkSvg: muiSvgWordmarkString,
|
||
versions: [
|
||
{
|
||
text: 'v0.0.0',
|
||
href: `https://mui.com${languagePrefix}/versions/`,
|
||
},
|
||
],
|
||
};
|
||
}
|
||
|
||
return null;
|
||
}, [pageProps.userLanguage, productId]);
|
||
|
||
const pageContextValue = React.useMemo(() => {
|
||
let pages = generalDocsPages;
|
||
if (productId === 'material-ui') {
|
||
pages = materialPages;
|
||
} else if (productId === 'joy-ui') {
|
||
pages = joyPages;
|
||
} else if (productId === 'system') {
|
||
pages = systemPages;
|
||
} else if (productId === 'docs-infra') {
|
||
pages = docsInfraPages;
|
||
}
|
||
|
||
const { activePage, activePageParents } = findActivePage(pages, router.pathname);
|
||
|
||
return {
|
||
activePage,
|
||
activePageParents,
|
||
pages,
|
||
productIdentifier,
|
||
productId,
|
||
productCategoryId,
|
||
};
|
||
}, [productId, productCategoryId, productIdentifier, router.pathname]);
|
||
|
||
return (
|
||
<React.Fragment>
|
||
<NextHead>
|
||
<meta name="viewport" content="initial-scale=1, width=device-width" />
|
||
<meta name="mui:productId" content={productId} />
|
||
<meta name="mui:productCategoryId" content={productCategoryId} />
|
||
</NextHead>
|
||
<DocsProvider
|
||
config={config}
|
||
adConfig={{ GADisplayRatio: 0.1 }}
|
||
defaultUserLanguage={pageProps.userLanguage}
|
||
translations={pageProps.translations}
|
||
>
|
||
<CodeCopyProvider>
|
||
<CodeVariantProvider>
|
||
<PageContext.Provider value={pageContextValue}>
|
||
<ThemeProvider>
|
||
<DocsStyledEngineProvider cacheLtr={emotionCache}>
|
||
{children}
|
||
<GoogleAnalytics />
|
||
</DocsStyledEngineProvider>
|
||
</ThemeProvider>
|
||
</PageContext.Provider>
|
||
</CodeVariantProvider>
|
||
</CodeCopyProvider>
|
||
</DocsProvider>
|
||
</React.Fragment>
|
||
);
|
||
}
|
||
|
||
AppWrapper.propTypes = {
|
||
children: PropTypes.node.isRequired,
|
||
emotionCache: PropTypes.object.isRequired,
|
||
pageProps: PropTypes.object.isRequired,
|
||
};
|
||
|
||
export default function MyApp(props) {
|
||
const { Component, emotionCache = clientSideEmotionCache, pageProps } = props;
|
||
const getLayout = Component.getLayout ?? ((page) => page);
|
||
|
||
return (
|
||
<AppWrapper emotionCache={emotionCache} pageProps={pageProps}>
|
||
{getLayout(<Component {...pageProps} />)}
|
||
</AppWrapper>
|
||
);
|
||
}
|
||
MyApp.propTypes = {
|
||
Component: PropTypes.elementType.isRequired,
|
||
emotionCache: PropTypes.object,
|
||
pageProps: PropTypes.object.isRequired,
|
||
};
|
||
|
||
MyApp.getInitialProps = async ({ ctx, Component }) => {
|
||
let pageProps = {};
|
||
|
||
const req = require.context('docs/translations', false, /\.\/translations.*\.json$/);
|
||
const translations = mapTranslations(req);
|
||
|
||
if (Component.getInitialProps) {
|
||
pageProps = await Component.getInitialProps(ctx);
|
||
}
|
||
|
||
return {
|
||
pageProps: {
|
||
userLanguage: ctx.query.userLanguage || 'en',
|
||
translations,
|
||
...pageProps,
|
||
},
|
||
};
|
||
};
|
||
|
||
// Track fraction of actual events to prevent exceeding event quota.
|
||
// Filter sessions instead of individual events so that we can track multiple metrics per device.
|
||
// See https://github.com/GoogleChromeLabs/web-vitals-report to use this data
|
||
const disableWebVitalsReporting = Math.random() > 0.0001;
|
||
export function reportWebVitals({ id, name, label, delta, value }) {
|
||
if (disableWebVitalsReporting) {
|
||
return;
|
||
}
|
||
|
||
window.gtag('event', name, {
|
||
value: delta,
|
||
metric_label: label === 'web-vital' ? 'Web Vitals' : 'Next.js custom metric',
|
||
metric_value: value,
|
||
metric_delta: delta,
|
||
metric_id: id, // id unique to current page load
|
||
});
|
||
}
|