@carbon/upgrade 11.20.0-rc.0 → 11.21.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/cli.js CHANGED
@@ -52641,6 +52641,38 @@ var upgrades = [
52641
52641
  });
52642
52642
  }
52643
52643
  },
52644
+ {
52645
+ name: "refactor-light-to-layer",
52646
+ description: `
52647
+ Refactor 'light' prop usage to instead wrap components with Layer
52648
+ Transforms:
52649
+ <Button light>Click me</Button>
52650
+ Into:
52651
+ <Layer><Button>Click me</Button></Layer>
52652
+ `,
52653
+ migrate: async (options) => {
52654
+ const transform = import_path2.default.join(
52655
+ TRANSFORM_DIR,
52656
+ "refactor-light-to-layer.js"
52657
+ );
52658
+ const paths = Array.isArray(options.paths) && options.paths.length > 0 ? options.paths : await (0, import_fast_glob2.default)(["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"], {
52659
+ cwd: options.workspaceDir,
52660
+ ignore: [
52661
+ "**/es/**",
52662
+ "**/lib/**",
52663
+ "**/umd/**",
52664
+ "**/node_modules/**",
52665
+ "**/storybook-static/**"
52666
+ ]
52667
+ });
52668
+ await run2({
52669
+ dry: !options.write,
52670
+ transform,
52671
+ paths,
52672
+ verbose: options.verbose
52673
+ });
52674
+ }
52675
+ },
52644
52676
  {
52645
52677
  name: "refactor-to-callout",
52646
52678
  description: "Rewrites imports and usages of StaticNotification to Callout",
@@ -52663,6 +52695,32 @@ var upgrades = [
52663
52695
  verbose: options.verbose
52664
52696
  });
52665
52697
  }
52698
+ },
52699
+ {
52700
+ name: "ibm-products-update-userprofileimage",
52701
+ description: "Rewrites UserProfileImage to UserAvatar",
52702
+ migrate: async (options) => {
52703
+ const transform = import_path2.default.join(
52704
+ TRANSFORM_DIR,
52705
+ "ibm-products-update-userprofileimage.js"
52706
+ );
52707
+ const paths = Array.isArray(options.paths) && options.paths.length > 0 ? options.paths : await (0, import_fast_glob2.default)(["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"], {
52708
+ cwd: options.workspaceDir,
52709
+ ignore: [
52710
+ "**/es/**",
52711
+ "**/lib/**",
52712
+ "**/umd/**",
52713
+ "**/node_modules/**",
52714
+ "**/storybook-static/**"
52715
+ ]
52716
+ });
52717
+ await run2({
52718
+ dry: !options.write,
52719
+ transform,
52720
+ paths,
52721
+ verbose: options.verbose
52722
+ });
52723
+ }
52666
52724
  }
52667
52725
  ]
52668
52726
  },
