diff --git a/.size-limit.js b/.size-limit.js index f31cff6a63df7e..625821edfa1f5e 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -41,7 +41,7 @@ module.exports = [ name: 'The main docs bundle', webpack: false, path: main.path, - limit: '176 KB', + limit: '176.1 KB', }, { name: 'The docs home page', diff --git a/packages/material-ui-styles/package.json b/packages/material-ui-styles/package.json index 0e13aefc7b7667..bbc3362c43b2bb 100644 --- a/packages/material-ui-styles/package.json +++ b/packages/material-ui-styles/package.json @@ -40,7 +40,6 @@ "@material-ui/utils": "^3.0.0-alpha.0", "classnames": "^2.2.5", "deepmerge": "^3.0.0", - "hoist-non-react-statics": "^3.2.1", "jss": "^9.3.3", "jss-camel-case": "^6.0.0", "jss-default-unit": "^8.0.2", diff --git a/packages/material-ui-styles/src/hoistInternalStatics.js b/packages/material-ui-styles/src/hoistInternalStatics.js new file mode 100644 index 00000000000000..9015336b5e8057 --- /dev/null +++ b/packages/material-ui-styles/src/hoistInternalStatics.js @@ -0,0 +1,18 @@ +/** + * Copies internal immediate statics from material-ui from source to target + */ +export default function hoistStatics(target, source) { + const internals = ['muiName']; + + for (let i = 0; i < internals.length; i += 1) { + const key = internals[i]; + const descriptor = Object.getOwnPropertyDescriptor(source, key); + try { + Object.defineProperty(target, key, descriptor); + } catch (e) { + // Avoid failures from read-only properties and undefined descriptors + } + } + + return target; +} diff --git a/packages/material-ui-styles/src/withStyles.js b/packages/material-ui-styles/src/withStyles.js index c9b7a51ed2dbd6..cff81d1d9be324 100644 --- a/packages/material-ui-styles/src/withStyles.js +++ b/packages/material-ui-styles/src/withStyles.js @@ -3,12 +3,12 @@ import PropTypes from 'prop-types'; import warning from 'warning'; import getDynamicStyles from 'jss/lib/utils/getDynamicStyles'; import { getDisplayName } from '@material-ui/utils'; -import hoistNonReactStatics from 'hoist-non-react-statics'; import { increment } from './indexCounter'; import mergeClasses from './mergeClasses'; import multiKeyStore from './multiKeyStore'; import getStylesCreator from './getStylesCreator'; import getThemeProps from './getThemeProps'; +import hoistStatics from './hoistInternalStatics'; import { StylesContext } from './StylesProvider'; import { ThemeContext } from './ThemeProvider'; @@ -333,7 +333,7 @@ const withStyles = (stylesOrCreator, options = {}) => Component => { WithStyles.displayName = `WithStyles(${getDisplayName(Component)})`; } - hoistNonReactStatics(WithStyles, Component); + hoistStatics(WithStyles, Component); if (process.env.NODE_ENV !== 'production') { // Exposed for test purposes. diff --git a/packages/material-ui-styles/src/withStyles.test.js b/packages/material-ui-styles/src/withStyles.test.js new file mode 100644 index 00000000000000..73d4e7e1302672 --- /dev/null +++ b/packages/material-ui-styles/src/withStyles.test.js @@ -0,0 +1,23 @@ +import { assert } from 'chai'; +import React from 'react'; +import { Input } from '@material-ui/core'; +import { isMuiElement } from '@material-ui/core/utils/reactHelpers'; +import withStyles from './withStyles'; + +describe('withStyles', () => { + it('does not hoist statics', () => { + const Test = () => null; + Test.someStatic = 'will not get hoisted'; + const TestWithStyles = withStyles({})(Test); + assert.strictEqual(TestWithStyles.someStatic, undefined); + }); + + it('hoists mui internals', () => { + assert.strictEqual(isMuiElement(, ['Input']), true); + + // the imported Input is decorated with @material-ui/core/styles + const StyledInput = withStyles({})(Input); + + assert.strictEqual(isMuiElement(, ['Input']), true); + }); +}); diff --git a/packages/material-ui-styles/src/withTheme.js b/packages/material-ui-styles/src/withTheme.js index da2fc0695006ac..820630f3e38113 100644 --- a/packages/material-ui-styles/src/withTheme.js +++ b/packages/material-ui-styles/src/withTheme.js @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; -import hoistNonReactStatics from 'hoist-non-react-statics'; import { getDisplayName } from '@material-ui/utils'; +import hoistStatics from './hoistInternalStatics'; import { ThemeContext } from './ThemeProvider'; // Provide the theme object as a property to the input component. @@ -26,7 +26,7 @@ const withTheme = () => Component => { WithTheme.displayName = `WithTheme(${getDisplayName(Component)})`; } - hoistNonReactStatics(WithTheme, Component); + hoistStatics(WithTheme, Component); return WithTheme; }; diff --git a/packages/material-ui-styles/src/withTheme.test.js b/packages/material-ui-styles/src/withTheme.test.js index 4eaf0f45366fe9..5da506e72829c9 100644 --- a/packages/material-ui-styles/src/withTheme.test.js +++ b/packages/material-ui-styles/src/withTheme.test.js @@ -1,6 +1,8 @@ import React from 'react'; import { assert } from 'chai'; import { createMount } from '@material-ui/core/test-utils'; +import { Input } from '@material-ui/core'; +import { isMuiElement } from '@material-ui/core/utils/reactHelpers'; import PropTypes from 'prop-types'; import withTheme from './withTheme'; import ThemeProvider from './ThemeProvider'; @@ -34,4 +36,19 @@ describe('withTheme', () => { ); assert.strictEqual(wrapper.text(), 'foo'); }); + + it('does not hoist statics', () => { + const Test = () => null; + Test.someStatic = 'will not get hoisted'; + const TestWithTheme = withTheme()(Test); + assert.strictEqual(TestWithTheme.someStatic, undefined); + }); + + it('hoists mui internals', () => { + assert.strictEqual(isMuiElement(, ['Input']), true); + + const ThemedInput = withTheme()(Input); + + assert.strictEqual(isMuiElement(, ['Input']), true); + }); });