@carbon/upgrade 11.23.0 → 11.24.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,44 @@ var upgrades = [
52641
52641
  });
52642
52642
  }
52643
52643
  },
52644
+ {
52645
+ name: "enable-v12-overflowmenu",
52646
+ description: `
52647
+ Updates OverflowMenu components to v12 with optional FeatureFlags wrapping:
52648
+ 1. Migrates to new API (OverflowMenuItem -> MenuItem)
52649
+ 2. Updates props (itemText -> label, etc)
52650
+ 3. Optional FeatureFlags wrapping (--wrapWithFeatureFlag=false to disable)
52651
+
52652
+ Example:
52653
+ Before: <OverflowMenu aria-label="menu"><OverflowMenuItem itemText="Option" /></OverflowMenu>
52654
+ After: <FeatureFlags enableV12Overflowmenu>
52655
+ <OverflowMenu label="menu"><MenuItem label="Option" /></OverflowMenu>
52656
+ </FeatureFlags>
52657
+ `,
52658
+ migrate: async (options) => {
52659
+ const transform = import_path2.default.join(
52660
+ TRANSFORM_DIR,
52661
+ "enable-v12-overflowmenu.js"
52662
+ );
52663
+ const paths = Array.isArray(options.paths) && options.paths.length > 0 ? options.paths : await (0, import_fast_glob2.default)(["**/*.{js,jsx,ts,tsx}"], {
52664
+ cwd: options.workspaceDir,
52665
+ ignore: [
52666
+ "**/es/**",
52667
+ "**/lib/**",
52668
+ "**/umd/**",
52669
+ "**/node_modules/**",
52670
+ "**/storybook-static/**"
52671
+ ]
52672
+ });
52673
+ await run2({
52674
+ dry: !options.write,
52675
+ transform,
52676
+ paths,
52677
+ verbose: options.verbose,
52678
+ wrapWithFeatureFlag: options.wrapWithFeatureFlag
52679
+ });
52680
+ }
52681
+ },
52644
52682
  {
52645
52683
  name: "slug-prop-to-decorator-prop",
52646
52684
  description: `
@@ -52929,7 +52967,7 @@ var upgrades = [
52929
52967
  var package_default = {
52930
52968
  name: "@carbon/upgrade",
52931
52969
  description: "A tool for upgrading Carbon versions",
52932
- version: "11.23.0",
52970
+ version: "11.24.0",
52933
52971
  license: "Apache-2.0",
52934
52972
  bin: {
52935
52973
  "carbon-upgrade": "./bin/carbon-upgrade.js"
@@ -52969,7 +53007,7 @@ var package_default = {
52969
53007
  devDependencies: {
52970
53008
  chalk: "^4.1.1",
52971
53009
  "change-case": "^4.1.2",
52972
- esbuild: "^0.24.0",
53010
+ esbuild: "^0.25.0",
52973
53011
  execa: "^5.1.1",
52974
53012
  "fast-glob": "^3.2.11",
52975
53013
  "fs-extra": "^11.0.0",
@@ -53009,6 +53047,10 @@ async function main({ argv, cwd }) {
53009
53047
  default: false,
53010
53048
  describe: "optionally include additional logs, useful for debugging",
53011
53049
  type: "boolean"
53050
+ }).option("wrapWithFeatureFlag", {
53051
+ default: true,
53052
+ describe: "wrap the migration with a feature flag",
53053
+ type: "boolean"
53012
53054
  });
53013
53055
  cli.usage("Usage: $0 [options]").command(
53014
53056
  ["upgrade", "$0"],
@@ -53040,14 +53082,19 @@ async function main({ argv, cwd }) {
53040
53082
  );
53041
53083
  },
53042
53084
  run3(async (args) => {
53043
- const { verbose, migration, write, paths } = args;
53085
+ const { verbose, migration, write, paths, wrapWithFeatureFlag } = args;
53044
53086
  const options = {
53045
53087
  cwd: cwd(),
53046
53088
  verbose,
53047
53089
  write,
53048
53090
  migration,
53049
- paths
53091
+ paths,
53092
+ wrapWithFeatureFlag
53050
53093
  };
53094
+ console.log(
53095
+ "CLI options wrapWithFeatureFlag:",
53096
+ options.wrapWithFeatureFlag
53097
+ );
53051
53098
  await migrate(options, upgrades);
53052
53099
  })
53053
53100
  );
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.23.0",
4
+ "version": "11.24.0",
5
5
  "license": "Apache-2.0",
6
6
  "bin": {
7
7
  "carbon-upgrade": "./bin/carbon-upgrade.js"
@@ -41,7 +41,7 @@
41
41
  "devDependencies": {
42
42
  "chalk": "^4.1.1",
43
43
  "change-case": "^4.1.2",
44
- "esbuild": "^0.24.0",
44
+ "esbuild": "^0.25.0",
45
45
  "execa": "^5.1.1",
46
46
  "fast-glob": "^3.2.11",
47
47
  "fs-extra": "^11.0.0",
@@ -61,5 +61,5 @@
61
61
  "@ibm/telemetry-js": "^1.5.0",
62
62
  "jscodeshift": "^17.0.0"
63
63
  },
64
- "gitHead": "fd1b7ab668473833c250488e0f7fc4feb55f1d88"
64
+ "gitHead": "2a32901cb1c74c149164122f0742305440716d35"
65
65
  }
@@ -0,0 +1,41 @@
1
+ //prettier-ignore
2
+ import React from 'react';
3
+ import { OverflowMenu, OverflowMenuItem } from '@carbon/react';
4
+
5
+ function TestComponent({ menuProps }) {
6
+ return (
7
+ <div>
8
+ {/* Old API usage - with explicit props */}
9
+ <OverflowMenu
10
+ aria-label="overflow-menu"
11
+ align="bottom"
12
+ flipped={true}
13
+ light={true}
14
+ size="xl">
15
+ <OverflowMenuItem
16
+ className="test-class"
17
+ itemText="Stop app"
18
+ disabled={false}
19
+ onClick={() => {}}
20
+ />
21
+ <OverflowMenuItem itemText="Restart app" />
22
+ <OverflowMenuItem hasDivider isDelete itemText="Delete app" />
23
+ </OverflowMenu>
24
+
25
+ {/* Old API with spread props */}
26
+ <OverflowMenu {...menuProps}>
27
+ <OverflowMenuItem itemText="Dynamic item" />
28
+ <OverflowMenuItem hasDivider isDelete itemText="Remove" />
29
+ </OverflowMenu>
30
+
31
+ {/* Already using new API - should not be transformed */}
32
+ <OverflowMenu label="Already migrated">
33
+ <MenuItem label="Option 1" />
34
+ <MenuItemDivider />
35
+ <MenuItem label="Delete" kind="danger" />
36
+ </OverflowMenu>
37
+ </div>
38
+ );
39
+ }
40
+
41
+ export default TestComponent;
@@ -0,0 +1,37 @@
1
+ //prettier-ignore
2
+ import React from 'react';
3
+ import type { FC } from 'react';
4
+ import { OverflowMenu, OverflowMenuItem } from '@carbon/react';
5
+
6
+ interface MenuItem {
7
+ id: string;
8
+ label: string;
9
+ action?: () => void;
10
+ }
11
+
12
+ interface Props {
13
+ items: MenuItem[];
14
+ }
15
+
16
+ const TestComponent: FC<Props> = ({ items }) => {
17
+ return (
18
+ <div>
19
+ {/* Old API usage - mapped items */}
20
+ <OverflowMenu aria-label="mapped-menu">
21
+ {items.map((item) => (
22
+ <OverflowMenuItem
23
+ key={item.id}
24
+ itemText={item.label}
25
+ onClick={item.action}
26
+ />
27
+ ))}
28
+ </OverflowMenu>
29
+ {/* Old API - explicit props */}
30
+ <OverflowMenu direction="top" size="lg" flipped={true}>
31
+ <OverflowMenuItem hasDivider isDelete itemText="TypeScript Item" />
32
+ </OverflowMenu>
33
+ </div>
34
+ );
35
+ };
36
+
37
+ export default TestComponent;
@@ -0,0 +1,50 @@
1
+ //prettier-ignore
2
+ import React from 'react';
3
+ import { OverflowMenu, OverflowMenuItem, MenuItem, MenuItemDivider, Button } from '@carbon/react';
4
+ import { FeatureFlags } from '@carbon/feature-flags';
5
+
6
+ function TestComponent({ menuProps }) {
7
+ return (
8
+ <div>
9
+ {/* Old API usage with props - transformed */}
10
+ <OverflowMenu
11
+ label="overflow-menu"
12
+ align="bottom"
13
+ flipped={true}
14
+ light={true}
15
+ size="xl"
16
+ >
17
+ <MenuItem
18
+ className="test-class"
19
+ label="Stop app"
20
+ disabled={false}
21
+ onClick={() => {}}
22
+ />
23
+ <MenuItem label="Restart app" />
24
+ <MenuItemDivider />
25
+ <MenuItem label="Delete app" kind="danger" />
26
+ </OverflowMenu>
27
+
28
+ {/* Old API with spread props */}
29
+ <OverflowMenu {...menuProps}>
30
+ <MenuItem label="Dynamic item" />
31
+ <MenuItemDivider />
32
+ <MenuItem label="Remove" kind="danger" />
33
+ </OverflowMenu>
34
+
35
+ {/* Already using new API - should not be transformed */}
36
+ <FeatureFlags enableV12Overflowmenu>
37
+ <OverflowMenu label="Already migrated">
38
+ <MenuItem label="Option 1" />
39
+ <MenuItemDivider />
40
+ <MenuItem label="Delete" kind="danger" />
41
+ </OverflowMenu>
42
+ </FeatureFlags>
43
+
44
+ {/* Other components - unchanged */}
45
+ <Button>Normal button</Button>
46
+ </div>
47
+ );
48
+ }
49
+
50
+ export default TestComponent;
@@ -0,0 +1,42 @@
1
+ //prettier-ignore
2
+ import React from 'react';
3
+ import { FeatureFlags } from '@carbon/feature-flags';
4
+ import type { FC } from 'react';
5
+ import { MenuItem, MenuItemDivider, OverflowMenu, OverflowMenuItem } from '@carbon/react';
6
+
7
+ interface MenuItem {
8
+ id: string;
9
+ label: string;
10
+ action?: () => void;
11
+ }
12
+
13
+ interface Props {
14
+ items: MenuItem[];
15
+ }
16
+
17
+ const TestComponent: FC<Props> = ({ items }) => {
18
+ return (
19
+ (<div>
20
+ {/* Old API usage - mapped items */}
21
+ <FeatureFlags enableV12Overflowmenu>
22
+ <OverflowMenu aria-label="mapped-menu">
23
+ {items.map((item) => (
24
+ <OverflowMenuItem
25
+ key={item.id}
26
+ itemText={item.label}
27
+ onClick={item.action}
28
+ />
29
+ ))}
30
+ </OverflowMenu>
31
+ </FeatureFlags>
32
+ {/* Old API - explicit props */}
33
+ <FeatureFlags enableV12Overflowmenu>
34
+ <OverflowMenu direction="top" size="lg" flipped={true}>
35
+ <MenuItemDivider /><MenuItem kind='danger' label="TypeScript Item" />
36
+ </OverflowMenu>
37
+ </FeatureFlags>
38
+ </div>)
39
+ );
40
+ };
41
+
42
+ export default TestComponent;
@@ -0,0 +1,45 @@
1
+ //prettier-ignore
2
+ import React from 'react';
3
+ import { OverflowMenu, OverflowMenuItem, Button } from '@carbon/react';
4
+
5
+ function TestComponent({ menuProps }) {
6
+ return (
7
+ <div>
8
+ {/* Old API usage - with explicit props */}
9
+ <OverflowMenu
10
+ aria-label="overflow-menu"
11
+ flipped={true}
12
+ light={true}
13
+ size="xl">
14
+ <OverflowMenuItem
15
+ className="test-class"
16
+ itemText="Stop app"
17
+ disabled={false}
18
+ onClick={() => {}}
19
+ />
20
+ <OverflowMenuItem itemText="Restart app" />
21
+ <OverflowMenuItem hasDivider isDelete itemText="Delete app" />
22
+ </OverflowMenu>
23
+
24
+ {/* Old API with spread props */}
25
+ <OverflowMenu {...menuProps}>
26
+ <OverflowMenuItem itemText="Dynamic item" />
27
+ <OverflowMenuItem hasDivider isDelete itemText="Remove" />
28
+ </OverflowMenu>
29
+
30
+ {/* Already using new API - should not be transformed */}
31
+ <FeatureFlags enableV12Overflowmenu>
32
+ <OverflowMenu label="Already migrated">
33
+ <MenuItem label="Option 1" />
34
+ <MenuItemDivider />
35
+ <MenuItem label="Delete" kind="danger" />
36
+ </OverflowMenu>
37
+ </FeatureFlags>
38
+
39
+ {/* Other components - should not be transformed */}
40
+ <Button>Normal button</Button>
41
+ </div>
42
+ );
43
+ }
44
+
45
+ export default TestComponent;
@@ -0,0 +1,37 @@
1
+ //prettier-ignore
2
+ import React from 'react';
3
+ import type { FC } from 'react';
4
+ import { OverflowMenu, OverflowMenuItem } from '@carbon/react';
5
+
6
+ interface MenuItem {
7
+ id: string;
8
+ label: string;
9
+ action?: () => void;
10
+ }
11
+
12
+ interface Props {
13
+ items: MenuItem[];
14
+ }
15
+
16
+ const TestComponent: FC<Props> = ({ items }) => {
17
+ return (
18
+ <div>
19
+ {/* Old API usage - mapped items */}
20
+ <OverflowMenu aria-label="mapped-menu">
21
+ {items.map((item) => (
22
+ <OverflowMenuItem
23
+ key={item.id}
24
+ itemText={item.label}
25
+ onClick={item.action}
26
+ />
27
+ ))}
28
+ </OverflowMenu>
29
+ {/* Old API - explicit props */}
30
+ <OverflowMenu direction="top" size="lg" flipped={true}>
31
+ <OverflowMenuItem hasDivider isDelete itemText="TypeScript Item" />
32
+ </OverflowMenu>
33
+ </div>
34
+ );
35
+ };
36
+
37
+ export default TestComponent;
@@ -0,0 +1,54 @@
1
+ //prettier-ignore
2
+ import React from 'react';
3
+ import { OverflowMenu, OverflowMenuItem, MenuItem, MenuItemDivider, Button } from '@carbon/react';
4
+ import { FeatureFlags } from '@carbon/feature-flags';
5
+
6
+ function TestComponent({ menuProps }) {
7
+ return (
8
+ (<div>
9
+ {/* Old API usage with props - transformed */}
10
+ <FeatureFlags enableV12Overflowmenu>
11
+ <OverflowMenu
12
+ label="overflow-menu"
13
+ align="bottom"
14
+ flipped={true}
15
+ light={true}
16
+ size="xl"
17
+ >
18
+ <MenuItem
19
+ className="test-class"
20
+ label="Stop app"
21
+ disabled={false}
22
+ onClick={() => {}}
23
+ />
24
+ <MenuItem label="Restart app" />
25
+ <MenuItemDivider />
26
+ <MenuItem label="Delete app" kind="danger" />
27
+ </OverflowMenu>
28
+ </FeatureFlags>
29
+
30
+ {/* Old API with spread props */}
31
+ <FeatureFlags enableV12Overflowmenu>
32
+ <OverflowMenu {...menuProps}>
33
+ <MenuItem label="Dynamic item" />
34
+ <MenuItemDivider />
35
+ <MenuItem label="Remove" kind="danger" />
36
+ </OverflowMenu>
37
+ </FeatureFlags>
38
+
39
+ {/* Already using new API - should not be transformed */}
40
+ <FeatureFlags enableV12Overflowmenu>
41
+ <OverflowMenu label="Already migrated">
42
+ <MenuItem label="Option 1" />
43
+ <MenuItemDivider />
44
+ <MenuItem label="Delete" kind="danger" />
45
+ </OverflowMenu>
46
+ </FeatureFlags>
47
+
48
+ {/* Other components - unchanged */}
49
+ <Button>Normal button</Button>
50
+ </div>)
51
+ );
52
+ }
53
+
54
+ export default TestComponent;
@@ -0,0 +1,42 @@
1
+ //prettier-ignore
2
+ import React from 'react';
3
+ import { FeatureFlags } from '@carbon/feature-flags';
4
+ import type { FC } from 'react';
5
+ import { MenuItem, MenuItemDivider, OverflowMenu, OverflowMenuItem } from '@carbon/react';
6
+
7
+ interface MenuItem {
8
+ id: string;
9
+ label: string;
10
+ action?: () => void;
11
+ }
12
+
13
+ interface Props {
14
+ items: MenuItem[];
15
+ }
16
+
17
+ const TestComponent: FC<Props> = ({ items }) => {
18
+ return (
19
+ (<div>
20
+ {/* Old API usage - mapped items */}
21
+ <FeatureFlags enableV12Overflowmenu>
22
+ <OverflowMenu aria-label="mapped-menu">
23
+ {items.map((item) => (
24
+ <OverflowMenuItem
25
+ key={item.id}
26
+ itemText={item.label}
27
+ onClick={item.action}
28
+ />
29
+ ))}
30
+ </OverflowMenu>
31
+ </FeatureFlags>
32
+ {/* Old API - explicit props */}
33
+ <FeatureFlags enableV12Overflowmenu>
34
+ <OverflowMenu direction="top" size="lg" flipped={true}>
35
+ <MenuItemDivider /><MenuItem kind='danger' label="TypeScript Item" />
36
+ </OverflowMenu>
37
+ </FeatureFlags>
38
+ </div>)
39
+ );
40
+ };
41
+
42
+ export default TestComponent;
@@ -0,0 +1,26 @@
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
+
8
+ 'use strict';
9
+
10
+ const { defineTest } = require('jscodeshift/dist/testUtils');
11
+
12
+ // Test with wrapping (default)
13
+ defineTest(
14
+ __dirname,
15
+ 'enable-v12-overflowmenu',
16
+ { wrapWithFeatureFlag: 'true' },
17
+ 'enable-v12-overflowmenu'
18
+ );
19
+
20
+ // Test without wrapping
21
+ defineTest(
22
+ __dirname,
23
+ 'enable-v12-overflowmenu',
24
+ { wrapWithFeatureFlag: 'false' },
25
+ 'enable-v12-overflowmenu-nowrap'
26
+ );
@@ -0,0 +1,218 @@
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 OverflowMenu components to v12 API
8
+ */
9
+
10
+ 'use strict';
11
+
12
+ const defaultOptions = {
13
+ quote: 'single',
14
+ trailingComma: true,
15
+ };
16
+
17
+ // Props mapping from OverflowMenuItem to MenuItem
18
+ const MENU_ITEM_PROPS_MAP = {
19
+ itemText: 'label',
20
+ href: 'href',
21
+ disabled: 'disabled',
22
+ className: 'className',
23
+ };
24
+
25
+ const EVENT_HANDLERS = new Set(['onClick']);
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
+ const shouldWrapWithFlags = options.wrapWithFeatureFlag !== false;
32
+ const overflowMenuElements = root
33
+ .find(j.JSXElement, {
34
+ openingElement: { name: { name: 'OverflowMenu' } },
35
+ })
36
+ .filter((path) => {
37
+ let parent = path.parent;
38
+ while (parent) {
39
+ if (
40
+ parent.node.type === 'JSXElement' &&
41
+ parent.node.openingElement.name.name === 'FeatureFlags'
42
+ ) {
43
+ return false;
44
+ }
45
+ parent = parent.parent;
46
+ }
47
+ return true;
48
+ });
49
+
50
+ if (!overflowMenuElements.length) {
51
+ return null;
52
+ }
53
+
54
+ // Add required imports
55
+ const importsToAdd = ['MenuItem', 'MenuItemDivider'].sort();
56
+ const carbonImport = root.find(j.ImportDeclaration, {
57
+ source: { value: '@carbon/react' },
58
+ });
59
+
60
+ if (carbonImport.length) {
61
+ const importNode = carbonImport.get(0);
62
+ const existingSpecifiers = new Set(
63
+ importNode.node.specifiers
64
+ .filter((spec) => spec.type === 'ImportSpecifier')
65
+ .map((spec) => spec.imported.name)
66
+ );
67
+
68
+ importsToAdd.forEach((importName) => {
69
+ if (!existingSpecifiers.has(importName)) {
70
+ importNode.node.specifiers.push(
71
+ j.importSpecifier(j.identifier(importName))
72
+ );
73
+ }
74
+ });
75
+
76
+ // Sort specifiers alphabetically
77
+ importNode.node.specifiers.sort((a, b) =>
78
+ a.imported.name.localeCompare(b.imported.name)
79
+ );
80
+ }
81
+
82
+ function transformOverflowMenuItems(elements) {
83
+ elements.forEach((path) => {
84
+ path.node.children.forEach((child, index) => {
85
+ if (
86
+ child.type === 'JSXElement' &&
87
+ child.openingElement.name.name === 'OverflowMenuItem'
88
+ ) {
89
+ const itemProps = [];
90
+ let needsDivider = false;
91
+ let classNames = [];
92
+
93
+ child.openingElement.attributes.forEach((attr) => {
94
+ if (attr.type === 'JSXSpreadAttribute') {
95
+ itemProps.push(attr);
96
+ return;
97
+ }
98
+
99
+ const propName = attr.name.name;
100
+
101
+ if (MENU_ITEM_PROPS_MAP[propName]) {
102
+ if (propName === 'className') {
103
+ classNames.push(attr.value.value);
104
+ } else {
105
+ itemProps.push(
106
+ j.jsxAttribute(
107
+ j.jsxIdentifier(MENU_ITEM_PROPS_MAP[propName]),
108
+ attr.value
109
+ )
110
+ );
111
+ }
112
+ } else if (propName === 'wrapperClassName') {
113
+ classNames.push(attr.value.value);
114
+ } else if (propName === 'hasDivider') {
115
+ needsDivider = true;
116
+ } else if (propName === 'isDelete') {
117
+ itemProps.push(
118
+ j.jsxAttribute(
119
+ j.jsxIdentifier('kind'),
120
+ j.stringLiteral('danger')
121
+ )
122
+ );
123
+ } else if (EVENT_HANDLERS.has(propName)) {
124
+ itemProps.push(attr);
125
+ }
126
+ });
127
+
128
+ if (classNames.length > 0) {
129
+ itemProps.push(
130
+ j.jsxAttribute(
131
+ j.jsxIdentifier('className'),
132
+ j.stringLiteral(classNames.join(' '))
133
+ )
134
+ );
135
+ }
136
+
137
+ if (needsDivider) {
138
+ path.node.children.splice(
139
+ index,
140
+ 0,
141
+ j.jsxElement(
142
+ j.jsxOpeningElement(
143
+ j.jsxIdentifier('MenuItemDivider'),
144
+ [],
145
+ true
146
+ ),
147
+ null,
148
+ [],
149
+ true
150
+ )
151
+ );
152
+ }
153
+
154
+ child.openingElement.name = j.jsxIdentifier('MenuItem');
155
+ child.openingElement.attributes = itemProps;
156
+ if (child.closingElement) {
157
+ child.closingElement.name = j.jsxIdentifier('MenuItem');
158
+ }
159
+ }
160
+ });
161
+ });
162
+ }
163
+
164
+ function addFeatureFlagsImport() {
165
+ const hasFeatureFlagsImport = root
166
+ .find(j.ImportDeclaration)
167
+ .some(
168
+ (path) =>
169
+ path.node.source.value === '@carbon/feature-flags' &&
170
+ path.node.specifiers.some(
171
+ (spec) => spec.imported && spec.imported.name === 'FeatureFlags'
172
+ )
173
+ );
174
+
175
+ if (!hasFeatureFlagsImport) {
176
+ const featureFlagsImport = j.importDeclaration(
177
+ [j.importSpecifier(j.identifier('FeatureFlags'))],
178
+ j.literal('@carbon/feature-flags')
179
+ );
180
+
181
+ const firstImport = root.find(j.ImportDeclaration).at(0);
182
+ if (firstImport.length) {
183
+ firstImport.insertAfter(featureFlagsImport);
184
+ } else {
185
+ root.get().node.program.body.unshift(featureFlagsImport);
186
+ }
187
+ }
188
+ }
189
+
190
+ function wrapWithFeatureFlags(elements) {
191
+ elements.forEach((path) => {
192
+ const wrappedElement = j.jsxElement(
193
+ j.jsxOpeningElement(
194
+ j.jsxIdentifier('FeatureFlags'),
195
+ [j.jsxAttribute(j.jsxIdentifier('enableV12Overflowmenu'))],
196
+ false
197
+ ),
198
+ j.jsxClosingElement(j.jsxIdentifier('FeatureFlags')),
199
+ [j.jsxText('\n '), path.node, j.jsxText('\n ')]
200
+ );
201
+
202
+ j(path).replaceWith(wrappedElement);
203
+ });
204
+ }
205
+
206
+ // Transform based on wrap option
207
+ transformOverflowMenuItems(overflowMenuElements);
208
+
209
+ if (shouldWrapWithFlags) {
210
+ addFeatureFlagsImport();
211
+ wrapWithFeatureFlags(overflowMenuElements);
212
+ }
213
+
214
+ return root.toSource(printOptions);
215
+ }
216
+
217
+ module.exports = transform;
218
+ module.exports.parser = 'tsx';