@@ -52691,7 +52749,7 @@ var upgrades = [
52691
52749
  var package_default = {
52692
52750
  name: "@carbon/upgrade",
52693
52751
  description: "A tool for upgrading Carbon versions",
52694
- version: "11.20.0-rc.0",
52752
+ version: "11.21.0",
52695
52753
  license: "Apache-2.0",
52696
52754
  bin: {
52697
52755
  "carbon-upgrade": "./bin/carbon-upgrade.js"
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@carbon/upgrade",
3
3
  "description": "A tool for upgrading Carbon versions",
4
- "version": "11.20.0-rc.0",
4
+ "version": "11.21.0",
5
5
  "license": "Apache-2.0",
6
6
  "bin": {
7
7
  "carbon-upgrade": "./bin/carbon-upgrade.js"
@@ -61,5 +61,5 @@
61
61
  "@ibm/telemetry-js": "^1.5.0",
62
62
  "jscodeshift": "^17.0.0"
63
63
  },
64
- "gitHead": "e48f5e6815bd93e518e8da73c7555590b85cda22"
64
+ "gitHead": "ab3eba8531c341d5ee5d956b962d7cce04944ac3"
65
65
  }
@@ -0,0 +1,48 @@
1
+ import React from 'react';
2
+ import { UserProfileImage } from '@carbon/ibm-products';
3
+ import { Add } from '@carbon/react/icons';
4
+
5
+ const ImageUrl =
6
+ 'https://img.freepik.com/free-photo/portrait-man-cartoon-style_23-2151133939.jpg?semt=ais_hybrid';
7
+
8
+ export const Example = () => (
9
+ <>
10
+ <UserProfileImage
11
+ size="md"
12
+ tooltipAlignment="bottom"
13
+ backgroundColor="light-purple"
14
+ theme="light"
15
+ tooltipText="Thomas Watson"
16
+ className="myClass"
17
+ initials="thomas j. watson"
18
+ />
19
+ <UserProfileImage
20
+ size="md"
21
+ tooltipAlignment="bottom"
22
+ backgroundColor="light-purple"
23
+ theme="light"
24
+ tooltipText="Thomas Watson"
25
+ className="myClass"
26
+ kind="user"
27
+ />
28
+ <UserProfileImage
29
+ size="md"
30
+ tooltipAlignment="bottom"
31
+ backgroundColor="light-purple"
32
+ theme="light"
33
+ tooltipText="Thomas Watson"
34
+ className="myClass"
35
+ icon={() => <Add size={20} />}
36
+ />
37
+ <UserProfileImage
38
+ size="md"
39
+ tooltipAlignment="bottom"
40
+ backgroundColor="light-purple"
41
+ theme="light"
42
+ tooltipText="Thomas Watson"
43
+ className="myClass"
44
+ image={ImageUrl}
45
+ imageDescription="Avatar of Thomas Watson"
46
+ />
47
+ </>
48
+ );
@@ -0,0 +1,41 @@
1
+ import { User } from "@carbon/react/icons";
2
+ import React from 'react';
3
+ import { UserAvatar } from '@carbon/ibm-products';
4
+ import { Add } from '@carbon/react/icons';
5
+
6
+ const ImageUrl =
7
+ 'https://img.freepik.com/free-photo/portrait-man-cartoon-style_23-2151133939.jpg?semt=ais_hybrid';
8
+
9
+ export const Example = () => (
10
+ <>
11
+ <UserAvatar
12
+ size="md"
13
+ tooltipAlignment="bottom"
14
+ backgroundColor="order-5-purple"
15
+ tooltipText="Thomas Watson"
16
+ className="myClass"
17
+ name="thomas j. watson" />
18
+ <UserAvatar
19
+ size="md"
20
+ tooltipAlignment="bottom"
21
+ backgroundColor="order-5-purple"
22
+ tooltipText="Thomas Watson"
23
+ className="myClass"
24
+ renderIcon={User} />
25
+ <UserAvatar
26
+ size="md"
27
+ tooltipAlignment="bottom"
28
+ backgroundColor="order-5-purple"
29
+ tooltipText="Thomas Watson"
30
+ className="myClass"
31
+ renderIcon={() => <Add size={20} />} />
32
+ <UserAvatar
33
+ size="md"
34
+ tooltipAlignment="bottom"
35
+ backgroundColor="order-5-purple"
36
+ tooltipText="Thomas Watson"
37
+ className="myClass"
38
+ image={ImageUrl}
39
+ imageDescription="Avatar of Thomas Watson" />
40
+ </>
41
+ );
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import { Button, Layer } from '@carbon/react';
3
+
4
+ function TestComponent() {
5
+ <div>
6
+ <Button light>Click me</Button>
7
+ <Button>Another button</Button>
8
+ <Layer>
9
+ <Button light>Nested light button</Button>
10
+ </Layer>
11
+ </div>;
12
+ }
13
+
14
+ export default TestComponent;
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import { Button, Layer } from '@carbon/react';
3
+
4
+ function TestComponent() {
5
+ <div>
6
+ <Layer><Button>Click me</Button></Layer>
7
+ <Button>Another button</Button>
8
+ <Layer>
9
+ <Layer><Button>Nested light button</Button></Layer>
10
+ </Layer>
11
+ </div>;
12
+ }
13
+
14
+ export default TestComponent;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Copyright IBM Corp. 2021, 2024
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ 'use strict';
9
+
10
+ const { defineTest } = require('jscodeshift/dist/testUtils');
11
+
12
+ defineTest(__dirname, 'ibm-products-update-userprofileimage');
@@ -0,0 +1,5 @@
1
+ 'use strict';
2
+
3
+ const { defineTest } = require('jscodeshift/dist/testUtils');
4
+
5
+ defineTest(__dirname, 'refactor-light-to-layer');
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Copyright IBM Corp. 2021, 2024
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * Rewrites UserProfileImage to UserAvatar
8
+ *
9
+ * Transforms:
10
+ *
11
+ * <UserProfileImage />
12
+ *
13
+ * Into:
14
+ *
15
+ * <UserAvatar />
16
+ */
17
+
18
+ 'use strict';
19
+
20
+ const transform = (fileInfo, api) => {
21
+ const j = api.jscodeshift;
22
+ const root = j(fileInfo.source);
23
+ let shouldImportUser = false;
24
+ let shouldImportGroup = false;
25
+
26
+ const ensureImport = (identifierName) => {
27
+ const importDeclaration = j.importDeclaration(
28
+ [j.importSpecifier(j.identifier(identifierName))],
29
+ j.literal('@carbon/react/icons')
30
+ );
31
+
32
+ const existingImport = root
33
+ .find(j.ImportDeclaration, {
34
+ source: { value: '@carbon/react/icons' },
35
+ })
36
+ .filter((path) => {
37
+ return path.node.specifiers.some(
38
+ (specifier) => specifier.imported.name === identifierName
39
+ );
40
+ });
41
+
42
+ if (existingImport.size() === 0) {
43
+ root.find(j.Program).get('body', 0).insertBefore(importDeclaration);
44
+ }
45
+ };
46
+ // Transform UserProfileImage to UserAvatar
47
+ root
48
+ .find(j.JSXElement, {
49
+ openingElement: { name: { name: 'UserProfileImage' } },
50
+ })
51
+ .forEach((path) => {
52
+ // Change the component name
53
+ path.node.openingElement.name.name = 'UserAvatar';
54
+ if (path.node.closingElement) {
55
+ path.node.closingElement.name.name = 'UserAvatar';
56
+ }
57
+
58
+ const colorMapping = {
59
+ 'light-cyan': 'order-1-cyan',
60
+ 'dark-cyan': 'order-7-cyan',
61
+ 'light-gray': 'order-2-gray',
62
+ 'dark-gray': 'order-8-gray',
63
+ 'light-green': 'order-3-green',
64
+ 'dark-green': 'order-9-green',
65
+ 'light-magenta': 'order-10-magenta',
66
+ 'dark-magenta': 'order-10-magenta',
67
+ 'light-purple': 'order-5-purple',
68
+ 'dark-purple': 'order-11-purple',
69
+ 'light-teal': 'order-6-teal',
70
+ 'dark-teal': 'order-12-teal',
71
+ };
72
+ const updatedAttributes = [];
73
+ // Update attributes
74
+ path.node.openingElement.attributes.forEach((attr) => {
75
+ if (attr.name.name === 'backgroundColor') {
76
+ if (colorMapping[attr.value.value]) {
77
+ attr.value.value = colorMapping[attr.value.value];
78
+ }
79
+ }
80
+ if (attr.name.name === 'theme') {
81
+ return;
82
+ }
83
+ if (attr.name.name === 'initials') {
84
+ attr.name.name = 'name';
85
+ }
86
+ if (attr.name.name === 'kind' || attr.name.name === 'icon') {
87
+ const originalName = attr.name.name;
88
+ attr.name.name = 'renderIcon';
89
+ if (originalName === 'kind') {
90
+ if (attr.value.value === 'user') {
91
+ attr.value = j.jsxExpressionContainer(j.identifier('User'));
92
+ shouldImportUser = true;
93
+ } else if (attr.value.value === 'group') {
94
+ attr.value = j.jsxExpressionContainer(j.identifier('Group'));
95
+ shouldImportGroup = true;
96
+ }
97
+ }
98
+ }
99
+ updatedAttributes.push(attr);
100
+ });
101
+ path.node.openingElement.attributes = updatedAttributes;
102
+ });
103
+ // Update import statement
104
+ root
105
+ .find(j.ImportDeclaration)
106
+ .filter((path) => path.node.source.value === '@carbon/ibm-products')
107
+ .forEach((path) => {
108
+ path.node.specifiers.forEach((specifier) => {
109
+ if (specifier.imported.name === 'UserProfileImage') {
110
+ specifier.imported.name = 'UserAvatar';
111
+ }
112
+ });
113
+ });
114
+
115
+ if (shouldImportUser) {
116
+ ensureImport('User');
117
+ }
118
+
119
+ if (shouldImportGroup) {
120
+ ensureImport('Group');
121
+ }
122
+ return root.toSource();
123
+ };
124
+
125
+ module.exports = transform;
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Copyright IBM Corp. 2024
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * Deprecate the `light` prop and wrap components with `Layer`
8
+ *
9
+ * Transforms:
10
+ *
11
+ * <Button light>Click me</Button>
12
+ *
13
+ * Into:
14
+ *
15
+ * <Layer>
16
+ * <Button>Click me</Button>
17
+ * </Layer>
18
+ */
19
+
20
+ 'use strict';
21
+
22
+ const defaultOptions = {
23
+ quote: 'single',
24
+ trailingComma: true,
25
+ };
26
+
27
+ function transform(fileInfo, api, options) {
28
+ const { jscodeshift: j } = api;
29
+ const root = j(fileInfo.source);
30
+ const printOptions = options.printOptions || defaultOptions;
31
+
32
+ // Check if there are any components with the 'light' prop
33
+ const hasLightProp =
34
+ root.find(j.JSXAttribute, { name: { name: 'light' } }).size() > 0;
35
+
36
+ if (!hasLightProp) {
37
+ return null; // if no 'light' prop found, don't modify & return the file
38
+ }
39
+
40
+ // Import Layer component if not already imported
41
+ const layerImport = root.find(j.ImportDeclaration, {
42
+ source: { value: '@carbon/react' },
43
+ });
44
+
45
+ if (layerImport.length) {
46
+ const specifiers = layerImport.get('specifiers');
47
+ const hasLayerImport = specifiers.value.some(
48
+ (specifier) => specifier.imported && specifier.imported.name === 'Layer'
49
+ );
50
+
51
+ if (!hasLayerImport) {
52
+ specifiers.value.push(j.importSpecifier(j.identifier('Layer')));
53
+ }
54
+ } else {
55
+ const newImport = j.importDeclaration(
56
+ [j.importSpecifier(j.identifier('Layer'))],
57
+ j.literal('@carbon/react')
58
+ );
59
+ // Find the first import declaration
60
+ const firstImport = root.find(j.ImportDeclaration).at(0);
61
+
62
+ if (firstImport.length) {
63
+ // Insert the new import before the first existing import
64
+ firstImport.insertAfter(newImport);
65
+ } else {
66
+ // If no imports, find the first non-comment node
67
+ const firstNonCommentNode = root
68
+ .find(j.Program)
69
+ .get('body')
70
+ .filter(
71
+ (path) =>
72
+ path.value.type !== 'CommentBlock' &&
73
+ path.value.type !== 'CommentLine'
74
+ )[0];
75
+
76
+ // Insert the new import before the first non-comment node
77
+ j(firstNonCommentNode).insertBefore(newImport);
78
+ }
79
+ }
80
+
81
+ // Find all JSX elements with a 'light' prop
82
+ root.find(j.JSXElement).forEach((path) => {
83
+ const lightProp = path.node.openingElement.attributes.find(
84
+ (attr) => attr.type === 'JSXAttribute' && attr.name.name === 'light'
85
+ );
86
+
87
+ if (lightProp) {
88
+ // Remove the 'light' prop
89
+ path.node.openingElement.attributes =
90
+ path.node.openingElement.attributes.filter(
91
+ (attr) => attr !== lightProp
92
+ );
93
+ // Wrap the component with Layer
94
+ const layerElement = j.jsxElement(
95
+ j.jsxOpeningElement(j.jsxIdentifier('Layer'), []),
96
+ j.jsxClosingElement(j.jsxIdentifier('Layer')),
97
+ [path.node]
98
+ );
99
+
100
+ // Replace the original element with the wrapped version
101
+ j(path).replaceWith(layerElement);
102
+ }
103
+ });
104
+
105
+ return root.toSource(printOptions);
106
+ }
107
+
108
+ module.exports = transform;