@kaizen/components 1.69.1 → 1.70.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.
Files changed (66) hide show
  1. package/codemods/migrateBrandMomentMoodToVariant/index.ts +5 -3
  2. package/codemods/migrateBrandMomentMoodToVariant/transformBrandMomentMoodToVariant.spec.ts +16 -5
  3. package/codemods/migrateCardVariantToColor/index.ts +5 -3
  4. package/codemods/migrateCardVariantToColor/transformCardVariantToColor.spec.ts +16 -5
  5. package/codemods/migrateConfirmationModalMoodsToVariant/index.ts +3 -1
  6. package/codemods/migrateConfirmationModalMoodsToVariant/transformConfirmationModalMoodsToVariant.spec.ts +27 -44
  7. package/codemods/migrateEmptyStateIllustrationTypeToVariant/index.ts +5 -3
  8. package/codemods/migrateEmptyStateIllustrationTypeToVariant/transformEmptyStateIllustrationTypeToVariant.spec.ts +16 -5
  9. package/codemods/migrateGlobalNotificationTypeToVariant/index.ts +5 -3
  10. package/codemods/migrateInformationTileMoodToVariant/index.ts +5 -3
  11. package/codemods/migrateInformationTileMoodToVariant/transformInformationTileMoodToVariant.spec.ts +16 -7
  12. package/codemods/migrateInlineNotificationTypeToVariant/index.ts +5 -3
  13. package/codemods/migrateMultiActionTileMoodToVariant/index.ts +5 -3
  14. package/codemods/migrateMultiActionTileMoodToVariant/transformMultiActionTileMoodToVariant.spec.ts +16 -7
  15. package/codemods/migrateNotificationTypeToVariant/migrateNotificationTypeToVariant.spec.ts +42 -43
  16. package/codemods/migrateProgressBarMoodToColor/index.ts +5 -3
  17. package/codemods/migrateProgressBarMoodToColor/transformProgressBarMoodToColor.spec.ts +16 -5
  18. package/codemods/migrateToastNotificationTypeToVariant/index.ts +6 -4
  19. package/codemods/migrateWellVariantToColor/index.ts +5 -3
  20. package/codemods/migrateWellVariantToColor/transformWellVariantToColor.spec.ts +26 -68
  21. package/codemods/migrateWellVariantToColor/transformWellVariantToColor.ts +10 -4
  22. package/codemods/removeInputEditModalMood/index.ts +3 -1
  23. package/codemods/removeInputEditModalMood/removeInputEditModalMood.spec.ts +23 -20
  24. package/codemods/removePopoverVariant/index.ts +1 -1
  25. package/codemods/removePopoverVariant/removePopoverVariant.spec.ts +23 -25
  26. package/codemods/upgradeIconV1/index.ts +2 -17
  27. package/codemods/upgradeIconV1/upgradeIconV1.spec.ts +18 -120
  28. package/codemods/upgradeIconV1/upgradeIconV1.ts +21 -28
  29. package/codemods/utils/__snapshots__/transformSource.spec.ts.snap +0 -10
  30. package/codemods/utils/getKaioTagName.spec.ts +167 -23
  31. package/codemods/utils/getKaioTagName.ts +71 -35
  32. package/codemods/utils/migrateStringProp.spec.ts +16 -5
  33. package/codemods/utils/migrateStringProp.ts +10 -3
  34. package/codemods/utils/removeProps.spec.ts +26 -25
  35. package/codemods/utils/removeProps.ts +10 -3
  36. package/codemods/utils/transformComponentsInDir.ts +40 -13
  37. package/codemods/utils/transformSource.spec.ts +1 -27
  38. package/codemods/utils/transformSource.ts +0 -26
  39. package/codemods/utils/updateKaioImports.ts +2 -0
  40. package/dist/cjs/LinkButton/LinkButton.cjs +59 -0
  41. package/dist/cjs/LinkButton/LinkButton.module.css.cjs +6 -0
  42. package/dist/cjs/__rc__/Button/Button.module.css.cjs +1 -1
  43. package/dist/cjs/index.cjs +2 -0
  44. package/dist/esm/LinkButton/LinkButton.mjs +53 -0
  45. package/dist/esm/LinkButton/LinkButton.module.css.mjs +4 -0
  46. package/dist/esm/__rc__/Button/Button.module.css.mjs +1 -1
  47. package/dist/esm/index.mjs +1 -0
  48. package/dist/styles.css +3259 -3229
  49. package/dist/types/LinkButton/LinkButton.d.ts +11 -0
  50. package/dist/types/LinkButton/index.d.ts +1 -0
  51. package/dist/types/__rc__/Button/Button.d.ts +6 -5
  52. package/dist/types/index.d.ts +1 -2
  53. package/package.json +1 -1
  54. package/src/LinkButton/LinkButton.module.css +4 -0
  55. package/src/LinkButton/LinkButton.tsx +71 -0
  56. package/src/LinkButton/_docs/LinkButton--api-specification.mdx +281 -0
  57. package/src/LinkButton/_docs/LinkButton--usage-guidelines.mdx +29 -0
  58. package/src/LinkButton/_docs/LinkButton.doc.stories.tsx +136 -0
  59. package/src/LinkButton/_docs/LinkButton.spec.stories.tsx +80 -0
  60. package/src/LinkButton/_docs/LinkButton.stickersheet.stories.tsx +130 -0
  61. package/src/LinkButton/index.ts +1 -0
  62. package/src/__rc__/Button/Button.module.css +44 -19
  63. package/src/__rc__/Button/Button.tsx +8 -4
  64. package/src/__rc__/Button/_docs/Button--api-specification.mdx +5 -5
  65. package/src/__rc__/Button/_docs/Button--usage-guidelines.mdx +2 -5
  66. package/src/index.ts +1 -2
