Skip to content

Commit

Permalink
Merge e0adc10 into 0090887
Browse files Browse the repository at this point in the history
  • Loading branch information
mannycarrera4 authored Apr 4, 2022
2 parents 0090887 + e0adc10 commit dfb1069
Show file tree
Hide file tree
Showing 106 changed files with 2,195 additions and 1,669 deletions.
1 change: 0 additions & 1 deletion .storybook/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ const routes = {
'/tokens/type/': 'tokens-tokens-react--type',
'/components/buttons/button/': 'components-buttons-button-react--primary',
'/components/buttons/action-bar/': 'components-buttons-action-bar-react--basic',
'/components/buttons/icon-button/': 'components-buttons-button-react-icon-button--circle',
'/components/containers/card/': 'components-containers-card-react--basic',
'/components/containers/side-panel/': 'preview-side-panel-react--basic',
'/components/containers/table/': 'components-containers-table-react--basic',
Expand Down
6 changes: 3 additions & 3 deletions cypress/integration/ColorPicker.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,10 @@ describe('ColorPicker', () => {
cy.viewport(800, 1000);
});

describe('Icon Button ColorPicker Popup', () => {
context('when the IconButton is clicked', () => {
describe('Icon button ColorPicker Popup', () => {
context('when the SecondaryButton is clicked', () => {
beforeEach(() => {
h.stories.load(colorPickerStory, 'Icon Button Popup');
h.stories.load(colorPickerStory, 'Icon button Popup');
getOpenButton().click();
});

Expand Down
157 changes: 157 additions & 0 deletions modules/codemod/lib/v7/recategorizeIconButtons.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import {
API,
FileInfo,
Options,
StringLiteral,
JSXIdentifier,
JSXAttribute,
ASTPath,
JSXElement,
} from 'jscodeshift';
import {getImportRenameMap} from './utils/getImportRenameMap';

const updateJSXTag = (nodePath: ASTPath<JSXElement>, newTag: string) => {
const {name: componentName} = nodePath.value.openingElement.name as JSXIdentifier;
if (componentName === 'IconButton') {
(nodePath.value.openingElement.name as JSXIdentifier).name = newTag;
if (nodePath.value.closingElement) {
(nodePath.value.closingElement.name as JSXIdentifier).name = newTag;
}
}
};

export default function transformer(file: FileInfo, api: API, options: Options) {
const j = api.jscodeshift;
const root = j(file.source);
const requiredImportSpecifiers: string[] = [];

/**
* 1. Find button imports
*/
const {containsCanvasImports, importMap, styledMap} = getImportRenameMap(
j,
root,
'@workday/canvas-kit-react/button'
);
if (!containsCanvasImports) {
return file.source;
}

let buttonType = 'TertiaryButton'; //default button if no variant is specified

// Button Mapping
// circle -> tertiary
// circle-filled -> secondary
// inverse -> tertiary inverse
// inverse-filled -> secondary inverse
// plain/square -> not supported
// square-filled -> not supported

/**
* 2. Find `IconButton`
* - If it has no variant, it means it's "circle" which is the default
* - Swap to `TertiaryButton`
* - Add `TertiaryButton` import if it doesn't exist.
* - If not
* - check the variant of the IconButton
* - Swap it out for the appropriate mapping
*/
root
.find(
j.JSXElement,
(value: JSXElement) =>
value.openingElement.name.type === 'JSXIdentifier' &&
(value.openingElement.name.name === importMap.IconButton ||
value.openingElement.name.name === styledMap.IconButton)
)
.forEach(nodePath => {
const attrs = nodePath.value.openingElement.attributes;

const variantProp = attrs?.find(
attr => attr.type === 'JSXAttribute' && attr.name.name === 'variant'
);

// Default IconButton variant is `circle`
if (variantProp) {
const variantPropValue = ((variantProp as JSXAttribute).value as StringLiteral)?.value;
buttonType = /filled/gi.test(variantPropValue) ? 'SecondaryButton' : 'TertiaryButton';

if (!variantPropValue.includes('inverse')) {
nodePath.value.openingElement.attributes?.splice(attrs?.indexOf(variantProp)!, 1);
}
}

updateJSXTag(nodePath, buttonType);
requiredImportSpecifiers.push(buttonType);
});

// Find all instances of IconButton within a style function
// const StyledIconButton = styled(IconButton) gets renamed to
// const StyledIconButton = styled(CorrectButtonMapping)
root.find(j.VariableDeclarator).forEach(nodePath => {
if (
nodePath.value.init?.type === 'CallExpression' &&
nodePath.value.init.callee.type === 'CallExpression' &&
nodePath.value.init.callee.arguments[0].type === 'Identifier'
) {
nodePath.value.init.callee.arguments[0].name = buttonType;
requiredImportSpecifiers.push(buttonType);
}
});

/**
* Remove old imports: `IconButton`
* Add new required imports
*/
const buttonImports = root.find(j.ImportDeclaration, {
source: {value: (value: string) => value.includes('@workday/canvas-kit-react')},
});

if (!buttonImports.length) {
// Add new specifiers to a new import
const allImports = root.find(j.ImportDeclaration);

const lastImport = allImports.at(allImports.length);
if (lastImport) {
lastImport.insertAfter(
j.importDeclaration(
requiredImportSpecifiers.map(specifier => j.importSpecifier(j.identifier(specifier))),
j.stringLiteral('@workday/canvas-kit-react/button')
)
);
}
} else {
buttonImports.forEach(({node}) => {
const specifiersToRemove = ['IconButton'];

// Remove old specifiers
if (
typeof node.source.value === 'string' &&
node.source.value.includes('@workday/canvas-kit-react')
) {
node.specifiers?.forEach(specifier => {
if (
specifier.type === 'ImportSpecifier' &&
specifiersToRemove.includes(specifier.imported.name)
) {
// delete specifier
node.specifiers?.splice(node.specifiers?.indexOf(specifier)!, 1);
}
});
}

// Add new specifiers to existing import
requiredImportSpecifiers.forEach(specifier => {
if (
!node.specifiers?.find(
existing => existing.type === 'ImportSpecifier' && existing.imported.name === specifier
)
) {
node.specifiers?.push(j.importSpecifier(j.identifier(specifier)));
}
});
});
}

return root.toSource();
}
52 changes: 52 additions & 0 deletions modules/codemod/lib/v7/renameIconPosition.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {API, FileInfo, Options, JSXElement, JSXAttribute, JSXSpreadAttribute} from 'jscodeshift';

import {getImportRenameMap} from './utils/getImportRenameMap';

export default function transformer(file: FileInfo, api: API, options: Options) {
const j = api.jscodeshift;

const root = j(file.source);

const {containsCanvasImports, importMap, styledMap} = getImportRenameMap(
j,
root,
'@workday/canvas-kit-react/button'
);

if (!containsCanvasImports) {
return file.source;
}

root
.find(
j.JSXElement,
(value: JSXElement) =>
value.openingElement.name.type === 'JSXIdentifier' &&
(value.openingElement.name.name ===
(importMap.PrimaryButton || importMap.SecondaryButton) ||
value.openingElement.name.name === (styledMap.PrimaryButton || styledMap.SecondaryButton))
)
.forEach(nodePath => {
const findAttribute = (name: string) => (item: JSXAttribute | JSXSpreadAttribute) =>
item.type === 'JSXAttribute' &&
item.name.type === 'JSXIdentifier' &&
item.name.name === name;

const attributes = nodePath.value.openingElement.attributes;
if (attributes) {
const iconPosition = attributes.find(findAttribute('iconPosition')) as
| JSXAttribute
| undefined;

if (iconPosition?.value?.type === 'StringLiteral') {
if (iconPosition.value.value === 'left') {
iconPosition.value.value = 'start';
} else {
iconPosition.value.value = 'end';
}
}
}
});

return root.toSource();
}
82 changes: 82 additions & 0 deletions modules/codemod/lib/v7/renameIconRef.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import {API, FileInfo, Options, JSXIdentifier} from 'jscodeshift';
import {getImportRenameMap} from './utils/getImportRenameMap';

const inputsMap: {
[packageName: string]: string[];
} = {
'@workday/canvas-kit-react/icon': [
'AccentIcon',
'AppletIcon',
'SystemIcon',
'SystemIconCircle',
'Graphic',
'Svg',
],
};

export default function transformer(file: FileInfo, api: API, options: Options) {
const j = api.jscodeshift;

const root = j(file.source);

// defaultImports should be an array of local names that were imported using
// a default import from any of the modules listed in inputsMap. For example,
// given...
//
// ```
// import Checkbox from '@workday/canvas-kit-react/checkbox';
// import CanvasTextArea from '@workday/canvas-kit-react/text-area';
// import {TextInput} from '@workday/canvas-kit-react/text-input';
// import StatusIndicator from '@workday/canvas-kit-react/status-indicator';
// ```
//
// ... defaultImports should be set to `['Checkbox', 'CanvasTextArea']`
const defaultImports: string[] = [];
root.find(j.ImportDefaultSpecifier).forEach(nodePath => {
const packageName = nodePath.parent.node.source.value;
const localName = nodePath.value.local?.name;
if (packageName in inputsMap && localName) {
defaultImports.push(localName);
}
});

let runningSource = file.source;
for (const inputPackageName of Object.keys(inputsMap)) {
const currentRoot = j(runningSource);

const {containsCanvasImports, importMap, styledMap} = getImportRenameMap(
j,
currentRoot,
inputPackageName
);

if (containsCanvasImports) {
const inputNames = inputsMap[inputPackageName];
currentRoot
.find(j.JSXIdentifier, (value: JSXIdentifier) => value.name === 'iconRef')
.replaceWith(nodePath => {
const elementName = nodePath.parent?.parent?.value?.name?.name;
// Rewrite inputRef to ref if any of the following are true:
// (a) elementName was the name used in a default import of the current
// input being processed (e.g., `import TextInput ...`)
// (b) elementName was the name used in a named import of the current
// input being processed (e.g., `import {TextInput} ...` or
// `import {TextInput as CanvasTextInput} ...`)
// (c) elementName was created by calling `styled` on the current input
// being processed (e.g., `const StyledTextInput = styled(TextInput)`)
if (
defaultImports.includes(elementName) ||
inputNames.map(n => importMap[n]).includes(elementName) ||
inputNames.map(n => styledMap[n]).includes(elementName)
) {
return j.jsxIdentifier('ref');
}
return nodePath.value;
});

runningSource = currentRoot.toSource();
}
}

return runningSource;
}
Loading

0 comments on commit dfb1069

Please sign in to comment.