Skip to content

Commit

Permalink
[styled-engine] Add support for goober
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviertassinari committed Aug 15, 2021
1 parent f6e6151 commit c6f812f
Showing 18 changed files with 230 additions and 5 deletions.
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"

0 comments on commit c6f812f

Please sign in to comment.