@mui/codemod 5.15.5 → 5.15.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -60,11 +60,42 @@ npx @mui/codemod@latest <transform> <path> --jscodeshift="--printOptions='{\"quo
60
60
 
61
61
  ## Included scripts
62
62
 
63
+ - [Deprecation](#deprecations)
64
+ - [v5](#v500)
65
+ - [v4](#v400)
66
+ - [v1](#v100)
67
+ - [v0.15](#v0150)
68
+
69
+ ### Deprecations
70
+
71
+ ```bash
72
+ npx @mui/codemod@latest deprecations/all <path>
73
+ ```
74
+
75
+ #### `all`
76
+
77
+ A combination of all deprecations.
78
+
79
+ #### `accordion-props`
80
+
81
+ ```diff
82
+ <Accordion
83
+ - TransitionComponent={CustomTransition}
84
+ - TransitionProps={{ unmountOnExit: true }}
85
+ + slots={{ transition: CustomTransition }}
86
+ + slotProps={{ transition: { unmountOnExit: true } }}
87
+ />
88
+ ```
89
+
90
+ ```bash
91
+ npx @mui/codemod@latest deprecations/accordion-props <path>
92
+ ```
93
+
63
94
  ### v5.0.0
64
95
 
65
- ### `base-use-named-exports`
96
+ #### `base-use-named-exports`
66
97
 
67
- Base UI default exports were changed to named ones. Previously we had a mix of default and named ones.
98
+ Base UI default exports were changed to named ones. Previously we had a mix of default and named ones.
68
99
  This was changed to improve consistency and avoid problems some bundlers have with default exports.
69
100
  See https://github.com/mui/material-ui/issues/21862 for more context.
70
101
 
@@ -81,9 +112,9 @@ This codemod updates the import and re-export statements.
81
112
  npx @mui/codemod@latest v5.0.0/base-use-named-exports <path>
82
113
  ```
83
114
 
84
- ### `base-remove-unstyled-suffix`
115
+ #### `base-remove-unstyled-suffix`
85
116
 
86
- The `Unstyled` suffix has been removed from all Base UI component names, including names of types and other related identifiers.
117
+ The `Unstyled` suffix has been removed from all Base UI component names, including names of types and other related identifiers.
87
118
 
88
119
  ```diff
89
120
  - <Input component='a' href='url' />;
@@ -96,9 +127,9 @@ npx @mui/codemod@latest v5.0.0/base-remove-unstyled-suffix <path>
96
127
 
97
128
  #### `base-remove-component-prop`
98
129
 
99
- Remove `component` prop from all Base UI components by transferring its value into `slots.root`.
130
+ Remove `component` prop from all Base UI components by transferring its value into `slots.root`.
100
131
 
101
- This change only affects Base UI components.
132
+ This change only affects Base UI components.
102
133
 
103
134
  ```diff
104
135
  - <Input component={CustomRoot} />
@@ -126,7 +157,7 @@ npx @mui/codemod@latest v5.0.0/rename-css-variables <path>
126
157
 
127
158
  #### `base-hook-imports`
128
159
 
129
- Updates the sources of the imports of the Base UI hooks to adapt to the new directories of the hooks.
160
+ Updates the sources of the imports of the Base UI hooks to adapt to the new directories of the hooks.
130
161
 
131
162
  ```diff
132
163
  - import { useBadge } from '@mui/base/BadgeUnstyled';
@@ -452,7 +483,7 @@ You can find more details about this breaking change in [the migration guide](ht
452
483
  Renames the `components` and `componentsProps` props to `slots` and `slotProps`, respectively.
453
484
  Also, changes `slots`' fields names to camelCase.
454
485
 
455
- This change only affects Base UI components.
486
+ This change only affects Base UI components.
456
487
 
457
488
  ```diff
458
489
  <BadgeUnstyled
@@ -1551,7 +1582,7 @@ Head to https://mui.com/guides/minimizing-bundle-size/ to understand when it's u
1551
1582
  #### `import-path`
1552
1583
 
1553
1584
  Updates the `import-paths` for the new location of the components.
1554
- MUI v1.0.0 flatten the import paths.
1585
+ Material UI v1.0.0 flatten the import paths.
1555
1586
  The diff should look like this:
1556
1587
 
1557
1588
  ```diff
@@ -1576,7 +1607,7 @@ Subsequently, you can run the above `find ...` command to flatten your imports.
1576
1607
 
1577
1608
  #### `color-imports`
1578
1609
 
1579
- Updates the `color-imports` for the new location of MUI color palettes.
1610
+ Updates the `color-imports` for the new location of Material UI color palettes.
1580
1611
  The diff should look like this:
1581
1612
 
1582
1613
  ```diff
@@ -1641,7 +1672,7 @@ npx @mui/codemod@latest v1.0.0/menu-item-primary-text <path>
1641
1672
  #### `import-path`
1642
1673
 
1643
1674
  Updates the `import-paths` for the new location of the components.
1644
- MUI v0.15.0 is reorganizing the folder distribution of the project.
1675
+ Material UI v0.15.0 is reorganizing the folder distribution of the project.
1645
1676
  The diff should look like this:
1646
1677
 
1647
1678
  ```diff
package/codemod.js CHANGED
@@ -10,27 +10,39 @@ const jscodeshiftDirectory = path.dirname(require.resolve('jscodeshift'));
10
10
  const jscodeshiftExecutable = path.join(jscodeshiftDirectory, jscodeshiftPackage.bin.jscodeshift);
11
11
 
12
12
  async function runTransform(transform, files, flags, codemodFlags) {
13
- const transformerSrcPath = path.resolve(__dirname, './src', `${transform}.js`);
14
- const transformerBuildPath = path.resolve(__dirname, './node', `${transform}.js`);
13
+ const paths = [
14
+ path.resolve(__dirname, './src', `${transform}/index.js`),
15
+ path.resolve(__dirname, './src', `${transform}.js`),
16
+ path.resolve(__dirname, './node', `${transform}/index.js`),
17
+ path.resolve(__dirname, './node', `${transform}.js`),
18
+ ];
19
+
15
20
  let transformerPath;
16
- try {
17
- await fs.stat(transformerSrcPath);
18
- transformerPath = transformerSrcPath;
19
- } catch (srcPathError) {
21
+ let error;
22
+ // eslint-disable-next-line no-restricted-syntax
23
+ for (const item of paths) {
20
24
  try {
21
- await fs.stat(transformerBuildPath);
22
- transformerPath = transformerBuildPath;
23
- } catch (buildPathError) {
24
- if (buildPathError.code === 'ENOENT') {
25
- throw new Error(
26
- `Transform '${transform}' not found. Check out ${path.resolve(
27
- __dirname,
28
- './README.md for a list of available codemods.',
29
- )}`,
30
- );
31
- }
32
- throw buildPathError;
25
+ // eslint-disable-next-line no-await-in-loop
26
+ await fs.stat(item);
27
+ error = undefined;
28
+ transformerPath = item;
29
+ break;
30
+ } catch (srcPathError) {
31
+ error = srcPathError;
32
+ continue;
33
+ }
34
+ }
35
+
36
+ if (error) {
37
+ if (error?.code === 'ENOENT') {
38
+ throw new Error(
39
+ `Transform '${transform}' not found. Check out ${path.resolve(
40
+ __dirname,
41
+ './README.md for a list of available codemods.',
42
+ )}`,
43
+ );
33
44
  }
45
+ throw error;
34
46
  }
35
47
 
36
48
  const args = [
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = transformer;
8
+ var _findComponentJSX = _interopRequireDefault(require("../../util/findComponentJSX"));
9
+ var _assignObject = _interopRequireDefault(require("../../util/assignObject"));
10
+ var _appendAttribute = _interopRequireDefault(require("../../util/appendAttribute"));
11
+ /**
12
+ * @param {import('jscodeshift').FileInfo} file
13
+ * @param {import('jscodeshift').API} api
14
+ */
15
+ function transformer(file, api, options) {
16
+ const j = api.jscodeshift;
17
+ const root = j(file.source);
18
+ const printOptions = options.printOptions;
19
+ (0, _findComponentJSX.default)(j, {
20
+ root,
21
+ componentName: 'Accordion'
22
+ }, elementPath => {
23
+ let index = elementPath.node.openingElement.attributes.findIndex(attr => attr.type === 'JSXAttribute' && attr.name.name === 'TransitionComponent');
24
+ if (index !== -1) {
25
+ const removed = elementPath.node.openingElement.attributes.splice(index, 1);
26
+ let hasNode = false;
27
+ elementPath.node.openingElement.attributes.forEach(attr => {
28
+ var _attr$name;
29
+ if (((_attr$name = attr.name) == null ? void 0 : _attr$name.name) === 'slots') {
30
+ hasNode = true;
31
+ (0, _assignObject.default)(j, {
32
+ target: attr,
33
+ key: 'transition',
34
+ expression: removed[0].value.expression
35
+ });
36
+ }
37
+ });
38
+ if (!hasNode) {
39
+ (0, _appendAttribute.default)(j, {
40
+ target: elementPath.node,
41
+ attributeName: 'slots',
42
+ expression: j.objectExpression([j.objectProperty(j.identifier('transition'), removed[0].value.expression)])
43
+ });
44
+ }
45
+ }
46
+ index = elementPath.node.openingElement.attributes.findIndex(attr => attr.type === 'JSXAttribute' && attr.name.name === 'TransitionProps');
47
+ if (index !== -1) {
48
+ const removed = elementPath.node.openingElement.attributes.splice(index, 1);
49
+ let hasNode = false;
50
+ elementPath.node.openingElement.attributes.forEach(attr => {
51
+ var _attr$name2;
52
+ if (((_attr$name2 = attr.name) == null ? void 0 : _attr$name2.name) === 'slotProps') {
53
+ hasNode = true;
54
+ (0, _assignObject.default)(j, {
55
+ target: attr,
56
+ key: 'transition',
57
+ expression: removed[0].value.expression
58
+ });
59
+ }
60
+ });
61
+ if (!hasNode) {
62
+ (0, _appendAttribute.default)(j, {
63
+ target: elementPath.node,
64
+ attributeName: 'slotProps',
65
+ expression: j.objectExpression([j.objectProperty(j.identifier('transition'), removed[0].value.expression)])
66
+ });
67
+ }
68
+ }
69
+ });
70
+ root.find(j.ObjectProperty, {
71
+ key: {
72
+ name: 'TransitionComponent'
73
+ }
74
+ }).forEach(path => {
75
+ var _path$parent;
76
+ if (((_path$parent = path.parent) == null || (_path$parent = _path$parent.parent) == null || (_path$parent = _path$parent.parent) == null || (_path$parent = _path$parent.parent) == null || (_path$parent = _path$parent.node.key) == null ? void 0 : _path$parent.name) === 'MuiAccordion') {
77
+ path.replace(j.property('init', j.identifier('slots'), j.objectExpression([j.objectProperty(j.identifier('transition'), path.node.value)])));
78
+ }
79
+ });
80
+ root.find(j.ObjectProperty, {
81
+ key: {
82
+ name: 'TransitionProps'
83
+ }
84
+ }).forEach(path => {
85
+ var _path$parent2;
86
+ if (((_path$parent2 = path.parent) == null || (_path$parent2 = _path$parent2.parent) == null || (_path$parent2 = _path$parent2.parent) == null || (_path$parent2 = _path$parent2.parent) == null || (_path$parent2 = _path$parent2.node.key) == null ? void 0 : _path$parent2.name) === 'MuiAccordion') {
87
+ path.replace(j.property('init', j.identifier('slotProps'), j.objectExpression([j.objectProperty(j.identifier('transition'), path.node.value)])));
88
+ }
89
+ });
90
+ return root.toSource(printOptions);
91
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ Object.defineProperty(exports, "default", {
8
+ enumerable: true,
9
+ get: function () {
10
+ return _accordionProps.default;
11
+ }
12
+ });
13
+ var _accordionProps = _interopRequireDefault(require("./accordion-props"));
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
5
+ var _Accordion = _interopRequireDefault(require("@mui/material/Accordion"));
6
+ var _material = require("@mui/material");
7
+ var _jsxRuntime = require("react/jsx-runtime");
8
+ /*#__PURE__*/(0, _jsxRuntime.jsx)(_Accordion.default, {
9
+ slots: {
10
+ transition: CustomTransition
11
+ },
12
+ slotProps: {
13
+ transition: {
14
+ unmountOnExit: true
15
+ }
16
+ }
17
+ });
18
+ /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Accordion, {
19
+ slots: {
20
+ transition: CustomTransition
21
+ },
22
+ slotProps: {
23
+ transition: transitionVars
24
+ }
25
+ });
26
+ /*#__PURE__*/(0, _jsxRuntime.jsx)(_Accordion.default, {
27
+ slots: {
28
+ root: 'div',
29
+ transition: CustomTransition
30
+ },
31
+ slotProps: {
32
+ root: {
33
+ className: 'foo'
34
+ },
35
+ transition: {
36
+ unmountOnExit: true
37
+ }
38
+ }
39
+ });
40
+ /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Accordion, {
41
+ slots: (0, _extends2.default)({}, outerSlots, {
42
+ transition: CustomTransition
43
+ }),
44
+ slotProps: (0, _extends2.default)({}, outerSlotProps, {
45
+ transition: {
46
+ unmountOnExit: true
47
+ }
48
+ })
49
+ });
50
+ // should skip non MUI components
51
+ /*#__PURE__*/(0, _jsxRuntime.jsx)(NonMuiAccordion, {
52
+ TransitionComponent: CustomTransition,
53
+ TransitionProps: {
54
+ unmountOnExit: true
55
+ }
56
+ });
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
5
+ var _Accordion = _interopRequireDefault(require("@mui/material/Accordion"));
6
+ var _material = require("@mui/material");
7
+ var _jsxRuntime = require("react/jsx-runtime");
8
+ /*#__PURE__*/(0, _jsxRuntime.jsx)(_Accordion.default, {
9
+ slots: {
10
+ transition: CustomTransition
11
+ },
12
+ slotProps: {
13
+ transition: {
14
+ unmountOnExit: true
15
+ }
16
+ }
17
+ });
18
+ /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Accordion, {
19
+ slots: {
20
+ transition: CustomTransition
21
+ },
22
+ slotProps: {
23
+ transition: transitionVars
24
+ }
25
+ });
26
+ /*#__PURE__*/(0, _jsxRuntime.jsx)(_Accordion.default, {
27
+ slots: {
28
+ root: 'div',
29
+ transition: CustomTransition
30
+ },
31
+ slotProps: {
32
+ root: {
33
+ className: 'foo'
34
+ },
35
+ transition: {
36
+ unmountOnExit: true
37
+ }
38
+ }
39
+ });
40
+ /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Accordion, {
41
+ slots: (0, _extends2.default)({}, outerSlots, {
42
+ transition: CustomTransition
43
+ }),
44
+ slotProps: (0, _extends2.default)({}, outerSlotProps, {
45
+ transition: {
46
+ unmountOnExit: true
47
+ }
48
+ })
49
+ });
50
+ // should skip non MUI components
51
+ /*#__PURE__*/(0, _jsxRuntime.jsx)(NonMuiAccordion, {
52
+ TransitionComponent: CustomTransition,
53
+ TransitionProps: {
54
+ unmountOnExit: true
55
+ }
56
+ });
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ fn({
4
+ MuiAccordion: {
5
+ defaultProps: {
6
+ TransitionComponent: CustomTransition,
7
+ TransitionProps: {
8
+ unmountOnExit: true
9
+ }
10
+ }
11
+ }
12
+ });
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ fn({
4
+ MuiAccordion: {
5
+ defaultProps: {
6
+ slots: {
7
+ transition: CustomTransition
8
+ },
9
+ slotProps: {
10
+ transition: {
11
+ unmountOnExit: true
12
+ }
13
+ }
14
+ }
15
+ }
16
+ });
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = deprecationsAll;
8
+ var _accordionProps = _interopRequireDefault(require("../accordion-props/accordion-props"));
9
+ /**
10
+ * @param {import('jscodeshift').FileInfo} file
11
+ * @param {import('jscodeshift').API} api
12
+ */
13
+ function deprecationsAll(file, api, options) {
14
+ file.source = (0, _accordionProps.default)(file, api, options);
15
+ return file.source;
16
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ Object.defineProperty(exports, "default", {
8
+ enumerable: true,
9
+ get: function () {
10
+ return _deprecationsAll.default;
11
+ }
12
+ });
13
+ var _deprecationsAll = _interopRequireDefault(require("./deprecations-all"));
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = appendAttribute;
7
+ /**
8
+ * @param {import('jscodeshift')} j
9
+ * @param {{ target: import('jscodeshift').JSXElement; attributeName: string; expression: import('ast-types/gen/kinds').ExpressionKind | import('ast-types/gen/kinds').JSXEmptyExpressionKind; }} options
10
+ */
11
+ function appendAttribute(j, options) {
12
+ const {
13
+ target,
14
+ attributeName,
15
+ expression
16
+ } = options;
17
+ target.openingElement.attributes.push(j.jsxAttribute(j.jsxIdentifier(attributeName), j.jsxExpressionContainer(expression)));
18
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = assignObject;
7
+ /**
8
+ * Pushes an expression to a known object. handles local object and variable declaration.
9
+ *
10
+ * @param {import('jscodeshift')} j
11
+ * @param {{ target: import('jscodeshift').JSXAttribute; expression: import('ast-types/gen/kinds').ExpressionKind; key: string }} options
12
+ *
13
+ * @example push expression to `slots.transition` => <Component slots={{ transition: <expression> }} />
14
+ * @example push expression to `slots.transition` => <Component slots={{ ...slots, transition: <expression> }} />
15
+ */
16
+ function assignObject(j, options) {
17
+ const {
18
+ target,
19
+ expression,
20
+ key
21
+ } = options;
22
+ if (target && target.type === 'JSXAttribute') {
23
+ const expContainer = /** @type import('jscodeshift').JSXExpressionContainer */target.value;
24
+ if (expContainer.expression.type === 'ObjectExpression') {
25
+ // case `<prop>={{ ... }}`
26
+ expContainer.expression.properties.push(j.objectProperty(j.identifier(key), expression));
27
+ } else if (expContainer.expression.type === 'Identifier') {
28
+ // case `<prop>={outerVariable}
29
+ expContainer.expression = j.objectExpression([j.spreadElement(j.identifier(expContainer.expression.name)), j.objectProperty(j.identifier(key), expression)]);
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = findComponentJSX;
7
+ /**
8
+ * Find all the JSXElements of a given component name.
9
+ *
10
+ * @param {import('jscodeshift')} j
11
+ * @param {{ root: import('jscodeshift').Collection; componentName: string }} options
12
+ * @param {(path: import('jscodeshift').ASTPath<import('jscodeshift').JSXElement>) => void} callback
13
+ *
14
+ */
15
+ function findComponentJSX(j, options, callback) {
16
+ const {
17
+ root,
18
+ componentName
19
+ } = options;
20
+
21
+ // case 1: import ComponentName from '@mui/material/ComponentName';
22
+ // case 2: import { ComponentName } from '@mui/material';
23
+ // case 3: import { ComponentName as SomethingElse } from '@mui/material';
24
+
25
+ const importName = new Set();
26
+ root.find(j.ImportDeclaration).filter(path => path.node.source.value.match(new RegExp(`^@mui/material/?(${componentName})?`))).forEach(path => {
27
+ path.node.specifiers.forEach(specifier => {
28
+ if (specifier.type === 'ImportDefaultSpecifier') {
29
+ importName.add(specifier.local.name);
30
+ }
31
+ if (specifier.type === 'ImportSpecifier' && specifier.imported.name === componentName) {
32
+ importName.add(specifier.local.name);
33
+ }
34
+ });
35
+ });
36
+ [...importName].forEach(name => {
37
+ root.findJSXElements(name).forEach(elementPath => {
38
+ callback(elementPath);
39
+ });
40
+ });
41
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mui/codemod",
3
- "version": "5.15.5",
3
+ "version": "5.15.7",
4
4
  "bin": "./codemod.js",
5
5
  "private": false,
6
6
  "author": "MUI Team",
@@ -24,9 +24,9 @@
24
24
  "url": "https://opencollective.com/mui-org"
25
25
  },
26
26
  "dependencies": {
27
- "@babel/core": "^7.23.7",
28
- "@babel/runtime": "^7.23.8",
29
- "@babel/traverse": "^7.23.7",
27
+ "@babel/core": "^7.23.9",
28
+ "@babel/runtime": "^7.23.9",
29
+ "@babel/traverse": "^7.23.9",
30
30
  "jscodeshift": "^0.13.1",
31
31
  "jscodeshift-add-imports": "^1.0.10",
32
32
  "yargs": "^17.7.2"