@wise/wds-codemods 1.0.0-experimental-49d2d08 → 1.0.0-experimental-88f6022

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.
@@ -1,6 +1,353 @@
1
1
  Object.defineProperty(exports, '__esModule', { value: true });
2
- const require_helpers = require('../../helpers-59xSDDPO.js');
2
+ const require_helpers = require('../../helpers-RWhTD5Is.js');
3
3
 
4
+ //#region src/helpers/addImport.ts
5
+ /**
6
+ * Adds a named import if it doesn't already exist.
7
+ */
8
+ function addImport(root, sourceValue, importName, j) {
9
+ const existingImports = root.find(j.ImportDeclaration, { source: { value: sourceValue } });
10
+ if (existingImports.size() > 0) {
11
+ if (existingImports.find(j.ImportSpecifier, { imported: { name: importName } }).size() > 0) return;
12
+ existingImports.forEach((path) => {
13
+ if (path.node.specifiers) path.node.specifiers.push(j.importSpecifier(j.identifier(importName)));
14
+ });
15
+ } else {
16
+ const newImport = j.importDeclaration([j.importSpecifier(j.identifier(importName))], j.literal(sourceValue));
17
+ const firstImport = root.find(j.ImportDeclaration).at(0);
18
+ if (firstImport.size() > 0) firstImport.insertBefore(newImport);
19
+ else {
20
+ const program = root.find(j.Program);
21
+ if (program.size() > 0) program.get("body", 0).insertBefore(newImport);
22
+ }
23
+ }
24
+ }
25
+ var addImport_default = addImport;
26
+
27
+ //#endregion
28
+ //#region src/helpers/hasImport.ts
29
+ /**
30
+ * Checks if a specific import exists in the given root collection and provides
31
+ * a method to remove it if found.
32
+ */
33
+ function hasImport(root, sourceValue, importName, j) {
34
+ const importDeclarations = root.find(j.ImportDeclaration, { source: { value: sourceValue } });
35
+ /**
36
+ * Finds all ImportSpecifier nodes that expose `importName` but
37
+ * from a different source than `sourceValue`.
38
+ */
39
+ const conflictingImports = (() => {
40
+ const result = [];
41
+ root.find(j.ImportDeclaration).filter((path) => path.node.source.value !== sourceValue).forEach((path) => {
42
+ for (const specifier of path.node.specifiers ?? []) if (specifier.type === "ImportSpecifier" && specifier.imported.name === importName && specifier.local?.name === importName) result.push(specifier);
43
+ });
44
+ return result;
45
+ })();
46
+ if (importDeclarations.size() === 0) return {
47
+ exists: false,
48
+ remove: () => {},
49
+ resolvedName: importName,
50
+ conflictingImports
51
+ };
52
+ const namedImport = importDeclarations.find(j.ImportSpecifier, { imported: { name: importName } });
53
+ const defaultImport = importDeclarations.find(j.ImportDefaultSpecifier, { local: { name: importName } });
54
+ const aliasImport = importDeclarations.find(j.ImportSpecifier).filter((path) => {
55
+ return path.node.imported.name === importName && path.node.imported.name !== path.node.local?.name;
56
+ });
57
+ const exists = namedImport.size() > 0 || defaultImport.size() > 0;
58
+ const resolveName = () => {
59
+ if (aliasImport.size() > 0) {
60
+ const localName = aliasImport.get(0).node.local?.name;
61
+ if (typeof localName === "string") return localName;
62
+ if (localName && typeof localName === "object" && "name" in localName && typeof localName.name === "string") return localName.name;
63
+ return importName;
64
+ }
65
+ return importName;
66
+ };
67
+ const remove = () => {
68
+ importDeclarations.forEach((path) => {
69
+ const filteredSpecifiers = path.node.specifiers?.filter((specifier) => {
70
+ if (specifier.type === "ImportSpecifier" && specifier.imported.name === importName) return false;
71
+ if (specifier.type === "ImportDefaultSpecifier" && specifier.local?.name === importName) return false;
72
+ return true;
73
+ }) ?? [];
74
+ if (filteredSpecifiers.length === 0) path.prune();
75
+ else j(path).replaceWith(j.importDeclaration(filteredSpecifiers, path.node.source, path.node.importKind));
76
+ });
77
+ };
78
+ return {
79
+ exists,
80
+ remove,
81
+ aliases: aliasImport,
82
+ resolvedName: resolveName(),
83
+ conflictingImports
84
+ };
85
+ }
86
+ var hasImport_default = hasImport;
87
+
88
+ //#endregion
89
+ //#region src/helpers/iconUtils.ts
90
+ /**
91
+ * Process children of a JSX element to detect icon components and add iconStart or iconEnd attributes accordingly.
92
+ * This is specific to icon handling but can be reused in codemods dealing with icon children.
93
+ */
94
+ const processIconChildren = (j, children, iconImports, openingElement) => {
95
+ if (!children || !openingElement.attributes) return;
96
+ const unwrapJsxElement = (node) => {
97
+ if (typeof node === "object" && node !== null && "type" in node && node.type === "JSXExpressionContainer" && j.JSXElement.check(node.expression)) return node.expression;
98
+ return node;
99
+ };
100
+ const totalChildren = children.length;
101
+ const iconChildIndex = children.findIndex((child) => {
102
+ const unwrapped = unwrapJsxElement(child);
103
+ return j.JSXElement.check(unwrapped) && unwrapped.openingElement.name.type === "JSXIdentifier" && iconImports.has(unwrapped.openingElement.name.name);
104
+ });
105
+ if (iconChildIndex === -1) return;
106
+ const iconChild = unwrapJsxElement(children[iconChildIndex]);
107
+ if (!iconChild || iconChild.openingElement.name.type !== "JSXIdentifier") return;
108
+ iconChild.openingElement.name.name;
109
+ const iconPropName = iconChildIndex <= totalChildren - 1 - iconChildIndex ? "addonStart" : "addonEnd";
110
+ const iconObject = j.objectExpression([j.property("init", j.identifier("type"), j.literal("icon")), j.property("init", j.identifier("value"), iconChild)]);
111
+ const iconProp = j.jsxAttribute(j.jsxIdentifier(iconPropName), j.jsxExpressionContainer(iconObject));
112
+ openingElement.attributes.push(iconProp);
113
+ children.splice(iconChildIndex, 1);
114
+ const isWhitespaceJsxText = (node) => {
115
+ return typeof node === "object" && node !== null && node.type === "JSXText" && typeof node.value === "string" && node.value.trim() === "";
116
+ };
117
+ if (iconChildIndex - 1 >= 0 && isWhitespaceJsxText(children[iconChildIndex - 1])) children.splice(iconChildIndex - 1, 1);
118
+ else if (isWhitespaceJsxText(children[iconChildIndex])) children.splice(iconChildIndex, 1);
119
+ };
120
+ var iconUtils_default = processIconChildren;
121
+
122
+ //#endregion
123
+ //#region src/helpers/jsxElementUtils.ts
124
+ /**
125
+ * Rename a JSX element name if it is a JSXIdentifier.
126
+ */
127
+ const setNameIfJSXIdentifier = (elementName, newName) => {
128
+ if (elementName && elementName.type === "JSXIdentifier") return {
129
+ ...elementName,
130
+ name: newName
131
+ };
132
+ return elementName;
133
+ };
134
+ /**
135
+ * Check if a list of attributes contains a specific attribute by name.
136
+ */
137
+ const hasAttribute = (attributes, attributeName) => {
138
+ return Array.isArray(attributes) && attributes.some((attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === attributeName);
139
+ };
140
+ /**
141
+ * Check if a JSX element's openingElement has a specific attribute.
142
+ */
143
+ const hasAttributeOnElement = (element, attributeName) => {
144
+ return hasAttribute(element.attributes, attributeName);
145
+ };
146
+ /**
147
+ * Add specified attributes to a JSX element's openingElement if they are not already present.
148
+ */
149
+ const addAttributesIfMissing = (j, openingElement, attributesToAdd) => {
150
+ if (!Array.isArray(openingElement.attributes)) return;
151
+ const attrs = openingElement.attributes;
152
+ attributesToAdd.forEach(({ attribute, name }) => {
153
+ if (!hasAttributeOnElement(openingElement, name)) attrs.push(attribute);
154
+ });
155
+ };
156
+ /**
157
+ * Returns a collection of JSX elements that match the specified
158
+ * exported name or names of the found aliases.
159
+ */
160
+ const findJSXElementsByName = (root, j) => (exportedName, aliases) => {
161
+ const aliasNames = aliases?.size() ? aliases.paths().map((path) => path.node.local?.name) : [];
162
+ return root.find(j.JSXElement).filter((path) => {
163
+ const { name } = path.node.openingElement;
164
+ return name.type === "JSXIdentifier" && (name.name === exportedName || aliasNames.includes(name.name));
165
+ });
166
+ };
167
+ /**
168
+ * Removes an attribute by name from a JSX element's openingElement.
169
+ */
170
+ const removeAttributeByName = (j, openingElement, attributeName) => {
171
+ if (!Array.isArray(openingElement.attributes)) return;
172
+ openingElement.attributes = openingElement.attributes.filter((attr) => {
173
+ return !(attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === attributeName);
174
+ });
175
+ };
176
+
177
+ //#endregion
178
+ //#region src/helpers/jsxReportingUtils.ts
179
+ /**
180
+ * CodemodReporter is a utility class for reporting issues found during codemod transformations.
181
+ * It provides methods to report issues related to JSX elements, props, and attributes.
182
+ *
183
+ * @example
184
+ * ```typescript
185
+ * const issues: string[] = [];
186
+ * const reporter = createReporter(j, issues);
187
+ *
188
+ * // Report a deprecated prop
189
+ * reporter.reportDeprecatedProp(buttonElement, 'flat', 'variant="text"');
190
+ *
191
+ * // Report complex expression that needs review
192
+ * reporter.reportAmbiguousExpression(element, 'size');
193
+ *
194
+ * // Auto-detect common issues
195
+ * reporter.reportAttributeIssues(element);
196
+ * ```
197
+ */
198
+ var CodemodReporter = class {
199
+ j;
200
+ issues;
201
+ constructor(options) {
202
+ this.j = options.jscodeshift;
203
+ this.issues = options.issues;
204
+ }
205
+ /**
206
+ * Reports an issue with a JSX element
207
+ */
208
+ reportElement(element, reason) {
209
+ const node = this.getNode(element);
210
+ const componentName = this.getComponentName(node);
211
+ const line = this.getLineNumber(node);
212
+ this.addIssue(`Manual review required: <${componentName}> at line ${line} ${reason}.`);
213
+ }
214
+ /**
215
+ * Reports an issue with a specific prop
216
+ */
217
+ reportProp(element, propName, reason) {
218
+ const node = this.getNode(element);
219
+ const componentName = this.getComponentName(node);
220
+ const line = this.getLineNumber(node);
221
+ this.addIssue(`Manual review required: prop "${propName}" on <${componentName}> at line ${line} ${reason}.`);
222
+ }
223
+ /**
224
+ * Reports an issue with a JSX attribute directly
225
+ */
226
+ reportAttribute(attr, element, reason) {
227
+ const node = this.getNode(element);
228
+ const componentName = this.getComponentName(node);
229
+ const propName = this.getAttributeName(attr);
230
+ const line = this.getLineNumber(attr) || this.getLineNumber(node);
231
+ const defaultReason = this.getAttributeReason(attr);
232
+ const finalReason = reason || defaultReason;
233
+ this.addIssue(`Manual review required: prop "${propName}" on <${componentName}> at line ${line} ${finalReason}.`);
234
+ }
235
+ /**
236
+ * Reports spread props on an element
237
+ */
238
+ reportSpreadProps(element) {
239
+ this.reportElement(element, "contains spread props that need manual review");
240
+ }
241
+ /**
242
+ * Reports conflicting prop and children
243
+ */
244
+ reportPropWithChildren(element, propName) {
245
+ this.reportProp(element, propName, `conflicts with children - both "${propName}" prop and children are present`);
246
+ }
247
+ /**
248
+ * Reports unsupported prop value
249
+ */
250
+ reportUnsupportedValue(element, propName, value) {
251
+ this.reportProp(element, propName, `has unsupported value "${value}"`);
252
+ }
253
+ /**
254
+ * Reports ambiguous expression in prop
255
+ */
256
+ reportAmbiguousExpression(element, propName) {
257
+ this.reportProp(element, propName, "contains a complex expression that needs manual review");
258
+ }
259
+ /**
260
+ * Reports ambiguous children (like dynamic icons)
261
+ */
262
+ reportAmbiguousChildren(element, childType = "content") {
263
+ this.reportElement(element, `contains ambiguous ${childType} that needs manual review`);
264
+ }
265
+ /**
266
+ * Reports deprecated prop usage
267
+ */
268
+ reportDeprecatedProp(element, propName, alternative) {
269
+ const suggestion = alternative ? ` Use ${alternative} instead` : "";
270
+ this.reportProp(element, propName, `is deprecated${suggestion}`);
271
+ }
272
+ /**
273
+ * Reports missing required prop
274
+ */
275
+ reportMissingRequiredProp(element, propName) {
276
+ this.reportProp(element, propName, "is required but missing");
277
+ }
278
+ /**
279
+ * Reports conflicting props
280
+ */
281
+ reportConflictingProps(element, propNames) {
282
+ const propList = propNames.map((name) => `"${name}"`).join(", ");
283
+ this.reportElement(element, `has conflicting props: ${propList} cannot be used together`);
284
+ }
285
+ /**
286
+ * Auto-detects and reports common attribute issues
287
+ */
288
+ reportAttributeIssues(element) {
289
+ const { attributes } = this.getNode(element).openingElement;
290
+ if (!attributes) return;
291
+ if (attributes.some((attr) => attr.type === "JSXSpreadAttribute")) this.reportSpreadProps(element);
292
+ attributes.forEach((attr) => {
293
+ if (attr.type === "JSXAttribute" && attr.value?.type === "JSXExpressionContainer") this.reportAttribute(attr, element);
294
+ });
295
+ }
296
+ /**
297
+ * Finds and reports instances of components that are under an alias (imported with a different name)
298
+ */
299
+ reportAliases(element) {
300
+ this.reportElement(element, "is used via an import alias and needs manual review");
301
+ }
302
+ /**
303
+ * Finds and reports instances of non-DS import declarations that conflict with the component name
304
+ */
305
+ reportConflictingImports(node) {
306
+ this.addIssue(`Manual review required: Non-WDS package resulting in an import conflict at line ${this.getLineNumber(node)}.`);
307
+ }
308
+ /**
309
+ * Reports enum usage for future conversion tracking
310
+ */
311
+ reportEnumUsage(element, propName, enumValue) {
312
+ this.reportProp(element, propName, `uses enum value "${enumValue}" which has been preserved but should be migrated to a string literal in the future`);
313
+ }
314
+ getNode(element) {
315
+ return "node" in element ? element.node : element;
316
+ }
317
+ getComponentName(node) {
318
+ const { name } = node.openingElement;
319
+ if (name.type === "JSXIdentifier") return name.name;
320
+ return this.j(name).toSource();
321
+ }
322
+ getLineNumber(node) {
323
+ return node.loc?.start.line?.toString() || "unknown";
324
+ }
325
+ getAttributeName(attr) {
326
+ if (attr.name.type === "JSXIdentifier") return attr.name.name;
327
+ return this.j(attr.name).toSource();
328
+ }
329
+ getAttributeReason(attr) {
330
+ if (!attr.value) return "has no value";
331
+ if (attr.value.type === "JSXExpressionContainer") {
332
+ const expr = attr.value.expression;
333
+ const expressionType = expr.type.replace("Expression", "").toLowerCase();
334
+ if (expr.type === "Identifier" || expr.type === "MemberExpression") return `contains a ${expressionType} (${this.j(expr).toSource()})`;
335
+ return `contains a complex ${expressionType} expression`;
336
+ }
337
+ return "needs manual review";
338
+ }
339
+ addIssue(message) {
340
+ this.issues.push(message);
341
+ }
342
+ };
343
+ const createReporter = (j, issues) => {
344
+ return new CodemodReporter({
345
+ jscodeshift: j,
346
+ issues
347
+ });
348
+ };
349
+
350
+ //#endregion
4
351
  //#region src/transforms/button/transformer.ts
5
352
  const parser = "tsx";
6
353
  const buildPriorityMapping = (opts) => {
@@ -135,10 +482,10 @@ const transformer = (file, api, options) => {
135
482
  if (type && priority) return priorityMapping[type]?.[priority] || priority;
136
483
  return priority;
137
484
  };
138
- const reporter = require_helpers.createReporter(j, manualReviewIssues);
139
- const { exists: hasButtonImport, aliases: buttonAliases, resolvedName: buttonName, conflictingImports: conflictingButtonImport } = require_helpers.hasImport_default(root, "@transferwise/components", "Button", j);
485
+ const reporter = createReporter(j, manualReviewIssues);
486
+ const { exists: hasButtonImport, aliases: buttonAliases, resolvedName: buttonName, conflictingImports: conflictingButtonImport } = hasImport_default(root, "@transferwise/components", "Button", j);
140
487
  if (conflictingButtonImport.length) conflictingButtonImport.forEach((node) => reporter.reportConflictingImports(node));
141
- const { exists: hasActionButtonImport, remove: removeActionButtonImport, aliases: actionButtonAliases } = require_helpers.hasImport_default(root, "@transferwise/components", "ActionButton", j);
488
+ const { exists: hasActionButtonImport, remove: removeActionButtonImport, aliases: actionButtonAliases } = hasImport_default(root, "@transferwise/components", "ActionButton", j);
142
489
  if (!hasButtonImport && !hasActionButtonImport) return file.source;
143
490
  const iconImports = /* @__PURE__ */ new Set();
144
491
  root.find(j.ImportDeclaration, { source: { value: "@transferwise/icons" } }).forEach((path) => {
@@ -150,12 +497,12 @@ const transformer = (file, api, options) => {
150
497
  });
151
498
  });
152
499
  if (hasActionButtonImport) {
153
- if (!hasButtonImport) require_helpers.addImport_default(root, "@transferwise/components", "Button", j);
154
- require_helpers.findJSXElementsByName(root, j)("ActionButton", actionButtonAliases).forEach((path) => {
500
+ if (!hasButtonImport) addImport_default(root, "@transferwise/components", "Button", j);
501
+ findJSXElementsByName(root, j)("ActionButton", actionButtonAliases).forEach((path) => {
155
502
  const { openingElement, closingElement } = path.node;
156
- openingElement.name = require_helpers.setNameIfJSXIdentifier(openingElement.name, buttonName);
157
- if (closingElement) closingElement.name = require_helpers.setNameIfJSXIdentifier(closingElement.name, buttonName);
158
- require_helpers.iconUtils_default(j, path.node.children, iconImports, openingElement);
503
+ openingElement.name = setNameIfJSXIdentifier(openingElement.name, buttonName);
504
+ if (closingElement) closingElement.name = setNameIfJSXIdentifier(closingElement.name, buttonName);
505
+ iconUtils_default(j, path.node.children, iconImports, openingElement);
159
506
  if ((openingElement.attributes ?? []).some((attr) => attr.type === "JSXSpreadAttribute")) reporter.reportSpreadProps(path);
160
507
  const legacyPropNames = [
161
508
  "priority",
@@ -178,7 +525,7 @@ const transformer = (file, api, options) => {
178
525
  const hasChildren = path.node.children?.some((child) => child.type === "JSXText" && child.value.trim() !== "" || child.type === "JSXElement" || child.type === "JSXExpressionContainer") || path.node.children && path.node.children?.length > 0;
179
526
  if (hasTextProp && hasChildren) reporter.reportPropWithChildren(path, "text");
180
527
  else if (hasTextProp && !hasChildren && openingElement.selfClosing) path.replace(j.jsxElement(j.jsxOpeningElement(openingElement.name, openingElement.attributes), j.jsxClosingElement(openingElement.name), [j.jsxText(legacyProps.text || "")]));
181
- require_helpers.addAttributesIfMissing(j, path.node.openingElement, [{
528
+ addAttributesIfMissing(j, path.node.openingElement, [{
182
529
  attribute: j.jsxAttribute(j.jsxIdentifier("v2")),
183
530
  name: "v2"
184
531
  }, {
@@ -194,17 +541,17 @@ const transformer = (file, api, options) => {
194
541
  });
195
542
  removeActionButtonImport();
196
543
  }
197
- if (hasButtonImport) require_helpers.findJSXElementsByName(root, j)("Button", buttonAliases).forEach((path) => {
544
+ if (hasButtonImport) findJSXElementsByName(root, j)("Button", buttonAliases).forEach((path) => {
198
545
  const { openingElement } = path.node;
199
- if (require_helpers.hasAttributeOnElement(openingElement, "v2")) return;
546
+ if (hasAttributeOnElement(openingElement, "v2")) return;
200
547
  const hasJSXChildren = path.node.children?.some((child) => child.type === "JSXText" && child.value.trim() !== "" || child.type === "JSXElement" || child.type === "JSXFragment" && child.children && child.children.length > 0 || child.type === "JSXExpressionContainer" && child.expression.type !== "JSXEmptyExpression");
201
548
  const hasChildrenAsProp = openingElement.attributes?.some((attr) => attr.type === "JSXAttribute" && attr.name?.type === "JSXIdentifier" && attr.name.name === "children");
202
549
  if (!hasJSXChildren && !hasChildrenAsProp) return;
203
- require_helpers.addAttributesIfMissing(j, openingElement, [{
550
+ addAttributesIfMissing(j, openingElement, [{
204
551
  attribute: j.jsxAttribute(j.jsxIdentifier("v2")),
205
552
  name: "v2"
206
553
  }]);
207
- require_helpers.iconUtils_default(j, path.node.children, iconImports, openingElement);
554
+ iconUtils_default(j, path.node.children, iconImports, openingElement);
208
555
  const legacyProps = {};
209
556
  const legacyPropNames = [
210
557
  "priority",
@@ -240,7 +587,7 @@ const transformer = (file, api, options) => {
240
587
  "lg",
241
588
  "xl"
242
589
  ].includes(resolved)) {
243
- require_helpers.removeAttributeByName(j, openingElement, "size");
590
+ removeAttributeByName(j, openingElement, "size");
244
591
  openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("size"), j.literal(resolved)));
245
592
  } else if (typeof rawValue === "string") reporter.reportUnsupportedValue(path, "size", rawValue);
246
593
  else if (rawValue !== void 0) reporter.reportAmbiguousExpression(path, "size");
@@ -265,7 +612,7 @@ const transformer = (file, api, options) => {
265
612
  "tertiary",
266
613
  "secondary-neutral"
267
614
  ].includes(mapped)) {
268
- require_helpers.removeAttributeByName(j, openingElement, "priority");
615
+ removeAttributeByName(j, openingElement, "priority");
269
616
  openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("priority"), j.literal(mapped)));
270
617
  } else if (typeof rawValue === "string") reporter.reportUnsupportedValue(path, "priority", rawValue);
271
618
  else if (rawValue !== void 0) reporter.reportAmbiguousExpression(path, "priority");
@@ -297,20 +644,20 @@ const transformer = (file, api, options) => {
297
644
  "reset"
298
645
  ];
299
646
  if (resolvedType === "negative" && isControlTypeEnum) {
300
- require_helpers.removeAttributeByName(j, openingElement, "type");
301
- if (require_helpers.hasAttributeOnElement(openingElement, "sentiment")) require_helpers.removeAttributeByName(j, openingElement, "sentiment");
302
- require_helpers.addAttributesIfMissing(j, openingElement, [{
647
+ removeAttributeByName(j, openingElement, "type");
648
+ if (hasAttributeOnElement(openingElement, "sentiment")) removeAttributeByName(j, openingElement, "sentiment");
649
+ addAttributesIfMissing(j, openingElement, [{
303
650
  attribute: j.jsxAttribute(j.jsxIdentifier("priority"), j.literal("primary")),
304
651
  name: "priority"
305
652
  }]);
306
653
  if (rawType) openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("sentiment"), j.jsxExpressionContainer(j.identifier(rawType))));
307
654
  } else if (resolvedType === "negative" && !isTypeEnum) {
308
- require_helpers.removeAttributeByName(j, openingElement, "type");
309
- if (require_helpers.hasAttributeOnElement(openingElement, "sentiment")) require_helpers.removeAttributeByName(j, openingElement, "sentiment");
655
+ removeAttributeByName(j, openingElement, "type");
656
+ if (hasAttributeOnElement(openingElement, "sentiment")) removeAttributeByName(j, openingElement, "sentiment");
310
657
  openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("sentiment"), j.literal("negative")));
311
658
  } else if (isControlTypeEnum && resolvedType && ["positive", "accent"].includes(resolvedType)) {
312
- require_helpers.removeAttributeByName(j, openingElement, "type");
313
- require_helpers.addAttributesIfMissing(j, openingElement, [{
659
+ removeAttributeByName(j, openingElement, "type");
660
+ addAttributesIfMissing(j, openingElement, [{
314
661
  attribute: j.jsxAttribute(j.jsxIdentifier("priority"), j.literal("primary")),
315
662
  name: "priority"
316
663
  }]);
@@ -318,21 +665,21 @@ const transformer = (file, api, options) => {
318
665
  if (resolvedType && typeof resolvedType === "string" && legacyButtonTypes.includes(resolvedType) && !isTypeEnum) {
319
666
  const consistentConversion = getConsistentTypeConversions(resolvedType);
320
667
  if (consistentConversion) {
321
- require_helpers.removeAttributeByName(j, openingElement, "type");
322
- require_helpers.removeAttributeByName(j, openingElement, "priority");
323
- require_helpers.removeAttributeByName(j, openingElement, "sentiment");
668
+ removeAttributeByName(j, openingElement, "type");
669
+ removeAttributeByName(j, openingElement, "priority");
670
+ removeAttributeByName(j, openingElement, "sentiment");
324
671
  if (consistentConversion.priority) openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("priority"), j.literal(consistentConversion.priority)));
325
672
  if (consistentConversion.sentiment) openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("sentiment"), j.literal(consistentConversion.sentiment)));
326
673
  } else {
327
- require_helpers.removeAttributeByName(j, openingElement, "type");
328
- require_helpers.addAttributesIfMissing(j, openingElement, [{
674
+ removeAttributeByName(j, openingElement, "type");
675
+ addAttributesIfMissing(j, openingElement, [{
329
676
  attribute: j.jsxAttribute(j.jsxIdentifier("priority"), j.literal("primary")),
330
677
  name: "priority"
331
678
  }]);
332
679
  }
333
680
  } else if (isTypeEnum) {}
334
681
  if (typeof finalHtmlType === "string" && htmlTypes.includes(finalHtmlType)) {
335
- require_helpers.removeAttributeByName(j, openingElement, "htmlType");
682
+ removeAttributeByName(j, openingElement, "htmlType");
336
683
  openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("type"), j.literal(finalHtmlType)));
337
684
  } else if (typeof rawType === "string" || typeof rawHtmlType === "string") {
338
685
  const valueToCheck = rawType ?? rawHtmlType ?? "";
@@ -351,7 +698,7 @@ const transformer = (file, api, options) => {
351
698
  if (!openingElement.attributes?.some((attr) => attr.type === "JSXAttribute" && attr.name && attr.name.name === "sentiment")) {
352
699
  const rawValue = legacyProps.sentiment;
353
700
  if (rawValue === "negative") {
354
- require_helpers.removeAttributeByName(j, openingElement, "sentiment");
701
+ removeAttributeByName(j, openingElement, "sentiment");
355
702
  openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("sentiment"), j.literal("negative")));
356
703
  } else if (typeof rawValue === "string") reporter.reportUnsupportedValue(path, "sentiment", rawValue);
357
704
  else if (rawValue !== void 0) reporter.reportAmbiguousExpression(path, "sentiment");