@atlaskit/codemod-cli 0.24.4 → 0.25.1

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.
Files changed (55) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +19 -9
  3. package/bin/codemod-cli.js +10 -10
  4. package/dist/cjs/main.js +1 -1
  5. package/dist/cjs/presets/migrate-to-new-buttons/codemods/next-migrate-link-button-to-link.js +94 -0
  6. package/dist/cjs/presets/migrate-to-new-buttons/codemods/next-migrate-to-new-button-variants.js +30 -8
  7. package/dist/cjs/presets/migrate-to-new-buttons/codemods/next-remove-unsafe-size.js +4 -3
  8. package/dist/cjs/presets/migrate-to-new-buttons/migrate-to-new-buttons.js +2 -1
  9. package/dist/cjs/presets/migrate-to-new-buttons/utils/add-comment-for-custom-theme-buttons.js +2 -0
  10. package/dist/cjs/presets/migrate-to-new-buttons/utils/add-comment-for-overlay-prop.js +15 -0
  11. package/dist/cjs/presets/migrate-to-new-buttons/utils/constants.js +2 -1
  12. package/dist/cjs/presets/migrate-to-new-buttons/utils/find-attribute-with-value.js +17 -0
  13. package/dist/cjs/presets/migrate-to-new-buttons/utils/generate-link-element.js +40 -0
  14. package/dist/cjs/presets/migrate-to-new-buttons/utils/generate-new-button-element.js +6 -1
  15. package/dist/cjs/presets/migrate-to-new-buttons/utils/move-icon-value-from-link-button-to-link-children.js +30 -0
  16. package/dist/es2019/presets/migrate-to-new-buttons/codemods/next-migrate-link-button-to-link.js +81 -0
  17. package/dist/es2019/presets/migrate-to-new-buttons/codemods/next-migrate-to-new-button-variants.js +30 -8
  18. package/dist/es2019/presets/migrate-to-new-buttons/codemods/next-remove-unsafe-size.js +3 -2
  19. package/dist/es2019/presets/migrate-to-new-buttons/migrate-to-new-buttons.js +2 -1
  20. package/dist/es2019/presets/migrate-to-new-buttons/utils/add-comment-for-custom-theme-buttons.js +2 -0
  21. package/dist/es2019/presets/migrate-to-new-buttons/utils/add-comment-for-overlay-prop.js +7 -0
  22. package/dist/es2019/presets/migrate-to-new-buttons/utils/constants.js +1 -0
  23. package/dist/es2019/presets/migrate-to-new-buttons/utils/find-attribute-with-value.js +11 -0
  24. package/dist/es2019/presets/migrate-to-new-buttons/utils/generate-link-element.js +36 -0
  25. package/dist/es2019/presets/migrate-to-new-buttons/utils/generate-new-button-element.js +6 -1
  26. package/dist/es2019/presets/migrate-to-new-buttons/utils/move-icon-value-from-link-button-to-link-children.js +24 -0
  27. package/dist/esm/main.js +1 -1
  28. package/dist/esm/presets/migrate-to-new-buttons/codemods/next-migrate-link-button-to-link.js +87 -0
  29. package/dist/esm/presets/migrate-to-new-buttons/codemods/next-migrate-to-new-button-variants.js +30 -8
  30. package/dist/esm/presets/migrate-to-new-buttons/codemods/next-remove-unsafe-size.js +3 -2
  31. package/dist/esm/presets/migrate-to-new-buttons/migrate-to-new-buttons.js +2 -1
  32. package/dist/esm/presets/migrate-to-new-buttons/utils/add-comment-for-custom-theme-buttons.js +2 -0
  33. package/dist/esm/presets/migrate-to-new-buttons/utils/add-comment-for-overlay-prop.js +9 -0
  34. package/dist/esm/presets/migrate-to-new-buttons/utils/constants.js +1 -0
  35. package/dist/esm/presets/migrate-to-new-buttons/utils/find-attribute-with-value.js +11 -0
  36. package/dist/esm/presets/migrate-to-new-buttons/utils/generate-link-element.js +34 -0
  37. package/dist/esm/presets/migrate-to-new-buttons/utils/generate-new-button-element.js +6 -1
  38. package/dist/esm/presets/migrate-to-new-buttons/utils/move-icon-value-from-link-button-to-link-children.js +24 -0
  39. package/dist/types/presets/migrate-to-new-buttons/codemods/next-migrate-link-button-to-link.d.ts +3 -0
  40. package/dist/types/presets/migrate-to-new-buttons/codemods/next-remove-unsafe-size.d.ts +2 -1
  41. package/dist/types/presets/migrate-to-new-buttons/utils/add-comment-for-overlay-prop.d.ts +2 -0
  42. package/dist/types/presets/migrate-to-new-buttons/utils/constants.d.ts +1 -0
  43. package/dist/types/presets/migrate-to-new-buttons/utils/find-attribute-with-value.d.ts +2 -0
  44. package/dist/types/presets/migrate-to-new-buttons/utils/generate-link-element.d.ts +3 -0
  45. package/dist/types/presets/migrate-to-new-buttons/utils/move-icon-value-from-link-button-to-link-children.d.ts +3 -0
  46. package/dist/types-ts4.5/presets/migrate-to-new-buttons/codemods/next-migrate-link-button-to-link.d.ts +3 -0
  47. package/dist/types-ts4.5/presets/migrate-to-new-buttons/codemods/next-remove-unsafe-size.d.ts +2 -1
  48. package/dist/types-ts4.5/presets/migrate-to-new-buttons/utils/add-comment-for-overlay-prop.d.ts +2 -0
  49. package/dist/types-ts4.5/presets/migrate-to-new-buttons/utils/constants.d.ts +1 -0
  50. package/dist/types-ts4.5/presets/migrate-to-new-buttons/utils/find-attribute-with-value.d.ts +2 -0
  51. package/dist/types-ts4.5/presets/migrate-to-new-buttons/utils/generate-link-element.d.ts +3 -0
  52. package/dist/types-ts4.5/presets/migrate-to-new-buttons/utils/move-icon-value-from-link-button-to-link-children.d.ts +3 -0
  53. package/index.js +6 -6
  54. package/package.json +63 -63
  55. package/report.api.md +29 -28
