Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[styled-engine] Add support for goober #27776

Closed
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
[styled-engine] Add support for goober
oliviertassinari committed Aug 15, 2021
commit be825e1575c7f9bc1acd62f9df59afa91b18cbbe
4 changes: 3 additions & 1 deletion .codesandbox/ci.json
Original file line number Diff line number Diff line change
@@ -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",
3 changes: 3 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -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'),
4 changes: 2 additions & 2 deletions docs/babel.config.js
Original file line number Diff line number Diff line change
@@ -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',
2 changes: 2 additions & 0 deletions docs/package.json
Original file line number Diff line number Diff line change
@@ -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",
2 changes: 1 addition & 1 deletion docs/src/modules/components/ThemeContext.js
Original file line number Diff line number Diff line change
@@ -216,7 +216,7 @@ export function ThemeProvider(props) {
components: {
MuiCssBaseline: {
styleOverrides: {
body: paletteMode === 'dark' ? darkScrollbar() : null,
body: paletteMode === 'dark' ? darkScrollbar() : {},
},
},
},
23 changes: 23 additions & 0 deletions packages/material-ui-styled-engine-goober/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# @material-ui/styled-engine-goober

This package is a wrapper around the `goober` package.
It is created to be used as alias for the `@material-ui/styled-engine` package, for the developers who would like to use `goober` as a styled engine instead of `@emotion/styled`.

## Installation

The installation of the dependency in your package is slightly different from the usual.
You need to alias the default `emotion` implementation to the `goober` one.
Depending on the bundler you are using, you made add it like this:

### webpack

```js
module.exports = {
//...
resolve: {
alias: {
'@material-ui/styled-engine': '@material-ui/styled-engine-goober',
},
},
};
```
54 changes: 54 additions & 0 deletions packages/material-ui-styled-engine-goober/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"name": "@material-ui/styled-engine-goober",
"version": "5.0.0-beta.1",
"private": false,
"author": "Material-UI Team",
"description": "styled() API wrapper package for goober.",
"main": "./src/index.js",
"keywords": [
"react",
"react-component",
"material-ui",
"goober"
],
"repository": {
"type": "git",
"url": "https://github.com/mui-org/material-ui.git",
"directory": "packages/material-ui-styled-engine-goober"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/mui-org/material-ui/issues"
},
"homepage": "https://next.material-ui.com/guides/styled-engine/",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/material-ui"
},
"scripts": {
"build": "yarn build:legacy && yarn build:modern && yarn build:node && yarn build:stable && yarn build:copy-files",
"build:legacy": "node ../../scripts/build legacy",
"build:modern": "node ../../scripts/build modern",
"build:node": "node ../../scripts/build node",
"build:stable": "node ../../scripts/build stable",
"build:copy-files": "node ../../scripts/copy-files.js",
"prebuild": "rimraf build",
"release": "yarn build && npm publish build --tag next",
"test": "cd ../../ && cross-env NODE_ENV=test mocha 'packages/material-ui-styled-engine-goober/**/*.test.{js,ts,tsx}'",
"typescript": "tslint -p tsconfig.json \"{src,test}/**/*.{spec,d}.{ts,tsx}\" && tsc -p tsconfig.json"
},
"dependencies": {
"@emotion/unitless": "^0.7.5",
"prop-types": "^15.7.2"
},
"peerDependencies": {
"goober": "^5.0.0"
},
"sideEffects": false,
"publishConfig": {
"access": "public"
},
"engines": {
"node": ">=12.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from './GlobalStyles';
export * from './GlobalStyles';
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function StyledEngineProvider(props) {
return props.children;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from './StyledEngineProvider';
export * from './StyledEngineProvider';
83 changes: 83 additions & 0 deletions packages/material-ui-styled-engine-goober/src/index.tsx
Original file line number Diff line number Diff line change
@@ -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';
4 changes: 4 additions & 0 deletions packages/material-ui-styled-engine-goober/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "../../tsconfig",
"include": ["src/**/*", "test/**/*"]
}
2 changes: 1 addition & 1 deletion packages/material-ui-system/src/createStyled.js
Original file line number Diff line number Diff line change
@@ -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) => {
7 changes: 7 additions & 0 deletions test/karma.tests.js
Original file line number Diff line number Diff line change
@@ -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,
2 changes: 2 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -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"],
4 changes: 4 additions & 0 deletions webpackBaseConfig.js
Original file line number Diff line number Diff line change
@@ -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(
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
@@ -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"