@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
|
@@ -1,1043 +0,0 @@
|
|
|
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 (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.functionMap = void 0;
|
|
27
|
-
exports.commentIfNestedColumns = commentIfNestedColumns;
|
|
28
|
-
const utils_1 = require("./utils");
|
|
29
|
-
const dimensions_1 = require("./dimensions");
|
|
30
|
-
const getComponents_1 = require("../getComponents");
|
|
31
|
-
const t = __importStar(require("@babel/types"));
|
|
32
|
-
let availableComponents = (0, getComponents_1.getComponents)();
|
|
33
|
-
/**
|
|
34
|
-
* Update prop name and value to new prop name and value.
|
|
35
|
-
*
|
|
36
|
-
* Example:
|
|
37
|
-
* - Button: Change variant="cta" to variant="accent".
|
|
38
|
-
* - Link: Change `variant="overBackground"` to `staticColor="white"`.
|
|
39
|
-
*/
|
|
40
|
-
function updatePropNameAndValue(path, options) {
|
|
41
|
-
const { oldProp, oldValue, newProp, newValue } = options;
|
|
42
|
-
let attrPath = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === oldProp);
|
|
43
|
-
if (attrPath && t.isJSXAttribute(attrPath.node) && attrPath.node.name.name === oldProp) {
|
|
44
|
-
if (t.isStringLiteral(attrPath.node.value) &&
|
|
45
|
-
attrPath.node.value.value === oldValue) {
|
|
46
|
-
// Update old prop name to new prop name
|
|
47
|
-
attrPath.node.name.name = newProp;
|
|
48
|
-
// If prop value is a string and matches the old value, replace it with the new value
|
|
49
|
-
if (typeof newValue === 'string') {
|
|
50
|
-
attrPath.node.value = t.stringLiteral(newValue);
|
|
51
|
-
}
|
|
52
|
-
else if (typeof newValue === 'boolean') {
|
|
53
|
-
if (!newValue) {
|
|
54
|
-
attrPath.node.value = t.jsxExpressionContainer(t.booleanLiteral(newValue));
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
attrPath.node.value = null;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
else if (t.isJSXExpressionContainer(attrPath.node.value)) {
|
|
62
|
-
if (t.isIdentifier(attrPath.node.value.expression)) {
|
|
63
|
-
// @ts-ignore
|
|
64
|
-
if (attrPath.node.comments && [...attrPath.node.comments].some((comment) => comment.value.includes('could not be automatically'))) {
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
(0, utils_1.addComment)(attrPath.node, ` TODO(S2-upgrade): Prop ${oldProp} could not be automatically updated because ${attrPath.node.value.expression.name} could not be followed.`);
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
// If prop value is an expression, traverse to find a string literal that matches the old and replace it with the new value
|
|
71
|
-
attrPath.traverse({
|
|
72
|
-
StringLiteral(stringPath) {
|
|
73
|
-
if (t.isStringLiteral(stringPath.node) &&
|
|
74
|
-
stringPath.node.value === oldValue) {
|
|
75
|
-
// Update old prop name to new prop name
|
|
76
|
-
attrPath.node.name.name = newProp;
|
|
77
|
-
if (typeof newValue === 'string') {
|
|
78
|
-
stringPath.replaceWith(t.stringLiteral(newValue));
|
|
79
|
-
}
|
|
80
|
-
else if (typeof newValue === 'boolean') {
|
|
81
|
-
if (!newValue) {
|
|
82
|
-
stringPath.replaceWith(t.booleanLiteral(newValue));
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
attrPath.node.value = null;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Updates a prop name and value to new prop name and value, and adds an additional prop.
|
|
97
|
-
*
|
|
98
|
-
* Example:
|
|
99
|
-
* - Button: Change `variant="overBackground"` to `variant="primary" staticColor="white"`.
|
|
100
|
-
*/
|
|
101
|
-
function updatePropValueAndAddNewProp(path, options) {
|
|
102
|
-
const { oldProp, oldValue, newProp, newValue, additionalProp, additionalValue } = options;
|
|
103
|
-
let attrPath = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === oldProp);
|
|
104
|
-
if (attrPath && t.isStringLiteral(attrPath.node.value) && attrPath.node.value.value === oldValue) {
|
|
105
|
-
// Update old prop name to new prop name
|
|
106
|
-
attrPath.node.name.name = newProp;
|
|
107
|
-
// If prop value is a string and matches the old value, replace it with the new value
|
|
108
|
-
if (typeof newValue === 'string') {
|
|
109
|
-
attrPath.node.value = t.stringLiteral(newValue);
|
|
110
|
-
}
|
|
111
|
-
else if (typeof newValue === 'boolean') {
|
|
112
|
-
attrPath.node.value = t.jsxExpressionContainer(t.booleanLiteral(newValue));
|
|
113
|
-
}
|
|
114
|
-
if (additionalProp && additionalValue) {
|
|
115
|
-
attrPath.insertAfter(t.jsxAttribute(t.jsxIdentifier(additionalProp), t.stringLiteral(additionalValue)));
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
else if (attrPath && t.isJSXExpressionContainer(attrPath.node.value)) {
|
|
119
|
-
// If prop value is an expression, traverse to find a string literal that matches the old and replace it with the new value
|
|
120
|
-
attrPath.traverse({
|
|
121
|
-
StringLiteral(stringPath) {
|
|
122
|
-
if (t.isStringLiteral(stringPath.node) &&
|
|
123
|
-
stringPath.node.value === oldValue) {
|
|
124
|
-
// Update old prop name to new prop name
|
|
125
|
-
attrPath.node.name.name = newProp;
|
|
126
|
-
if (typeof newValue === 'string') {
|
|
127
|
-
stringPath.replaceWith(t.stringLiteral(newValue));
|
|
128
|
-
}
|
|
129
|
-
else if (typeof newValue === 'boolean') {
|
|
130
|
-
stringPath.replaceWith(t.booleanLiteral(newValue));
|
|
131
|
-
}
|
|
132
|
-
if (additionalProp && additionalValue) {
|
|
133
|
-
attrPath.insertAfter(t.jsxAttribute(t.jsxIdentifier(additionalProp), t.stringLiteral(additionalValue)));
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Updates a prop name to new prop name.
|
|
142
|
-
*
|
|
143
|
-
* Example:
|
|
144
|
-
* - Button: Change style to fillStyle.
|
|
145
|
-
*/
|
|
146
|
-
function updatePropName(path, options) {
|
|
147
|
-
const { oldProp, newProp } = options;
|
|
148
|
-
let attrPath = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === oldProp);
|
|
149
|
-
if (attrPath && t.isJSXAttribute(attrPath.node) && attrPath.node.name.name === oldProp) {
|
|
150
|
-
attrPath.node.name.name = newProp;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Removes a prop.
|
|
155
|
-
*
|
|
156
|
-
* Example:
|
|
157
|
-
* - Button: Remove isQuiet (it is no longer supported).
|
|
158
|
-
*/
|
|
159
|
-
function removeProp(path, options) {
|
|
160
|
-
const { propToRemove, propValue } = options;
|
|
161
|
-
let attrPath = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === propToRemove);
|
|
162
|
-
if (attrPath && t.isJSXAttribute(attrPath.node) && attrPath.node.name.name === propToRemove) {
|
|
163
|
-
if (propValue) {
|
|
164
|
-
// If prop value is provided, remove prop only if it matches the value
|
|
165
|
-
if (t.isStringLiteral(attrPath.node.value) && attrPath.node.value.value === propValue) {
|
|
166
|
-
attrPath.remove();
|
|
167
|
-
}
|
|
168
|
-
else if (t.isJSXExpressionContainer(attrPath.node.value)) {
|
|
169
|
-
if (t.isIdentifier(attrPath.node.value.expression)) {
|
|
170
|
-
// @ts-ignore
|
|
171
|
-
// eslint-disable-next-line max-depth
|
|
172
|
-
if (attrPath.node.comments && [...attrPath.node.comments].some((comment) => comment.value.includes('could not be automatically'))) {
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
(0, utils_1.addComment)(attrPath.node, ` TODO(S2-upgrade): Prop ${propToRemove} could not be automatically removed because ${attrPath.node.value.expression.name} could not be followed.`);
|
|
176
|
-
}
|
|
177
|
-
else {
|
|
178
|
-
attrPath.traverse({
|
|
179
|
-
StringLiteral(stringPath) {
|
|
180
|
-
if (t.isStringLiteral(stringPath.node) &&
|
|
181
|
-
stringPath.node.value === propValue) {
|
|
182
|
-
// Invalid prop value was found inside expression.
|
|
183
|
-
(0, utils_1.addComment)(attrPath.node, ` TODO(S2-upgrade): ${propToRemove}="${propValue}" is no longer supported. You'll need to update this manually.`);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
else {
|
|
191
|
-
// No prop value provided, so remove prop regardless of value
|
|
192
|
-
attrPath.remove();
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* Comments out a prop.
|
|
198
|
-
*
|
|
199
|
-
* Example:
|
|
200
|
-
* - Button: Comment out isPending (it has not been implemented yet).
|
|
201
|
-
*/
|
|
202
|
-
function commentOutProp(path, options) {
|
|
203
|
-
const { propToComment, propValue } = options;
|
|
204
|
-
let attrPath = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === propToComment);
|
|
205
|
-
if (attrPath && t.isJSXAttribute(attrPath.node) && attrPath.node.name.name === propToComment) {
|
|
206
|
-
if (propValue) {
|
|
207
|
-
// If prop value is provided, comment out prop only if it matches the value
|
|
208
|
-
if (t.isStringLiteral(attrPath.node.value) && attrPath.node.value.value === propValue) {
|
|
209
|
-
(0, utils_1.addComment)(attrPath.parentPath.node, ` TODO(S2-upgrade): ${propToComment}="${propValue}" has not been implemented yet.`);
|
|
210
|
-
attrPath.remove();
|
|
211
|
-
}
|
|
212
|
-
else {
|
|
213
|
-
attrPath.traverse({
|
|
214
|
-
StringLiteral(stringPath) {
|
|
215
|
-
if (t.isStringLiteral(stringPath.node) &&
|
|
216
|
-
stringPath.node.value === propValue) {
|
|
217
|
-
(0, utils_1.addComment)(attrPath.parentPath.node, ` TODO(S2-upgrade): ${propToComment}="${propValue}" has not been implemented yet.`);
|
|
218
|
-
attrPath.remove();
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
else {
|
|
225
|
-
(0, utils_1.addComment)(attrPath.parentPath.node, ` TODO(S2-upgrade): ${propToComment} has not been implemented yet.`);
|
|
226
|
-
attrPath.remove();
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Add a comment above an element.
|
|
232
|
-
*
|
|
233
|
-
* Example:
|
|
234
|
-
* - Breadcrumbs: Check if nav needs to be added around Bre.
|
|
235
|
-
*/
|
|
236
|
-
function addCommentToElement(path, options) {
|
|
237
|
-
const { comment } = options;
|
|
238
|
-
(0, utils_1.addComment)(path.node, ` TODO(S2-upgrade): ${comment}`);
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* If a prop is present, updates to use a new component.
|
|
242
|
-
*
|
|
243
|
-
* Example:
|
|
244
|
-
* - Button: If `href` is present, Button should be converted to `LinkButton`.
|
|
245
|
-
*/
|
|
246
|
-
function updateComponentIfPropPresent(path, options) {
|
|
247
|
-
const { newComponent, propToCheck } = options;
|
|
248
|
-
let attrPath = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === propToCheck);
|
|
249
|
-
if (attrPath && t.isJSXAttribute(attrPath.node) && attrPath.node.name.name === propToCheck) {
|
|
250
|
-
let node = attrPath.findParent((p) => t.isJSXElement(p.node))?.node;
|
|
251
|
-
if (node && t.isJSXElement(node)) {
|
|
252
|
-
let localName = newComponent;
|
|
253
|
-
if (availableComponents.has(newComponent)) {
|
|
254
|
-
let program = path.findParent((p) => t.isProgram(p.node));
|
|
255
|
-
localName = (0, utils_1.addComponentImport)(program, newComponent);
|
|
256
|
-
}
|
|
257
|
-
node.openingElement.name = t.jsxIdentifier(localName);
|
|
258
|
-
if (node.closingElement) {
|
|
259
|
-
node.closingElement.name = t.jsxIdentifier(localName);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
/**
|
|
265
|
-
* Remove render props, and move usage to a child component.
|
|
266
|
-
*
|
|
267
|
-
* Example:
|
|
268
|
-
* - DialogTrigger: Update children to remove render props usage, and note that `close` function moved from `DialogTrigger` to `Dialog`.
|
|
269
|
-
*/
|
|
270
|
-
function moveRenderPropsToChild(path, options) {
|
|
271
|
-
const { newChildComponent } = options;
|
|
272
|
-
const renderFunctionIndex = path.node.children.findIndex((child) => t.isJSXExpressionContainer(child) &&
|
|
273
|
-
t.isArrowFunctionExpression(child.expression) &&
|
|
274
|
-
t.isJSXElement(child.expression.body) &&
|
|
275
|
-
t.isJSXIdentifier(child.expression.body.openingElement.name));
|
|
276
|
-
const renderFunction = path.node.children[renderFunctionIndex];
|
|
277
|
-
if (t.isJSXExpressionContainer(renderFunction) &&
|
|
278
|
-
t.isArrowFunctionExpression(renderFunction.expression) &&
|
|
279
|
-
t.isJSXElement(renderFunction.expression.body) &&
|
|
280
|
-
t.isJSXIdentifier(renderFunction.expression.body.openingElement.name) &&
|
|
281
|
-
(0, utils_1.getName)(path, renderFunction.expression.body.openingElement.name) !== newChildComponent) {
|
|
282
|
-
(0, utils_1.addComment)(renderFunction, ' TODO(S2-upgrade): update this dialog to move the close function inside');
|
|
283
|
-
return;
|
|
284
|
-
}
|
|
285
|
-
if (renderFunction &&
|
|
286
|
-
t.isArrowFunctionExpression(renderFunction.expression) &&
|
|
287
|
-
t.isJSXElement(renderFunction.expression.body)) {
|
|
288
|
-
const dialogElement = renderFunction.expression.body;
|
|
289
|
-
const originalParam = renderFunction.expression.params[0];
|
|
290
|
-
if (!t.isIdentifier(originalParam)) {
|
|
291
|
-
(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.');
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
const paramName = originalParam.name;
|
|
295
|
-
const objectPattern = t.objectPattern([
|
|
296
|
-
t.objectProperty(t.identifier(paramName), t.identifier(paramName), false, true)
|
|
297
|
-
]);
|
|
298
|
-
const newRenderFunction = t.jsxExpressionContainer(t.arrowFunctionExpression([objectPattern], t.jsxFragment(t.jsxOpeningFragment(), t.jsxClosingFragment(), dialogElement.children)));
|
|
299
|
-
let removedOnDismiss = false;
|
|
300
|
-
const attributes = dialogElement.openingElement.attributes.filter((attr) => {
|
|
301
|
-
if (t.isJSXAttribute(attr) && attr.name.name === 'onDismiss') {
|
|
302
|
-
removedOnDismiss = true;
|
|
303
|
-
return false;
|
|
304
|
-
}
|
|
305
|
-
return true;
|
|
306
|
-
});
|
|
307
|
-
path.node.children[renderFunctionIndex] = t.jsxElement(t.jsxOpeningElement(t.jsxIdentifier(newChildComponent), attributes), t.jsxClosingElement(t.jsxIdentifier(newChildComponent)), [newRenderFunction]);
|
|
308
|
-
if (removedOnDismiss) {
|
|
309
|
-
(0, utils_1.addComment)(path.node.children[renderFunctionIndex], ' onDismiss was removed from Dialog. Use onOpenChange on the DialogTrigger, or onDismiss on the DialogContainer instead');
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
|
-
* If within a collection component, updates to use a new component.
|
|
315
|
-
*
|
|
316
|
-
* Example:
|
|
317
|
-
* - Item: If within `Menu`, update name from `Item` to `MenuItem`.
|
|
318
|
-
*/
|
|
319
|
-
function updateComponentWithinCollection(path, options) {
|
|
320
|
-
const { parentComponent, newComponent } = options;
|
|
321
|
-
// Collections currently implemented
|
|
322
|
-
// TODO: Add 'ActionGroup', 'ListBox', 'ListView' once implemented
|
|
323
|
-
const collectionItemParents = new Set(['Menu', 'ActionMenu', 'TagGroup', 'Breadcrumbs', 'Picker', 'ComboBox', 'ListBox', 'TabList', 'TabPanels', 'Collection']);
|
|
324
|
-
if (t.isJSXElement(path.node) &&
|
|
325
|
-
t.isJSXIdentifier(path.node.openingElement.name)) {
|
|
326
|
-
// Find closest parent collection component
|
|
327
|
-
let closestParentCollection = path.findParent((p) => t.isJSXElement(p.node) &&
|
|
328
|
-
t.isJSXIdentifier(p.node.openingElement.name) &&
|
|
329
|
-
collectionItemParents.has((0, utils_1.getName)(path, p.node.openingElement.name)));
|
|
330
|
-
if (closestParentCollection &&
|
|
331
|
-
t.isJSXElement(closestParentCollection.node) &&
|
|
332
|
-
t.isJSXIdentifier(closestParentCollection.node.openingElement.name) &&
|
|
333
|
-
(0, utils_1.getName)(path, closestParentCollection.node.openingElement.name) === parentComponent) {
|
|
334
|
-
// If closest parent collection component matches parentComponent, replace with newComponent
|
|
335
|
-
updateKeyToId(path);
|
|
336
|
-
let localName = newComponent;
|
|
337
|
-
if (availableComponents.has(newComponent)) {
|
|
338
|
-
let program = path.findParent((p) => t.isProgram(p.node));
|
|
339
|
-
localName = (0, utils_1.addComponentImport)(program, newComponent);
|
|
340
|
-
}
|
|
341
|
-
let newNode = t.jsxElement(t.jsxOpeningElement(t.jsxIdentifier(localName), path.node.openingElement.attributes), t.jsxClosingElement(t.jsxIdentifier(localName)), path.node.children);
|
|
342
|
-
path.replaceWith(newNode);
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
/**
|
|
347
|
-
* If no parent collection detected, leave a comment for the user to check manually.
|
|
348
|
-
*
|
|
349
|
-
* Example: If they're declaring declaring Items somewhere above the collection.
|
|
350
|
-
*/
|
|
351
|
-
function commentIfParentCollectionNotDetected(path) {
|
|
352
|
-
const collectionItemParents = new Set(['Menu', 'ActionMenu', 'TagGroup', 'Breadcrumbs', 'Picker', 'ComboBox', 'ListBox', 'TabList', 'TabPanels', 'ActionGroup', 'ActionButtonGroup', 'ToggleButtonGroup', 'ListBox', 'ListView', 'Collection', 'SearchAutocomplete', 'Accordion', 'ActionBar', 'StepList']);
|
|
353
|
-
if (t.isJSXElement(path.node)) {
|
|
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
|
-
// If we couldn't find a parent collection parent, leave a comment for them to check manually
|
|
360
|
-
(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.');
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
/**
|
|
365
|
-
* Updates Tabs to the new API.
|
|
366
|
-
*
|
|
367
|
-
* Example:
|
|
368
|
-
* - Tabs: Remove TabPanels components and keep individual TabPanel components inside.
|
|
369
|
-
*/
|
|
370
|
-
function updateTabs(path) {
|
|
371
|
-
function transformTabs(path) {
|
|
372
|
-
let tabListNode = null;
|
|
373
|
-
let tabPanelsNodes = [];
|
|
374
|
-
let itemsProp = null;
|
|
375
|
-
path.node.openingElement.attributes = path.node.openingElement.attributes.filter(attr => {
|
|
376
|
-
if (t.isJSXAttribute(attr) && attr.name.name === 'items') {
|
|
377
|
-
itemsProp = attr;
|
|
378
|
-
return false;
|
|
379
|
-
}
|
|
380
|
-
return true;
|
|
381
|
-
});
|
|
382
|
-
path.get('children').forEach(childPath => {
|
|
383
|
-
if (t.isJSXElement(childPath.node)) {
|
|
384
|
-
if (t.isJSXIdentifier(childPath.node.openingElement.name) &&
|
|
385
|
-
(0, utils_1.getName)(childPath, childPath.node.openingElement.name) === 'TabList') {
|
|
386
|
-
tabListNode = transformTabList(childPath);
|
|
387
|
-
if (itemsProp) {
|
|
388
|
-
tabListNode.openingElement.attributes.push(itemsProp);
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
else if (t.isJSXIdentifier(childPath.node.openingElement.name) &&
|
|
392
|
-
(0, utils_1.getName)(childPath, childPath.node.openingElement.name) === 'TabPanels') {
|
|
393
|
-
tabPanelsNodes = transformTabPanels(childPath, itemsProp);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
});
|
|
397
|
-
if (tabListNode) {
|
|
398
|
-
path.node.children = [tabListNode, ...tabPanelsNodes];
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
function transformTabList(tabListPath) {
|
|
402
|
-
tabListPath.get('children').forEach(itemPath => {
|
|
403
|
-
if (t.isJSXElement(itemPath.node) &&
|
|
404
|
-
t.isJSXIdentifier(itemPath.node.openingElement.name) &&
|
|
405
|
-
(0, utils_1.getName)(itemPath, itemPath.node.openingElement.name) === 'Item') {
|
|
406
|
-
updateComponentWithinCollection(itemPath, { parentComponent: 'TabList', newComponent: 'Tab' });
|
|
407
|
-
}
|
|
408
|
-
});
|
|
409
|
-
return tabListPath.node;
|
|
410
|
-
}
|
|
411
|
-
function transformTabPanels(tabPanelsPath, itemsProp) {
|
|
412
|
-
// Dynamic case
|
|
413
|
-
let dynamicRender = tabPanelsPath.get('children').find(path => t.isJSXExpressionContainer(path.node));
|
|
414
|
-
if (dynamicRender) {
|
|
415
|
-
updateToNewComponent(tabPanelsPath, { newComponent: 'Collection' });
|
|
416
|
-
let itemPath = dynamicRender.get('expression').get('body');
|
|
417
|
-
updateComponentWithinCollection(itemPath, { parentComponent: 'Collection', newComponent: 'TabPanel' });
|
|
418
|
-
if (itemsProp) {
|
|
419
|
-
tabPanelsPath.node.openingElement.attributes.push(t.jsxAttribute(t.jsxIdentifier('items'), itemsProp.value));
|
|
420
|
-
}
|
|
421
|
-
return [tabPanelsPath.node];
|
|
422
|
-
}
|
|
423
|
-
// Static case
|
|
424
|
-
return tabPanelsPath.get('children').map(itemPath => {
|
|
425
|
-
if (t.isJSXElement(itemPath.node) &&
|
|
426
|
-
t.isJSXIdentifier(itemPath.node.openingElement.name) &&
|
|
427
|
-
(0, utils_1.getName)(itemPath, itemPath.node.openingElement.name) === 'Item') {
|
|
428
|
-
updateComponentWithinCollection(itemPath, { parentComponent: 'TabPanels', newComponent: 'TabPanel' });
|
|
429
|
-
return itemPath.node;
|
|
430
|
-
}
|
|
431
|
-
return null;
|
|
432
|
-
}).filter(Boolean);
|
|
433
|
-
}
|
|
434
|
-
let program = path.findParent((p) => t.isProgram(p.node));
|
|
435
|
-
(0, utils_1.removeComponentImport)(program, 'TabPanels');
|
|
436
|
-
transformTabs(path);
|
|
437
|
-
}
|
|
438
|
-
/**
|
|
439
|
-
* If within a component, moves prop to new child component.
|
|
440
|
-
*
|
|
441
|
-
* Example:
|
|
442
|
-
* - Section: If within `Menu`, move `title` prop string to be a child of new `Heading` within a `Header`.
|
|
443
|
-
*/
|
|
444
|
-
function movePropToNewChildComponent(path, options) {
|
|
445
|
-
const { parentComponent, childComponent, propToMove, newChildComponent } = options;
|
|
446
|
-
if (t.isJSXElement(path.node) &&
|
|
447
|
-
t.isJSXElement(path.parentPath.node) &&
|
|
448
|
-
t.isJSXIdentifier(path.node.openingElement.name) &&
|
|
449
|
-
t.isJSXIdentifier(path.parentPath.node.openingElement.name) &&
|
|
450
|
-
(0, utils_1.getName)(path, path.node.openingElement.name) === childComponent &&
|
|
451
|
-
(0, utils_1.getName)(path, path.parentPath.node.openingElement.name) === parentComponent) {
|
|
452
|
-
let propValue;
|
|
453
|
-
path.node.openingElement.attributes =
|
|
454
|
-
path.node.openingElement.attributes.filter((attr) => {
|
|
455
|
-
if (t.isJSXAttribute(attr) && attr.name.name === propToMove) {
|
|
456
|
-
propValue = attr.value;
|
|
457
|
-
return false;
|
|
458
|
-
}
|
|
459
|
-
return true;
|
|
460
|
-
});
|
|
461
|
-
if (propValue) {
|
|
462
|
-
path.node.children.unshift(t.jsxElement(t.jsxOpeningElement(t.jsxIdentifier(newChildComponent), []), t.jsxClosingElement(t.jsxIdentifier(newChildComponent)), [t.isStringLiteral(propValue) ? t.jsxText(propValue.value) : propValue]));
|
|
463
|
-
// TODO: handle dynamic collections. Need to wrap function child in <Collection> and move `items` prop down.
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
/**
|
|
468
|
-
* Updates prop to be on parent component.
|
|
469
|
-
*
|
|
470
|
-
* Example:
|
|
471
|
-
* - Tooltip: Remove `placement` and add to the parent `TooltipTrigger` instead.
|
|
472
|
-
*/
|
|
473
|
-
function movePropToParentComponent(path, options) {
|
|
474
|
-
const { parentComponent, childComponent, propToMove } = options;
|
|
475
|
-
path.traverse({
|
|
476
|
-
JSXAttribute(attributePath) {
|
|
477
|
-
if (t.isJSXElement(path.parentPath.node) &&
|
|
478
|
-
t.isJSXIdentifier(path.node.openingElement.name) &&
|
|
479
|
-
t.isJSXIdentifier(path.parentPath.node.openingElement.name) &&
|
|
480
|
-
attributePath.node.name.name === propToMove &&
|
|
481
|
-
(0, utils_1.getName)(path, path.node.openingElement.name) === childComponent &&
|
|
482
|
-
(0, utils_1.getName)(path, path.parentPath.node.openingElement.name) === parentComponent) {
|
|
483
|
-
path.parentPath.node.openingElement.attributes.push(t.jsxAttribute(t.jsxIdentifier(propToMove), attributePath.node.value));
|
|
484
|
-
attributePath.remove();
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
});
|
|
488
|
-
}
|
|
489
|
-
/**
|
|
490
|
-
* Update to use a new component.
|
|
491
|
-
*
|
|
492
|
-
* Example:
|
|
493
|
-
* - Flex: Update `Flex` to be a `div` and apply flex styles using the style macro.
|
|
494
|
-
*/
|
|
495
|
-
function updateToNewComponent(path, options) {
|
|
496
|
-
const { newComponent } = options;
|
|
497
|
-
let localName = newComponent;
|
|
498
|
-
if (availableComponents.has(newComponent)) {
|
|
499
|
-
let program = path.findParent((p) => t.isProgram(p.node));
|
|
500
|
-
localName = (0, utils_1.addComponentImport)(program, newComponent);
|
|
501
|
-
}
|
|
502
|
-
path.node.openingElement.name = t.jsxIdentifier(localName);
|
|
503
|
-
if (path.node.closingElement) {
|
|
504
|
-
path.node.closingElement.name = t.jsxIdentifier(localName);
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
const conversions = {
|
|
508
|
-
'cm': 37.8,
|
|
509
|
-
'mm': 3.78,
|
|
510
|
-
'in': 96,
|
|
511
|
-
'pt': 1.33,
|
|
512
|
-
'pc': 16
|
|
513
|
-
};
|
|
514
|
-
/**
|
|
515
|
-
* Updates prop to use pixel value instead.
|
|
516
|
-
*
|
|
517
|
-
* Example:
|
|
518
|
-
* - ComboBox: Update `menuWidth` to a pixel value.
|
|
519
|
-
*/
|
|
520
|
-
function convertDimensionValueToPx(path, options) {
|
|
521
|
-
const { propToConvertValue } = options;
|
|
522
|
-
let attrPath = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === propToConvertValue);
|
|
523
|
-
if (attrPath && t.isJSXAttribute(attrPath.node) && attrPath.node.name.name === propToConvertValue) {
|
|
524
|
-
if (t.isStringLiteral(attrPath.node.value)) {
|
|
525
|
-
try {
|
|
526
|
-
let value = (0, dimensions_1.convertDimension)(attrPath.node.value.value, 'size');
|
|
527
|
-
if (value && typeof value === 'number') {
|
|
528
|
-
attrPath.node.value = t.jsxExpressionContainer(t.numericLiteral(value));
|
|
529
|
-
}
|
|
530
|
-
else if (value && typeof value === 'string') {
|
|
531
|
-
// eslint-disable-next-line max-depth
|
|
532
|
-
if ((/%|vw|vh|auto|ex|ch|rem|vmin|vmax/).test(value)) {
|
|
533
|
-
(0, utils_1.addComment)(attrPath.node, ' TODO(S2-upgrade): Unable to convert CSS unit to a pixel value');
|
|
534
|
-
}
|
|
535
|
-
else if ((/cm|mm|in|pt|pc/).test(value)) {
|
|
536
|
-
let unit = value.replace(/\[|\]|\d+/g, '');
|
|
537
|
-
let conversion = conversions[unit];
|
|
538
|
-
value = Number(value.replace(/\[|\]|cm|mm|in|pt|pc/g, ''));
|
|
539
|
-
// eslint-disable-next-line max-depth
|
|
540
|
-
if (!isNaN(value)) {
|
|
541
|
-
let pixelValue = Math.round(conversion * value);
|
|
542
|
-
attrPath.node.value = t.jsxExpressionContainer(t.numericLiteral(pixelValue));
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
else if ((/px/).test(value)) {
|
|
546
|
-
let pixelValue = Number(value.replace(/\[|\]|px/g, ''));
|
|
547
|
-
// eslint-disable-next-line max-depth
|
|
548
|
-
if (!isNaN(pixelValue)) {
|
|
549
|
-
attrPath.node.value = t.jsxExpressionContainer(t.numericLiteral(pixelValue));
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
catch (error) {
|
|
555
|
-
(0, utils_1.addComment)(attrPath.node, ` TODO(S2-upgrade): Prop ${propToConvertValue} could not be automatically updated due to error: ${error}`);
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
else if (t.isJSXExpressionContainer(attrPath.node.value)) {
|
|
559
|
-
if (t.isIdentifier(attrPath.node.value.expression)) {
|
|
560
|
-
(0, utils_1.addComment)(attrPath.node, ` TODO(S2-upgrade): Prop ${propToConvertValue} could not be automatically updated because ${attrPath.node.value.expression.name} could not be followed.`);
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
/**
|
|
566
|
-
* Updates double placement values to a single value.
|
|
567
|
-
*
|
|
568
|
-
* Example:
|
|
569
|
-
* - TooltipTrigger: Update `placement="bottom left"` to `placement="bottom"`.
|
|
570
|
-
*/
|
|
571
|
-
function updatePlacementToSingleValue(path, options) {
|
|
572
|
-
const { propToUpdate, childComponent } = options;
|
|
573
|
-
const doublePlacementValues = new Set([
|
|
574
|
-
'bottom left',
|
|
575
|
-
'bottom right',
|
|
576
|
-
'bottom start',
|
|
577
|
-
'bottom end',
|
|
578
|
-
'top left',
|
|
579
|
-
'top right',
|
|
580
|
-
'top start',
|
|
581
|
-
'top end',
|
|
582
|
-
'left top',
|
|
583
|
-
'left bottom',
|
|
584
|
-
'start top',
|
|
585
|
-
'start bottom',
|
|
586
|
-
'right top',
|
|
587
|
-
'right bottom',
|
|
588
|
-
'end top',
|
|
589
|
-
'end bottom'
|
|
590
|
-
]);
|
|
591
|
-
let elementPath = childComponent ?
|
|
592
|
-
path.get('children').find((child) => t.isJSXElement(child.node) &&
|
|
593
|
-
t.isJSXIdentifier(child.node.openingElement.name) &&
|
|
594
|
-
(0, utils_1.getName)(path, child.node.openingElement.name) === childComponent) : path;
|
|
595
|
-
let attrPath = elementPath.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === propToUpdate);
|
|
596
|
-
if (attrPath && t.isJSXAttribute(attrPath.node) && attrPath.node.name.name === propToUpdate) {
|
|
597
|
-
if (t.isStringLiteral(attrPath.node.value) && doublePlacementValues.has(attrPath.node.value.value)) {
|
|
598
|
-
attrPath.replaceWith(t.jsxAttribute(t.jsxIdentifier(propToUpdate), t.stringLiteral(attrPath.node.value.value.split(' ')[0])));
|
|
599
|
-
return;
|
|
600
|
-
}
|
|
601
|
-
else if (t.isJSXExpressionContainer(attrPath.node.value)) {
|
|
602
|
-
attrPath.traverse({
|
|
603
|
-
StringLiteral(stringPath) {
|
|
604
|
-
if (t.isStringLiteral(stringPath.node) &&
|
|
605
|
-
doublePlacementValues.has(stringPath.node.value)) {
|
|
606
|
-
stringPath.replaceWith(t.stringLiteral(stringPath.node.value.split(' ')[0]));
|
|
607
|
-
return;
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
});
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
/**
|
|
615
|
-
* Remove component if within a parent component.
|
|
616
|
-
*
|
|
617
|
-
* Example:
|
|
618
|
-
* - Divider: Remove `Divider` if used within a `Dialog`.
|
|
619
|
-
*/
|
|
620
|
-
function removeComponentIfWithinParent(path, options) {
|
|
621
|
-
const { parentComponent } = options;
|
|
622
|
-
if (t.isJSXElement(path.node) &&
|
|
623
|
-
t.isJSXElement(path.parentPath.node) &&
|
|
624
|
-
t.isJSXIdentifier(path.node.openingElement.name) &&
|
|
625
|
-
t.isJSXIdentifier(path.parentPath.node.openingElement.name) &&
|
|
626
|
-
(0, utils_1.getName)(path, path.parentPath.node.openingElement.name) === parentComponent) {
|
|
627
|
-
path.remove();
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
function updateAvatarSize(path) {
|
|
631
|
-
if (t.isJSXElement(path.node) &&
|
|
632
|
-
t.isJSXIdentifier(path.node.openingElement.name) &&
|
|
633
|
-
(0, utils_1.getName)(path, path.node.openingElement.name) === 'Avatar') {
|
|
634
|
-
let sizeAttrPath = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === 'size');
|
|
635
|
-
if (sizeAttrPath) {
|
|
636
|
-
let value = sizeAttrPath.node.value;
|
|
637
|
-
if (value?.type === 'StringLiteral') {
|
|
638
|
-
const avatarDimensions = {
|
|
639
|
-
'avatar-size-50': 16,
|
|
640
|
-
'avatar-size-75': 18,
|
|
641
|
-
'avatar-size-100': 20,
|
|
642
|
-
'avatar-size-200': 22,
|
|
643
|
-
'avatar-size-300': 26,
|
|
644
|
-
'avatar-size-400': 28,
|
|
645
|
-
'avatar-size-500': 32,
|
|
646
|
-
'avatar-size-600': 36,
|
|
647
|
-
'avatar-size-700': 40
|
|
648
|
-
};
|
|
649
|
-
let val = avatarDimensions[value.value];
|
|
650
|
-
if (val != null) {
|
|
651
|
-
sizeAttrPath.node.value = t.jsxExpressionContainer(t.numericLiteral(val));
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
/**
|
|
658
|
-
* Handles the legacy `Link` API where an `a` tag or custom router component could be used within a `Link` component.
|
|
659
|
-
* Removes the inner component and moves its attributes to the `Link` component.
|
|
660
|
-
*/
|
|
661
|
-
function updateLegacyLink(path) {
|
|
662
|
-
let missingOuterHref = t.isJSXElement(path.node) && !path.node.openingElement.attributes.some((attr) => t.isJSXAttribute(attr) && attr.name.name === 'href');
|
|
663
|
-
if (missingOuterHref) {
|
|
664
|
-
let innerLink = path.node.children.find((child) => t.isJSXElement(child) && t.isJSXIdentifier(child.openingElement.name));
|
|
665
|
-
if (innerLink && t.isJSXElement(innerLink)) {
|
|
666
|
-
let innerAttributes = innerLink.openingElement.attributes;
|
|
667
|
-
let outerAttributes = path.node.openingElement.attributes;
|
|
668
|
-
innerAttributes.forEach((attr) => {
|
|
669
|
-
outerAttributes.push(attr);
|
|
670
|
-
});
|
|
671
|
-
if (t.isJSXIdentifier(innerLink.openingElement.name) &&
|
|
672
|
-
innerLink.openingElement.name.name !== 'a') {
|
|
673
|
-
(0, utils_1.addComment)(path.node, ' TODO(S2-upgrade): You may have been using a custom link component here. You\'ll need to update this manually.');
|
|
674
|
-
}
|
|
675
|
-
path.node.children = innerLink.children;
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
/**
|
|
680
|
-
* Copies the columns prop from the TableHeader to the Row component.
|
|
681
|
-
*/
|
|
682
|
-
function addColumnsPropToRow(path) {
|
|
683
|
-
const tableHeaderPath = path.get('children').find((child) => t.isJSXElement(child.node) &&
|
|
684
|
-
t.isJSXIdentifier(child.node.openingElement.name) &&
|
|
685
|
-
(0, utils_1.getName)(child, child.node.openingElement.name) === 'TableHeader');
|
|
686
|
-
if (!tableHeaderPath) {
|
|
687
|
-
(0, utils_1.addComment)(path.node, ' TODO(S2-upgrade): Could not find TableHeader within Table to retrieve columns prop.');
|
|
688
|
-
return;
|
|
689
|
-
}
|
|
690
|
-
const columnsProp = tableHeaderPath
|
|
691
|
-
.get('openingElement')
|
|
692
|
-
.get('attributes')
|
|
693
|
-
.find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === 'columns');
|
|
694
|
-
if (columnsProp) {
|
|
695
|
-
path.traverse({
|
|
696
|
-
JSXElement(innerPath) {
|
|
697
|
-
if (t.isJSXElement(innerPath.node) &&
|
|
698
|
-
t.isJSXIdentifier(innerPath.node.openingElement.name) &&
|
|
699
|
-
(0, utils_1.getName)(innerPath, innerPath.node.openingElement.name) === 'Row') {
|
|
700
|
-
let rowPath = innerPath;
|
|
701
|
-
rowPath.node.openingElement.attributes.push(columnsProp.node);
|
|
702
|
-
// If Row doesn't contain id prop, leave a comment for the user to check manually
|
|
703
|
-
let idProp = rowPath.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === 'id');
|
|
704
|
-
if (!idProp) {
|
|
705
|
-
(0, utils_1.addComment)(rowPath.node, ' TODO(S2-upgrade): If the items do not have id properties, you\'ll need to add an id prop to the Row.');
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
});
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
/**
|
|
713
|
-
* Updates the function signature of the Row component.
|
|
714
|
-
*/
|
|
715
|
-
function updateRowFunctionArg(path) {
|
|
716
|
-
// Find the function passed as a child
|
|
717
|
-
let functionChild = path.get('children').find(childPath => childPath.isJSXExpressionContainer() &&
|
|
718
|
-
childPath.get('expression').isArrowFunctionExpression());
|
|
719
|
-
let tablePath = path.findParent((p) => t.isJSXElement(p.node) &&
|
|
720
|
-
t.isJSXIdentifier(p.node.openingElement.name) &&
|
|
721
|
-
(0, utils_1.getName)(path, p.node.openingElement.name) === 'TableView');
|
|
722
|
-
let tableHeaderPath = tablePath?.get('children').find((child) => t.isJSXElement(child.node) &&
|
|
723
|
-
t.isJSXIdentifier(child.node.openingElement.name) &&
|
|
724
|
-
(0, utils_1.getName)(child, child.node.openingElement.name) === 'TableHeader');
|
|
725
|
-
function findColumnKeyProp(path) {
|
|
726
|
-
let columnKeyProp = 'id';
|
|
727
|
-
path.traverse({
|
|
728
|
-
JSXElement(columnPath) {
|
|
729
|
-
if (t.isArrowFunctionExpression(columnPath.parentPath.node) &&
|
|
730
|
-
t.isJSXElement(columnPath.node) &&
|
|
731
|
-
t.isJSXIdentifier(columnPath.node.openingElement.name) &&
|
|
732
|
-
(0, utils_1.getName)(columnPath, columnPath.node.openingElement.name) === 'Column') {
|
|
733
|
-
let openingElement = columnPath.get('openingElement');
|
|
734
|
-
let keyPropPath = openingElement.get('attributes').find(attr => t.isJSXAttribute(attr.node) &&
|
|
735
|
-
(attr.node.name.name === 'key' || attr.node.name.name === 'id'));
|
|
736
|
-
keyPropPath?.traverse({
|
|
737
|
-
Identifier(innerPath) {
|
|
738
|
-
if (innerPath.node.name === 'column' &&
|
|
739
|
-
innerPath.parentPath.node.type === 'MemberExpression' &&
|
|
740
|
-
t.isIdentifier(innerPath.parentPath.node.property)) {
|
|
741
|
-
columnKeyProp = innerPath.parentPath.node.property.name;
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
});
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
});
|
|
748
|
-
return columnKeyProp || 'id';
|
|
749
|
-
}
|
|
750
|
-
let columnKey = findColumnKeyProp(tableHeaderPath);
|
|
751
|
-
if (functionChild && functionChild.isJSXExpressionContainer()) {
|
|
752
|
-
let arrowFuncPath = functionChild.get('expression');
|
|
753
|
-
if (arrowFuncPath.isArrowFunctionExpression()) {
|
|
754
|
-
let params = arrowFuncPath.node.params;
|
|
755
|
-
if (params.length === 1 && t.isIdentifier(params[0])) {
|
|
756
|
-
let paramName = params[0].name;
|
|
757
|
-
// Rename parameter to 'column'
|
|
758
|
-
params[0].name = 'column';
|
|
759
|
-
// Replace references to the old parameter name inside the function body
|
|
760
|
-
arrowFuncPath.get('body').traverse({
|
|
761
|
-
Identifier(innerPath) {
|
|
762
|
-
if (innerPath.node.name === paramName &&
|
|
763
|
-
// Ensure we're not replacing the parameter declaration
|
|
764
|
-
innerPath.node !== params[0]) {
|
|
765
|
-
// Replace with column key
|
|
766
|
-
innerPath.replaceWith(t.memberExpression(t.identifier('column'), t.identifier(columnKey ?? 'id')));
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
});
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
/**
|
|
775
|
-
* Updates the key prop to id. Keeps the key prop if it's used in an array.map function.
|
|
776
|
-
*/
|
|
777
|
-
function updateKeyToId(path) {
|
|
778
|
-
let attributes = path.node.openingElement.attributes;
|
|
779
|
-
let keyProp = attributes.find((attr) => t.isJSXAttribute(attr) && attr.name.name === 'key');
|
|
780
|
-
if (keyProp &&
|
|
781
|
-
t.isJSXAttribute(keyProp)) {
|
|
782
|
-
// Update key prop to be id
|
|
783
|
-
keyProp.name = t.jsxIdentifier('id');
|
|
784
|
-
}
|
|
785
|
-
if (t.isArrowFunctionExpression(path.parentPath.node) &&
|
|
786
|
-
path.parentPath.parentPath &&
|
|
787
|
-
t.isCallExpression(path.parentPath.parentPath.node) &&
|
|
788
|
-
path.parentPath.parentPath.node.callee.type === 'MemberExpression' &&
|
|
789
|
-
path.parentPath.parentPath.node.callee.property.type === 'Identifier' &&
|
|
790
|
-
path.parentPath.parentPath.node.callee.property.name === 'map') {
|
|
791
|
-
// If Array.map is used, keep the key prop
|
|
792
|
-
if (keyProp &&
|
|
793
|
-
t.isJSXAttribute(keyProp)) {
|
|
794
|
-
let newKeyProp = t.jsxAttribute(t.jsxIdentifier('key'), keyProp.value);
|
|
795
|
-
attributes.push(newKeyProp);
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
function commentIfNestedColumns(path) {
|
|
800
|
-
const headerPath = path.get('children').find((child) => t.isJSXElement(child.node) &&
|
|
801
|
-
t.isJSXIdentifier(child.node.openingElement.name) &&
|
|
802
|
-
(0, utils_1.getName)(child, child.node.openingElement.name) === 'TableHeader');
|
|
803
|
-
const columns = headerPath?.get('children') || [];
|
|
804
|
-
let hasNestedColumns = false;
|
|
805
|
-
columns.forEach(column => {
|
|
806
|
-
let columnChildren = column.get('children');
|
|
807
|
-
if (columnChildren.find(child => t.isJSXElement(child.node) &&
|
|
808
|
-
t.isJSXIdentifier(child.node.openingElement.name) &&
|
|
809
|
-
(0, utils_1.getName)(child, child.node.openingElement.name) === 'Column')) {
|
|
810
|
-
hasNestedColumns = true;
|
|
811
|
-
}
|
|
812
|
-
});
|
|
813
|
-
if (hasNestedColumns) {
|
|
814
|
-
(0, utils_1.addComment)(path.node, ' TODO(S2-upgrade): Nested Column components are not supported yet.');
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
/**
|
|
818
|
-
* Updates DialogTrigger and DialogContainer to the new API.
|
|
819
|
-
*
|
|
820
|
-
* Example:
|
|
821
|
-
* - When `type="popover"`, replaces Dialog with `<Popover>`.
|
|
822
|
-
* - When `type="fullscreen"`, replaces Dialog with `<FullscreenDialog>`.
|
|
823
|
-
* - When `type="fullscreenTakeover"`, replaces Dialog with `<FullscreenDialog variant="fullscreenTakeover">`.
|
|
824
|
-
*/
|
|
825
|
-
function updateDialogChild(path) {
|
|
826
|
-
let typePath = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === 'type');
|
|
827
|
-
let type = typePath?.node.value?.type === 'StringLiteral' ? typePath.node.value?.value : 'modal';
|
|
828
|
-
let newComponent = 'Dialog';
|
|
829
|
-
let props = [];
|
|
830
|
-
if (type === 'popover') {
|
|
831
|
-
newComponent = 'Popover';
|
|
832
|
-
}
|
|
833
|
-
else if (type === 'fullscreen' || type === 'fullscreenTakeover') {
|
|
834
|
-
newComponent = 'FullscreenDialog';
|
|
835
|
-
if (type === 'fullscreenTakeover') {
|
|
836
|
-
props.push(t.jsxAttribute(t.jsxIdentifier('variant'), t.stringLiteral(type)));
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
for (let prop of ['isDismissible', 'mobileType', 'hideArrow', 'placement', 'shouldFlip', 'isKeyboardDismissDisabled', 'containerPadding', 'offset', 'crossOffset']) {
|
|
840
|
-
let attr = path.get('openingElement').get('attributes').find(attr => attr.isJSXAttribute() && attr.node.name.name === prop);
|
|
841
|
-
if (attr) {
|
|
842
|
-
props.push(attr.node);
|
|
843
|
-
attr.remove();
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
typePath?.remove();
|
|
847
|
-
let localName = newComponent;
|
|
848
|
-
if (newComponent !== 'Dialog' && availableComponents.has(newComponent)) {
|
|
849
|
-
let program = path.findParent((p) => t.isProgram(p.node));
|
|
850
|
-
localName = (0, utils_1.addComponentImport)(program, newComponent);
|
|
851
|
-
}
|
|
852
|
-
path.traverse({
|
|
853
|
-
JSXElement(dialog) {
|
|
854
|
-
if (!t.isJSXIdentifier(dialog.node.openingElement.name) || (0, utils_1.getName)(dialog, dialog.node.openingElement.name) !== 'Dialog') {
|
|
855
|
-
return;
|
|
856
|
-
}
|
|
857
|
-
dialog.node.openingElement.name = t.jsxIdentifier(localName);
|
|
858
|
-
if (dialog.node.closingElement) {
|
|
859
|
-
dialog.node.closingElement.name = t.jsxIdentifier(localName);
|
|
860
|
-
}
|
|
861
|
-
dialog.node.openingElement.attributes.push(...props);
|
|
862
|
-
}
|
|
863
|
-
});
|
|
864
|
-
}
|
|
865
|
-
function updateActionGroup(path) {
|
|
866
|
-
let selectionModePath = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === 'selectionMode');
|
|
867
|
-
let selectionMode = t.isStringLiteral(selectionModePath?.node.value) ? selectionModePath.node.value.value : 'none';
|
|
868
|
-
let newComponent, childComponent;
|
|
869
|
-
if (selectionMode === 'none') {
|
|
870
|
-
newComponent = 'ActionButtonGroup';
|
|
871
|
-
childComponent = 'ActionButton';
|
|
872
|
-
selectionModePath?.remove();
|
|
873
|
-
}
|
|
874
|
-
else {
|
|
875
|
-
newComponent = 'ToggleButtonGroup';
|
|
876
|
-
childComponent = 'ToggleButton';
|
|
877
|
-
}
|
|
878
|
-
let localName = newComponent;
|
|
879
|
-
if (availableComponents.has(newComponent)) {
|
|
880
|
-
let program = path.findParent((p) => t.isProgram(p.node));
|
|
881
|
-
localName = (0, utils_1.addComponentImport)(program, newComponent);
|
|
882
|
-
}
|
|
883
|
-
let localChildName = childComponent;
|
|
884
|
-
if (availableComponents.has(childComponent)) {
|
|
885
|
-
let program = path.findParent((p) => t.isProgram(p.node));
|
|
886
|
-
localChildName = (0, utils_1.addComponentImport)(program, childComponent);
|
|
887
|
-
}
|
|
888
|
-
// Convert dynamic collection to an array.map.
|
|
889
|
-
let items = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === 'items');
|
|
890
|
-
let itemArg;
|
|
891
|
-
if (items && t.isJSXExpressionContainer(items.node.value) && t.isExpression(items.node.value.expression)) {
|
|
892
|
-
let child = path.get('children').find(c => c.isJSXExpressionContainer());
|
|
893
|
-
if (child && child.isJSXExpressionContainer() && t.isFunction(child.node.expression)) {
|
|
894
|
-
let arg = child.node.expression.params[0];
|
|
895
|
-
if (t.isIdentifier(arg)) {
|
|
896
|
-
itemArg = arg;
|
|
897
|
-
}
|
|
898
|
-
child.replaceWith(t.jsxExpressionContainer(t.callExpression(t.memberExpression(items.node.value.expression, t.identifier('map')), [child.node.expression])));
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
items?.remove();
|
|
902
|
-
let onAction = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === 'onAction');
|
|
903
|
-
// Pull disabledKeys prop out into a variable, converted to a Set.
|
|
904
|
-
// Then we can check it in the isDisabled prop of each item.
|
|
905
|
-
let disabledKeysPath = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === 'disabledKeys');
|
|
906
|
-
let disabledKeys;
|
|
907
|
-
if (disabledKeysPath && t.isJSXExpressionContainer(disabledKeysPath.node.value) && t.isExpression(disabledKeysPath.node.value.expression)) {
|
|
908
|
-
disabledKeys = path.scope.generateUidIdentifier('disabledKeys');
|
|
909
|
-
path.scope.push({
|
|
910
|
-
id: disabledKeys,
|
|
911
|
-
init: t.newExpression(t.identifier('Set'), [disabledKeysPath.node.value.expression]),
|
|
912
|
-
kind: 'let'
|
|
913
|
-
});
|
|
914
|
-
disabledKeysPath.remove();
|
|
915
|
-
}
|
|
916
|
-
path.traverse({
|
|
917
|
-
JSXElement(child) {
|
|
918
|
-
if (t.isJSXIdentifier(child.node.openingElement.name) && child.node.openingElement.name.name === 'Item') {
|
|
919
|
-
// Replace Item with ActionButton or ToggleButton.
|
|
920
|
-
let childNode = t.cloneNode(child.node);
|
|
921
|
-
childNode.openingElement.name = t.jsxIdentifier(localChildName);
|
|
922
|
-
if (childNode.closingElement) {
|
|
923
|
-
childNode.closingElement.name = t.jsxIdentifier(localChildName);
|
|
924
|
-
}
|
|
925
|
-
// If there is no key prop and we are using dynamic collections, add a default computed from item.key ?? item.id.
|
|
926
|
-
let key = childNode.openingElement.attributes.find(attr => t.isJSXAttribute(attr) && attr.name.name === 'key');
|
|
927
|
-
if (!key && itemArg) {
|
|
928
|
-
let id = t.jsxExpressionContainer(t.logicalExpression('??', t.memberExpression(itemArg, t.identifier('key')), t.memberExpression(itemArg, t.identifier('id'))));
|
|
929
|
-
key = t.jsxAttribute(t.jsxIdentifier('key'), id);
|
|
930
|
-
childNode.openingElement.attributes.push(key);
|
|
931
|
-
}
|
|
932
|
-
// If this is a ToggleButtonGroup, add an id prop in addition to key when needed.
|
|
933
|
-
if (key && newComponent === 'ToggleButtonGroup') {
|
|
934
|
-
// If we are in an array.map we need both key and id. Otherwise, we only need id.
|
|
935
|
-
if (itemArg) {
|
|
936
|
-
childNode.openingElement.attributes.push(t.jsxAttribute(t.jsxIdentifier('id'), key.value));
|
|
937
|
-
}
|
|
938
|
-
else {
|
|
939
|
-
key.name.name = 'id';
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
let keyValue = undefined;
|
|
943
|
-
if (key && t.isJSXExpressionContainer(key.value) && t.isExpression(key.value.expression)) {
|
|
944
|
-
keyValue = key.value.expression;
|
|
945
|
-
}
|
|
946
|
-
else if (key && t.isStringLiteral(key.value)) {
|
|
947
|
-
keyValue = key.value;
|
|
948
|
-
}
|
|
949
|
-
// Add an onPress to each item that calls the previous onAction, passing in the key.
|
|
950
|
-
if (onAction && t.isJSXExpressionContainer(onAction.node.value) && t.isExpression(onAction.node.value.expression)) {
|
|
951
|
-
childNode.openingElement.attributes.push(t.jsxAttribute(t.jsxIdentifier('onPress'), t.jsxExpressionContainer(keyValue
|
|
952
|
-
? t.arrowFunctionExpression([], t.callExpression(onAction.node.value.expression, [keyValue]))
|
|
953
|
-
: onAction.node.value.expression)));
|
|
954
|
-
}
|
|
955
|
-
// Add an isDisabled prop to each item, testing whether it is in disabledKeys.
|
|
956
|
-
if (disabledKeys && keyValue) {
|
|
957
|
-
childNode.openingElement.attributes.push(t.jsxAttribute(t.jsxIdentifier('isDisabled'), t.jsxExpressionContainer(t.callExpression(t.memberExpression(disabledKeys, t.identifier('has')), [keyValue]))));
|
|
958
|
-
}
|
|
959
|
-
child.replaceWith(childNode);
|
|
960
|
-
}
|
|
961
|
-
}
|
|
962
|
-
});
|
|
963
|
-
onAction?.remove();
|
|
964
|
-
path.node.openingElement.name = t.jsxIdentifier(localName);
|
|
965
|
-
if (path.node.closingElement) {
|
|
966
|
-
path.node.closingElement.name = t.jsxIdentifier(localName);
|
|
967
|
-
}
|
|
968
|
-
}
|
|
969
|
-
/**
|
|
970
|
-
* Adds isRowHeader to the first Column in a table if there isn't already a row header.
|
|
971
|
-
* @param path
|
|
972
|
-
*/
|
|
973
|
-
function addRowHeader(path) {
|
|
974
|
-
let tableHeaderPath = path.get('children').find((child) => t.isJSXElement(child.node) &&
|
|
975
|
-
t.isJSXIdentifier(child.node.openingElement.name) &&
|
|
976
|
-
(0, utils_1.getName)(child, child.node.openingElement.name) === 'TableHeader');
|
|
977
|
-
// Check if isRowHeader is already set on a Column
|
|
978
|
-
let hasRowHeader = false;
|
|
979
|
-
tableHeaderPath?.get('children').forEach((child) => {
|
|
980
|
-
if (t.isJSXElement(child.node) &&
|
|
981
|
-
t.isJSXIdentifier(child.node.openingElement.name) &&
|
|
982
|
-
(0, utils_1.getName)(child, child.node.openingElement.name) === 'Column') {
|
|
983
|
-
let isRowHeaderProp = child.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === 'isRowHeader');
|
|
984
|
-
if (isRowHeaderProp) {
|
|
985
|
-
hasRowHeader = true;
|
|
986
|
-
}
|
|
987
|
-
}
|
|
988
|
-
});
|
|
989
|
-
// If there isn't already a row header, add one to the first Column if possible
|
|
990
|
-
if (!hasRowHeader) {
|
|
991
|
-
tableHeaderPath?.get('children').forEach((child) => {
|
|
992
|
-
// Add to first Column if static
|
|
993
|
-
if (!hasRowHeader &&
|
|
994
|
-
t.isJSXElement(child.node) &&
|
|
995
|
-
t.isJSXIdentifier(child.node.openingElement.name) &&
|
|
996
|
-
(0, utils_1.getName)(child, child.node.openingElement.name) === 'Column') {
|
|
997
|
-
child.node.openingElement.attributes.push(t.jsxAttribute(t.jsxIdentifier('isRowHeader'), t.jsxExpressionContainer(t.booleanLiteral(true))));
|
|
998
|
-
hasRowHeader = true;
|
|
999
|
-
}
|
|
1000
|
-
// If render function is used, leave a comment to update manually
|
|
1001
|
-
if (t.isJSXExpressionContainer(child.node) &&
|
|
1002
|
-
t.isArrowFunctionExpression(child.node.expression)) {
|
|
1003
|
-
(0, utils_1.addComment)(child.node, ' TODO(S2-upgrade): You\'ll need to add isRowHeader to one of the columns manually.');
|
|
1004
|
-
}
|
|
1005
|
-
// If array.map is used, leave a comment to update manually
|
|
1006
|
-
if (t.isJSXExpressionContainer(child.node) &&
|
|
1007
|
-
t.isCallExpression(child.node.expression) &&
|
|
1008
|
-
t.isMemberExpression(child.node.expression.callee) &&
|
|
1009
|
-
t.isIdentifier(child.node.expression.callee.property) &&
|
|
1010
|
-
child.node.expression.callee.property.name === 'map') {
|
|
1011
|
-
(0, utils_1.addComment)(child.node, ' TODO(S2-upgrade): You\'ll need to add isRowHeader to one of the columns manually.');
|
|
1012
|
-
}
|
|
1013
|
-
});
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
exports.functionMap = {
|
|
1017
|
-
updatePropNameAndValue,
|
|
1018
|
-
updatePropValueAndAddNewProp,
|
|
1019
|
-
updatePropName,
|
|
1020
|
-
removeProp,
|
|
1021
|
-
commentOutProp,
|
|
1022
|
-
addCommentToElement,
|
|
1023
|
-
updateComponentIfPropPresent,
|
|
1024
|
-
moveRenderPropsToChild,
|
|
1025
|
-
updateComponentWithinCollection,
|
|
1026
|
-
commentIfParentCollectionNotDetected,
|
|
1027
|
-
updateTabs,
|
|
1028
|
-
movePropToNewChildComponent,
|
|
1029
|
-
movePropToParentComponent,
|
|
1030
|
-
updateToNewComponent,
|
|
1031
|
-
convertDimensionValueToPx,
|
|
1032
|
-
updatePlacementToSingleValue,
|
|
1033
|
-
removeComponentIfWithinParent,
|
|
1034
|
-
updateAvatarSize,
|
|
1035
|
-
updateLegacyLink,
|
|
1036
|
-
addColumnsPropToRow,
|
|
1037
|
-
updateRowFunctionArg,
|
|
1038
|
-
updateDialogChild,
|
|
1039
|
-
updateActionGroup,
|
|
1040
|
-
updateKeyToId,
|
|
1041
|
-
commentIfNestedColumns,
|
|
1042
|
-
addRowHeader
|
|
1043
|
-
};
|