@@ -1,9 +1,10 @@
1
1
  import ts from 'typescript'
2
2
  import {
3
+ getKaioTagName,
3
4
  setImportToAdd,
4
5
  setImportToRemove,
5
6
  updateKaioImports,
6
- type ImportModuleNameTagsMap,
7
+ type TagImportAttributesMap,
7
8
  type UpdateKaioImportsArgs,
8
9
  } from '../utils'
9
10
  import { getNewIconPropsFromOldIconName } from './getNewIconPropsFromOldIconName'
@@ -11,56 +12,51 @@ import { transformCaMonogramIconToBrand } from './transformCaMonogramIconToBrand
11
12
  import { transformIcon } from './transformIcon'
12
13
  import { transformSpinnerIconToLoadingSpinner } from './transformSpinnerIconToLoadingSpinner'
13
14
 
14
- const reverseStringMap = <Key extends string, Value extends string>(
15
- map: Map<Key, Value>,
16
- ): Map<Value, Key> => {
17
- const reverseMap = new Map<Value, Key>()
18
- map.forEach((value, key) => reverseMap.set(value, key))
19
- return reverseMap
20
- }
21
-
22
15
  export const upgradeIconV1 =
23
- (tagNames: ImportModuleNameTagsMap): ts.TransformerFactory<ts.SourceFile> =>
16
+ (tagsMap: TagImportAttributesMap): ts.TransformerFactory<ts.SourceFile> =>
24
17
  (context) =>
