@mui/codemod 5.11.0 → 5.11.5

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
@@ -62,6 +62,64 @@ npx @mui/codemod <transform> <path> --jscodeshift="--printOptions='{\"quote\":\"
62
62
 
63
63
  ### v5.0.0
64
64
 
65
+ #### `joy-text-field-to-input`
66
+
67
+ Replace `<TextField>` with composition of `Input`
68
+
69
+ This change only affects Joy UI components.
70
+
71
+ ```diff
72
+ -import TextField from '@mui/joy/TextField';
73
+ +import FormControl from '@mui/joy/FormControl';
74
+ +import FormLabel from '@mui/joy/FormLabel';
75
+ +import FormHelperText from '@mui/joy/FormHelperText';
76
+ +import Input from '@mui/joy/Input';
77
+
78
+ -<TextField
79
+ - id="Id"
80
+ - label="Label"
81
+ - placeholder="Placeholder"
82
+ - helperText="Help!"
83
+ - name="Name"
84
+ - type="tel"
85
+ - autoComplete="on"
86
+ - autoFocus
87
+ - error
88
+ - required
89
+ - fullWidth
90
+ - defaultValue="DefaultValue"
91
+ - size="sm"
92
+ - color="primary"
93
+ - variant="outlined"
94
+ -/>
95
+ +<FormControl
96
+ + id="Id"
97
+ + required
98
+ + size="sm"
99
+ + color="primary">
100
+ + <FormLabel>
101
+ + Label
102
+ + </FormLabel>
103
+ + <JoyInput
104
+ + placeholder="Placeholder"
105
+ + name="Name"
106
+ + type="tel"
107
+ + autoComplete="on"
108
+ + autoFocus
109
+ + error
110
+ + fullWidth
111
+ + defaultValue="DefaultValue"
112
+ + variant="outlined" />
113
+ + <FormHelperText id="Id-helper-text">
114
+ + Help!
115
+ + </FormHelperText>
116
+ +</FormControl>
117
+ ```
118
+
119
+ ```sh
120
+ npx @mui/codemod v5.0.0/joy-text-field-to-input <path>
121
+ ```
122
+
65
123
  #### `joy-rename-components-to-slots`
66
124
 
67
125
  Renames the `components` and `componentsProps` props to `slots` and `slotProps`, respectively.