@@ -4,12 +4,15 @@ import { PRINT_SETTINGS, OLD_BUTTON_VARIANTS, NEW_BUTTON_VARIANTS, entryPointsMa
4
4
  import getDefaultImports from '../utils/get-default-imports';
5
5
  import getSpecifierNames from '../utils/get-specifier-names';
6
6
  import { generateNewElement, handleIconAttributes } from '../utils/generate-new-button-element';
7
+ import { generateLinkComponent } from '../utils/generate-link-element';
7
8
  import { ifHasUnsupportedProps } from '../utils/has-unsupported-props';
8
9
  import { checkIfVariantAlreadyImported } from '../utils/if-variant-already-imported';
9
10
  import { renameDefaultButtonToLegacyButtonImport } from '../utils/rename-default-button-to-legacy-button';
10
11
  import { migrateFitContainerIconButton } from '../utils/migrate-fit-container-icon-button';
11
12
  import { importTypesFromNewEntryPoint } from '../utils/import-types-from-new-entry-point';
12
13
  import { addCommentForCustomThemeButtons } from '../utils/add-comment-for-custom-theme-buttons';
14
+ import { addCommentForOverlayProp } from '../utils/add-comment-for-overlay-prop';
15
+ import { findJSXAttributeWithValue } from '../utils/find-attribute-with-value';
13
16
  const transformer = (file, api) => {
14
17
  const j = api.jscodeshift;
15
18
  const fileSource = j(file.source);
@@ -39,11 +42,13 @@ const transformer = (file, api) => {
39
42
  defaultButton: checkIfVariantAlreadyImported(NEW_BUTTON_VARIANTS.default, NEW_BUTTON_ENTRY_POINT, fileSource, j, true),
40
43
  linkButton: checkIfVariantAlreadyImported(NEW_BUTTON_VARIANTS.link, NEW_BUTTON_ENTRY_POINT, fileSource, j),
41
44
  iconButton: checkIfVariantAlreadyImported(NEW_BUTTON_VARIANTS.icon, NEW_BUTTON_ENTRY_POINT, fileSource, j),
42
- linkIconButton: checkIfVariantAlreadyImported(NEW_BUTTON_VARIANTS.linkIcon, NEW_BUTTON_ENTRY_POINT, fileSource, j)
45
+ linkIconButton: checkIfVariantAlreadyImported(NEW_BUTTON_VARIANTS.linkIcon, NEW_BUTTON_ENTRY_POINT, fileSource, j),
46
+ link: checkIfVariantAlreadyImported('link', '@atlaskit/link', fileSource, j)
43
47
  };
44
48
  const oldButtonElements = fileSource.find(j.JSXElement).filter(path => {
45
49
  return path.value.openingElement.name.type === 'JSXIdentifier' && ((oldDefaultImportSpecifiers === null || oldDefaultImportSpecifiers === void 0 ? void 0 : oldDefaultImportSpecifiers.includes(path.value.openingElement.name.name)) || Object.values(OLD_BUTTON_VARIANTS).includes(path.value.openingElement.name.name));
46
50
  });
51
+ addCommentForOverlayProp(oldButtonElements, j);
47
52
  const oldButtonsWithoutUnsupportedProps = oldButtonElements.filter(path => !ifHasUnsupportedProps(path.value.openingElement.attributes));
48
53
  oldButtonsWithoutUnsupportedProps.forEach(element => {
49
54
  var _element$value$childr;
@@ -57,18 +62,24 @@ const transformer = (file, api) => {
57
62
  const hasHref = buttonAttributes.includes('href');
58
63
  const hasIcon = buttonAttributes.includes('iconBefore') || buttonAttributes.includes('iconAfter');
59
64
  const hasNoChildren = ((_element$value$childr = element.value.children) === null || _element$value$childr === void 0 ? void 0 : _element$value$childr.length) === 0;
65
+ const hasSpacing = attributes.find(attr => {
66
+ var _attr$value;
67
+ return attr.type === 'JSXAttribute' && attr.name.name === 'spacing' && ((_attr$value = attr.value) === null || _attr$value === void 0 ? void 0 : _attr$value.type) === 'StringLiteral' && attr.value.value !== 'none';
68
+ }) || !buttonAttributes.includes('spacing');
69
+ const hasSpacingNone = findJSXAttributeWithValue(element.value.openingElement, 'spacing', 'none');
60
70
  const isFitContainerIconButton = hasIcon && hasNoChildren && buttonAttributes.includes('shouldFitContainer');
61
- const isLinkIconButton = hasHref && hasIcon && hasNoChildren && !isFitContainerIconButton;
62
- const isLinkButton = hasHref && !isLinkIconButton;
63
- let isIconButton = !hasHref && hasIcon && hasNoChildren && !isFitContainerIconButton;
64
- const isDefaultButton = !isLinkButton && !isLinkIconButton && !isIconButton && !isFitContainerIconButton;
65
- const isDefaultVariantWithAnIcon = !isLinkIconButton && !isIconButton && !isFitContainerIconButton && hasIcon;
66
- const isLoadingButton = element.value.openingElement.name.type === 'JSXIdentifier' && element.value.openingElement.name.name === loadingButtonDirectImportName;
67
71
  const linkAppearanceAttribute = attributes.find(node => {
68
72
  var _node$value, _node$name, _node$value2, _node$value3;
69
73
  return node.type === 'JSXAttribute' && ((_node$value = node.value) === null || _node$value === void 0 ? void 0 : _node$value.type) === 'StringLiteral' && (node === null || node === void 0 ? void 0 : (_node$name = node.name) === null || _node$name === void 0 ? void 0 : _node$name.name) === 'appearance' && ((node === null || node === void 0 ? void 0 : (_node$value2 = node.value) === null || _node$value2 === void 0 ? void 0 : _node$value2.value) === 'link' || (node === null || node === void 0 ? void 0 : (_node$value3 = node.value) === null || _node$value3 === void 0 ? void 0 : _node$value3.value) === 'subtle-link');
70
74
  });
71
- if (isDefaultVariantWithAnIcon) {
75
+ const isLinkIconButton = hasHref && hasIcon && hasNoChildren && !isFitContainerIconButton;
76
+ const isLinkButton = hasHref && !isLinkIconButton && !hasNoChildren && hasSpacing;
77
+ const isLink = hasHref && !isLinkIconButton && !hasNoChildren && hasSpacingNone && linkAppearanceAttribute;
78
+ let isIconButton = !hasHref && hasIcon && hasNoChildren && !isFitContainerIconButton && !isLink;
79
+ const isDefaultButton = !isLinkButton && !isLinkIconButton && !isIconButton && !isFitContainerIconButton && !isLink;
80
+ const isDefaultVariantWithAnIcon = !isLinkIconButton && !isIconButton && !isFitContainerIconButton && hasIcon && !isLink;
81
+ const isLoadingButton = element.value.openingElement.name.type === 'JSXIdentifier' && element.value.openingElement.name.name === loadingButtonDirectImportName;
82
+ if (isDefaultVariantWithAnIcon && !isLink) {
72
83
  handleIconAttributes(element.value, j);
73
84
  }
74
85
  if (isFitContainerIconButton) {
@@ -89,6 +100,10 @@ const transformer = (file, api) => {
89
100
  hasVariant.linkButton = true;
90
101
  j(element).replaceWith(generateNewElement(NEW_BUTTON_VARIANTS.link, element.value, j));
91
102
  }
103
+ if (isLink && !isLoadingButton) {
104
+ hasVariant.link = true;
105
+ j(element).replaceWith(generateLinkComponent(element.node, j));
106
+ }
92
107
  if (isDefaultButton && !isLoadingButton) {
93
108
  hasVariant.defaultButton = true;
94
109
  j(element).replaceWith(generateNewElement(newDefaultImportSpecifiers !== null && newDefaultImportSpecifiers !== void 0 && newDefaultImportSpecifiers.length ?
@@ -180,6 +195,13 @@ const transformer = (file, api) => {
180
195
  renameDefaultButtonToLegacyButtonImport(oldButtonImports, oldButtonsWithUnsupportedProps, j);
181
196
  }
182
197
  }
198
+ if (hasVariant.link) {
199
+ const linkImport = j.importDeclaration([j.importDefaultSpecifier(j.identifier('Link'))], j.stringLiteral('@atlaskit/link'));
200
+ oldButtonImports.at(0).insertBefore(linkImport);
201
+ if (!remainingDefaultButtons && !oldButtonsWithUnsupportedProps.length) {
202
+ oldButtonImports.at(0).remove();
203
+ }
204
+ }
183
205
  if (specifiers.length) {
184
206
  const existingNewButtonImports = fileSource.find(j.ImportDeclaration).filter(path => path.node.source.value === NEW_BUTTON_ENTRY_POINT);
185
207
  let newButtonImport = j.importDeclaration(specifiers, j.stringLiteral(NEW_BUTTON_ENTRY_POINT));
@@ -1,6 +1,6 @@
1
1
  import { getImportDeclaration, hasJSXAttributes } from '@hypermod/utils';
2
2
  import { PRINT_SETTINGS, NEW_BUTTON_ENTRY_POINT, UNSAFE_SIZE_PROPS_MAP } from '../utils/constants';
3
- export default function (file, api) {
3
+ function transformer(file, api) {
4
4
  const j = api.jscodeshift;
5
5
  const source = j(file.source);
6
6
 
@@ -91,4 +91,5 @@ export default function (file, api) {
91
91
  }
92
92
  });
93
93
  return source.toSource(PRINT_SETTINGS);
94
- }
94
+ }
95
+ export default transformer;
@@ -1,8 +1,9 @@
1
1
  import splitImportsTransformer from './codemods/next-split-imports';
2
2
  import migrateToNewButtonVariantsTransformer from './codemods/next-migrate-to-new-button-variants';
3
3
  import removeUnsafeSizeTransformer from './codemods/next-remove-unsafe-size';
4
+ import migrateLinkButtonToLinkTransformer from './codemods/next-migrate-link-button-to-link';
4
5
  export default async function transformer(file, api) {
5
- const transformers = [splitImportsTransformer, migrateToNewButtonVariantsTransformer, removeUnsafeSizeTransformer];
6
+ const transformers = [splitImportsTransformer, migrateToNewButtonVariantsTransformer, removeUnsafeSizeTransformer, migrateLinkButtonToLinkTransformer];
6
7
  let src = file.source;
7
8
  transformers.forEach(transformer => {
8
9
  if (typeof src === 'undefined') {
@@ -1,5 +1,6 @@
1
1
  import { addCommentBefore } from '@atlaskit/codemod-utils';
2
2
  import { entryPointsMapping, customThemeButtonComment } from './constants';
3
+ import { addCommentForOverlayProp } from './add-comment-for-overlay-prop';
3
4
  export const addCommentForCustomThemeButtons = (fileSource, j) => {
4
5
  var _fileSource$find$filt;
5
6
  let customThemeButtonImportName;
@@ -19,5 +20,6 @@ export const addCommentForCustomThemeButtons = (fileSource, j) => {
19
20
  if (!customThemeButtonElement.length) {
20
21
  return;
21
22
  }
23
+ addCommentForOverlayProp(customThemeButtonElement, j);
22
24
  addCommentBefore(j, j(customThemeButtonElement.get(0).node.openingElement), customThemeButtonComment, 'block');
23
25
  };
@@ -0,0 +1,7 @@
1
+ import { addCommentBefore } from '@atlaskit/codemod-utils';
2
+ import { overlayPropComment } from './constants';
3
+ export const addCommentForOverlayProp = (oldButtons, j) => {
4
+ oldButtons.find(j.JSXAttribute).filter(attribute => attribute.node.name.name === 'overlay').forEach(attribute => {
5
+ addCommentBefore(j, j(attribute), overlayPropComment, 'block');
6
+ });
7
+ };
@@ -34,6 +34,7 @@ export const buttonPropsNoLongerSupportedComment = `Buttons with "component", "c
34
34
  export const migrateFitContainerButtonToDefaultButtonComment = `Migrated to a default button with text which is from the icon label.`;
35
35
  export const migrateFitContainerButtonToIconButtonComment = `"shouldFitContainer" is not available in icon buttons, please consider using a default button with text.`;
36
36
  export const customThemeButtonComment = `CustomThemeButton will be deprecated. Please consider migrating to Pressable or Anchor Primitives with custom styles.`;
37
+ export const overlayPropComment = `The 'overlay' prop has been deprecated. This only existed in legacy buttons for supporting loading spinners, which can now be achieved in new buttons using the \`isLoading\` prop. Please remove the \`overlay\` prop and consider using the new \`isLoading\` prop.`;
37
38
  export const loadingButtonComment = ({
38
39
  hasLinkAppearance,
39
40
  hasHref
@@ -0,0 +1,11 @@
1
+ export const findJSXAttributeWithValue = (path, attributeName, attributeValue) => {
2
+ var _path$attributes;
3
+ if (!path || path.type === 'JSXSpreadAttribute') {
4
+ return false;
5
+ }
6
+ const attribute = path === null || path === void 0 ? void 0 : (_path$attributes = path.attributes) === null || _path$attributes === void 0 ? void 0 : _path$attributes.find(attribute => {
7
+ var _attribute$value;
8
+ return attribute.type === 'JSXAttribute' && attribute.name.name === attributeName && ((_attribute$value = attribute.value) === null || _attribute$value === void 0 ? void 0 : _attribute$value.type) === 'StringLiteral' && attribute.value.value === attributeValue;
9
+ });
10
+ return Boolean(attribute);
11
+ };
@@ -0,0 +1,36 @@
1
+ export const modifyLinkAttributes = (element, j) => {
2
+ j(element).find(j.JSXAttribute).filter(path => {
3
+ var _path$node$value, _path$node$value2;
4
+ return path.node.name.name === 'appearance' && ((_path$node$value = path.node.value) === null || _path$node$value === void 0 ? void 0 : _path$node$value.type) === 'StringLiteral' && path.node.value.value === 'link' || path.node.name.name === 'spacing' && ((_path$node$value2 = path.node.value) === null || _path$node$value2 === void 0 ? void 0 : _path$node$value2.type) === 'StringLiteral' && path.node.value.value === 'none';
5
+ }).remove();
6
+ j(element).find(j.JSXAttribute).filter(path => {
7
+ var _path$node$value3;
8
+ return path.node.name.name === 'appearance' && ((_path$node$value3 = path.node.value) === null || _path$node$value3 === void 0 ? void 0 : _path$node$value3.type) === 'StringLiteral' && path.node.value.value === 'subtle-link';
9
+ }).replaceWith(j.jsxAttribute(j.jsxIdentifier('appearance'), j.stringLiteral('subtle')));
10
+ };
11
+ export const generateLinkComponent = (element, j) => {
12
+ const {
13
+ attributes
14
+ } = element.openingElement;
15
+ if (!element.children) {
16
+ return;
17
+ }
18
+ modifyLinkAttributes(element, j);
19
+ j(element).find(j.JSXAttribute).filter(attribute => {
20
+ var _attribute$node$value;
21
+ const isIconAttribute = attribute.node.name.name === 'iconBefore' || attribute.node.name.name === 'iconAfter';
22
+ if (((_attribute$node$value = attribute.node.value) === null || _attribute$node$value === void 0 ? void 0 : _attribute$node$value.type) === 'JSXExpressionContainer' && isIconAttribute) {
23
+ const iconNode = attribute.node.value;
24
+ if (iconNode && iconNode.type === 'JSXExpressionContainer' && iconNode.expression.type === 'JSXElement' && element.children) {
25
+ const icon = iconNode.expression;
26
+ attribute.node.name.name === 'iconBefore' ? element.children.unshift(icon) : element.children.push(icon);
27
+ }
28
+ }
29
+ return isIconAttribute;
30
+ }).remove();
31
+ return j.jsxElement.from({
32
+ openingElement: j.jsxOpeningElement(j.jsxIdentifier('Link'), attributes, false),
33
+ closingElement: j.jsxClosingElement(j.jsxIdentifier('Link')),
34
+ children: element.children
35
+ });
36
+ };
@@ -31,7 +31,6 @@ export const handleIconAttributes = (element, j, iconRenamed = false) => {
31
31
  const {
32
32
  attributes: buttonAttributes
33
33
  } = element.openingElement;
34
-
35
34
  // Get iconBefore and iconAfter attributes
36
35
  const buttonIconAttributes = buttonAttributes && getIconAttributes(buttonAttributes);
37
36
  buttonIconAttributes === null || buttonIconAttributes === void 0 ? void 0 : buttonIconAttributes.forEach(iconAttribute => {
@@ -100,6 +99,12 @@ export const generateNewElement = (variant, element, j) => {
100
99
  } = element.openingElement;
101
100
  const iconAttrs = attributes && getIconAttributes(attributes);
102
101
  const isIconOrLinkIcon = variant === NEW_BUTTON_VARIANTS.icon || variant === NEW_BUTTON_VARIANTS.linkIcon;
102
+ if (variant === NEW_BUTTON_VARIANTS.link) {
103
+ j(element).find(j.JSXAttribute).filter(path => {
104
+ var _path$node$value;
105
+ return path.node.name.name === 'appearance' && ((_path$node$value = path.node.value) === null || _path$node$value === void 0 ? void 0 : _path$node$value.type) === 'StringLiteral' && (path.node.value.value === 'subtle-link' || path.node.value.value === 'link');
106
+ }).replaceWith(j.jsxAttribute(j.jsxIdentifier('appearance'), j.stringLiteral('subtle')));
107
+ }
103
108
  if (isIconOrLinkIcon && iconAttrs !== null && iconAttrs !== void 0 && iconAttrs.length) {
104
109
  handleIconAttributes(element, j, true);
105
110
 
@@ -0,0 +1,24 @@
1
+ const moveIcon = (j, path, iconNode, beforeOrAfter) => {
2
+ let element;
3
+ if (!iconNode) {
4
+ return;
5
+ }
6
+ if (iconNode.type === 'JSXExpressionContainer') {
7
+ // when iconBefore={(iconProps) => <AddIcon {...iconProps} />}
8
+ if (iconNode.expression.type === 'ArrowFunctionExpression' && iconNode.expression.body.type === 'JSXElement') {
9
+ // remove {...iconProps} spread attribute
10
+ element = iconNode.expression.body;
11
+ j(element).find(j.JSXSpreadAttribute).remove();
12
+ j(element).find(j.JSXAttribute).insertBefore(j.jsxAttribute(j.jsxIdentifier('label'), j.stringLiteral('')));
13
+ }
14
+
15
+ // when iconBefore={AddIcon}
16
+ if (iconNode.expression.type === 'Identifier') {
17
+ element = j.jsxElement(j.jsxOpeningElement(j.jsxIdentifier(iconNode.expression.name), [j.jsxAttribute(j.jsxIdentifier('label'), j.stringLiteral(''))], true));
18
+ }
19
+ if (element && path.node.children) {
20
+ beforeOrAfter === 'iconBefore' ? path.node.children.unshift(element) : path.node.children.push(element);
21
+ }
22
+ }
23
+ };
24
+ export default moveIcon;
package/dist/esm/main.js CHANGED
@@ -298,7 +298,7 @@ function _main() {
298
298
  case 4:
299
299
  _yield$parseArgs = _context5.sent;
300
300
  packages = _yield$parseArgs.packages;
301
- _process$env$_PACKAGE = "0.24.4", _PACKAGE_VERSION_ = _process$env$_PACKAGE === void 0 ? '0.0.0-dev' : _process$env$_PACKAGE;
301
+ _process$env$_PACKAGE = "0.25.1", _PACKAGE_VERSION_ = _process$env$_PACKAGE === void 0 ? '0.0.0-dev' : _process$env$_PACKAGE;
302
302
  logger.log(chalk.bgBlue(chalk.black("\uD83D\uDCDA Atlassian-Frontend codemod library @ ".concat(_PACKAGE_VERSION_, " \uD83D\uDCDA"))));
303
303
  if (packages && packages.length > 0) {
304
304
  logger.log(chalk.gray("Searching for codemods for newer versions of the following packages: ".concat(packages.map(function (pkg) {
@@ -0,0 +1,87 @@
1
+ import { getImportDeclaration } from '@hypermod/utils';
2
+ import { PRINT_SETTINGS, NEW_BUTTON_ENTRY_POINT, NEW_BUTTON_VARIANTS } from '../utils/constants';
3
+ import moveIconValueFromLinkButtonPropsToLinkChildren from '../utils/move-icon-value-from-link-button-to-link-children';
4
+ import { findJSXAttributeWithValue } from '../utils/find-attribute-with-value';
5
+ import { modifyLinkAttributes } from '../utils/generate-link-element';
6
+ function transformer(file, api) {
7
+ var j = api.jscodeshift;
8
+ var source = j(file.source);
9
+
10
+ // Find all new button imports
11
+ var newButtonImportDeclarations = getImportDeclaration(j, source, NEW_BUTTON_ENTRY_POINT);
12
+
13
+ // No imports for new button found, exit early
14
+ if (!newButtonImportDeclarations.length) {
15
+ return source.toSource();
16
+ }
17
+ var linkButtonSpecifier = '';
18
+ var linkButtonDeclaration;
19
+ newButtonImportDeclarations.forEach(function (newButtonImport) {
20
+ if (!newButtonImport.value.specifiers) {
21
+ return;
22
+ }
23
+ newButtonImport.value.specifiers.map(function (specifier) {
24
+ if (specifier.type === 'ImportSpecifier' && specifier.imported && specifier.imported.name === NEW_BUTTON_VARIANTS['link']) {
25
+ var _specifier$local;
26
+ linkButtonDeclaration = newButtonImport;
27
+ linkButtonSpecifier = ((_specifier$local = specifier.local) === null || _specifier$local === void 0 ? void 0 : _specifier$local.name) || '';
28
+ }
29
+ });
30
+ });
31
+ if (!linkButtonSpecifier) {
32
+ return source.toSource();
33
+ }
34
+ var hasLink = false;
35
+ var allLinkButtons = source.find(j.JSXElement).filter(function (path) {
36
+ return path.value.openingElement.name.type === 'JSXIdentifier' && path.value.openingElement.name.name === linkButtonSpecifier;
37
+ });
38
+ allLinkButtons.filter(function (path) {
39
+ return findJSXAttributeWithValue(path.value.openingElement, 'appearance', 'link') || findJSXAttributeWithValue(path.value.openingElement, 'appearance', 'subtle-link');
40
+ }).forEach(function (path) {
41
+ var hasSpacingNone = findJSXAttributeWithValue(path.value.openingElement, 'spacing', 'none');
42
+ if (!hasSpacingNone) {
43
+ j(path).find(j.JSXAttribute).filter(function (path) {
44
+ var _path$node$value;
45
+ return path.node.name.name === 'appearance' && ((_path$node$value = path.node.value) === null || _path$node$value === void 0 ? void 0 : _path$node$value.type) === 'StringLiteral' && (path.node.value.value === 'subtle-link' || path.node.value.value === 'link');
46
+ }).replaceWith(j.jsxAttribute(j.jsxIdentifier('appearance'), j.stringLiteral('subtle')));
47
+ }
48
+ if (hasSpacingNone) {
49
+ var attributes = path.node.openingElement.attributes;
50
+ modifyLinkAttributes(path.node, j);
51
+ j(path).find(j.JSXAttribute).filter(function (attribute) {
52
+ var _attribute$node$value;
53
+ var isIconAttribute = attribute.node.name.name === 'iconBefore' || attribute.node.name.name === 'iconAfter';
54
+ if (((_attribute$node$value = attribute.node.value) === null || _attribute$node$value === void 0 ? void 0 : _attribute$node$value.type) === 'JSXExpressionContainer' && isIconAttribute) {
55
+ moveIconValueFromLinkButtonPropsToLinkChildren(j, path, attribute.node.value, attribute.node.name.name);
56
+ }
57
+ return isIconAttribute;
58
+ }).remove();
59
+ hasLink = true;
60
+ j(path).replaceWith(j.jsxElement.from({
61
+ openingElement: j.jsxOpeningElement(j.jsxIdentifier('Link'), attributes, false),
62
+ closingElement: j.jsxClosingElement(j.jsxIdentifier('Link')),
63
+ children: path.node.children
64
+ }));
65
+ }
66
+ });
67
+
68
+ // add link import and remove link button import if no link button is found
69
+ if (hasLink && linkButtonDeclaration) {
70
+ var linkImport = j.importDeclaration([j.importDefaultSpecifier(j.identifier('Link'))], j.stringLiteral('@atlaskit/link'));
71
+ j(linkButtonDeclaration).insertAfter(linkImport);
72
+ var remainingLinkButton = source.find(j.JSXElement).filter(function (path) {
73
+ return path.value.openingElement.name.type === 'JSXIdentifier' && path.value.openingElement.name.name === linkButtonSpecifier;
74
+ });
75
+ if (!remainingLinkButton.length) {
76
+ var _value$specifiers;
77
+ j(linkButtonDeclaration).find(j.ImportSpecifier).filter(function (path) {
78
+ return path.node.imported.name === NEW_BUTTON_VARIANTS['link'];
79
+ }).remove();
80
+ if (((_value$specifiers = linkButtonDeclaration.value.specifiers) === null || _value$specifiers === void 0 ? void 0 : _value$specifiers.length) === 0) {
81
+ j(linkButtonDeclaration).remove();
82
+ }
83
+ }
84
+ }
85
+ return source.toSource(PRINT_SETTINGS);
86
+ }
87
+ export default transformer;
@@ -5,12 +5,15 @@ import { PRINT_SETTINGS, OLD_BUTTON_VARIANTS, NEW_BUTTON_VARIANTS, entryPointsMa
5
5
  import getDefaultImports from '../utils/get-default-imports';
6
6
  import getSpecifierNames from '../utils/get-specifier-names';
7
7
  import { generateNewElement, handleIconAttributes } from '../utils/generate-new-button-element';
8
+ import { generateLinkComponent } from '../utils/generate-link-element';
8
9
  import { ifHasUnsupportedProps } from '../utils/has-unsupported-props';
9
10
  import { checkIfVariantAlreadyImported } from '../utils/if-variant-already-imported';
10
11
  import { renameDefaultButtonToLegacyButtonImport } from '../utils/rename-default-button-to-legacy-button';
11
12
  import { migrateFitContainerIconButton } from '../utils/migrate-fit-container-icon-button';
12
13
  import { importTypesFromNewEntryPoint } from '../utils/import-types-from-new-entry-point';
13
14
  import { addCommentForCustomThemeButtons } from '../utils/add-comment-for-custom-theme-buttons';
15
+ import { addCommentForOverlayProp } from '../utils/add-comment-for-overlay-prop';
16
+ import { findJSXAttributeWithValue } from '../utils/find-attribute-with-value';
14
17
  var transformer = function transformer(file, api) {
15
18
  var j = api.jscodeshift;
16
19
  var fileSource = j(file.source);
@@ -44,11 +47,13 @@ var transformer = function transformer(file, api) {
44
47
  defaultButton: checkIfVariantAlreadyImported(NEW_BUTTON_VARIANTS.default, NEW_BUTTON_ENTRY_POINT, fileSource, j, true),
45
48
  linkButton: checkIfVariantAlreadyImported(NEW_BUTTON_VARIANTS.link, NEW_BUTTON_ENTRY_POINT, fileSource, j),
46
49
  iconButton: checkIfVariantAlreadyImported(NEW_BUTTON_VARIANTS.icon, NEW_BUTTON_ENTRY_POINT, fileSource, j),
47
- linkIconButton: checkIfVariantAlreadyImported(NEW_BUTTON_VARIANTS.linkIcon, NEW_BUTTON_ENTRY_POINT, fileSource, j)
50
+ linkIconButton: checkIfVariantAlreadyImported(NEW_BUTTON_VARIANTS.linkIcon, NEW_BUTTON_ENTRY_POINT, fileSource, j),
51
+ link: checkIfVariantAlreadyImported('link', '@atlaskit/link', fileSource, j)
48
52
  };
49
53
  var oldButtonElements = fileSource.find(j.JSXElement).filter(function (path) {
50
54
  return path.value.openingElement.name.type === 'JSXIdentifier' && ((oldDefaultImportSpecifiers === null || oldDefaultImportSpecifiers === void 0 ? void 0 : oldDefaultImportSpecifiers.includes(path.value.openingElement.name.name)) || Object.values(OLD_BUTTON_VARIANTS).includes(path.value.openingElement.name.name));
51
55
  });
56
+ addCommentForOverlayProp(oldButtonElements, j);
52
57
  var oldButtonsWithoutUnsupportedProps = oldButtonElements.filter(function (path) {
53
58
  return !ifHasUnsupportedProps(path.value.openingElement.attributes);
54
59
  });
@@ -64,18 +69,24 @@ var transformer = function transformer(file, api) {
64
69
  var hasHref = buttonAttributes.includes('href');
65
70
  var hasIcon = buttonAttributes.includes('iconBefore') || buttonAttributes.includes('iconAfter');
66
71
  var hasNoChildren = ((_element$value$childr = element.value.children) === null || _element$value$childr === void 0 ? void 0 : _element$value$childr.length) === 0;
72
+ var hasSpacing = attributes.find(function (attr) {
73
+ var _attr$value;
74
+ return attr.type === 'JSXAttribute' && attr.name.name === 'spacing' && ((_attr$value = attr.value) === null || _attr$value === void 0 ? void 0 : _attr$value.type) === 'StringLiteral' && attr.value.value !== 'none';
75
+ }) || !buttonAttributes.includes('spacing');
76
+ var hasSpacingNone = findJSXAttributeWithValue(element.value.openingElement, 'spacing', 'none');
67
77
  var isFitContainerIconButton = hasIcon && hasNoChildren && buttonAttributes.includes('shouldFitContainer');
68
- var isLinkIconButton = hasHref && hasIcon && hasNoChildren && !isFitContainerIconButton;
69
- var isLinkButton = hasHref && !isLinkIconButton;
70
- var isIconButton = !hasHref && hasIcon && hasNoChildren && !isFitContainerIconButton;
71
- var isDefaultButton = !isLinkButton && !isLinkIconButton && !isIconButton && !isFitContainerIconButton;
72
- var isDefaultVariantWithAnIcon = !isLinkIconButton && !isIconButton && !isFitContainerIconButton && hasIcon;
73
- var isLoadingButton = element.value.openingElement.name.type === 'JSXIdentifier' && element.value.openingElement.name.name === loadingButtonDirectImportName;
74
78
  var linkAppearanceAttribute = attributes.find(function (node) {
75
79
  var _node$value, _node$name, _node$value2, _node$value3;
76
80
  return node.type === 'JSXAttribute' && ((_node$value = node.value) === null || _node$value === void 0 ? void 0 : _node$value.type) === 'StringLiteral' && (node === null || node === void 0 || (_node$name = node.name) === null || _node$name === void 0 ? void 0 : _node$name.name) === 'appearance' && ((node === null || node === void 0 || (_node$value2 = node.value) === null || _node$value2 === void 0 ? void 0 : _node$value2.value) === 'link' || (node === null || node === void 0 || (_node$value3 = node.value) === null || _node$value3 === void 0 ? void 0 : _node$value3.value) === 'subtle-link');
77
81
  });
78
- if (isDefaultVariantWithAnIcon) {
82
+ var isLinkIconButton = hasHref && hasIcon && hasNoChildren && !isFitContainerIconButton;
83
+ var isLinkButton = hasHref && !isLinkIconButton && !hasNoChildren && hasSpacing;
84
+ var isLink = hasHref && !isLinkIconButton && !hasNoChildren && hasSpacingNone && linkAppearanceAttribute;
85
+ var isIconButton = !hasHref && hasIcon && hasNoChildren && !isFitContainerIconButton && !isLink;
86
+ var isDefaultButton = !isLinkButton && !isLinkIconButton && !isIconButton && !isFitContainerIconButton && !isLink;
87
+ var isDefaultVariantWithAnIcon = !isLinkIconButton && !isIconButton && !isFitContainerIconButton && hasIcon && !isLink;
88
+ var isLoadingButton = element.value.openingElement.name.type === 'JSXIdentifier' && element.value.openingElement.name.name === loadingButtonDirectImportName;
89
+ if (isDefaultVariantWithAnIcon && !isLink) {
79
90
  handleIconAttributes(element.value, j);
80
91
  }
81
92
  if (isFitContainerIconButton) {
@@ -96,6 +107,10 @@ var transformer = function transformer(file, api) {
96
107
  hasVariant.linkButton = true;
97
108
  j(element).replaceWith(generateNewElement(NEW_BUTTON_VARIANTS.link, element.value, j));
98
109
  }
110
+ if (isLink && !isLoadingButton) {
111
+ hasVariant.link = true;
112
+ j(element).replaceWith(generateLinkComponent(element.node, j));
113
+ }
99
114
  if (isDefaultButton && !isLoadingButton) {
100
115
  hasVariant.defaultButton = true;
101
116
  j(element).replaceWith(generateNewElement(newDefaultImportSpecifiers !== null && newDefaultImportSpecifiers !== void 0 && newDefaultImportSpecifiers.length ?
@@ -207,6 +222,13 @@ var transformer = function transformer(file, api) {
207
222
  renameDefaultButtonToLegacyButtonImport(oldButtonImports, oldButtonsWithUnsupportedProps, j);
208
223
  }
209
224
  }
225
+ if (hasVariant.link) {
226
+ var linkImport = j.importDeclaration([j.importDefaultSpecifier(j.identifier('Link'))], j.stringLiteral('@atlaskit/link'));
227
+ oldButtonImports.at(0).insertBefore(linkImport);
228
+ if (!remainingDefaultButtons && !oldButtonsWithUnsupportedProps.length) {
229
+ oldButtonImports.at(0).remove();
230
+ }
231
+ }
210
232
  if (specifiers.length) {
211
233
  var existingNewButtonImports = fileSource.find(j.ImportDeclaration).filter(function (path) {
212
234
  return path.node.source.value === NEW_BUTTON_ENTRY_POINT;
@@ -1,6 +1,6 @@
1
1
  import { getImportDeclaration, hasJSXAttributes } from '@hypermod/utils';
2
2
  import { PRINT_SETTINGS, NEW_BUTTON_ENTRY_POINT, UNSAFE_SIZE_PROPS_MAP } from '../utils/constants';
3
- export default function (file, api) {
3
+ function transformer(file, api) {
4
4
  var j = api.jscodeshift;
5
5
  var source = j(file.source);
6
6
 
@@ -112,4 +112,5 @@ export default function (file, api) {
112
112
  }
113
113
  });
114
114
  return source.toSource(PRINT_SETTINGS);
115
- }
115
+ }
116
+ export default transformer;
@@ -6,6 +6,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
6
6
  import splitImportsTransformer from './codemods/next-split-imports';
7
7
  import migrateToNewButtonVariantsTransformer from './codemods/next-migrate-to-new-button-variants';
8
8
  import removeUnsafeSizeTransformer from './codemods/next-remove-unsafe-size';
9
+ import migrateLinkButtonToLinkTransformer from './codemods/next-migrate-link-button-to-link';
9
10
  export default function transformer(_x, _x2) {
10
11
  return _transformer.apply(this, arguments);
11
12
  }
@@ -15,7 +16,7 @@ function _transformer() {
15
16
  return _regeneratorRuntime.wrap(function _callee$(_context) {
16
17
  while (1) switch (_context.prev = _context.next) {
17
18
  case 0:
18
- transformers = [splitImportsTransformer, migrateToNewButtonVariantsTransformer, removeUnsafeSizeTransformer];
19
+ transformers = [splitImportsTransformer, migrateToNewButtonVariantsTransformer, removeUnsafeSizeTransformer, migrateLinkButtonToLinkTransformer];
19
20
  src = file.source;
20
21
  transformers.forEach(function (transformer) {
21
22
  if (typeof src === 'undefined') {
@@ -1,5 +1,6 @@
1
1
  import { addCommentBefore } from '@atlaskit/codemod-utils';
2
2
  import { entryPointsMapping, customThemeButtonComment } from './constants';
3
+ import { addCommentForOverlayProp } from './add-comment-for-overlay-prop';
3
4
  export var addCommentForCustomThemeButtons = function addCommentForCustomThemeButtons(fileSource, j) {
4
5
  var _fileSource$find$filt;
5
6
  var customThemeButtonImportName;
@@ -23,5 +24,6 @@ export var addCommentForCustomThemeButtons = function addCommentForCustomThemeBu
23
24
  if (!customThemeButtonElement.length) {
24
25
  return;
25
26
  }
27
+ addCommentForOverlayProp(customThemeButtonElement, j);
26
28
  addCommentBefore(j, j(customThemeButtonElement.get(0).node.openingElement), customThemeButtonComment, 'block');
27
29
  };
@@ -0,0 +1,9 @@
1
+ import { addCommentBefore } from '@atlaskit/codemod-utils';
2
+ import { overlayPropComment } from './constants';
3
+ export var addCommentForOverlayProp = function addCommentForOverlayProp(oldButtons, j) {
4
+ oldButtons.find(j.JSXAttribute).filter(function (attribute) {
5
+ return attribute.node.name.name === 'overlay';
6
+ }).forEach(function (attribute) {
7
+ addCommentBefore(j, j(attribute), overlayPropComment, 'block');
8
+ });
9
+ };
@@ -34,6 +34,7 @@ export var buttonPropsNoLongerSupportedComment = "Buttons with \"component\", \"
34
34
  export var migrateFitContainerButtonToDefaultButtonComment = "Migrated to a default button with text which is from the icon label.";
35
35
  export var migrateFitContainerButtonToIconButtonComment = "\"shouldFitContainer\" is not available in icon buttons, please consider using a default button with text.";
36
36
  export var customThemeButtonComment = "CustomThemeButton will be deprecated. Please consider migrating to Pressable or Anchor Primitives with custom styles.";
37
+ export var overlayPropComment = "The 'overlay' prop has been deprecated. This only existed in legacy buttons for supporting loading spinners, which can now be achieved in new buttons using the `isLoading` prop. Please remove the `overlay` prop and consider using the new `isLoading` prop.";
37
38
  export var loadingButtonComment = function loadingButtonComment(_ref) {
38
39
  var hasLinkAppearance = _ref.hasLinkAppearance,
39
40
  hasHref = _ref.hasHref;
@@ -0,0 +1,11 @@
1
+ export var findJSXAttributeWithValue = function findJSXAttributeWithValue(path, attributeName, attributeValue) {
2
+ var _path$attributes;
3
+ if (!path || path.type === 'JSXSpreadAttribute') {
4
+ return false;
5
+ }
6
+ var attribute = path === null || path === void 0 || (_path$attributes = path.attributes) === null || _path$attributes === void 0 ? void 0 : _path$attributes.find(function (attribute) {
7
+ var _attribute$value;
8
+ return attribute.type === 'JSXAttribute' && attribute.name.name === attributeName && ((_attribute$value = attribute.value) === null || _attribute$value === void 0 ? void 0 : _attribute$value.type) === 'StringLiteral' && attribute.value.value === attributeValue;
9
+ });
10
+ return Boolean(attribute);
11
+ };
@@ -0,0 +1,34 @@
1
+ export var modifyLinkAttributes = function modifyLinkAttributes(element, j) {
2
+ j(element).find(j.JSXAttribute).filter(function (path) {
3
+ var _path$node$value, _path$node$value2;
4
+ return path.node.name.name === 'appearance' && ((_path$node$value = path.node.value) === null || _path$node$value === void 0 ? void 0 : _path$node$value.type) === 'StringLiteral' && path.node.value.value === 'link' || path.node.name.name === 'spacing' && ((_path$node$value2 = path.node.value) === null || _path$node$value2 === void 0 ? void 0 : _path$node$value2.type) === 'StringLiteral' && path.node.value.value === 'none';
5
+ }).remove();
6
+ j(element).find(j.JSXAttribute).filter(function (path) {
7
+ var _path$node$value3;
8
+ return path.node.name.name === 'appearance' && ((_path$node$value3 = path.node.value) === null || _path$node$value3 === void 0 ? void 0 : _path$node$value3.type) === 'StringLiteral' && path.node.value.value === 'subtle-link';
9
+ }).replaceWith(j.jsxAttribute(j.jsxIdentifier('appearance'), j.stringLiteral('subtle')));
10
+ };
11
+ export var generateLinkComponent = function generateLinkComponent(element, j) {
12
+ var attributes = element.openingElement.attributes;
13
+ if (!element.children) {
14
+ return;
15
+ }
16
+ modifyLinkAttributes(element, j);
17
+ j(element).find(j.JSXAttribute).filter(function (attribute) {
18
+ var _attribute$node$value;
19
+ var isIconAttribute = attribute.node.name.name === 'iconBefore' || attribute.node.name.name === 'iconAfter';
20
+ if (((_attribute$node$value = attribute.node.value) === null || _attribute$node$value === void 0 ? void 0 : _attribute$node$value.type) === 'JSXExpressionContainer' && isIconAttribute) {
21
+ var iconNode = attribute.node.value;
22
+ if (iconNode && iconNode.type === 'JSXExpressionContainer' && iconNode.expression.type === 'JSXElement' && element.children) {
23
+ var icon = iconNode.expression;
24
+ attribute.node.name.name === 'iconBefore' ? element.children.unshift(icon) : element.children.push(icon);
25
+ }
26
+ }
27
+ return isIconAttribute;
28
+ }).remove();
29
+ return j.jsxElement.from({
30
+ openingElement: j.jsxOpeningElement(j.jsxIdentifier('Link'), attributes, false),
31
+ closingElement: j.jsxClosingElement(j.jsxIdentifier('Link')),
32
+ children: element.children
33
+ });
34
+ };
@@ -32,7 +32,6 @@ export var getIconElement = function getIconElement(iconAttr) {
32
32
  export var handleIconAttributes = function handleIconAttributes(element, j) {
33
33
  var iconRenamed = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
34
34
  var buttonAttributes = element.openingElement.attributes;
35
-
36
35
  // Get iconBefore and iconAfter attributes
37
36
  var buttonIconAttributes = buttonAttributes && getIconAttributes(buttonAttributes);
38
37
  buttonIconAttributes === null || buttonIconAttributes === void 0 || buttonIconAttributes.forEach(function (iconAttribute) {
@@ -107,6 +106,12 @@ export var generateNewElement = function generateNewElement(variant, element, j)
107
106
  var attributes = element.openingElement.attributes;
108
107
  var iconAttrs = attributes && getIconAttributes(attributes);
109
108
  var isIconOrLinkIcon = variant === NEW_BUTTON_VARIANTS.icon || variant === NEW_BUTTON_VARIANTS.linkIcon;
109
+ if (variant === NEW_BUTTON_VARIANTS.link) {
110
+ j(element).find(j.JSXAttribute).filter(function (path) {
111
+ var _path$node$value;
112
+ return path.node.name.name === 'appearance' && ((_path$node$value = path.node.value) === null || _path$node$value === void 0 ? void 0 : _path$node$value.type) === 'StringLiteral' && (path.node.value.value === 'subtle-link' || path.node.value.value === 'link');
113
+ }).replaceWith(j.jsxAttribute(j.jsxIdentifier('appearance'), j.stringLiteral('subtle')));
114
+ }
110
115
  if (isIconOrLinkIcon && iconAttrs !== null && iconAttrs !== void 0 && iconAttrs.length) {
111
116
  handleIconAttributes(element, j, true);
112
117
 
@@ -0,0 +1,24 @@
1
+ var moveIcon = function moveIcon(j, path, iconNode, beforeOrAfter) {
2
+ var element;
3
+ if (!iconNode) {
4
+ return;
5
+ }
6
+ if (iconNode.type === 'JSXExpressionContainer') {
7
+ // when iconBefore={(iconProps) => <AddIcon {...iconProps} />}
8
+ if (iconNode.expression.type === 'ArrowFunctionExpression' && iconNode.expression.body.type === 'JSXElement') {
9
+ // remove {...iconProps} spread attribute
10
+ element = iconNode.expression.body;
11
+ j(element).find(j.JSXSpreadAttribute).remove();
12
+ j(element).find(j.JSXAttribute).insertBefore(j.jsxAttribute(j.jsxIdentifier('label'), j.stringLiteral('')));
13
+ }
14
+
15
+ // when iconBefore={AddIcon}
16
+ if (iconNode.expression.type === 'Identifier') {
17
+ element = j.jsxElement(j.jsxOpeningElement(j.jsxIdentifier(iconNode.expression.name), [j.jsxAttribute(j.jsxIdentifier('label'), j.stringLiteral(''))], true));
18
+ }
19
+ if (element && path.node.children) {
20
+ beforeOrAfter === 'iconBefore' ? path.node.children.unshift(element) : path.node.children.push(element);
21
+ }
22
+ }
23
+ };
24
+ export default moveIcon;
@@ -0,0 +1,3 @@
1
+ import { type API, type FileInfo } from 'jscodeshift';
2
+ declare function transformer(file: FileInfo, api: API): string;
3
+ export default transformer;
@@ -1,2 +1,3 @@
1
1
  import { type API, type FileInfo } from 'jscodeshift';
2
- export default function (file: FileInfo, api: API): string;
2
+ declare function transformer(file: FileInfo, api: API): string;
3
+ export default transformer;
@@ -0,0 +1,2 @@
1
+ import type { API, Collection, JSXElement } from 'jscodeshift';
2
+ export declare const addCommentForOverlayProp: (oldButtons: Collection<JSXElement>, j: API['jscodeshift']) => void;
@@ -22,6 +22,7 @@ export declare const buttonPropsNoLongerSupportedComment = "Buttons with \"compo
22
22
  export declare const migrateFitContainerButtonToDefaultButtonComment = "Migrated to a default button with text which is from the icon label.";
23
23
  export declare const migrateFitContainerButtonToIconButtonComment = "\"shouldFitContainer\" is not available in icon buttons, please consider using a default button with text.";
24
24
  export declare const customThemeButtonComment = "CustomThemeButton will be deprecated. Please consider migrating to Pressable or Anchor Primitives with custom styles.";
25
+ export declare const overlayPropComment = "The 'overlay' prop has been deprecated. This only existed in legacy buttons for supporting loading spinners, which can now be achieved in new buttons using the `isLoading` prop. Please remove the `overlay` prop and consider using the new `isLoading` prop.";
25
26
  export declare const loadingButtonComment: ({ hasLinkAppearance, hasHref, }: {
26
27
  hasLinkAppearance: boolean;
27
28
  hasHref: boolean;