@carbon/upgrade 11.22.0 → 11.23.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.
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Copyright IBM Corp. 2025
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
+ * Migrate RadioTile components by wrapping them with FeatureFlags
8
+ */
9
+
10
+ 'use strict';
11
+
12
+ const defaultOptions = {
13
+ quote: 'single',
14
+ trailingComma: true,
15
+ };
16
+
17
+ function transform(fileInfo, api, options) {
18
+ const j = api.jscodeshift;
19
+ const root = j(fileInfo.source);
20
+ const printOptions = options.printOptions || defaultOptions;
21
+
22
+ // Early return if no RadioTile components found
23
+ if (
24
+ !root
25
+ .find(j.JSXElement, { openingElement: { name: { name: 'RadioTile' } } })
26
+ .size()
27
+ ) {
28
+ return null;
29
+ }
30
+
31
+ let needsFeatureFlagsImport = false;
32
+
33
+ // First update all existing FeatureFlags wrappers that need the attribute
34
+ root
35
+ .find(j.JSXElement, {
36
+ openingElement: { name: { name: 'FeatureFlags' } },
37
+ })
38
+ .forEach((path) => {
39
+ const hasRadioTileInside =
40
+ j(path)
41
+ .find(j.JSXElement, {
42
+ openingElement: { name: { name: 'RadioTile' } },
43
+ })
44
+ .size() > 0;
45
+
46
+ const hasTileGroupWithRadioTile =
47
+ j(path)
48
+ .find(j.JSXElement, {
49
+ openingElement: { name: { name: 'TileGroup' } },
50
+ })
51
+ .filter((tileGroupPath) => {
52
+ return (
53
+ j(tileGroupPath)
54
+ .find(j.JSXElement, {
55
+ openingElement: { name: { name: 'RadioTile' } },
56
+ })
57
+ .size() > 0
58
+ );
59
+ })
60
+ .size() > 0;
61
+
62
+ if (hasRadioTileInside || hasTileGroupWithRadioTile) {
63
+ const hasAttribute = path.node.openingElement.attributes.some(
64
+ (attr) =>
65
+ attr.type === 'JSXAttribute' &&
66
+ attr.name.name === 'enableV12TileRadioIcons'
67
+ );
68
+
69
+ if (!hasAttribute) {
70
+ path.node.openingElement.attributes.push(
71
+ j.jsxAttribute(j.jsxIdentifier('enableV12TileRadioIcons'))
72
+ );
73
+ needsFeatureFlagsImport = true;
74
+ }
75
+ }
76
+ });
77
+
78
+ // Handle RadioTiles within TileGroups
79
+ root
80
+ .find(j.JSXElement, {
81
+ openingElement: { name: { name: 'TileGroup' } },
82
+ })
83
+ .forEach((path) => {
84
+ const hasRadioTile =
85
+ j(path)
86
+ .find(j.JSXElement, {
87
+ openingElement: { name: { name: 'RadioTile' } },
88
+ })
89
+ .size() > 0;
90
+
91
+ const wrappingFeatureFlags = j(path).closest(j.JSXElement, {
92
+ openingElement: { name: { name: 'FeatureFlags' } },
93
+ });
94
+
95
+ if (hasRadioTile) {
96
+ if (wrappingFeatureFlags.size() === 0) {
97
+ // Not wrapped, add wrapper
98
+ const featureFlagsWrapper = j.jsxElement(
99
+ j.jsxOpeningElement(
100
+ j.jsxIdentifier('FeatureFlags'),
101
+ [j.jsxAttribute(j.jsxIdentifier('enableV12TileRadioIcons'))],
102
+ false
103
+ ),
104
+ j.jsxClosingElement(j.jsxIdentifier('FeatureFlags')),
105
+ [path.node]
106
+ );
107
+
108
+ j(path).replaceWith(featureFlagsWrapper);
109
+ needsFeatureFlagsImport = true;
110
+ }
111
+ }
112
+ });
113
+
114
+ // Handle standalone RadioTiles
115
+ root
116
+ .find(j.JSXElement, {
117
+ openingElement: { name: { name: 'RadioTile' } },
118
+ })
119
+ .forEach((path) => {
120
+ const isInsideTileGroup =
121
+ j(path)
122
+ .closest(j.JSXElement, {
123
+ openingElement: { name: { name: 'TileGroup' } },
124
+ })
125
+ .size() > 0;
126
+
127
+ const wrappingFeatureFlags = j(path).closest(j.JSXElement, {
128
+ openingElement: { name: { name: 'FeatureFlags' } },
129
+ });
130
+
131
+ if (!isInsideTileGroup) {
132
+ if (wrappingFeatureFlags.size() === 0) {
133
+ // Not wrapped, add wrapper
134
+ const featureFlagsWrapper = j.jsxElement(
135
+ j.jsxOpeningElement(
136
+ j.jsxIdentifier('FeatureFlags'),
137
+ [j.jsxAttribute(j.jsxIdentifier('enableV12TileRadioIcons'))],
138
+ false
139
+ ),
140
+ j.jsxClosingElement(j.jsxIdentifier('FeatureFlags')),
141
+ [path.node]
142
+ );
143
+
144
+ j(path).replaceWith(featureFlagsWrapper);
145
+ needsFeatureFlagsImport = true;
146
+ }
147
+ }
148
+ });
149
+
150
+ // Add FeatureFlags import only if we've added wrappers or attributes
151
+ if (needsFeatureFlagsImport) {
152
+ const hasFeatureFlagsImport =
153
+ root
154
+ .find(j.ImportDeclaration, {
155
+ source: { value: '@carbon/feature-flags' },
156
+ })
157
+ .size() > 0;
158
+
159
+ if (!hasFeatureFlagsImport) {
160
+ // Find the last import declaration
161
+ const lastImport = root.find(j.ImportDeclaration).at(-1);
162
+ const featureFlagsImport = j.importDeclaration(
163
+ [j.importSpecifier(j.identifier('FeatureFlags'))],
164
+ j.literal('@carbon/feature-flags')
165
+ );
166
+
167
+ if (lastImport.size() > 0) {
168
+ // Add newline after the last import
169
+ const newline = j.template.statement`\n`;
170
+ lastImport.insertAfter(newline);
171
+ lastImport.insertAfter(featureFlagsImport);
172
+ } else {
173
+ // If no imports exist, add at the beginning of the file
174
+ root.get().node.program.body.unshift(featureFlagsImport);
175
+ }
176
+ }
177
+ }
178
+
179
+ return root.toSource(printOptions);
180
+ }
181
+
182
+ module.exports = transform;
183
+ module.exports.parser = 'tsx';
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Copyright IBM Corp. 2025
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
+ * Replace slug prop with decorator
8
+ */
9
+
10
+ 'use strict';
11
+
12
+ const defaultOptions = {
13
+ quote: 'single',
14
+ trailingComma: true,
15
+ };
16
+
17
+ function transform(fileInfo, api, options) {
18
+ const j = api.jscodeshift;
19
+ const root = j(fileInfo.source);
20
+ const printOptions = options.printOptions || defaultOptions;
21
+
22
+ // Early return if no JSX elements with slug prop found
23
+ if (!root.find(j.JSXAttribute, { name: { name: 'slug' } }).size()) {
24
+ return null;
25
+ }
26
+
27
+ // Replace slug with decorator
28
+ root
29
+ .find(j.JSXAttribute, {
30
+ name: { name: 'slug' },
31
+ })
32
+ .forEach((path) => {
33
+ // Create new decorator attribute with same value as slug
34
+ const newAttribute = j.jsxAttribute(
35
+ j.jsxIdentifier('decorator'),
36
+ path.node.value
37
+ );
38
+
39
+ // Replace the slug attribute with decorator
40
+ j(path).replaceWith(newAttribute);
41
+ });
42
+
43
+ return root.toSource(printOptions);
44
+ }
45
+
46
+ module.exports = transform;
47
+ module.exports.parser = 'tsx';