@react-spectrum/codemods 0.5.2 → 0.6.0
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/dist/index.js +0 -0
- package/dist/s1-to-s2/src/codemods/codemod.js +33 -25
- package/dist/s1-to-s2/src/codemods/components/ActionGroup/transform.js +164 -0
- package/dist/s1-to-s2/src/codemods/components/ActionMenu/transform.js +15 -0
- package/dist/s1-to-s2/src/codemods/components/Avatar/transform.js +77 -0
- package/dist/s1-to-s2/src/codemods/components/Badge/transform.js +17 -0
- package/dist/s1-to-s2/src/codemods/components/Breadcrumbs/transform.js +26 -0
- package/dist/s1-to-s2/src/codemods/components/Button/transform.js +45 -0
- package/dist/s1-to-s2/src/codemods/components/CheckboxGroup/transform.js +12 -0
- package/dist/s1-to-s2/src/codemods/components/ColorField/transform.js +26 -0
- package/dist/s1-to-s2/src/codemods/components/ColorSlider/transform.js +12 -0
- package/dist/s1-to-s2/src/codemods/components/Column/transform.js +12 -0
- package/dist/s1-to-s2/src/codemods/components/ComboBox/transform.js +29 -0
- package/dist/s1-to-s2/src/codemods/components/ContextualHelp/transform.js +15 -0
- package/dist/s1-to-s2/src/codemods/components/DialogContainer/transform.js +16 -0
- package/dist/s1-to-s2/src/codemods/components/DialogTrigger/transform.js +111 -0
- package/dist/s1-to-s2/src/codemods/components/Divider/transform.js +12 -0
- package/dist/s1-to-s2/src/codemods/components/Form/transform.js +21 -0
- package/dist/s1-to-s2/src/codemods/components/InlineAlert/transform.js +17 -0
- package/dist/s1-to-s2/src/codemods/components/Item/transform.js +25 -0
- package/dist/s1-to-s2/src/codemods/components/Link/transform.js +76 -0
- package/dist/s1-to-s2/src/codemods/components/NumberField/transform.js +23 -0
- package/dist/s1-to-s2/src/codemods/components/Picker/transform.js +33 -0
- package/dist/s1-to-s2/src/codemods/components/ProgressBar/transform.js +23 -0
- package/dist/s1-to-s2/src/codemods/components/ProgressCircle/transform.js +17 -0
- package/dist/s1-to-s2/src/codemods/components/RadioGroup/transform.js +23 -0
- package/dist/s1-to-s2/src/codemods/components/RangeSlider/transform.js +18 -0
- package/dist/s1-to-s2/src/codemods/components/Row/transform.js +111 -0
- package/dist/s1-to-s2/src/codemods/components/SearchField/transform.js +29 -0
- package/dist/s1-to-s2/src/codemods/components/Section/transform.js +37 -0
- package/dist/s1-to-s2/src/codemods/components/Slider/transform.js +24 -0
- package/dist/s1-to-s2/src/codemods/components/StatusLight/transform.js +20 -0
- package/dist/s1-to-s2/src/codemods/components/TableView/transform.js +189 -0
- package/dist/s1-to-s2/src/codemods/components/Tabs/transform.js +116 -0
- package/dist/s1-to-s2/src/codemods/components/TagGroup/transform.js +27 -0
- package/dist/s1-to-s2/src/codemods/components/TextArea/transform.js +29 -0
- package/dist/s1-to-s2/src/codemods/components/TextField/transform.js +29 -0
- package/dist/s1-to-s2/src/codemods/components/Tooltip/transform.js +29 -0
- package/dist/s1-to-s2/src/codemods/components/TooltipTrigger/transform.js +15 -0
- package/dist/s1-to-s2/src/codemods/{styleProps.js → shared/styleProps.js} +22 -9
- package/dist/s1-to-s2/src/codemods/shared/transforms.js +608 -0
- package/dist/s1-to-s2/src/codemods/{unsafeStyle.js → shared/unsafeStyle.js} +1 -1
- package/dist/s1-to-s2/src/codemods/{utils.js → shared/utils.js} +26 -16
- package/package.json +6 -6
- package/dist/s1-to-s2/src/codemods/button.js +0 -52
- package/dist/s1-to-s2/src/codemods/changes.js +0 -1260
- package/dist/s1-to-s2/src/codemods/dialog.js +0 -63
- package/dist/s1-to-s2/src/codemods/transforms.js +0 -1043
- /package/dist/s1-to-s2/src/{iconMap.js → codemods/icons/iconMap.js} +0 -0
- /package/dist/s1-to-s2/src/codemods/{colors.js → shared/colors.js} +0 -0
- /package/dist/s1-to-s2/src/codemods/{dimensions.js → shared/dimensions.js} +0 -0
|
@@ -0,0 +1,608 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.updatePropNameAndValue = updatePropNameAndValue;
|
|
37
|
+
exports.updatePropValueAndAddNewPropName = updatePropValueAndAddNewPropName;
|
|
38
|
+
exports.updatePropName = updatePropName;
|
|
39
|
+
exports.removeProp = removeProp;
|
|
40
|
+
exports.commentOutProp = commentOutProp;
|
|
41
|
+
exports.addCommentToElement = addCommentToElement;
|
|
42
|
+
exports.updateComponentIfPropPresent = updateComponentIfPropPresent;
|
|
43
|
+
exports.moveRenderPropsToChild = moveRenderPropsToChild;
|
|
44
|
+
exports.updateComponentWithinCollection = updateComponentWithinCollection;
|
|
45
|
+
exports.commentIfParentCollectionNotDetected = commentIfParentCollectionNotDetected;
|
|
46
|
+
exports.movePropToNewChildComponentName = movePropToNewChildComponentName;
|
|
47
|
+
exports.movePropToParentComponent = movePropToParentComponent;
|
|
48
|
+
exports.updateToNewComponentName = updateToNewComponentName;
|
|
49
|
+
exports.convertDimensionValueToPx = convertDimensionValueToPx;
|
|
50
|
+
exports.updatePlacementToSingleValue = updatePlacementToSingleValue;
|
|
51
|
+
exports.removeComponentIfWithinParent = removeComponentIfWithinParent;
|
|
52
|
+
exports.updateKeyToId = updateKeyToId;
|
|
53
|
+
const utils_1 = require("./utils");
|
|
54
|
+
const dimensions_1 = require("./dimensions");
|
|
55
|
+
const getComponents_1 = require("../../getComponents");
|
|
56
|
+
const t = __importStar(require("@babel/types"));
|
|
57
|
+
let availableComponents = (0, getComponents_1.getComponents)();
|
|
58
|
+
/**
|
|
59
|
+
* Update prop name and value to new prop name and value.
|
|
60
|
+
*
|
|
61
|
+
* Example:
|
|
62
|
+
* - Button: Change variant="cta" to variant="accent".
|
|
63
|
+
* - Link: Change `variant="overBackground"` to `staticColor="white"`.
|
|
64
|
+
*/
|
|
65
|
+
function updatePropNameAndValue(path, options) {
|
|
66
|
+
const { oldPropName, oldPropValue, newPropName, newPropValue } = options;
|
|
67
|
+
let attrPath = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === oldPropName);
|
|
68
|
+
if (attrPath && t.isJSXAttribute(attrPath.node) && attrPath.node.name.name === oldPropName) {
|
|
69
|
+
if (t.isStringLiteral(attrPath.node.value) &&
|
|
70
|
+
attrPath.node.value.value === oldPropValue) {
|
|
71
|
+
// Update old prop name to new prop name
|
|
72
|
+
attrPath.node.name.name = newPropName;
|
|
73
|
+
// If prop value is a string and matches the old value, replace it with the new value
|
|
74
|
+
if (typeof newPropValue === 'string') {
|
|
75
|
+
attrPath.node.value = t.stringLiteral(newPropValue);
|
|
76
|
+
}
|
|
77
|
+
else if (typeof newPropValue === 'boolean') {
|
|
78
|
+
if (!newPropValue) {
|
|
79
|
+
attrPath.node.value = t.jsxExpressionContainer(t.booleanLiteral(newPropValue));
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
attrPath.node.value = null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else if (t.isJSXExpressionContainer(attrPath.node.value)) {
|
|
87
|
+
if (t.isIdentifier(attrPath.node.value.expression)) {
|
|
88
|
+
// @ts-ignore
|
|
89
|
+
if (attrPath.node.comments && [...attrPath.node.comments].some((comment) => comment.value.includes('could not be automatically'))) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
(0, utils_1.addComment)(attrPath.node, ` TODO(S2-upgrade): Prop ${oldPropName} could not be automatically updated because ${attrPath.node.value.expression.name} could not be followed.`);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// If prop value is an expression, traverse to find a string literal that matches the old and replace it with the new value
|
|
96
|
+
attrPath.traverse({
|
|
97
|
+
StringLiteral(stringPath) {
|
|
98
|
+
if (t.isStringLiteral(stringPath.node) &&
|
|
99
|
+
stringPath.node.value === oldPropValue) {
|
|
100
|
+
// Update old prop name to new prop name
|
|
101
|
+
attrPath.node.name.name = newPropName;
|
|
102
|
+
if (typeof newPropValue === 'string') {
|
|
103
|
+
stringPath.replaceWith(t.stringLiteral(newPropValue));
|
|
104
|
+
}
|
|
105
|
+
else if (typeof newPropValue === 'boolean') {
|
|
106
|
+
if (!newPropValue) {
|
|
107
|
+
stringPath.replaceWith(t.booleanLiteral(newPropValue));
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
attrPath.node.value = null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Updates a prop name and value to new prop name and value, and adds an additional prop.
|
|
122
|
+
*
|
|
123
|
+
* Example:
|
|
124
|
+
* - Button: Change `variant="overBackground"` to `variant="primary" staticColor="white"`.
|
|
125
|
+
*/
|
|
126
|
+
function updatePropValueAndAddNewPropName(path, options) {
|
|
127
|
+
const { oldPropName, oldPropValue, newPropName, newPropValue, additionalPropName, additionalPropValue } = options;
|
|
128
|
+
let attrPath = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === oldPropName);
|
|
129
|
+
if (attrPath && t.isStringLiteral(attrPath.node.value) && attrPath.node.value.value === oldPropValue) {
|
|
130
|
+
// Update old prop name to new prop name
|
|
131
|
+
attrPath.node.name.name = newPropName;
|
|
132
|
+
// If prop value is a string and matches the old value, replace it with the new value
|
|
133
|
+
if (typeof newPropValue === 'string') {
|
|
134
|
+
attrPath.node.value = t.stringLiteral(newPropValue);
|
|
135
|
+
}
|
|
136
|
+
else if (typeof newPropValue === 'boolean') {
|
|
137
|
+
attrPath.node.value = t.jsxExpressionContainer(t.booleanLiteral(newPropValue));
|
|
138
|
+
}
|
|
139
|
+
if (additionalPropName && additionalPropValue) {
|
|
140
|
+
attrPath.insertAfter(t.jsxAttribute(t.jsxIdentifier(additionalPropName), t.stringLiteral(additionalPropValue)));
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
else if (attrPath && t.isJSXExpressionContainer(attrPath.node.value)) {
|
|
144
|
+
// If prop value is an expression, traverse to find a string literal that matches the old and replace it with the new value
|
|
145
|
+
attrPath.traverse({
|
|
146
|
+
StringLiteral(stringPath) {
|
|
147
|
+
if (t.isStringLiteral(stringPath.node) &&
|
|
148
|
+
stringPath.node.value === oldPropValue) {
|
|
149
|
+
// Update old prop name to new prop name
|
|
150
|
+
attrPath.node.name.name = newPropName;
|
|
151
|
+
if (typeof newPropValue === 'string') {
|
|
152
|
+
stringPath.replaceWith(t.stringLiteral(newPropValue));
|
|
153
|
+
}
|
|
154
|
+
else if (typeof newPropValue === 'boolean') {
|
|
155
|
+
stringPath.replaceWith(t.booleanLiteral(newPropValue));
|
|
156
|
+
}
|
|
157
|
+
if (additionalPropName && additionalPropValue) {
|
|
158
|
+
attrPath.insertAfter(t.jsxAttribute(t.jsxIdentifier(additionalPropName), t.stringLiteral(additionalPropValue)));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Updates a prop name to new prop name.
|
|
167
|
+
*
|
|
168
|
+
* Example:
|
|
169
|
+
* - Button: Change style to fillStyle.
|
|
170
|
+
*/
|
|
171
|
+
function updatePropName(path, options) {
|
|
172
|
+
const { oldPropName, newPropName, comment } = options;
|
|
173
|
+
let attrPath = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === oldPropName);
|
|
174
|
+
if (attrPath && t.isJSXAttribute(attrPath.node) && attrPath.node.name.name === oldPropName) {
|
|
175
|
+
attrPath.node.name.name = newPropName;
|
|
176
|
+
if (comment) {
|
|
177
|
+
(0, utils_1.addComment)(attrPath.parentPath.node, ` TODO(S2-upgrade): ${comment}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Removes a prop.
|
|
183
|
+
*
|
|
184
|
+
* Example:
|
|
185
|
+
* - Button: Remove isQuiet (it is no longer supported).
|
|
186
|
+
*/
|
|
187
|
+
function removeProp(path, options) {
|
|
188
|
+
const { propName, propValue } = options;
|
|
189
|
+
let attrPath = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === propName);
|
|
190
|
+
if (attrPath && t.isJSXAttribute(attrPath.node) && attrPath.node.name.name === propName) {
|
|
191
|
+
if (propValue) {
|
|
192
|
+
// If prop value is provided, remove prop only if it matches the value
|
|
193
|
+
if (t.isStringLiteral(attrPath.node.value) && attrPath.node.value.value === propValue) {
|
|
194
|
+
attrPath.remove();
|
|
195
|
+
}
|
|
196
|
+
else if (t.isJSXExpressionContainer(attrPath.node.value)) {
|
|
197
|
+
if (t.isIdentifier(attrPath.node.value.expression)) {
|
|
198
|
+
// @ts-ignore
|
|
199
|
+
// eslint-disable-next-line max-depth
|
|
200
|
+
if (attrPath.node.comments && [...attrPath.node.comments].some((comment) => comment.value.includes('could not be automatically'))) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
(0, utils_1.addComment)(attrPath.node, ` TODO(S2-upgrade): Prop ${propName} could not be automatically removed because ${attrPath.node.value.expression.name} could not be followed.`);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
attrPath.traverse({
|
|
207
|
+
StringLiteral(stringPath) {
|
|
208
|
+
if (t.isStringLiteral(stringPath.node) &&
|
|
209
|
+
stringPath.node.value === propValue) {
|
|
210
|
+
// Invalid prop value was found inside expression.
|
|
211
|
+
(0, utils_1.addComment)(attrPath.node, ` TODO(S2-upgrade): ${propName}="${propValue}" is no longer supported. You'll need to update this manually.`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
// No prop value provided, so remove prop regardless of value
|
|
220
|
+
attrPath.remove();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Comments out a prop.
|
|
226
|
+
*
|
|
227
|
+
* Example:
|
|
228
|
+
* - Button: Comment out isPending (it has not been implemented yet).
|
|
229
|
+
*/
|
|
230
|
+
function commentOutProp(path, options) {
|
|
231
|
+
const { propName, propValue } = options;
|
|
232
|
+
let attrPath = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === propName);
|
|
233
|
+
if (attrPath && t.isJSXAttribute(attrPath.node) && attrPath.node.name.name === propName) {
|
|
234
|
+
if (propValue) {
|
|
235
|
+
// If prop value is provided, comment out prop only if it matches the value
|
|
236
|
+
if (t.isStringLiteral(attrPath.node.value) && attrPath.node.value.value === propValue) {
|
|
237
|
+
(0, utils_1.addComment)(attrPath.parentPath.node, ` TODO(S2-upgrade): ${propName}="${propValue}" has not been implemented yet.`);
|
|
238
|
+
attrPath.remove();
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
attrPath.traverse({
|
|
242
|
+
StringLiteral(stringPath) {
|
|
243
|
+
if (t.isStringLiteral(stringPath.node) &&
|
|
244
|
+
stringPath.node.value === propValue) {
|
|
245
|
+
(0, utils_1.addComment)(attrPath.parentPath.node, ` TODO(S2-upgrade): ${propName}="${propValue}" has not been implemented yet.`);
|
|
246
|
+
attrPath.remove();
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
(0, utils_1.addComment)(attrPath.parentPath.node, ` TODO(S2-upgrade): ${propName} has not been implemented yet.`);
|
|
254
|
+
attrPath.remove();
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Add a comment above an element.
|
|
260
|
+
*
|
|
261
|
+
* Example:
|
|
262
|
+
* - Breadcrumbs: Check if nav needs to be added around Bre.
|
|
263
|
+
*/
|
|
264
|
+
function addCommentToElement(path, options) {
|
|
265
|
+
const { comment } = options;
|
|
266
|
+
(0, utils_1.addComment)(path.node, ` TODO(S2-upgrade): ${comment}`);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* If a prop is present, updates to use a new component.
|
|
270
|
+
*
|
|
271
|
+
* Example:
|
|
272
|
+
* - Button: If `href` is present, Button should be converted to `LinkButton`.
|
|
273
|
+
*/
|
|
274
|
+
function updateComponentIfPropPresent(path, options) {
|
|
275
|
+
const { newComponentName, propName } = options;
|
|
276
|
+
let attrPath = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === propName);
|
|
277
|
+
if (attrPath && t.isJSXAttribute(attrPath.node) && attrPath.node.name.name === propName) {
|
|
278
|
+
let node = attrPath.findParent((p) => t.isJSXElement(p.node))?.node;
|
|
279
|
+
if (node && t.isJSXElement(node)) {
|
|
280
|
+
let localName = newComponentName;
|
|
281
|
+
if (availableComponents.has(newComponentName)) {
|
|
282
|
+
let program = path.findParent((p) => t.isProgram(p.node));
|
|
283
|
+
localName = (0, utils_1.addComponentImport)(program, newComponentName);
|
|
284
|
+
}
|
|
285
|
+
node.openingElement.name = t.jsxIdentifier(localName);
|
|
286
|
+
if (node.closingElement) {
|
|
287
|
+
node.closingElement.name = t.jsxIdentifier(localName);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Remove render props, and move usage to a child component.
|
|
294
|
+
*
|
|
295
|
+
* Example:
|
|
296
|
+
* - DialogTrigger: Update children to remove render props usage, and note that `close` export function moved from `DialogTrigger` to `Dialog`.
|
|
297
|
+
*/
|
|
298
|
+
function moveRenderPropsToChild(path, options) {
|
|
299
|
+
const { newChildComponentName } = options;
|
|
300
|
+
const renderFunctionIndex = path.node.children.findIndex((child) => t.isJSXExpressionContainer(child) &&
|
|
301
|
+
t.isArrowFunctionExpression(child.expression) &&
|
|
302
|
+
t.isJSXElement(child.expression.body) &&
|
|
303
|
+
t.isJSXIdentifier(child.expression.body.openingElement.name));
|
|
304
|
+
const renderFunction = path.node.children[renderFunctionIndex];
|
|
305
|
+
if (t.isJSXExpressionContainer(renderFunction) &&
|
|
306
|
+
t.isArrowFunctionExpression(renderFunction.expression) &&
|
|
307
|
+
t.isJSXElement(renderFunction.expression.body) &&
|
|
308
|
+
t.isJSXIdentifier(renderFunction.expression.body.openingElement.name) &&
|
|
309
|
+
(0, utils_1.getName)(path, renderFunction.expression.body.openingElement.name) !== newChildComponentName) {
|
|
310
|
+
(0, utils_1.addComment)(renderFunction, ' TODO(S2-upgrade): update this dialog to move the close function inside');
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
if (renderFunction &&
|
|
314
|
+
t.isArrowFunctionExpression(renderFunction.expression) &&
|
|
315
|
+
t.isJSXElement(renderFunction.expression.body)) {
|
|
316
|
+
const dialogElement = renderFunction.expression.body;
|
|
317
|
+
const originalParam = renderFunction.expression.params[0];
|
|
318
|
+
if (!t.isIdentifier(originalParam)) {
|
|
319
|
+
(0, utils_1.addComment)(path.node.children[renderFunctionIndex], ' TODO(S2-upgrade): Could not automatically move the render props. You\'ll need to update this manually.');
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
const paramName = originalParam.name;
|
|
323
|
+
const objectPattern = t.objectPattern([
|
|
324
|
+
t.objectProperty(t.identifier(paramName), t.identifier(paramName), false, true)
|
|
325
|
+
]);
|
|
326
|
+
const newRenderFunction = t.jsxExpressionContainer(t.arrowFunctionExpression([objectPattern], t.jsxFragment(t.jsxOpeningFragment(), t.jsxClosingFragment(), dialogElement.children)));
|
|
327
|
+
let removedOnDismiss = false;
|
|
328
|
+
const attributes = dialogElement.openingElement.attributes.filter((attr) => {
|
|
329
|
+
if (t.isJSXAttribute(attr) && attr.name.name === 'onDismiss') {
|
|
330
|
+
removedOnDismiss = true;
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
return true;
|
|
334
|
+
});
|
|
335
|
+
path.node.children[renderFunctionIndex] = t.jsxElement(t.jsxOpeningElement(t.jsxIdentifier(newChildComponentName), attributes), t.jsxClosingElement(t.jsxIdentifier(newChildComponentName)), [newRenderFunction]);
|
|
336
|
+
if (removedOnDismiss) {
|
|
337
|
+
(0, utils_1.addComment)(path.node.children[renderFunctionIndex], ' onDismiss was removed from Dialog. Use onOpenChange on the DialogTrigger, or onDismiss on the DialogContainer instead');
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* If within a collection component, updates to use a new component.
|
|
343
|
+
*
|
|
344
|
+
* Example:
|
|
345
|
+
* - Item: If within `Menu`, update name from `Item` to `MenuItem`.
|
|
346
|
+
*/
|
|
347
|
+
function updateComponentWithinCollection(path, options) {
|
|
348
|
+
const { parentComponentName, newComponentName } = options;
|
|
349
|
+
// Collections currently implemented
|
|
350
|
+
// TODO: Add 'ActionGroup', 'ListBox', 'ListView' once implemented
|
|
351
|
+
const collectionItemParents = new Set(['Menu', 'ActionMenu', 'TagGroup', 'Breadcrumbs', 'Picker', 'ComboBox', 'ListBox', 'TabList', 'TabPanels', 'Collection']);
|
|
352
|
+
if (t.isJSXElement(path.node) &&
|
|
353
|
+
t.isJSXIdentifier(path.node.openingElement.name)) {
|
|
354
|
+
// Find closest parent collection component
|
|
355
|
+
let closestParentCollection = path.findParent((p) => t.isJSXElement(p.node) &&
|
|
356
|
+
t.isJSXIdentifier(p.node.openingElement.name) &&
|
|
357
|
+
collectionItemParents.has((0, utils_1.getName)(path, p.node.openingElement.name)));
|
|
358
|
+
if (closestParentCollection &&
|
|
359
|
+
t.isJSXElement(closestParentCollection.node) &&
|
|
360
|
+
t.isJSXIdentifier(closestParentCollection.node.openingElement.name) &&
|
|
361
|
+
(0, utils_1.getName)(path, closestParentCollection.node.openingElement.name) === parentComponentName) {
|
|
362
|
+
// If closest parent collection component matches parentComponentName, replace with newComponentName
|
|
363
|
+
updateKeyToId(path);
|
|
364
|
+
let localName = newComponentName;
|
|
365
|
+
if (availableComponents.has(newComponentName)) {
|
|
366
|
+
let program = path.findParent((p) => t.isProgram(p.node));
|
|
367
|
+
localName = (0, utils_1.addComponentImport)(program, newComponentName);
|
|
368
|
+
}
|
|
369
|
+
let newNode = t.jsxElement(t.jsxOpeningElement(t.jsxIdentifier(localName), path.node.openingElement.attributes), t.jsxClosingElement(t.jsxIdentifier(localName)), path.node.children);
|
|
370
|
+
path.replaceWith(newNode);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* If no parent collection detected, leave a comment for the user to check manually.
|
|
376
|
+
*
|
|
377
|
+
* Example: If they're declaring declaring Items somewhere above the collection.
|
|
378
|
+
*/
|
|
379
|
+
function commentIfParentCollectionNotDetected(path) {
|
|
380
|
+
const collectionItemParents = new Set(['Menu', 'ActionMenu', 'TagGroup', 'Breadcrumbs', 'Picker', 'ComboBox', 'ListBox', 'TabList', 'TabPanels', 'ActionGroup', 'ActionButtonGroup', 'ToggleButtonGroup', 'ListBox', 'ListView', 'Collection', 'SearchAutocomplete', 'Accordion', 'ActionBar', 'StepList']);
|
|
381
|
+
if (t.isJSXElement(path.node)) {
|
|
382
|
+
// Find closest parent collection component
|
|
383
|
+
let closestParentCollection = path.findParent((p) => t.isJSXElement(p.node) &&
|
|
384
|
+
t.isJSXIdentifier(p.node.openingElement.name) &&
|
|
385
|
+
collectionItemParents.has((0, utils_1.getName)(path, p.node.openingElement.name)));
|
|
386
|
+
if (!closestParentCollection) {
|
|
387
|
+
// If we couldn't find a parent collection parent, leave a comment for them to check manually
|
|
388
|
+
(0, utils_1.addComment)(path.node, ' TODO(S2-upgrade): Couldn\'t automatically detect what type of collection component this is rendered in. You\'ll need to update this manually.');
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* If within a component, moves prop to new child component.
|
|
394
|
+
*
|
|
395
|
+
* Example:
|
|
396
|
+
* - Section: If within `Menu`, move `title` prop string to be a child of new `Heading` within a `Header`.
|
|
397
|
+
*/
|
|
398
|
+
function movePropToNewChildComponentName(path, options) {
|
|
399
|
+
const { parentComponentName, childComponentName, propName, newChildComponentName } = options;
|
|
400
|
+
if (t.isJSXElement(path.node) &&
|
|
401
|
+
t.isJSXElement(path.parentPath.node) &&
|
|
402
|
+
t.isJSXIdentifier(path.node.openingElement.name) &&
|
|
403
|
+
t.isJSXIdentifier(path.parentPath.node.openingElement.name) &&
|
|
404
|
+
(0, utils_1.getName)(path, path.node.openingElement.name) === childComponentName &&
|
|
405
|
+
(0, utils_1.getName)(path, path.parentPath.node.openingElement.name) === parentComponentName) {
|
|
406
|
+
let propValue;
|
|
407
|
+
path.node.openingElement.attributes =
|
|
408
|
+
path.node.openingElement.attributes.filter((attr) => {
|
|
409
|
+
if (t.isJSXAttribute(attr) && attr.name.name === propName) {
|
|
410
|
+
propValue = attr.value;
|
|
411
|
+
return false;
|
|
412
|
+
}
|
|
413
|
+
return true;
|
|
414
|
+
});
|
|
415
|
+
if (propValue) {
|
|
416
|
+
path.node.children.unshift(t.jsxElement(t.jsxOpeningElement(t.jsxIdentifier(newChildComponentName), []), t.jsxClosingElement(t.jsxIdentifier(newChildComponentName)), [t.isStringLiteral(propValue) ? t.jsxText(propValue.value) : propValue]));
|
|
417
|
+
// TODO: handle dynamic collections. Need to wrap export function child in <Collection> and move `items` prop down.
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Updates prop to be on parent component.
|
|
423
|
+
*
|
|
424
|
+
* Example:
|
|
425
|
+
* - Tooltip: Remove `placement` and add to the parent `TooltipTrigger` instead.
|
|
426
|
+
*/
|
|
427
|
+
function movePropToParentComponent(path, options) {
|
|
428
|
+
const { parentComponentName, childComponentName, propName } = options;
|
|
429
|
+
path.traverse({
|
|
430
|
+
JSXAttribute(attributePath) {
|
|
431
|
+
if (t.isJSXElement(path.parentPath.node) &&
|
|
432
|
+
t.isJSXIdentifier(path.node.openingElement.name) &&
|
|
433
|
+
t.isJSXIdentifier(path.parentPath.node.openingElement.name) &&
|
|
434
|
+
attributePath.node.name.name === propName &&
|
|
435
|
+
(0, utils_1.getName)(path, path.node.openingElement.name) === childComponentName &&
|
|
436
|
+
(0, utils_1.getName)(path, path.parentPath.node.openingElement.name) === parentComponentName) {
|
|
437
|
+
path.parentPath.node.openingElement.attributes.push(t.jsxAttribute(t.jsxIdentifier(propName), attributePath.node.value));
|
|
438
|
+
attributePath.remove();
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Update to use a new component.
|
|
445
|
+
*
|
|
446
|
+
* Example:
|
|
447
|
+
* - Flex: Update `Flex` to be a `div` and apply flex styles using the style macro.
|
|
448
|
+
*/
|
|
449
|
+
function updateToNewComponentName(path, options) {
|
|
450
|
+
const { newComponentName } = options;
|
|
451
|
+
let localName = newComponentName;
|
|
452
|
+
if (availableComponents.has(newComponentName)) {
|
|
453
|
+
let program = path.findParent((p) => t.isProgram(p.node));
|
|
454
|
+
localName = (0, utils_1.addComponentImport)(program, newComponentName);
|
|
455
|
+
}
|
|
456
|
+
path.node.openingElement.name = t.jsxIdentifier(localName);
|
|
457
|
+
if (path.node.closingElement) {
|
|
458
|
+
path.node.closingElement.name = t.jsxIdentifier(localName);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
const conversions = {
|
|
462
|
+
'cm': 37.8,
|
|
463
|
+
'mm': 3.78,
|
|
464
|
+
'in': 96,
|
|
465
|
+
'pt': 1.33,
|
|
466
|
+
'pc': 16
|
|
467
|
+
};
|
|
468
|
+
/**
|
|
469
|
+
* Updates prop to use pixel value instead.
|
|
470
|
+
*
|
|
471
|
+
* Example:
|
|
472
|
+
* - ComboBox: Update `menuWidth` to a pixel value.
|
|
473
|
+
*/
|
|
474
|
+
function convertDimensionValueToPx(path, options) {
|
|
475
|
+
const { propName } = options;
|
|
476
|
+
let attrPath = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === propName);
|
|
477
|
+
if (attrPath && t.isJSXAttribute(attrPath.node) && attrPath.node.name.name === propName) {
|
|
478
|
+
if (t.isStringLiteral(attrPath.node.value)) {
|
|
479
|
+
try {
|
|
480
|
+
let value = (0, dimensions_1.convertDimension)(attrPath.node.value.value, 'size');
|
|
481
|
+
if (value && typeof value === 'number') {
|
|
482
|
+
attrPath.node.value = t.jsxExpressionContainer(t.numericLiteral(value));
|
|
483
|
+
}
|
|
484
|
+
else if (value && typeof value === 'string') {
|
|
485
|
+
// eslint-disable-next-line max-depth
|
|
486
|
+
if ((/%|vw|vh|auto|ex|ch|rem|vmin|vmax/).test(value)) {
|
|
487
|
+
(0, utils_1.addComment)(attrPath.node, ' TODO(S2-upgrade): Unable to convert CSS unit to a pixel value');
|
|
488
|
+
}
|
|
489
|
+
else if ((/cm|mm|in|pt|pc/).test(value)) {
|
|
490
|
+
let unit = value.replace(/\[|\]|\d+/g, '');
|
|
491
|
+
let conversion = conversions[unit];
|
|
492
|
+
value = Number(value.replace(/\[|\]|cm|mm|in|pt|pc/g, ''));
|
|
493
|
+
// eslint-disable-next-line max-depth
|
|
494
|
+
if (!isNaN(value)) {
|
|
495
|
+
let pixelValue = Math.round(conversion * value);
|
|
496
|
+
attrPath.node.value = t.jsxExpressionContainer(t.numericLiteral(pixelValue));
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
else if ((/px/).test(value)) {
|
|
500
|
+
let pixelValue = Number(value.replace(/\[|\]|px/g, ''));
|
|
501
|
+
// eslint-disable-next-line max-depth
|
|
502
|
+
if (!isNaN(pixelValue)) {
|
|
503
|
+
attrPath.node.value = t.jsxExpressionContainer(t.numericLiteral(pixelValue));
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
catch (error) {
|
|
509
|
+
(0, utils_1.addComment)(attrPath.node, ` TODO(S2-upgrade): Prop ${propName} could not be automatically updated due to error: ${error}`);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
else if (t.isJSXExpressionContainer(attrPath.node.value)) {
|
|
513
|
+
if (t.isIdentifier(attrPath.node.value.expression)) {
|
|
514
|
+
(0, utils_1.addComment)(attrPath.node, ` TODO(S2-upgrade): Prop ${propName} could not be automatically updated because ${attrPath.node.value.expression.name} could not be followed.`);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Updates double placement values to a single value.
|
|
521
|
+
*
|
|
522
|
+
* Example:
|
|
523
|
+
* - TooltipTrigger: Update `placement="bottom left"` to `placement="bottom"`.
|
|
524
|
+
*/
|
|
525
|
+
function updatePlacementToSingleValue(path, options) {
|
|
526
|
+
const { propToUpdateName, childComponentName } = options;
|
|
527
|
+
const doublePlacementValues = new Set([
|
|
528
|
+
'bottom left',
|
|
529
|
+
'bottom right',
|
|
530
|
+
'bottom start',
|
|
531
|
+
'bottom end',
|
|
532
|
+
'top left',
|
|
533
|
+
'top right',
|
|
534
|
+
'top start',
|
|
535
|
+
'top end',
|
|
536
|
+
'left top',
|
|
537
|
+
'left bottom',
|
|
538
|
+
'start top',
|
|
539
|
+
'start bottom',
|
|
540
|
+
'right top',
|
|
541
|
+
'right bottom',
|
|
542
|
+
'end top',
|
|
543
|
+
'end bottom'
|
|
544
|
+
]);
|
|
545
|
+
let elementPath = childComponentName ?
|
|
546
|
+
path.get('children').find((child) => t.isJSXElement(child.node) &&
|
|
547
|
+
t.isJSXIdentifier(child.node.openingElement.name) &&
|
|
548
|
+
(0, utils_1.getName)(path, child.node.openingElement.name) === childComponentName) : path;
|
|
549
|
+
let attrPath = elementPath.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === propToUpdateName);
|
|
550
|
+
if (attrPath && t.isJSXAttribute(attrPath.node) && attrPath.node.name.name === propToUpdateName) {
|
|
551
|
+
if (t.isStringLiteral(attrPath.node.value) && doublePlacementValues.has(attrPath.node.value.value)) {
|
|
552
|
+
attrPath.replaceWith(t.jsxAttribute(t.jsxIdentifier(propToUpdateName), t.stringLiteral(attrPath.node.value.value.split(' ')[0])));
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
else if (t.isJSXExpressionContainer(attrPath.node.value)) {
|
|
556
|
+
attrPath.traverse({
|
|
557
|
+
StringLiteral(stringPath) {
|
|
558
|
+
if (t.isStringLiteral(stringPath.node) &&
|
|
559
|
+
doublePlacementValues.has(stringPath.node.value)) {
|
|
560
|
+
stringPath.replaceWith(t.stringLiteral(stringPath.node.value.split(' ')[0]));
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Remove component if within a parent component.
|
|
570
|
+
*
|
|
571
|
+
* Example:
|
|
572
|
+
* - Divider: Remove `Divider` if used within a `Dialog`.
|
|
573
|
+
*/
|
|
574
|
+
function removeComponentIfWithinParent(path, options) {
|
|
575
|
+
const { parentComponentName } = options;
|
|
576
|
+
if (t.isJSXElement(path.node) &&
|
|
577
|
+
t.isJSXElement(path.parentPath.node) &&
|
|
578
|
+
t.isJSXIdentifier(path.node.openingElement.name) &&
|
|
579
|
+
t.isJSXIdentifier(path.parentPath.node.openingElement.name) &&
|
|
580
|
+
(0, utils_1.getName)(path, path.parentPath.node.openingElement.name) === parentComponentName) {
|
|
581
|
+
path.remove();
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Updates the key prop to id. Keeps the key prop if it's used in an array.map function.
|
|
586
|
+
*/
|
|
587
|
+
function updateKeyToId(path) {
|
|
588
|
+
let attributes = path.node.openingElement.attributes;
|
|
589
|
+
let keyProp = attributes.find((attr) => t.isJSXAttribute(attr) && attr.name.name === 'key');
|
|
590
|
+
if (keyProp &&
|
|
591
|
+
t.isJSXAttribute(keyProp)) {
|
|
592
|
+
// Update key prop to be id
|
|
593
|
+
keyProp.name = t.jsxIdentifier('id');
|
|
594
|
+
}
|
|
595
|
+
if (t.isArrowFunctionExpression(path.parentPath.node) &&
|
|
596
|
+
path.parentPath.parentPath &&
|
|
597
|
+
t.isCallExpression(path.parentPath.parentPath.node) &&
|
|
598
|
+
path.parentPath.parentPath.node.callee.type === 'MemberExpression' &&
|
|
599
|
+
path.parentPath.parentPath.node.callee.property.type === 'Identifier' &&
|
|
600
|
+
path.parentPath.parentPath.node.callee.property.name === 'map') {
|
|
601
|
+
// If Array.map is used, keep the key prop
|
|
602
|
+
if (keyProp &&
|
|
603
|
+
t.isJSXAttribute(keyProp)) {
|
|
604
|
+
let newKeyProp = t.jsxAttribute(t.jsxIdentifier('key'), keyProp.value);
|
|
605
|
+
attributes.push(newKeyProp);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.default = transformUnsafeStyle;
|
|
4
4
|
const styleProps_1 = require("./styleProps");
|
|
5
5
|
const utils_1 = require("./utils");
|
|
6
6
|
const dimensions_1 = require("./dimensions");
|