package/codemod.js CHANGED
File without changes
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = transformer;
7
+ /**
8
+ * @param {import('jscodeshift').FileInfo} file
9
+ * @param {import('jscodeshift').API} api
10
+ */
11
+ function transformer(file, api, options) {
12
+ const j = api.jscodeshift;
13
+ const root = j(file.source);
14
+ const printOptions = options.printOptions;
15
+ root.find(j.ImportDeclaration).filter(({
16
+ node
17
+ }) => {
18
+ const sourceVal = node.source.value;
19
+ if (sourceVal === '@mui/joy/TextField') {
20
+ node.source.value = '@mui/joy/Input';
21
+ }
22
+ return ['@mui/joy',
23
+ // Process only Joy UI components
24
+ '@mui/joy/TextField' // Filter default imports of components other than TextField
25
+ ].includes(sourceVal);
26
+ }).forEach(path => {
27
+ path.node.specifiers.forEach(elementNode => {
28
+ var _elementNode$imported;
29
+ if (elementNode.type === 'ImportSpecifier' && ((_elementNode$imported = elementNode.imported) == null ? void 0 : _elementNode$imported.name) === 'TextField' || elementNode.type === 'ImportDefaultSpecifier') {
30
+ var _elementNode$imported2;
31
+ if (((_elementNode$imported2 = elementNode.imported) == null ? void 0 : _elementNode$imported2.name) === 'TextField') {
32
+ elementNode.imported.name = 'Input';
33
+ }
34
+ let newElementName;
35
+ root.findJSXElements(elementNode.local.name).forEach(elementPath => {
36
+ if (elementPath.node.type !== 'JSXElement') {
37
+ return;
38
+ }
39
+ newElementName = elementPath.node.openingElement.name.name.replace(/TextField/gm, 'Input');
40
+ elementPath.node.openingElement.name.name = newElementName;
41
+ const formControlAttributeNodes = [];
42
+ const formLabelAttributeNodes = [];
43
+ const formHelperTextAttributeNodes = [];
44
+ const inputAttributeNodes = [];
45
+ let formLabelValue;
46
+ let formHelperTextValue;
47
+ elementPath.node.openingElement.attributes.forEach(attributeNode => {
48
+ var _attributeNode$value$, _attributeNode$value$2;
49
+ if (attributeNode.type !== 'JSXAttribute') {
50
+ return;
51
+ }
52
+ const attributeName = attributeNode.name.name;
53
+ switch (attributeName) {
54
+ case 'size':
55
+ case 'color':
56
+ case 'required':
57
+ formControlAttributeNodes.push(attributeNode);
58
+ break;
59
+ case 'slotProps':
60
+ if (((_attributeNode$value$ = attributeNode.value.expression) == null ? void 0 : _attributeNode$value$.type) === 'ObjectExpression') {
61
+ attributeNode.value.expression.properties.forEach(propNode => {
62
+ if (propNode.value.type !== 'ObjectExpression') {
63
+ return;
64
+ }
65
+ propNode.value.properties.forEach(prop => {
66
+ const key = prop.key.value;
67
+ // const value = prop.value.value;
68
+ const newAttributeNode = j.jsxAttribute(j.jsxIdentifier(key), j.jsxExpressionContainer(prop.value));
69
+ switch (propNode.key.name) {
70
+ case 'root':
71
+ formControlAttributeNodes.push(newAttributeNode);
72
+ break;
73
+ case 'label':
74
+ formLabelAttributeNodes.push(newAttributeNode);
75
+ break;
76
+ case 'input':
77
+ inputAttributeNodes.push(newAttributeNode);
78
+ break;
79
+ case 'helperText':
80
+ formHelperTextAttributeNodes.push(newAttributeNode);
81
+ break;
82
+ default:
83
+ }
84
+ });
85
+ });
86
+ }
87
+ break;
88
+ case 'slots':
89
+ if (((_attributeNode$value$2 = attributeNode.value.expression) == null ? void 0 : _attributeNode$value$2.type) === 'ObjectExpression') {
90
+ attributeNode.value.expression.properties.forEach(propNode => {
91
+ const newAttributeNode = j.jsxAttribute(j.jsxIdentifier('component'), j.jsxExpressionContainer(propNode.value));
92
+ switch (propNode.key.name) {
93
+ case 'root':
94
+ formControlAttributeNodes.push(newAttributeNode);
95
+ break;
96
+ case 'label':
97
+ formLabelAttributeNodes.push(newAttributeNode);
98
+ break;
99
+ case 'input':
100
+ inputAttributeNodes.push(newAttributeNode);
101
+ break;
102
+ case 'helperText':
103
+ formHelperTextAttributeNodes.push(newAttributeNode);
104
+ break;
105
+ default:
106
+ }
107
+ });
108
+ }
109
+ break;
110
+ case 'label':
111
+ formLabelValue = attributeNode.value.value;
112
+ break;
113
+ case 'helperText':
114
+ formHelperTextValue = attributeNode.value.value;
115
+ break;
116
+ case 'id':
117
+ formControlAttributeNodes.push(attributeNode);
118
+ formLabelAttributeNodes.push(j.jsxAttribute(j.jsxIdentifier('id'), j.literal(`${attributeNode.value.value}-label`)));
119
+ formHelperTextAttributeNodes.push(j.jsxAttribute(j.jsxIdentifier('id'), j.literal(`${attributeNode.value.value}-helper-text`)));
120
+ break;
121
+ default:
122
+ }
123
+ if (!['size', 'color', 'slotProps', 'slots', 'label', 'helperText', 'id', 'required'].includes(attributeName)) {
124
+ inputAttributeNodes.push(attributeNode);
125
+ }
126
+ });
127
+ elementPath.node.openingElement.attributes = inputAttributeNodes;
128
+ if (formControlAttributeNodes.length > 0 || formLabelValue || formHelperTextValue) {
129
+ const formControlIdentifier = j.jsxIdentifier('FormControl');
130
+ const childrenOfFormControl = [];
131
+ if (formLabelValue) {
132
+ const formLabelIdentifier = j.jsxIdentifier('FormLabel');
133
+ const formLabelElement = j.jsxElement(j.jsxOpeningElement(formLabelIdentifier, formLabelAttributeNodes), j.jsxClosingElement(formLabelIdentifier), [j.jsxText('\n'), j.jsxText(formLabelValue), j.jsxText('\n')]);
134
+ childrenOfFormControl.push(formLabelElement, j.jsxText('\n'));
135
+ }
136
+ childrenOfFormControl.push(elementPath.node, j.jsxText('\n'));
137
+ if (formHelperTextValue) {
138
+ const formHelperTextIdentifier = j.jsxIdentifier('FormHelperText');
139
+ const formHelperTextElement = j.jsxElement(j.jsxOpeningElement(formHelperTextIdentifier, formHelperTextAttributeNodes), j.jsxClosingElement(formHelperTextIdentifier), [j.jsxText('\n'), j.jsxText(formHelperTextValue), j.jsxText('\n')]);
140
+ childrenOfFormControl.push(formHelperTextElement);
141
+ }
142
+ elementPath.replace(j.jsxElement(j.jsxOpeningElement(formControlIdentifier, formControlAttributeNodes), j.jsxClosingElement(formControlIdentifier), [j.jsxText('\n'), ...childrenOfFormControl, j.jsxText('\n')]));
143
+ }
144
+ });
145
+ if (newElementName) {
146
+ elementNode.local.name = newElementName;
147
+ }
148
+ }
149
+ });
150
+ });
151
+ const transformed = root.findJSXElements();
152
+ return transformed.toSource(printOptions);
153
+ }
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _joy = require("@mui/joy");
5
+ var _TextField = _interopRequireDefault(require("@mui/joy/TextField"));
6
+ var _TextField2 = _interopRequireDefault(require("@mui/material/TextField"));
7
+ var _jsxRuntime = require("react/jsx-runtime");
8
+ // the codemod should transform only Joy TextField
9
+
10
+ /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
11
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_joy.TextField, {
12
+ slotProps: {
13
+ root: {
14
+ ['aria-hidden']: false
15
+ },
16
+ label: {
17
+ ['aria-hidden']: false
18
+ },
19
+ input: {
20
+ ['aria-hidden']: false
21
+ },
22
+ helperText: {
23
+ ['aria-hidden']: false
24
+ }
25
+ },
26
+ slots: {
27
+ root: 'span',
28
+ label: 'span',
29
+ input: 'span',
30
+ helperText: 'span'
31
+ },
32
+ id: "Id",
33
+ label: "Label",
34
+ placeholder: "Placeholder",
35
+ helperText: "Help!",
36
+ name: "Name",
37
+ type: "button",
38
+ autoComplete: "on",
39
+ autoFocus: true,
40
+ error: true,
41
+ required: true,
42
+ fullWidth: true,
43
+ defaultValue: "DefaultValue",
44
+ size: "sm",
45
+ color: "primary",
46
+ variant: "outlined"
47
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_TextField.default, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_TextField2.default, {})]
48
+ });
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _joy = require("@mui/joy");
5
+ var _Input = _interopRequireDefault(require("@mui/joy/Input"));
6
+ var _TextField = _interopRequireDefault(require("@mui/material/TextField"));
7
+ var _jsxRuntime = require("react/jsx-runtime");
8
+ // the codemod should transform only Joy TextField
9
+
10
+ /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
11
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(FormControl, {
12
+ "aria-hidden": false,
13
+ component: 'span',
14
+ id: "Id",
15
+ required: true,
16
+ size: "sm",
17
+ color: "primary",
18
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(FormLabel, {
19
+ "aria-hidden": false,
20
+ component: 'span',
21
+ id: "Id-label",
22
+ children: "Label"
23
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_joy.Input, {
24
+ "aria-hidden": false,
25
+ component: 'span',
26
+ placeholder: "Placeholder",
27
+ name: "Name",
28
+ type: "button",
29
+ autoComplete: "on",
30
+ autoFocus: true,
31
+ error: true,
32
+ fullWidth: true,
33
+ defaultValue: "DefaultValue",
34
+ variant: "outlined"
35
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(FormHelperText, {
36
+ "aria-hidden": false,
37
+ component: 'span',
38
+ id: "Id-helper-text",
39
+ children: "Help!"
40
+ })]
41
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input.default, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_TextField.default, {})]
42
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mui/codemod",
3
- "version": "5.11.0",
3
+ "version": "5.11.5",
4
4
  "bin": "./codemod.js",
5
5
  "private": false,
6
6
  "author": "MUI Team",
@@ -30,9 +30,9 @@
30
30
  "url": "https://opencollective.com/mui"
31
31
  },
32
32
  "dependencies": {
33
- "@babel/core": "^7.20.5",
34
- "@babel/runtime": "^7.20.6",
35
- "@babel/traverse": "^7.20.5",
33
+ "@babel/core": "^7.20.7",
34
+ "@babel/runtime": "^7.20.7",
35
+ "@babel/traverse": "^7.20.10",
36
36
  "jscodeshift": "^0.13.1",
37
37
  "jscodeshift-add-imports": "^1.0.10",
38
38
  "yargs": "^17.6.2"