diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json
index 6dae83fb6a85b5..78dff475afaed9 100644
--- a/.codesandbox/ci.json
+++ b/.codesandbox/ci.json
@@ -14,7 +14,8 @@
"packages/material-ui-utils",
"packages/material-ui-unstyled",
"packages/material-ui-styled-engine",
- "packages/material-ui-styled-engine-sc"
+ "packages/material-ui-styled-engine-sc",
+ "packages/material-ui-styled-engine-goober"
],
"publishDirectory": {
"@material-ui/codemod": "packages/material-ui-codemod/build",
@@ -24,6 +25,7 @@
"@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/styled-engine-goober": "packages/material-ui-styled-engine-goober/build",
"@material-ui/system": "packages/material-ui-system/build",
"@material-ui/private-theming": "packages/material-ui-private-theming/build",
"@material-ui/types": "packages/material-ui-types/build",
diff --git a/babel.config.js b/babel.config.js
index 7c3ba507ed0bee..09f50bfceb0fb3 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -15,6 +15,9 @@ const defaultAlias = {
'@material-ui/lab': resolveAliasPath('./packages/material-ui-lab/src'),
'@material-ui/styled-engine': resolveAliasPath('./packages/material-ui-styled-engine/src'),
'@material-ui/styled-engine-sc': resolveAliasPath('./packages/material-ui-styled-engine-sc/src'),
+ '@material-ui/styled-engine-goober': resolveAliasPath(
+ './packages/material-ui-styled-engine-goober/src',
+ ),
'@material-ui/styles': resolveAliasPath('./packages/material-ui-styles/src'),
'@material-ui/system': resolveAliasPath('./packages/material-ui-system/src'),
'@material-ui/private-theming': resolveAliasPath('./packages/material-ui-private-theming/src'),
diff --git a/docs/babel.config.js b/docs/babel.config.js
index c9e98edcca5209..843ba61d0debde 100644
--- a/docs/babel.config.js
+++ b/docs/babel.config.js
@@ -19,10 +19,10 @@ const alias = {
'@material-ui/icons': '../packages/material-ui-icons/lib',
'@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/src',
// '@material-ui/styled-engine': '../packages/material-ui-styled-engine-sc/src',
+ '@material-ui/styled-engine': '../packages/material-ui-styled-engine-goober/src',
'@material-ui/system': '../packages/material-ui-system/src',
'@material-ui/private-theming': '../packages/material-ui-private-theming/src',
'@material-ui/utils': '../packages/material-ui-utils/src',
diff --git a/docs/package.json b/docs/package.json
index 0a82208bcbee35..f6e26674f5a33b 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -37,6 +37,7 @@
"@material-ui/lab": "5.0.0-alpha.43",
"@material-ui/styled-engine": "5.0.0-beta.4",
"@material-ui/styled-engine-sc": "5.0.0-beta.1",
+ "@material-ui/styled-engine-goober": "5.0.0-beta.1",
"@material-ui/styles": "5.0.0-beta.4",
"@material-ui/system": "5.0.0-beta.4",
"@material-ui/types": "6.0.2",
@@ -77,6 +78,7 @@
"final-form": "^4.18.5",
"flexsearch": "^0.7.0",
"fs-extra": "^10.0.0",
+ "goober": "^2.0.0",
"json2mq": "^0.2.0",
"jss": "^10.0.3",
"jss-plugin-template": "^10.0.3",
diff --git a/docs/src/modules/components/AppNavDrawerItem.js b/docs/src/modules/components/AppNavDrawerItem.js
index 59d2ca85eb0359..943cd5e573b429 100644
--- a/docs/src/modules/components/AppNavDrawerItem.js
+++ b/docs/src/modules/components/AppNavDrawerItem.js
@@ -6,39 +6,36 @@ import ButtonBase from '@material-ui/core/ButtonBase';
import ArrowRightIcon from '@material-ui/icons/ArrowRight';
import Link from 'docs/src/modules/components/Link';
-const Item = styled('div', {
- shouldForwardProp:
- // disable `as` prop
- () => true,
-})(({ theme }) => {
- return {
- ...theme.typography.body2,
- display: 'flex',
- borderRadius: theme.shape.borderRadius,
- outline: 0,
- width: '100%',
- paddingTop: 8,
- paddingBottom: 8,
- justifyContent: 'flex-start',
- fontWeight: theme.typography.fontWeightMedium,
- transition: theme.transitions.create(['color', 'background-color'], {
- duration: theme.transitions.duration.shortest,
- }),
- '&:hover': {
- color: theme.palette.text.primary,
- backgroundColor: alpha(theme.palette.text.primary, theme.palette.action.hoverOpacity),
- },
- '&.Mui-focusVisible': {
- backgroundColor: theme.palette.action.focus,
- },
- [theme.breakpoints.up('md')]: {
- paddingTop: 6,
- paddingBottom: 6,
- },
- };
-});
+const Item = styled(({ component: Component = 'div', ...props }) => , {
+ // disable `as` prop
+ shouldForwardProp: () => true,
+})(({ theme }) => ({
+ ...theme.typography.body2,
+ display: 'flex',
+ borderRadius: theme.shape.borderRadius,
+ outline: 0,
+ width: '100%',
+ paddingTop: 8,
+ paddingBottom: 8,
+ justifyContent: 'flex-start',
+ fontWeight: theme.typography.fontWeightMedium,
+ transition: theme.transitions.create(['color', 'background-color'], {
+ duration: theme.transitions.duration.shortest,
+ }),
+ '&:hover': {
+ color: theme.palette.text.primary,
+ backgroundColor: alpha(theme.palette.text.primary, theme.palette.action.hoverOpacity),
+ },
+ '&.Mui-focusVisible': {
+ backgroundColor: theme.palette.action.focus,
+ },
+ [theme.breakpoints.up('md')]: {
+ paddingTop: 6,
+ paddingBottom: 6,
+ },
+}));
-const ItemLink = styled(Item.withComponent(Link), {
+const ItemLink = styled(Item, {
shouldForwardProp: (prop) => prop !== 'depth',
})(({ depth, theme }) => {
return {
@@ -78,7 +75,7 @@ const ItemButtonIcon = styled(ArrowRightIcon, {
};
});
-const ItemButton = styled(Item.withComponent(ButtonBase), {
+const ItemButton = styled(Item, {
shouldForwardProp: (prop) => prop !== 'depth',
})(({ depth, theme }) => {
return {
@@ -120,6 +117,7 @@ export default function AppNavDrawerItem(props) {
return (
=12.0.0"
+ }
+}
diff --git a/packages/material-ui-styled-engine-goober/src/GlobalStyles/GlobalStyles.ts b/packages/material-ui-styled-engine-goober/src/GlobalStyles/GlobalStyles.ts
new file mode 100644
index 00000000000000..34725b2535a337
--- /dev/null
+++ b/packages/material-ui-styled-engine-goober/src/GlobalStyles/GlobalStyles.ts
@@ -0,0 +1,29 @@
+import PropTypes from 'prop-types';
+import { deepmerge } from '@material-ui/utils';
+import { createGlobalStyles } from 'goober/global';
+
+function isEmpty(obj) {
+ return obj === undefined || obj === null || Object.keys(obj).length === 0;
+}
+
+const GlobalStyles = createGlobalStyles((props) => {
+ const { styles, defaultTheme = {} } = props;
+
+ if (typeof styles === 'function') {
+ const globalStyles = styles(isEmpty(props.theme) ? defaultTheme : props.theme);
+ const mergeStyles = Array.isArray(globalStyles)
+ ? globalStyles.reduce((acc, item) => deepmerge(acc, item), {})
+ : globalStyles;
+
+ return mergeStyles;
+ }
+
+ return styles;
+});
+
+GlobalStyles.propTypes = {
+ defaultTheme: PropTypes.object,
+ styles: PropTypes.oneOfType([PropTypes.string, PropTypes.object, PropTypes.func]),
+};
+
+export default GlobalStyles;
diff --git a/packages/material-ui-styled-engine-goober/src/GlobalStyles/index.ts b/packages/material-ui-styled-engine-goober/src/GlobalStyles/index.ts
new file mode 100644
index 00000000000000..a815f5c4a572b2
--- /dev/null
+++ b/packages/material-ui-styled-engine-goober/src/GlobalStyles/index.ts
@@ -0,0 +1,2 @@
+export { default } from './GlobalStyles';
+export * from './GlobalStyles';
diff --git a/packages/material-ui-styled-engine-goober/src/StyledEngineProvider/StyledEngineProvider.tsx b/packages/material-ui-styled-engine-goober/src/StyledEngineProvider/StyledEngineProvider.tsx
new file mode 100644
index 00000000000000..087e736373a426
--- /dev/null
+++ b/packages/material-ui-styled-engine-goober/src/StyledEngineProvider/StyledEngineProvider.tsx
@@ -0,0 +1,3 @@
+export default function StyledEngineProvider(props) {
+ return props.children;
+}
diff --git a/packages/material-ui-styled-engine-goober/src/StyledEngineProvider/index.ts b/packages/material-ui-styled-engine-goober/src/StyledEngineProvider/index.ts
new file mode 100644
index 00000000000000..7fdd272b28e6ca
--- /dev/null
+++ b/packages/material-ui-styled-engine-goober/src/StyledEngineProvider/index.ts
@@ -0,0 +1,2 @@
+export { default } from './StyledEngineProvider';
+export * from './StyledEngineProvider';
diff --git a/packages/material-ui-styled-engine-goober/src/index.tsx b/packages/material-ui-styled-engine-goober/src/index.tsx
new file mode 100644
index 00000000000000..7be9304407e14a
--- /dev/null
+++ b/packages/material-ui-styled-engine-goober/src/index.tsx
@@ -0,0 +1,83 @@
+import * as React from 'react';
+import { styled as styledGoober, setup } from 'goober';
+import unitless from '@emotion/unitless';
+import { prefix } from 'goober/prefixer';
+
+export const ThemeContext = React.createContext({});
+
+// TODO drop hard coded function
+function shouldForwardProp(prop: string) {
+ return prop !== 'styleProps' && prop !== 'theme' && prop !== 'sx' && prop !== 'as';
+}
+
+const useTheme = () => React.useContext(ThemeContext);
+
+function forwardProps(props: object) {
+ Object.keys(props).forEach((prop) => {
+ // Or any other conditions.
+ // This could also check if this is a dev build and not remove the props
+ if (!shouldForwardProp(prop)) {
+ // @ts-ignore
+ delete props[prop];
+ }
+ });
+}
+
+function isCustomProperty(property: string) {
+ // 45 is -
+ return property.charCodeAt(1) === 45;
+}
+
+function camelize(str: string) {
+ return str.replace(/-./g, (chunk) => chunk[1].toUpperCase());
+}
+
+function plugins(property: string, inValue: any) {
+ // Add default px unit when needed
+ let value = inValue;
+ const key = camelize(property);
+ if (
+ unitless[key] !== 1 &&
+ !isCustomProperty(property) &&
+ typeof value === 'number' &&
+ value !== 0
+ ) {
+ value = `${value}px`;
+ }
+
+ return prefix(property, value);
+}
+
+// @ts-expect-error Wrong type https://github.com/cristianbote/goober/pull/364
+setup(React.createElement, plugins, useTheme, forwardProps);
+
+// TODO hanle options
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+export default function styled(tag: any, options: any) {
+ const stylesFactory = styledGoober(tag, React.forwardRef);
+
+ return (...styles: any[]) => {
+ if (process.env.NODE_ENV !== 'production') {
+ const component = typeof tag === 'string' ? `"${tag}"` : 'component';
+ if (styles.length === 0) {
+ console.error(
+ [
+ `Material-UI: Seems like you called \`styled(${component})()\` without a \`style\` argument.`,
+ 'You must provide a `styles` argument: `styled("div")(styleYouForgotToPass)`.',
+ ].join('\n'),
+ );
+ } else if (styles.some((style) => style === undefined)) {
+ console.error(
+ `Material-UI: the styled(${component})(...args) API requires all its args to be defined.`,
+ );
+ }
+ }
+
+ // @ts-ignore
+ return stylesFactory(styles);
+ };
+}
+
+export { keyframes, css } from 'goober';
+export { default as StyledEngineProvider } from './StyledEngineProvider';
+export { default as GlobalStyles } from './GlobalStyles';
diff --git a/packages/material-ui-styled-engine-goober/tsconfig.json b/packages/material-ui-styled-engine-goober/tsconfig.json
new file mode 100644
index 00000000000000..57220954971e1e
--- /dev/null
+++ b/packages/material-ui-styled-engine-goober/tsconfig.json
@@ -0,0 +1,4 @@
+{
+ "extends": "../../tsconfig",
+ "include": ["src/**/*", "test/**/*"]
+}
diff --git a/packages/material-ui-system/src/createStyled.d.ts b/packages/material-ui-system/src/createStyled.d.ts
index 946cb4467b4653..0f007169da9741 100644
--- a/packages/material-ui-system/src/createStyled.d.ts
+++ b/packages/material-ui-system/src/createStyled.d.ts
@@ -77,17 +77,7 @@ export type Overwrapped = Pick>;
export interface StyledComponent
extends React.FunctionComponent,
- ComponentSelector {
- /**
- * @desc this method is type-unsafe
- */
- withComponent(
- tag: NewTag,
- ): StyledComponent;
- withComponent>(
- tag: Tag,
- ): StyledComponent, StyleProps, Theme>;
-}
+ ComponentSelector {}
export interface StyledOptions {
label?: string;
diff --git a/packages/material-ui-system/src/createStyled.js b/packages/material-ui-system/src/createStyled.js
index 892d08d8d77c7a..75d9106c588d9d 100644
--- a/packages/material-ui-system/src/createStyled.js
+++ b/packages/material-ui-system/src/createStyled.js
@@ -5,7 +5,7 @@ import styleFunctionSx from './styleFunctionSx';
import propsToClassKey from './propsToClassKey';
function isEmpty(obj) {
- return Object.keys(obj).length === 0;
+ return obj == null || Object.keys(obj).length === 0;
}
const getStyleOverrides = (name, theme) => {
diff --git a/test/karma.tests.js b/test/karma.tests.js
index 0d9e3477dd9e56..bc9638dd454160 100644
--- a/test/karma.tests.js
+++ b/test/karma.tests.js
@@ -36,6 +36,13 @@ const styledEngineSCContext = require.context(
);
styledEngineSCContext.keys().forEach(styledEngineSCContext);
+const styledEngineGooberContext = require.context(
+ '../packages/material-ui-styled-engine-goober/src/',
+ true,
+ /\.test\.(js|ts|tsx)$/,
+);
+styledEngineGooberContext.keys().forEach(styledEngineGooberContext);
+
const systemContext = require.context(
'../packages/material-ui-system/src/',
true,
diff --git a/tsconfig.json b/tsconfig.json
index ded72cb01a3a2d..0563e0f195dc41 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -23,6 +23,8 @@
"@material-ui/styled-engine/*": ["./packages/material-ui-styled-engine/src/*"],
"@material-ui/styled-engine-sc": ["./packages/material-ui-styled-engine-sc/src"],
"@material-ui/styled-engine-sc/*": ["./packages/material-ui-styled-engine-sc/src/*"],
+ "@material-ui/styled-engine-goober": ["./packages/material-ui-styled-engine-goober/src"],
+ "@material-ui/styled-engine-goober/*": ["./packages/material-ui-styled-engine-goober/src/*"],
"@material-ui/styles": ["./packages/material-ui-styles/src"],
"@material-ui/styles/*": ["./packages/material-ui-styles/src/*"],
"@material-ui/system": ["./packages/material-ui-system/src"],
diff --git a/webpackBaseConfig.js b/webpackBaseConfig.js
index d41bffde4cd26a..d7f0151cb04bb3 100644
--- a/webpackBaseConfig.js
+++ b/webpackBaseConfig.js
@@ -21,6 +21,10 @@ module.exports = {
__dirname,
'./packages/material-ui-styled-engine-sc/src',
),
+ '@material-ui/styled-engine-goober': path.resolve(
+ __dirname,
+ './packages/material-ui-styled-engine-goober/src',
+ ),
'@material-ui/styles': path.resolve(__dirname, './packages/material-ui-styles/src'),
'@material-ui/system': path.resolve(__dirname, './packages/material-ui-system/src'),
'@material-ui/private-theming': path.resolve(
diff --git a/yarn.lock b/yarn.lock
index d8fd2b5940d645..93d1ced622c350 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -8674,6 +8674,11 @@ gonzales-pe@^4.3.0:
dependencies:
minimist "^1.2.5"
+goober@^2.0.0:
+ version "2.0.40"
+ resolved "https://registry.yarnpkg.com/goober/-/goober-2.0.40.tgz#7f3d4cafdf6854da55460a639e9b3a15848aaaf3"
+ integrity sha512-LnYclgtz+t2Q9fDEIEdMKCoh5+JyBwG6ORJme52Av18ZrajhqEtzACXWhL/+IIB0SegvwXLcGG7FH+BJ/Z3Ljw==
+
good-listener@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50"