@react-spectrum/codemods 1.0.1 → 1.2.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 CHANGED
@@ -4,9 +4,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const { parseArgs } = require('node:util');
5
5
  const src_1 = require("./s1-to-s2/src");
6
6
  const src_2 = require("./use-monopackages/src");
7
+ const src_3 = require("./use-subpaths/src");
7
8
  const codemods = {
8
9
  's1-to-s2': src_1.s1_to_s2,
9
- 'use-monopackages': src_2.use_monopackages
10
+ 'use-monopackages': src_2.use_monopackages,
11
+ 'use-subpaths': src_3.use_subpaths
10
12
  };
11
13
  // https://github.com/facebook/jscodeshift?tab=readme-ov-file#usage-cli
12
14
  const options = {
@@ -25,6 +27,9 @@ const options = {
25
27
  },
26
28
  'components': {
27
29
  type: 'string'
30
+ },
31
+ 'agent': {
32
+ type: 'boolean'
28
33
  }
29
34
  };
30
35
  const { values, positionals } = parseArgs({
@@ -35,21 +40,22 @@ if (positionals.length < 1) {
35
40
  console.error('Please specify a codemod to run. Available codemods: ', Object.keys(codemods).join(', '));
36
41
  process.exit(1);
37
42
  }
38
- const codemodName = positionals[0];
39
- const codemodFunction = codemods[codemodName];
40
- if (!codemodFunction) {
41
- console.error(`Unknown codemod: ${codemodName}, available codemods: ${Object.keys(codemods).join(', ')}`);
42
- process.exit(1);
43
- }
44
- try {
45
- codemodFunction({
43
+ async function main() {
44
+ const codemodName = positionals[0];
45
+ const codemodFunction = codemods[codemodName];
46
+ if (!codemodFunction) {
47
+ console.error(`Unknown codemod: ${codemodName}, available codemods: ${Object.keys(codemods).join(', ')}`);
48
+ process.exit(1);
49
+ }
50
+ await Promise.resolve(codemodFunction({
46
51
  parser: 'tsx',
47
52
  ignorePattern: '**/node_modules/**',
48
53
  path: '.',
54
+ extensions: 'js,jsx,mjs,cjs,ts,tsx',
49
55
  ...values
50
- });
56
+ }));
51
57
  }
52
- catch (error) {
58
+ main().catch((error) => {
53
59
  console.error(`Error running codemod: ${error}`);
54
60
  process.exit(1);
55
- }
61
+ });
@@ -41,6 +41,7 @@ exports.default = transformer;
41
41
  const utils_1 = require("./shared/utils");
42
42
  const getComponents_1 = require("../getComponents");
43
43
  const iconMap_1 = require("./icons/iconMap");
44
+ const illustrationMap_1 = require("./illustrations/illustrationMap");
44
45
  const recast_1 = require("recast");
45
46
  const t = __importStar(require("@babel/types"));
46
47
  const styleProps_1 = __importDefault(require("./shared/styleProps"));
@@ -59,6 +60,112 @@ availableComponents.add('Section');
59
60
  availableComponents.delete('Provider');
60
61
  // Replaced by ActionButtonGroup and ToggleButtonGroup
61
62
  availableComponents.add('ActionGroup');
63
+ // components renamed between v3 and S2
64
+ let renamedComponents = {
65
+ ContextualHelpTrigger: 'UnavailableMenuItemTrigger'
66
+ };
67
+ const relatedComponentGroups = {
68
+ ActionMenu: {
69
+ scopedComponents: {
70
+ Item: ['ActionMenu']
71
+ }
72
+ },
73
+ Breadcrumbs: {
74
+ scopedComponents: {
75
+ Item: ['Breadcrumbs']
76
+ }
77
+ },
78
+ ComboBox: {
79
+ scopedComponents: {
80
+ Item: ['ComboBox'],
81
+ Section: ['ComboBox']
82
+ }
83
+ },
84
+ DialogContainer: {
85
+ components: ['Dialog']
86
+ },
87
+ DialogTrigger: {
88
+ components: ['Dialog']
89
+ },
90
+ Menu: {
91
+ components: ['ContextualHelpTrigger', 'MenuTrigger', 'SubmenuTrigger'],
92
+ scopedComponents: {
93
+ Item: ['Menu'],
94
+ Section: ['Menu']
95
+ }
96
+ },
97
+ Picker: {
98
+ scopedComponents: {
99
+ Item: ['Picker'],
100
+ Section: ['Picker']
101
+ }
102
+ },
103
+ TableView: {
104
+ components: ['Cell', 'Column', 'Row', 'TableBody', 'TableHeader']
105
+ },
106
+ Tabs: {
107
+ components: ['TabList', 'TabPanels']
108
+ },
109
+ TagGroup: {
110
+ scopedComponents: {
111
+ Item: ['TagGroup']
112
+ }
113
+ },
114
+ TooltipTrigger: {
115
+ components: ['Tooltip']
116
+ }
117
+ };
118
+ function addScopedParents(scopedComponents, component, parents) {
119
+ let existingParents = scopedComponents.get(component) ?? new Set();
120
+ for (let parent of parents) {
121
+ existingParents.add(parent);
122
+ }
123
+ scopedComponents.set(component, existingParents);
124
+ }
125
+ function getComponentSelection(components) {
126
+ if (!components) {
127
+ return {
128
+ components: new Set(availableComponents),
129
+ explicitComponents: new Set(availableComponents),
130
+ scopedComponents: new Map()
131
+ };
132
+ }
133
+ let explicitComponents = new Set(components.split(',').map(s => s.trim()).filter(Boolean));
134
+ let expandedComponents = new Set(explicitComponents);
135
+ let scopedComponents = new Map();
136
+ for (let component of explicitComponents) {
137
+ let relatedComponents = relatedComponentGroups[component];
138
+ if (!relatedComponents) {
139
+ continue;
140
+ }
141
+ for (let relatedComponent of relatedComponents.components ?? []) {
142
+ expandedComponents.add(relatedComponent);
143
+ }
144
+ for (let [relatedComponent, parents] of Object.entries(relatedComponents.scopedComponents ?? {})) {
145
+ expandedComponents.add(relatedComponent);
146
+ if (!explicitComponents.has(relatedComponent)) {
147
+ addScopedParents(scopedComponents, relatedComponent, parents);
148
+ }
149
+ }
150
+ }
151
+ return {
152
+ components: new Set([...expandedComponents].filter(component => availableComponents.has(component))),
153
+ explicitComponents: new Set([...explicitComponents].filter(component => availableComponents.has(component))),
154
+ scopedComponents
155
+ };
156
+ }
157
+ function shouldTransformElement(componentName, path, selection) {
158
+ if (selection.explicitComponents.has(componentName)) {
159
+ return true;
160
+ }
161
+ let allowedParents = selection.scopedComponents.get(componentName);
162
+ if (!allowedParents || allowedParents.size === 0) {
163
+ return true;
164
+ }
165
+ return !!path.findParent((parentPath) => t.isJSXElement(parentPath.node)
166
+ && t.isJSXIdentifier(parentPath.node.openingElement.name)
167
+ && allowedParents.has((0, utils_1.getName)(path, parentPath.node.openingElement.name)));
168
+ }
62
169
  function transformer(file, api, options) {
63
170
  let j = api.jscodeshift.withParser({
64
171
  parse(source) {
@@ -68,14 +175,22 @@ function transformer(file, api, options) {
68
175
  }
69
176
  });
70
177
  let root = j(file.source);
71
- let componentsToTransform = options.components ? new Set(options.components.split(',').filter(s => availableComponents.has(s))) : availableComponents;
178
+ let selection = getComponentSelection(options.components);
179
+ let componentsToTransform = selection.components;
180
+ let v3ComponentsToRename = new Set(Object.keys(renamedComponents));
181
+ let S2ComponentsToImport = new Set();
72
182
  let bindings = [];
73
183
  let importedComponents = new Map();
74
184
  let elements = [];
75
185
  let lastImportPath = null;
76
186
  let iconImports = new Map();
187
+ let illustrationImports = new Map();
188
+ let programPath = null;
77
189
  const leadingComments = root.find(j.Program).get('body', 0).node.leadingComments;
78
190
  (0, traverse_1.default)(root.paths()[0].node, {
191
+ Program(path) {
192
+ programPath = path;
193
+ },
79
194
  ImportDeclaration(path) {
80
195
  if (path.node.source.value === '@adobe/react-spectrum' || (path.node.source.value.startsWith('@react-spectrum/') && path.node.source.value !== '@react-spectrum/s2')) {
81
196
  lastImportPath = path;
@@ -87,9 +202,22 @@ function transformer(file, api, options) {
87
202
  if (binding) {
88
203
  let isUsed = false;
89
204
  for (let path of binding.referencePaths) {
90
- if (path.parentPath?.isJSXMemberExpression() && componentsToTransform.has(path.parentPath.node.property.name) && path.parentPath.parentPath.parentPath?.isJSXElement()) {
91
- importedComponents.set(path.parentPath.node.property.name, clonedSpecifier);
92
- elements.push([path.parentPath.node.property.name, path.parentPath.parentPath.parentPath]);
205
+ let propName = path.parentPath?.isJSXMemberExpression() && path.parentPath.node.property.name;
206
+ if (propName && path.parentPath.parentPath?.parentPath?.isJSXElement()) {
207
+ if (componentsToTransform.has(propName)) {
208
+ importedComponents.set(propName, clonedSpecifier);
209
+ let elementPath = path.parentPath.parentPath.parentPath;
210
+ if (shouldTransformElement(propName, elementPath, selection)) {
211
+ elements.push([propName, elementPath]);
212
+ }
213
+ }
214
+ else if (v3ComponentsToRename.has(propName)) {
215
+ S2ComponentsToImport.add(renamedComponents[propName]);
216
+ elements.push([propName, path.parentPath.parentPath.parentPath]);
217
+ }
218
+ else {
219
+ isUsed = true;
220
+ }
93
221
  }
94
222
  else {
95
223
  isUsed = true;
@@ -112,15 +240,23 @@ function transformer(file, api, options) {
112
240
  typeof specifier.local.name === 'string' &&
113
241
  specifier.imported.type === 'Identifier' &&
114
242
  typeof specifier.imported.name === 'string' &&
115
- componentsToTransform.has(specifier.imported.name)) {
116
- // e.g. import {Button} from '@adobe/react-spectrum';
243
+ (componentsToTransform.has(specifier.imported.name) || v3ComponentsToRename.has(specifier.imported.name))) {
244
+ // e.g. import {Button} from '@adobe/react-spectrum'; or import {ContextualHelpTrigger} from '@adobe/react-spectrum';
117
245
  let binding = path.scope.getBinding(specifier.local.name);
118
246
  if (binding) {
119
- importedComponents.set(specifier.imported.name, specifier);
247
+ if (componentsToTransform.has(specifier.imported.name)) {
248
+ importedComponents.set(specifier.imported.name, specifier);
249
+ }
250
+ else {
251
+ S2ComponentsToImport.add(renamedComponents[specifier.imported.name]);
252
+ }
120
253
  bindings.push(binding);
121
254
  for (let path of binding.referencePaths) {
122
255
  if (path.parentPath?.isJSXOpeningElement() && path.parentPath.parentPath.isJSXElement()) {
123
- elements.push([specifier.imported.name, path.parentPath.parentPath]);
256
+ let elementPath = path.parentPath.parentPath;
257
+ if (shouldTransformElement(specifier.imported.name, elementPath, selection)) {
258
+ elements.push([specifier.imported.name, elementPath]);
259
+ }
124
260
  }
125
261
  }
126
262
  }
@@ -146,6 +282,24 @@ function transformer(file, api, options) {
146
282
  iconImports.set(localName, { path, newName: null });
147
283
  }
148
284
  }
285
+ else if (path.node.source.value.startsWith('@spectrum-icons/illustrations/')) {
286
+ let illustrationName = path.node.source.value.split('/').pop();
287
+ if (!illustrationName) {
288
+ return;
289
+ }
290
+ let specifier = path.node.specifiers[0];
291
+ if (!specifier || !t.isImportDefaultSpecifier(specifier)) {
292
+ return;
293
+ }
294
+ let localName = specifier.local.name;
295
+ if (illustrationMap_1.illustrationMap.has(illustrationName)) {
296
+ let newIllustrationName = illustrationMap_1.illustrationMap.get(illustrationName);
297
+ illustrationImports.set(localName, { path, newName: newIllustrationName });
298
+ }
299
+ else {
300
+ illustrationImports.set(localName, { path, newName: null });
301
+ }
302
+ }
149
303
  },
150
304
  Import(path) {
151
305
  let call = path.parentPath;
@@ -156,7 +310,9 @@ function transformer(file, api, options) {
156
310
  if (arg.type !== 'StringLiteral') {
157
311
  return;
158
312
  }
159
- if (arg.value !== '@adobe/react-spectrum' && !arg.value.startsWith('@react-spectrum/')) {
313
+ let isV3ImportSource = arg.value === '@adobe/react-spectrum'
314
+ || (arg.value.startsWith('@react-spectrum/') && arg.value !== '@react-spectrum/s2');
315
+ if (!isV3ImportSource) {
160
316
  return;
161
317
  }
162
318
  // TODO: implement this. could be a bit challenging. punting for now.
@@ -170,6 +326,12 @@ function transformer(file, api, options) {
170
326
  (0, utils_1.addComment)(path.node, ` TODO(S2-upgrade): A Spectrum 2 equivalent to '${name.name}' was not found. Please update this icon manually.`);
171
327
  }
172
328
  }
329
+ if (t.isJSXIdentifier(name) && illustrationImports.has(name.name)) {
330
+ let illustrationInfo = illustrationImports.get(name.name);
331
+ if (illustrationInfo.newName === null) {
332
+ (0, utils_1.addComment)(path.node, ` TODO(S2-upgrade): A Spectrum 2 equivalent to '${name.name}' was not found. Please update this illustration manually.`);
333
+ }
334
+ }
173
335
  }
174
336
  });
175
337
  iconImports.forEach((iconInfo, localName) => {
@@ -195,6 +357,26 @@ function transformer(file, api, options) {
195
357
  path.node.specifiers = [t.importDefaultSpecifier(t.identifier(newLocalName))];
196
358
  }
197
359
  });
360
+ illustrationImports.forEach((illustrationInfo, localName) => {
361
+ let { path, newName } = illustrationInfo;
362
+ if (newName) {
363
+ let newImportSource = `@react-spectrum/s2/illustrations/linear/${newName}`;
364
+ let newLocalName = localName;
365
+ if (localName === path.node.source.value.split('/').pop() && localName !== newName) {
366
+ let binding = path.scope.getBinding(localName);
367
+ if (binding && !path.scope.hasBinding(newName)) {
368
+ newLocalName = newName;
369
+ binding.referencePaths.forEach(refPath => {
370
+ if (t.isJSXIdentifier(refPath.node)) {
371
+ refPath.node.name = newName;
372
+ }
373
+ });
374
+ }
375
+ }
376
+ path.node.source = t.stringLiteral(newImportSource);
377
+ path.node.specifiers = [t.importDefaultSpecifier(t.identifier(newLocalName))];
378
+ }
379
+ });
198
380
  let hasMacros = false;
199
381
  let usedLightDark = false;
200
382
  elements.forEach(([elementName, path]) => {
@@ -234,26 +416,37 @@ function transformer(file, api, options) {
234
416
  macroImport.assertions = [t.importAttribute(t.identifier('type'), t.stringLiteral('macro'))];
235
417
  lastImportPath.insertAfter(macroImport);
236
418
  }
237
- if (importedComponents.size) {
419
+ if (importedComponents.size || S2ComponentsToImport.size) {
238
420
  // Add imports to existing @react-spectrum/s2 import if it exists, otherwise add a new one.
239
421
  let importSpecifiers = new Set([...importedComponents]
240
422
  .filter(([c]) => c !== 'Flex' && c !== 'Grid' && c !== 'View' && c !== 'Item' && c !== 'Section' && c !== 'ActionGroup')
241
423
  .map(([, specifier]) => specifier));
424
+ for (let s2Name of S2ComponentsToImport) {
425
+ importSpecifiers.add(t.importSpecifier(t.identifier(s2Name), t.identifier(s2Name)));
426
+ }
242
427
  let existingImport = root.find(j.ImportDeclaration, {
243
428
  source: { value: '@react-spectrum/s2' }
244
429
  });
245
430
  if (existingImport.length) {
246
431
  let importDecl = existingImport.get();
247
- for (let specifier of importDecl.node.specifiers) {
248
- if (specifier.type === 'ImportSpecifier'
249
- && importedComponents.has(specifier.imported.name)) {
250
- importSpecifiers.add(specifier);
251
- }
252
- }
432
+ let existingSpecifiers = importDecl.value.specifiers;
253
433
  // add importSpecifiers to existing import
254
434
  importDecl.value.specifiers = [...importDecl.value.specifiers, ...[...importSpecifiers].filter(specifier => {
255
- // @ts-ignore
256
- return specifier.imported.name !== 'Item' && ![...importDecl.value.specifiers].find(s => s.imported.name === specifier.imported.name);
435
+ if (t.isImportSpecifier(specifier) && t.isIdentifier(specifier.imported)) {
436
+ if (specifier.imported.name === 'Item') {
437
+ return false;
438
+ }
439
+ let importedName = specifier.imported.name;
440
+ let localName = specifier.local?.name || importedName;
441
+ return !existingSpecifiers.find((s) => t.isImportSpecifier(s)
442
+ && t.isIdentifier(s.imported)
443
+ && s.imported.name === importedName
444
+ && (s.local?.name || s.imported.name) === localName);
445
+ }
446
+ if (t.isImportNamespaceSpecifier(specifier)) {
447
+ return !existingSpecifiers.find((s) => t.isImportNamespaceSpecifier(s) && s.local.name === specifier.local.name);
448
+ }
449
+ return false;
257
450
  })];
258
451
  }
259
452
  else {
@@ -281,6 +474,9 @@ function transformer(file, api, options) {
281
474
  }
282
475
  });
283
476
  }
477
+ if (programPath) {
478
+ (0, utils_1.removeUnusedImports)(programPath, ['@react-spectrum/s2']);
479
+ }
284
480
  root.find(j.Program).get('body', 0).node.comments = leadingComments;
285
481
  return root.toSource().replace(/assert\s*\{\s*type:\s*"macro"\s*\}/g, 'with { type: "macro" }');
286
482
  }
@@ -51,6 +51,7 @@ let availableComponents = (0, getComponents_1.getComponents)();
51
51
  * - Convert dynamic collections render function to items.map.
52
52
  */
53
53
  function transformActionGroup(path) {
54
+ let program = path.findParent((p) => t.isProgram(p.node));
54
55
  // Comment out overflowMode
55
56
  (0, transforms_1.commentOutProp)(path, { propName: 'overflowMode' });
56
57
  // Comment out buttonLabelBehavior
@@ -73,12 +74,10 @@ function transformActionGroup(path) {
73
74
  }
74
75
  let localName = newComponentName;
75
76
  if (availableComponents.has(newComponentName)) {
76
- let program = path.findParent((p) => t.isProgram(p.node));
77
77
  localName = (0, utils_1.addComponentImport)(program, newComponentName);
78
78
  }
79
79
  let localChildName = childComponentName;
80
80
  if (availableComponents.has(childComponentName)) {
81
- let program = path.findParent((p) => t.isProgram(p.node));
82
81
  localChildName = (0, utils_1.addComponentImport)(program, childComponentName);
83
82
  }
84
83
  // Convert dynamic collection to an array.map.
@@ -161,4 +160,5 @@ function transformActionGroup(path) {
161
160
  if (path.node.closingElement) {
162
161
  path.node.closingElement.name = t.jsxIdentifier(localName);
163
162
  }
163
+ (0, utils_1.removeComponentImportIfUnused)(program, 'Item');
164
164
  }
@@ -4,12 +4,12 @@ exports.default = transformActionMenu;
4
4
  const transforms_1 = require("../../shared/transforms");
5
5
  /**
6
6
  * Transforms ActionMenu:
7
- * - Comment out closeOnSelect (it has not been implemented yet).
7
+ * - Rename `closeOnSelect` to `shouldCloseOnSelect`.
8
8
  * - Comment out trigger (it has not been implemented yet).
9
9
  */
10
10
  function transformActionMenu(path) {
11
- // Comment out closeOnSelect
12
- (0, transforms_1.commentOutProp)(path, { propName: 'closeOnSelect' });
11
+ // Rename `closeOnSelect` to `shouldCloseOnSelect`
12
+ (0, transforms_1.updatePropName)(path, { oldPropName: 'closeOnSelect', newPropName: 'shouldCloseOnSelect' });
13
13
  // Comment out trigger
14
14
  (0, transforms_1.commentOutProp)(path, { propName: 'trigger' });
15
15
  }
@@ -0,0 +1,69 @@
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.default = transformContextualHelpTrigger;
37
+ const utils_1 = require("../../shared/utils");
38
+ const getComponents_1 = require("../../../getComponents");
39
+ const t = __importStar(require("@babel/types"));
40
+ let availableComponents = (0, getComponents_1.getComponents)();
41
+ /**
42
+ * Transforms ContextualHelpTrigger:
43
+ * - Rename ContextualHelpTrigger to UnavailableMenuItemTrigger.
44
+ * - Replace the old Dialog with ContextualHelpPopover.
45
+ */
46
+ function transformContextualHelpTrigger(path) {
47
+ let program = path.findParent((p) => t.isProgram(p.node));
48
+ let localName = (0, utils_1.addComponentImport)(program, 'UnavailableMenuItemTrigger');
49
+ // replace ContextualHelpTrigger with UnavailableMenuItemTrigger
50
+ path.node.openingElement.name = t.jsxIdentifier(localName);
51
+ if (path.node.closingElement) {
52
+ path.node.closingElement.name = t.jsxIdentifier(localName);
53
+ }
54
+ // replace Dialog with ContextualHelpPopover
55
+ let dialog = path.node.children.filter((c) => t.isJSXElement(c))[1];
56
+ if (dialog && t.isJSXIdentifier(dialog.openingElement.name)) {
57
+ let name = (0, utils_1.getName)(path, dialog.openingElement.name);
58
+ if (name === 'Dialog') {
59
+ let contextualHelpPopover = availableComponents.has('ContextualHelpPopover')
60
+ ? (0, utils_1.addComponentImport)(program, 'ContextualHelpPopover')
61
+ : 'ContextualHelpPopover';
62
+ dialog.openingElement.name = t.jsxIdentifier(contextualHelpPopover);
63
+ if (dialog.closingElement) {
64
+ dialog.closingElement.name = t.jsxIdentifier(contextualHelpPopover);
65
+ }
66
+ }
67
+ }
68
+ (0, utils_1.removeComponentImportIfUnused)(program, 'Dialog');
69
+ }
@@ -49,6 +49,7 @@ let availableComponents = (0, getComponents_1.getComponents)();
49
49
  * - When `type="fullscreenTakeover"`, replaces Dialog with `<FullscreenDialog variant="fullscreenTakeover">`.
50
50
  */
51
51
  function updateDialogChild(path) {
52
+ let program = path.findParent((p) => t.isProgram(p.node));
52
53
  let typePath = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === 'type');
53
54
  let type = typePath?.node.value?.type === 'StringLiteral' ? typePath.node.value?.value : 'modal';
54
55
  let newComponentName = 'Dialog';
@@ -72,7 +73,6 @@ function updateDialogChild(path) {
72
73
  typePath?.remove();
73
74
  let localName = newComponentName;
74
75
  if (newComponentName !== 'Dialog' && availableComponents.has(newComponentName)) {
75
- let program = path.findParent((p) => t.isProgram(p.node));
76
76
  localName = (0, utils_1.addComponentImport)(program, newComponentName);
77
77
  }
78
78
  path.traverse({
@@ -87,6 +87,20 @@ function updateDialogChild(path) {
87
87
  dialog.node.openingElement.attributes.push(...props);
88
88
  }
89
89
  });
90
+ path.traverse({
91
+ JSXElement(childPath) {
92
+ if (t.isJSXIdentifier(childPath.node.openingElement.name)
93
+ && (0, utils_1.getName)(childPath, childPath.node.openingElement.name) === 'Divider'
94
+ && t.isJSXElement(childPath.parentPath.node)
95
+ && t.isJSXIdentifier(childPath.parentPath.node.openingElement.name)) {
96
+ let parentName = (0, utils_1.getName)(childPath, childPath.parentPath.node.openingElement.name);
97
+ if (parentName === 'Dialog' || parentName === 'Popover' || parentName === 'FullscreenDialog') {
98
+ childPath.remove();
99
+ }
100
+ }
101
+ }
102
+ });
103
+ (0, utils_1.removeComponentImportIfUnused)(program, 'Divider');
90
104
  }
91
105
  /**
92
106
  * Transforms DialogTrigger:
@@ -10,16 +10,19 @@ const transforms_1 = require("../../shared/transforms");
10
10
  * - If within Breadcrumbs: Update Item to be a Breadcrumb.
11
11
  * - If within Picker: Update Item to be a PickerItem.
12
12
  * - If within ComboBox: Update Item to be a ComboBoxItem.
13
+ * - If within ListView: Update Item to be a ListViewItem.
13
14
  * - Update key to id (and keep key if rendered inside array.map).
14
15
  */
15
16
  function transformItem(path) {
16
17
  // Update Items based on parent collection component
17
18
  (0, transforms_1.updateComponentWithinCollection)(path, { parentComponentName: 'Menu', newComponentName: 'MenuItem' });
18
19
  (0, transforms_1.updateComponentWithinCollection)(path, { parentComponentName: 'ActionMenu', newComponentName: 'MenuItem' });
20
+ (0, transforms_1.updateComponentWithinCollection)(path, { parentComponentName: 'ContextualHelpTrigger', newComponentName: 'MenuItem' });
19
21
  (0, transforms_1.updateComponentWithinCollection)(path, { parentComponentName: 'TagGroup', newComponentName: 'Tag' });
20
22
  (0, transforms_1.updateComponentWithinCollection)(path, { parentComponentName: 'Breadcrumbs', newComponentName: 'Breadcrumb' });
21
23
  (0, transforms_1.updateComponentWithinCollection)(path, { parentComponentName: 'Picker', newComponentName: 'PickerItem' });
22
24
  (0, transforms_1.updateComponentWithinCollection)(path, { parentComponentName: 'ComboBox', newComponentName: 'ComboBoxItem' });
25
+ (0, transforms_1.updateComponentWithinCollection)(path, { parentComponentName: 'ListView', newComponentName: 'ListViewItem' });
23
26
  // Comment if parent collection not detected
24
27
  (0, transforms_1.commentIfParentCollectionNotDetected)(path);
25
28
  }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = transformListView;
4
+ const transforms_1 = require("../../shared/transforms");
5
+ /**
6
+ * Transforms ListView:
7
+ * - Comment out density (it has not been implemented yet).
8
+ * - Comment out dragAndDropHooks (it has not been implemented yet).
9
+ */
10
+ function transformListView(path) {
11
+ (0, transforms_1.commentOutProp)(path, { propName: 'density' });
12
+ (0, transforms_1.commentOutProp)(path, { propName: 'dragAndDropHooks' });
13
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = transformMenuTrigger;
4
+ const transforms_1 = require("../../shared/transforms");
5
+ /**
6
+ * Transforms MenuTrigger:
7
+ * - Rename `closeOnSelect` to `shouldCloseOnSelect` and move it to the child `Menu`.
8
+ */
9
+ function transformMenuTrigger(path) {
10
+ (0, transforms_1.updatePropName)(path, { oldPropName: 'closeOnSelect', newPropName: 'shouldCloseOnSelect' });
11
+ (0, transforms_1.movePropToChildComponent)(path, {
12
+ parentComponentName: 'MenuTrigger',
13
+ childComponentName: 'Menu',
14
+ propName: 'shouldCloseOnSelect'
15
+ });
16
+ }
@@ -9,6 +9,9 @@ const transforms_1 = require("../../shared/transforms");
9
9
  * - Change validationState="invalid" to isInvalid.
10
10
  * - Remove validationState="valid" (it is no longer supported in Spectrum 2).
11
11
  * - Replace isLoading with loadingState.
12
+ * - Rename onSelectionChange to onChange.
13
+ * - Rename selectedKey to value.
14
+ * - Rename defaultSelectedKey to defaultValue.
12
15
  */
13
16
  function transformPicker(path) {
14
17
  // Change menuWidth value from a DimensionValue to a pixel value
@@ -30,4 +33,19 @@ function transformPicker(path) {
30
33
  newPropName: 'loadingState',
31
34
  comment: 'Replace boolean passed to isLoading with appropriate loadingState.'
32
35
  });
36
+ // Rename onSelectionChange to onChange
37
+ (0, transforms_1.updatePropName)(path, {
38
+ oldPropName: 'onSelectionChange',
39
+ newPropName: 'onChange'
40
+ });
41
+ // Rename selectedKey to value
42
+ (0, transforms_1.updatePropName)(path, {
43
+ oldPropName: 'selectedKey',
44
+ newPropName: 'value'
45
+ });
46
+ // Rename defaultSelectedKey to defaultValue
47
+ (0, transforms_1.updatePropName)(path, {
48
+ oldPropName: 'defaultSelectedKey',
49
+ newPropName: 'defaultValue'
50
+ });
33
51
  }
@@ -38,11 +38,12 @@ const utils_1 = require("../../shared/utils");
38
38
  const transforms_1 = require("../../shared/transforms");
39
39
  const t = __importStar(require("@babel/types"));
40
40
  function transformTabList(tabListPath) {
41
- tabListPath.get('children').forEach(itemPath => {
42
- if (t.isJSXElement(itemPath.node) &&
43
- t.isJSXIdentifier(itemPath.node.openingElement.name) &&
44
- (0, utils_1.getName)(itemPath, itemPath.node.openingElement.name) === 'Item') {
45
- (0, transforms_1.updateComponentWithinCollection)(itemPath, { parentComponentName: 'TabList', newComponentName: 'Tab' });
41
+ tabListPath.traverse({
42
+ JSXElement(itemPath) {
43
+ if (t.isJSXIdentifier(itemPath.node.openingElement.name) &&
44
+ (0, utils_1.getName)(itemPath, itemPath.node.openingElement.name) === 'Item') {
45
+ (0, transforms_1.updateComponentWithinCollection)(itemPath, { parentComponentName: 'TabList', newComponentName: 'Tab' });
46
+ }
46
47
  }
47
48
  });
48
49
  return tabListPath.node;
@@ -113,4 +114,5 @@ function transformTabs(path) {
113
114
  (0, transforms_1.removeProp)(path, { propName: 'isEmphasized' });
114
115
  // Remove isQuiet
115
116
  (0, transforms_1.removeProp)(path, { propName: 'isQuiet' });
117
+ (0, utils_1.removeComponentImportIfUnused)(program, 'Item');
116
118
  }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.illustrationMap = void 0;
4
+ exports.illustrationMap = new Map([
5
+ ['Error', 'Error'],
6
+ ['File', 'Document'],
7
+ ['Folder', 'FolderClose'],
8
+ ['NoSearchResults', 'NoSearchResults'],
9
+ ['NotFound', 'NoSearchResults'],
10
+ ['Timeout', 'Clock'],
11
+ ['Unauthorized', 'LockClose'],
12
+ ['Unavailable', 'Error'],
13
+ ['Upload', 'Upload']
14
+ ]);