diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json index f1f80be03d4c90..fa2d24b4522891 100644 --- a/.codesandbox/ci.json +++ b/.codesandbox/ci.json @@ -7,13 +7,17 @@ "packages/material-ui-styles", "packages/material-ui-system", "packages/material-ui-types", - "packages/material-ui-utils" + "packages/material-ui-utils", + "packages/material-ui-styled-engine", + "packages/material-ui-styled-engine-sc" ], "publishDirectory": { "@material-ui/core": "packages/material-ui/build", "@material-ui/icons": "packages/material-ui-icons/build", "@material-ui/lab": "packages/material-ui-lab/build", "@material-ui/styles": "packages/material-ui-styles/build", + "@material-ui/styled-engine": "packages/material-ui-styled-engine/build", + "@material-ui/styled-engine-sc": "packages/material-ui-styled-engine-sc/build", "@material-ui/system": "packages/material-ui-system/build", "@material-ui/types": "packages/material-ui-types", "@material-ui/utils": "packages/material-ui-utils/build" diff --git a/babel.config.js b/babel.config.js index 162d469804993a..30bfea34532466 100644 --- a/babel.config.js +++ b/babel.config.js @@ -27,6 +27,8 @@ const defaultAlias = { '@material-ui/docs': './packages/material-ui-docs/src', '@material-ui/icons': './packages/material-ui-icons/src', '@material-ui/lab': './packages/material-ui-lab/src', + '@material-ui/styled-engine': './packages/material-ui-styled-engine/src', + '@material-ui/styled-engine-sc': './packages/material-ui-styled-engine-sc/src', '@material-ui/styles': './packages/material-ui-styles/src', '@material-ui/system': './packages/material-ui-system/src', '@material-ui/utils': './packages/material-ui-utils/src', diff --git a/docs/babel.config.js b/docs/babel.config.js index 5b3c1a4a066b8c..1c3513f83bc45a 100644 --- a/docs/babel.config.js +++ b/docs/babel.config.js @@ -19,6 +19,10 @@ const alias = { '@material-ui/icons': '../packages/material-ui-icons/src', '@material-ui/lab': '../packages/material-ui-lab/src', '@material-ui/styles': '../packages/material-ui-styles/src', + '@material-ui/styled-engine-sc': '../packages/material-ui-styled-engine-sc/src', + // Swap the comments on the next two lines for using the styled-components as style engine + '@material-ui/styled-engine': '../packages/material-ui-styled-engine/src', + // '@material-ui/styled-engine': '../packages/material-ui-styled-engine-sc/src', '@material-ui/system': '../packages/material-ui-system/src', '@material-ui/utils': '../packages/material-ui-utils/src', docs: './', diff --git a/docs/next.config.js b/docs/next.config.js index c995a4bbd49be5..4efc976d33276f 100644 --- a/docs/next.config.js +++ b/docs/next.config.js @@ -117,6 +117,9 @@ module.exports = { '@material-ui/docs': '../packages/material-ui-docs/src', '@material-ui/icons': '../packages/material-ui-icons/src', '@material-ui/lab': '../packages/material-ui-lab/src', + '@material-ui/styled-engine': '../packages/material-ui-styled-engine/src', + '@material-ui/styled-engine-sc': + '../packages/material-ui-styled-engine-sc/src', '@material-ui/styles': '../packages/material-ui-styles/src', '@material-ui/system': '../packages/material-ui-system/src', '@material-ui/utils': '../packages/material-ui-utils/src', diff --git a/docs/package.json b/docs/package.json index 268c79afd6bf8d..e7a4c4cc76141f 100644 --- a/docs/package.json +++ b/docs/package.json @@ -22,6 +22,7 @@ "@babel/plugin-transform-object-assign": "^7.10.1", "@babel/runtime-corejs2": "^7.10.2", "@date-io/core": "^1.3.9", + "@emotion/cache": "^10.0.27", "@emotion/core": "^10.0.27", "@emotion/styled": "^10.0.27", "@fortawesome/fontawesome-svg-core": "^1.2.30", @@ -32,6 +33,8 @@ "@material-ui/icons": "^5.0.0-alpha.1", "@material-ui/lab": "^5.0.0-alpha.1", "@material-ui/pickers": "^4.0.0-alpha.11", + "@material-ui/styled-engine": "^5.0.0-alpha.1", + "@material-ui/styled-engine-sc": "^5.0.0-alpha.1", "@material-ui/styles": "^5.0.0-alpha.1", "@material-ui/system": "^5.0.0-alpha.1", "@material-ui/types": "^5.0.0", @@ -68,6 +71,8 @@ "date-fns": "^2.15.0", "docsearch.js": "^2.6.3", "doctrine": "^3.0.0", + "emotion-server": "^10.0.27", + "emotion-theming": "^10.0.27", "express": "^4.17.1", "fg-loadcss": "^2.0.1", "final-form": "^4.18.5", @@ -111,6 +116,7 @@ "redux-logger": "^3.0.6", "rimraf": "^3.0.0", "styled-components": "^5.0.0", + "stylis-plugin-rtl": "^1.0.0", "webfontloader": "^1.6.28", "webpack": "^4.41.0", "webpack-bundle-analyzer": "^3.5.1" diff --git a/docs/pages/_app.js b/docs/pages/_app.js index afb3aa4578fbdb..80d6e1c7acc951 100644 --- a/docs/pages/_app.js +++ b/docs/pages/_app.js @@ -8,7 +8,11 @@ import NextHead from 'next/head'; import PropTypes from 'prop-types'; import acceptLanguage from 'accept-language'; import { create } from 'jss'; -import rtl from 'jss-rtl'; +import jssRtl from 'jss-rtl'; +import { StyleSheetManager } from 'styled-components'; +import { CacheProvider } from '@emotion/core'; +import createCache from '@emotion/cache'; +import rtlPlugin from 'stylis-plugin-rtl'; import { useRouter } from 'next/router'; import { StylesProvider, jssPreset } from '@material-ui/styles'; import pages from 'docs/src/pages'; @@ -16,13 +20,14 @@ import initRedux from 'docs/src/modules/redux/initRedux'; import PageContext from 'docs/src/modules/components/PageContext'; import GoogleAnalytics from 'docs/src/modules/components/GoogleAnalytics'; import loadScript from 'docs/src/modules/utils/loadScript'; +import RtlContext from 'docs/src/modules/utils/RtlContext'; import { ThemeProvider } from 'docs/src/modules/components/ThemeContext'; import { pathnameToLanguage, getCookie } from 'docs/src/modules/utils/helpers'; import { ACTION_TYPES, CODE_VARIANTS } from 'docs/src/modules/constants'; // Configure JSS const jss = create({ - plugins: [...jssPreset().plugins, rtl()], + plugins: [...jssPreset().plugins, jssRtl()], insertionPoint: process.browser ? document.querySelector('#insertion-point-jss') : null, }); @@ -275,6 +280,17 @@ function findActivePage(currentPages, pathname) { return activePage; } +// Cache for the ltr version of the styles +const cacheLtr = createCache(); +cacheLtr.compat = true; + +// Cache for the rtl version of the styles +const cacheRtl = createCache({ + key: 'rtl', + stylisPlugins: [rtlPlugin], +}); +cacheRtl.compat = true; + function AppWrapper(props) { const { children, pageProps } = props; @@ -283,6 +299,9 @@ function AppWrapper(props) { initRedux({ options: { userLanguage: pageProps.userLanguage } }), ); + const [rtl, setRtl] = React.useState(false); + const rtlContextValue = { rtl, setRtl }; + React.useEffect(() => { loadDependencies(); registerServiceWorker(); @@ -311,11 +330,17 @@ function AppWrapper(props) { ))} - - - {children} - - + + + + + + {children} + + + + + diff --git a/docs/pages/_document.js b/docs/pages/_document.js index 84aa2b00839faa..0229e37934d88f 100644 --- a/docs/pages/_document.js +++ b/docs/pages/_document.js @@ -1,5 +1,7 @@ import React from 'react'; import { ServerStyleSheets } from '@material-ui/styles'; +import { ServerStyleSheet } from 'styled-components'; +import { extractCritical } from 'emotion-server'; import Document, { Html, Head, Main, NextScript } from 'next/document'; import { LANGUAGES_SSR } from 'docs/src/modules/constants'; import { pathnameToLanguage } from 'docs/src/modules/utils/helpers'; @@ -92,55 +94,78 @@ export default class MyDocument extends Document { } } +// `getInitialProps` belongs to `_document` (instead of `_app`), +// it's compatible with static-site generation (SSG). MyDocument.getInitialProps = async (ctx) => { // Resolution order // // On the server: - // 1. page.getInitialProps - // 2. document.getInitialProps - // 3. page.render - // 4. document.render + // 1. app.getInitialProps + // 2. page.getInitialProps + // 3. document.getInitialProps + // 4. app.render + // 5. page.render + // 6. document.render // // On the server with error: - // 2. document.getInitialProps + // 1. document.getInitialProps + // 2. app.render // 3. page.render // 4. document.render // // On the client - // 1. page.getInitialProps - // 3. page.render + // 1. app.getInitialProps + // 2. page.getInitialProps + // 3. app.render + // 4. page.render // Render app and page and get the context of the page with collected side effects. - const sheets = new ServerStyleSheets(); + const materialSheets = new ServerStyleSheets(); + const styledComponentsSheet = new ServerStyleSheet(); const originalRenderPage = ctx.renderPage; - ctx.renderPage = () => - originalRenderPage({ - enhanceApp: (App) => (props) => sheets.collect(), - }); + try { + ctx.renderPage = () => + originalRenderPage({ + enhanceApp: (App) => (props) => + styledComponentsSheet.collectStyles(materialSheets.collect()), + }); - const initialProps = await Document.getInitialProps(ctx); + const initialProps = await Document.getInitialProps(ctx); + const emotionStyles = extractCritical(initialProps.html); - let css = sheets.toString(); - // It might be undefined, e.g. after an error. - if (css && process.env.NODE_ENV === 'production') { - const result1 = await prefixer.process(css, { from: undefined }); - css = result1.css; - css = cleanCSS.minify(css).styles; - } + let css = materialSheets.toString(); + // It might be undefined, e.g. after an error. + if (css && process.env.NODE_ENV === 'production') { + const result1 = await prefixer.process(css, { from: undefined }); + css = result1.css; + css = cleanCSS.minify(css).styles; + } - return { - ...initialProps, - canonical: pathnameToLanguage(ctx.req.url).canonical, - userLanguage: ctx.query.userLanguage || 'en', - styles: [ - ...React.Children.toArray(initialProps.styles), -