25
18
  (rootNode) => {
26
- const oldImportSource = '@kaizen/components'
27
-
28
- const kaioTagNames = tagNames.get(oldImportSource)
29
- if (!kaioTagNames) return rootNode
19
+ const importedBrandTagName = getKaioTagName(rootNode, 'Brand')
20
+ const importedLoadingSpinnerTagName = getKaioTagName(rootNode, 'LoadingSpinner')
30
21
 
31
- const componentToAliasMap = reverseStringMap(kaioTagNames)
32
22
  const importsToRemove = new Map() satisfies UpdateKaioImportsArgs['importsToRemove']
33
23
  const importsToAdd = new Map() satisfies UpdateKaioImportsArgs['importsToAdd']
34
24
 
35
25
  const visit = (node: ts.Node): ts.Node => {
36
26
  if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
37
27
  const tagName = node.tagName.getText()
38
- const kaioComponentName = kaioTagNames.get(tagName)
28
+ const tagImportAttributes = tagsMap.get(tagName)
29
+
30
+ if (!tagImportAttributes) return node
31
+
32
+ const kaioComponentName = tagImportAttributes.originalName
33
+ const oldImportSource = tagImportAttributes.importModuleName
39
34
 
40
35
  if (kaioComponentName === 'CaMonogramIcon') {
41
36
  setImportToRemove(importsToRemove, oldImportSource, kaioComponentName)
42
- const alias = componentToAliasMap.get('Brand')!
43
37
 
44
- if (!kaioTagNames.has(alias)) {
38
+ if (!importedBrandTagName) {
45
39
  setImportToAdd(importsToAdd, '@kaizen/components', {
46
40
  componentName: 'Brand',
47
- alias: alias !== 'Brand' ? alias : undefined,
41
+ alias: importedBrandTagName !== 'Brand' ? importedBrandTagName : undefined,
48
42
  })
49
43
  }
50
- return transformCaMonogramIconToBrand(node, alias)
44
+ return transformCaMonogramIconToBrand(node, importedBrandTagName)
51
45
  }
52
46
 
53
47
  if (kaioComponentName === 'SpinnerIcon') {
54
48
  setImportToRemove(importsToRemove, oldImportSource, kaioComponentName)
55
- const alias = componentToAliasMap.get('LoadingSpinner')!
56
49
 
57
- if (!kaioTagNames.has(alias)) {
50
+ if (!importedLoadingSpinnerTagName) {
58
51
  setImportToAdd(importsToAdd, '@kaizen/components', {
59
52
  componentName: 'LoadingSpinner',
60
- alias: alias !== 'LoadingSpinner' ? alias : undefined,
53
+ alias:
54
+ importedLoadingSpinnerTagName !== 'LoadingSpinner'
55
+ ? importedLoadingSpinnerTagName
56
+ : undefined,
61
57
  })
62
58
  }
63
- return transformSpinnerIconToLoadingSpinner(node, alias)
59
+ return transformSpinnerIconToLoadingSpinner(node, importedLoadingSpinnerTagName)
64
60
  }
65
61
 
66
62
  if (kaioComponentName) {
@@ -83,8 +79,5 @@ export const upgradeIconV1 =
83
79
 
84
80
  const node = ts.visitNode(rootNode, visit)
85
81
 
86
- return updateKaioImports({
87
- importsToRemove: importsToRemove.size > 0 ? importsToRemove : undefined,
88
- importsToAdd: importsToAdd.size > 0 ? importsToAdd : undefined,
89
- })(context)(node as ts.SourceFile)
82
+ return updateKaioImports({ importsToRemove, importsToAdd })(context)(node as ts.SourceFile)
90
83
  }
@@ -9,13 +9,3 @@ export const KaioComponent = (): JSX.Element => <Pancakes topping="jam"/>;
9
9
 
10
10
  "
11
11
  `;
12
-
13
- exports[`transformSourceForTagName > updates the value of Pancakes topping to jam 1`] = `
14
- "import React from 'react';
15
- // @ts-ignore
16
- import { Pancakes } from '@kaizen/components';
17
-
18
- export const KaioComponent = (): JSX.Element => <Pancakes topping="jam"/>;
19
-
20
- "
21
- `;
@@ -1,7 +1,11 @@
1
1
  import { parseJsx } from '../__tests__/utils'
2
- import { getKaioTagName, getKaioTagNamesByRegex } from './getKaioTagName'
2
+ import {
3
+ getKaioTagName,
4
+ getKaioTagNamesMapByComponentName,
5
+ getKaioTagNamesMapByPattern,
6
+ } from './getKaioTagName'
3
7
 
4
- describe('getKaioTagName', () => {
8
+ describe('getKaioTagName()', () => {
5
9
  it('returns the import name if it matches the target specifier', () => {
6
10
  const input = parseJsx('import { Well } from "@kaizen/components"')
7
11
  const tagName = getKaioTagName(input, 'Well')
@@ -21,61 +25,201 @@ describe('getKaioTagName', () => {
21
25
  })
22
26
  })
23
27
 
24
- describe('getKaioTagNamesByRegex', () => {
25
- it('returns the import names if it matches the regex target specifier', () => {
28
+ describe('getKaioTagNamesMapByComponentName()', () => {
29
+ it('returns import attributes that match the component name', () => {
30
+ const input = parseJsx('import { Button } from "@kaizen/components"')
31
+ const tagNames = getKaioTagNamesMapByComponentName(input, ['Button'])
32
+ expect(tagNames).toEqual(
33
+ new Map([
34
+ [
35
+ 'Button',
36
+ {
37
+ importModuleName: '@kaizen/components',
38
+ tagName: 'Button',
39
+ originalName: 'Button',
40
+ },
41
+ ],
42
+ ]),
43
+ )
44
+ })
45
+
46
+ it('returns import attributes that matches the component name when an alias exists', () => {
47
+ const input = parseJsx('import { Button as KzButton } from "@kaizen/components"')
48
+ const tagNames = getKaioTagNamesMapByComponentName(input, ['Button'])
49
+ expect(tagNames).toEqual(
50
+ new Map([
51
+ [
52
+ 'KzButton',
53
+ {
54
+ importModuleName: '@kaizen/components',
55
+ tagName: 'KzButton',
56
+ originalName: 'Button',
57
+ },
58
+ ],
59
+ ]),
60
+ )
61
+ })
62
+
63
+ it('returns import attributes from different KAIO imports', () => {
64
+ const input = parseJsx(`
65
+ import { Button as KzButton } from "@kaizen/components"
66
+ import { Button as FutureButton } from "@kaizen/components/future"
67
+ `)
68
+ const tagNames = getKaioTagNamesMapByComponentName(input, ['Button'])
69
+ expect(tagNames).toEqual(
70
+ new Map([
71
+ [
72
+ 'KzButton',
73
+ {
74
+ importModuleName: '@kaizen/components',
75
+ tagName: 'KzButton',
76
+ originalName: 'Button',
77
+ },
78
+ ],
79
+ [
80
+ 'FutureButton',
81
+ {
82
+ importModuleName: '@kaizen/components/future',
83
+ tagName: 'FutureButton',
84
+ originalName: 'Button',
85
+ },
86
+ ],
87
+ ]),
88
+ )
89
+ })
90
+
91
+ it('returns import attributes for multiple components', () => {
92
+ const input = parseJsx(`
93
+ import { Button, IconButton } from "@kaizen/components"
94
+ `)
95
+ const tagNames = getKaioTagNamesMapByComponentName(input, ['Button', 'IconButton'])
96
+ expect(tagNames).toEqual(
97
+ new Map([
98
+ [
99
+ 'Button',
100
+ {
101
+ importModuleName: '@kaizen/components',
102
+ tagName: 'Button',
103
+ originalName: 'Button',
104
+ },
105
+ ],
106
+ [
107
+ 'IconButton',
108
+ {
109
+ importModuleName: '@kaizen/components',
110
+ tagName: 'IconButton',
111
+ originalName: 'IconButton',
112
+ },
113
+ ],
114
+ ]),
115
+ )
116
+ })
117
+
118
+ it('returns undefined if there is no exact match component name', () => {
119
+ const input = parseJsx(`
120
+ import { IconButton } from "@kaizen/components"
121
+ `)
122
+ const tagNames = getKaioTagNamesMapByComponentName(input, ['Button'])
123
+ expect(tagNames).toBe(undefined)
124
+ })
125
+
126
+ it('returns undefined if there is no match in KAIO', () => {
127
+ const input = parseJsx(`
128
+ import { Well } from "@kaizen/components"
129
+ import { Button } from "@kaizen/button"
130
+ `)
131
+ const tagNames = getKaioTagNamesMapByComponentName(input, ['Button'])
132
+ expect(tagNames).toBe(undefined)
133
+ })
134
+ })
135
+
136
+ describe('getKaioTagNamesMapByPattern()', () => {
137
+ it('returns import attributes if it matches the regex pattern', () => {
26
138
  const input = parseJsx('import { AddIcon, ArrowDownIcon, Well } from "@kaizen/components"')
27
- const tagNames = getKaioTagNamesByRegex(input, 'Icon')
139
+ const tagNames = getKaioTagNamesMapByPattern(input, 'Icon$')
28
140
  expect(tagNames).toEqual(
29
141
  new Map([
30
142
  [
31
- '@kaizen/components',
32
- new Map([
33
- ['AddIcon', 'AddIcon'],
34
- ['ArrowDownIcon', 'ArrowDownIcon'],
35
- ]),
143
+ 'AddIcon',
144
+ {
145
+ importModuleName: '@kaizen/components',
146
+ tagName: 'AddIcon',
147
+ originalName: 'AddIcon',
148
+ },
149
+ ],
150
+ [
151
+ 'ArrowDownIcon',
152
+ {
153
+ importModuleName: '@kaizen/components',
154
+ tagName: 'ArrowDownIcon',
155
+ originalName: 'ArrowDownIcon',
156
+ },
36
157
  ],
37
158
  ]),
38
159
  )
39
160
  })
40
161
 
41
- it('returns the import alias if it matches the target specifier', () => {
162
+ it('returns import attributes that matches the regex pattern when an alias exists', () => {
42
163
  const input = parseJsx(
43
164
  'import { AddIcon as KzAddIcon, ArrowDownIcon, Well } from "@kaizen/components"',
44
165
  )
45
- const tagNames = getKaioTagNamesByRegex(input, 'Icon')
166
+ const tagNames = getKaioTagNamesMapByPattern(input, 'Icon$')
46
167
  expect(tagNames).toEqual(
47
168
  new Map([
48
169
  [
49
- '@kaizen/components',
50
- new Map([
51
- ['KzAddIcon', 'AddIcon'],
52
- ['ArrowDownIcon', 'ArrowDownIcon'],
53
- ]),
170
+ 'KzAddIcon',
171
+ {
172
+ importModuleName: '@kaizen/components',
173
+ tagName: 'KzAddIcon',
174
+ originalName: 'AddIcon',
175
+ },
176
+ ],
177
+ [
178
+ 'ArrowDownIcon',
179
+ {
180
+ importModuleName: '@kaizen/components',
181
+ tagName: 'ArrowDownIcon',
182
+ originalName: 'ArrowDownIcon',
183
+ },
54
184
  ],
55
185
  ]),
56
186
  )
57
187
  })
58
188
 
59
- it('returns matching import names from different KAIO imports', () => {
189
+ it('returns import attributes from different KAIO imports', () => {
60
190
  const input = parseJsx(`
61
191
  import { AddIcon, Well } from "@kaizen/components"
62
192
  import { Icon } from "@kaizen/components/future"
63
193
  `)
64
- const tagNames = getKaioTagNamesByRegex(input, 'Icon$')
194
+ const tagNames = getKaioTagNamesMapByPattern(input, 'Icon$')
65
195
  expect(tagNames).toEqual(
66
196
  new Map([
67
- ['@kaizen/components', new Map([['AddIcon', 'AddIcon']])],
68
- ['@kaizen/components/future', new Map([['Icon', 'Icon']])],
197
+ [
198
+ 'AddIcon',
199
+ {
200
+ importModuleName: '@kaizen/components',
201
+ tagName: 'AddIcon',
202
+ originalName: 'AddIcon',
203
+ },
204
+ ],
205
+ [
206
+ 'Icon',
207
+ {
208
+ importModuleName: '@kaizen/components/future',
209
+ tagName: 'Icon',
210
+ originalName: 'Icon',
211
+ },
212
+ ],
69
213
  ]),
70
214
  )
71
215
  })
72
216
 
73
- it('returns undefined if there is no match to the target specifier', () => {
217
+ it('returns undefined if there is no match to the regex pattern in KAIO', () => {
74
218
  const input = parseJsx(`
75
219
  import { Well } from "@kaizen/components"
76
220
  import { AddIcon } from "@kaizen/icons"
77
221
  `)
78
- const tagNames = getKaioTagNamesByRegex(input, 'Icon')
222
+ const tagNames = getKaioTagNamesMapByPattern(input, 'Icon')
79
223
  expect(tagNames).toBe(undefined)
80
224
  })
81
225
  })
@@ -1,13 +1,11 @@
1
1
  import ts from 'typescript'
2
2
 
3
- const getKaioNamedImports = (
4
- visitedNode: ts.Node,
5
- ):
6
- | {
7
- importModuleName: string
8
- namedImports: ts.NodeArray<ts.ImportSpecifier>
9
- }
10
- | undefined => {
3
+ type ImportModuleNamedImports = {
4
+ importModuleName: string
5
+ namedImports: ts.NodeArray<ts.ImportSpecifier>
6
+ }
7
+
8
+ const getKaioNamedImports = (visitedNode: ts.Node): ImportModuleNamedImports | undefined => {
11
9
  if (ts.isImportDeclaration(visitedNode)) {
12
10
  const moduleSpecifier = (visitedNode.moduleSpecifier as ts.StringLiteral).text
13
11
  if (moduleSpecifier.includes('@kaizen/components')) {
@@ -72,27 +70,31 @@ export const getKaioTagName = (
72
70
  return visitNode(node)
73
71
  }
74
72
 
75
- // Key is the tag name (component name or alias)
76
- // Value is the original component name
77
- type TagNamesMap = Map<string, string>
78
- // Key is the import module name (eg. `@kaizen/components/future`)
79
- export type ImportModuleNameTagsMap = Map<string, TagNamesMap>
73
+ type TagImportAttributes = {
74
+ // Import module name (eg. `@kaizen/components/future`)
75
+ importModuleName: string
76
+ // Component name or alias
77
+ tagName: string
78
+ // Original component name
79
+ originalName: string
80
+ }
81
+ /** Key is the tag name (component name or alias) */
82
+ export type TagImportAttributesMap = Map<string, TagImportAttributes>
80
83
 
81
84
  /**
82
- * Recurses through AST to find all the import names or aliases in KAIO that match the provided regex.
83
- *
84
- * @returns Map<string, Map<string, string>> | undefined
85
- * - `Map<string, Map<string, string>>` = Map<importModuleName, Map<tagName, originalName>>
86
- * - `importModuleName` = the module name of the KAIO import (eg. `@kaizen/components/future`)
87
- * - `tagName` = the component name or alias (eg. `KaizenWell`)
88
- * - `originalName` = the original component name (eg. `Well`)
89
- * - `undefined` no imports that match the target
85
+ * Recurses through AST to find all the import names or aliases in KAIO that exactly match the provided strings.
90
86
  */
91
- export const getKaioTagNamesByRegex = (
87
+ const getKaioTagNamesMap = (
92
88
  node: ts.Node,
93
- importSpecifierPattern: RegExp | string,
94
- ): ImportModuleNameTagsMap | undefined => {
95
- const tagsByImportModuleName = new Map() as ImportModuleNameTagsMap
89
+ onFilterAndUpdateTagsMap: (
90
+ kaioNamedImports: ImportModuleNamedImports,
91
+ checkAndUpdateTagsMap: (
92
+ namedImport: ts.ImportSpecifier,
93
+ checkToAddToMap: (originalName: string) => boolean,
94
+ ) => void,
95
+ ) => void,
96
+ ): TagImportAttributesMap | undefined => {
97
+ const tagsMap = new Map() as TagImportAttributesMap
96
98
 
97
99
  const visitNode = (visitedNode: ts.Node): ts.Node | undefined => {
98
100
  const kaioNamedImports = getKaioNamedImports(visitedNode)
@@ -101,23 +103,57 @@ export const getKaioTagNamesByRegex = (
101
103
  return ts.forEachChild(visitedNode, visitNode)
102
104
  }
103
105
 
104
- const tags = new Map() as TagNamesMap
105
- kaioNamedImports.namedImports.forEach((importSpecifier) => {
106
- const { tagName, originalName } = getNamesFromSpecifier(importSpecifier)
106
+ onFilterAndUpdateTagsMap(kaioNamedImports, (namedImport, checkToAddToMap) => {
107
+ const { originalName, tagName } = getNamesFromSpecifier(namedImport)
107
108
 
108
- if (new RegExp(importSpecifierPattern).test(originalName)) {
109
- tags.set(tagName, originalName)
109
+ if (checkToAddToMap(originalName)) {
110
+ tagsMap.set(tagName, {
111
+ importModuleName: kaioNamedImports.importModuleName,
112
+ tagName,
113
+ originalName,
114
+ })
115
+ return true
110
116
  }
111
- })
112
117
 
113
- if (tags.size > 0) {
114
- tagsByImportModuleName.set(kaioNamedImports.importModuleName, new Map(tags))
115
- }
118
+ return false
119
+ })
116
120
 
117
121
  return ts.forEachChild(visitedNode, visitNode)
118
122
  }
119
123
 
120
124
  visitNode(node)
121
125
 
122
- return tagsByImportModuleName.size === 0 ? undefined : tagsByImportModuleName
126
+ return tagsMap.size === 0 ? undefined : tagsMap
127
+ }
128
+
129
+ /**
130
+ * Recurses through AST to find all the import names or aliases in KAIO that exactly match the provided strings.
131
+ */
132
+ export const getKaioTagNamesMapByComponentName = (
133
+ node: ts.Node,
134
+ importSpecifiers: string[],
135
+ ): TagImportAttributesMap | undefined => {
136
+ return getKaioTagNamesMap(node, (kaioNamedImports, checkAndUpdateTagsMap) => {
137
+ importSpecifiers.forEach((importSpecifier) => {
138
+ kaioNamedImports.namedImports.find((namedImport) => {
139
+ checkAndUpdateTagsMap(namedImport, (originalName) => originalName === importSpecifier)
140
+ })
141
+ })
142
+ })
143
+ }
144
+
145
+ /**
146
+ * Recurses through AST to find all the import names or aliases in KAIO that match the provided regex pattern.
147
+ */
148
+ export const getKaioTagNamesMapByPattern = (
149
+ node: ts.Node,
150
+ importSpecifierPattern: RegExp | string,
151
+ ): TagImportAttributesMap | undefined => {
152
+ return getKaioTagNamesMap(node, (kaioNamedImports, checkAndUpdateTagsMap) => {
153
+ kaioNamedImports.namedImports.forEach((namedImport) => {
154
+ checkAndUpdateTagsMap(namedImport, (originalName) =>
155
+ new RegExp(importSpecifierPattern).test(originalName),
156
+ )
157
+ })
158
+ })
123
159
  }
@@ -1,5 +1,5 @@
1
1
  import { parseJsx } from '../__tests__/utils'
2
- import { printAst, transformSourceForTagName, type TransformSourceForTagNameArgs } from '../utils'
2
+ import { printAst, transformSource, type TransformSourceArgs } from '../utils'
3
3
  import { migrateStringProp } from './migrateStringProp'
4
4
 
5
5
  const transformTopping = (oldValue: string): string => {
@@ -11,12 +11,23 @@ const transformTopping = (oldValue: string): string => {
11
11
  }
12
12
  }
13
13
 
14
- const testMigrateStringProp = (sourceFile: TransformSourceForTagNameArgs['sourceFile']): string =>
15
- transformSourceForTagName({
14
+ const testMigrateStringProp = (sourceFile: TransformSourceArgs['sourceFile']): string => {
15
+ const tagsMap = new Map([
16
+ [
17
+ 'Pancakes',
18
+ {
19
+ importModuleName: '@kaizen/components',
20
+ tagName: 'Pancakes',
21
+ originalName: 'Pancakes',
22
+ },
23
+ ],
24
+ ])
25
+
26
+ return transformSource({
16
27
  sourceFile,
17
- astTransformer: migrateStringProp('toppingOld', 'toppingNew', transformTopping),
18
- tagName: 'Pancakes',
28
+ transformers: [migrateStringProp('toppingOld', 'toppingNew', transformTopping)(tagsMap)],
19
29
  })
30
+ }
20
31
 
21
32
  describe('migrateStringProp()', () => {
22
33
  describe('replaces old prop name and value with new prop name and value', () => {
@@ -1,4 +1,5 @@
1
1
  import ts from 'typescript'
2
+ import { type TagImportAttributesMap } from './getKaioTagName'
2
3
  import { getPropValueText } from './getPropValueText'
3
4
  import { updateJsxElementWithNewProps } from './updateJsxElementWithNewProps'
4
5
 
@@ -8,11 +9,17 @@ export const migrateStringProp =
8
9
  newPropName: string,
9
10
  valueTransformer: (value: OldValue) => NewValue,
10
11
  ) =>
11
- (context: ts.TransformationContext, tagName: string) =>
12
- (rootNode: ts.SourceFile): ts.SourceFile => {
12
+ (tagsMap: TagImportAttributesMap): ts.TransformerFactory<ts.SourceFile> =>
13
+ (context) =>
14
+ (rootNode) => {
13
15
  const visit = (node: ts.Node): ts.Node => {
14
16
  if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
15
- if (node.tagName.getText() === tagName) {
17
+ const tagName = node.tagName.getText()
18
+ const tagImportAttributes = tagsMap.get(tagName)
19
+
20
+ if (!tagImportAttributes) return node
21
+
22
+ if (tagName === tagImportAttributes.tagName) {
16
23
  const newAttributes = node.attributes.properties.map((attr) => {
17
24
  if (ts.isJsxAttribute(attr) && attr.name.getText() === oldPropName) {
18
25
  const oldValue = attr.initializer && getPropValueText(attr.initializer)
@@ -1,7 +1,28 @@
1
1
  import { parseJsx } from '../__tests__/utils'
2
- import { printAst, transformSourceForTagName } from '../utils'
2
+ import { printAst, transformSource, type TransformSourceArgs } from '../utils'
3
3
  import { removeProps } from './removeProps'
4
4
 
5
+ const testRemoveProps = (
6
+ sourceFile: TransformSourceArgs['sourceFile'],
7
+ propsToRemove: string[] = ['topping'],
8
+ ): string => {
9
+ const tagsMap = new Map([
10
+ [
11
+ 'Pancakes',
12
+ {
13
+ importModuleName: '@kaizen/components',
14
+ tagName: 'Pancakes',
15
+ originalName: 'Pancakes',
16
+ },
17
+ ],
18
+ ])
19
+
20
+ return transformSource({
21
+ sourceFile,
22
+ transformers: [removeProps(propsToRemove)(tagsMap)],
23
+ })
24
+ }
25
+
5
26
  describe('removeProps()', () => {
6
27
  it('removes single specified prop', () => {
7
28
  const inputAst = parseJsx(`
@@ -10,12 +31,7 @@ describe('removeProps()', () => {
10
31
  const outputAst = parseJsx(`
11
32
  export const TestComponent = () => <Pancakes />
12
33
  `)
13
- const transformed = transformSourceForTagName({
14
- sourceFile: inputAst,
15
- astTransformer: removeProps(['topping']),
16
- tagName: 'Pancakes',
17
- })
18
- expect(transformed).toEqual(printAst(outputAst))
34
+ expect(testRemoveProps(inputAst)).toEqual(printAst(outputAst))
19
35
  })
20
36
 
21
37
  it('removes multiple specified props', () => {
@@ -25,12 +41,7 @@ describe('removeProps()', () => {
25
41
  const outputAst = parseJsx(`
26
42
  export const TestComponent = () => <Pancakes />
27
43
  `)
28
- const transformed = transformSourceForTagName({
29
- sourceFile: inputAst,
30
- astTransformer: removeProps(['topping', 'fruit']),
31
- tagName: 'Pancakes',
32
- })
33
- expect(transformed).toEqual(printAst(outputAst))
44
+ expect(testRemoveProps(inputAst, ['topping', 'fruit'])).toEqual(printAst(outputAst))
34
45
  })
35
46
 
36
47
  it('handles multiple attributes and removes only specified props', () => {
@@ -40,12 +51,7 @@ describe('removeProps()', () => {
40
51
  const outputAst = parseJsx(`
41
52
  export const TestComponent = () => <Pancakes id="123"/>
42
53
  `)
43
- const transformed = transformSourceForTagName({
44
- sourceFile: inputAst,
45
- astTransformer: removeProps(['topping']),
46
- tagName: 'Pancakes',
47
- })
48
- expect(transformed).toBe(printAst(outputAst))
54
+ expect(testRemoveProps(inputAst)).toEqual(printAst(outputAst))
49
55
  })
50
56
 
51
57
  it('transforms multiple Pancakess', () => {
@@ -55,11 +61,6 @@ describe('removeProps()', () => {
55
61
  const outputAst = parseJsx(`
56
62
  export const TestComponent = () => <div><Pancakes /><Pancakes /></div>
57
63
  `)
58
- const transformed = transformSourceForTagName({
59
- sourceFile: inputAst,
60
- astTransformer: removeProps(['topping']),
61
- tagName: 'Pancakes',
62
- })
63
- expect(transformed).toBe(printAst(outputAst))
64
+ expect(testRemoveProps(inputAst)).toEqual(printAst(outputAst))
64
65
  })
65
66
  })
@@ -1,13 +1,20 @@
1
1
  import ts from 'typescript'
2
+ import { type TagImportAttributesMap } from './getKaioTagName'
2
3
  import { updateJsxElementWithNewProps } from './updateJsxElementWithNewProps'
3
4
 
4
5
  export const removeProps =
5
6
  (propsToRemove: string[]) =>
6
- (context: ts.TransformationContext, tagName: string) =>
7
- (rootNode: ts.SourceFile): ts.SourceFile => {
7
+ (tagsMap: TagImportAttributesMap): ts.TransformerFactory<ts.SourceFile> =>
8
+ (context) =>
9
+ (rootNode) => {
8
10
  function visit(node: ts.Node): ts.Node {
9
11
  if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
10
- if (node.tagName.getText() === tagName) {
12
+ const tagName = node.tagName.getText()
13
+ const tagImportAttributes = tagsMap.get(tagName)
14
+
15
+ if (!tagImportAttributes) return node
16
+
17
+ if (tagName === tagImportAttributes.tagName) {
11
18
  const newAttributes = node.attributes.properties.reduce<ts.JsxAttributeLike[]>(
12
19
  (acc, attr) => {
13
20
  if (ts.isJsxAttribute(attr) && propsToRemove.includes(attr.name.getText())) {