@kaizen/components 1.72.0 → 1.73.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.
- package/bin/codemod.sh +2 -0
- package/codemods/README.md +46 -0
- package/codemods/upgradeV1Buttons/index.ts +19 -0
- package/codemods/upgradeV1Buttons/transformV1ButtonAttributes.spec.ts +202 -0
- package/codemods/upgradeV1Buttons/transformV1ButtonAttributes.ts +146 -0
- package/codemods/upgradeV1Buttons/upgradeV1Buttons.spec.ts +658 -0
- package/codemods/upgradeV1Buttons/upgradeV1Buttons.ts +93 -0
- package/codemods/utils/createJsxElementWithChildren.spec.ts +119 -0
- package/codemods/utils/createJsxElementWithChildren.ts +55 -0
- package/codemods/utils/createProp.spec.ts +75 -19
- package/codemods/utils/createProp.ts +8 -1
- package/codemods/utils/getKaioTagName.ts +13 -5
- package/codemods/utils/index.ts +1 -0
- package/dist/cjs/Link/Link.cjs +45 -0
- package/dist/cjs/Link/Link.module.css.cjs +20 -0
- package/dist/cjs/Link/subcomponents/LinkContent.cjs +34 -0
- package/dist/cjs/index.cjs +2 -0
- package/dist/cjs/utilitiesV3.cjs +2 -0
- package/dist/esm/Link/Link.mjs +40 -0
- package/dist/esm/Link/Link.module.css.mjs +18 -0
- package/dist/esm/Link/subcomponents/LinkContent.mjs +26 -0
- package/dist/esm/index.mjs +1 -0
- package/dist/esm/utilitiesV3.mjs +1 -0
- package/dist/styles.css +120 -0
- package/dist/types/Link/Link.d.ts +39 -0
- package/dist/types/Link/index.d.ts +1 -0
- package/dist/types/Link/subcomponents/LinkContent.d.ts +8 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +3 -3
- package/src/Link/Link.module.css +119 -0
- package/src/Link/Link.tsx +90 -0
- package/src/Link/_docs/Link--api-specification.mdx +133 -0
- package/src/Link/_docs/Link--api-usage-guidelines.mdx +107 -0
- package/src/Link/_docs/Link.doc.stories.tsx +238 -0
- package/src/Link/_docs/Link.stickersheet.stories.tsx +191 -0
- package/src/Link/index.ts +1 -0
- package/src/Link/subcomponents/LinkContent.tsx +31 -0
- package/src/LinkButton/_docs/LinkButton--api-specification.mdx +1 -57
- package/src/__next__/Button/_docs/Button--migration-guide.mdx +81 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import ts from 'typescript'
|
|
2
|
+
import {
|
|
3
|
+
createJsxElementWithChildren,
|
|
4
|
+
getKaioTagName,
|
|
5
|
+
setImportToAdd,
|
|
6
|
+
setImportToRemove,
|
|
7
|
+
updateKaioImports,
|
|
8
|
+
type TagImportAttributesMap,
|
|
9
|
+
type UpdateKaioImportsArgs,
|
|
10
|
+
} from '../utils'
|
|
11
|
+
import { transformV1ButtonAttributes } from './transformV1ButtonAttributes'
|
|
12
|
+
|
|
13
|
+
const V1_BUTTONS = ['Button', 'IconButton']
|
|
14
|
+
const V1_BUTTONS_IMPORT_SOURCE = [
|
|
15
|
+
'@kaizen/components',
|
|
16
|
+
'@kaizen/components/v1/actions',
|
|
17
|
+
'@kaizen/components/v2/actions',
|
|
18
|
+
]
|
|
19
|
+
const BUTTON_IMPORT_DESTINATION = '@kaizen/components/next'
|
|
20
|
+
const LINKBUTTON_IMPORT_DESTINATION = '@kaizen/components'
|
|
21
|
+
|
|
22
|
+
export const upgradeV1Buttons =
|
|
23
|
+
(tagsMap: TagImportAttributesMap): ts.TransformerFactory<ts.SourceFile> =>
|
|
24
|
+
(context) =>
|
|
25
|
+
(rootNode) => {
|
|
26
|
+
const importsToRemove: UpdateKaioImportsArgs['importsToRemove'] = new Map()
|
|
27
|
+
const importsToAdd: UpdateKaioImportsArgs['importsToAdd'] = new Map()
|
|
28
|
+
|
|
29
|
+
const importedTargetButtonTagName = getKaioTagName(
|
|
30
|
+
rootNode,
|
|
31
|
+
'Button',
|
|
32
|
+
BUTTON_IMPORT_DESTINATION,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
const importedTargetLinkButtonTagName = getKaioTagName(
|
|
36
|
+
rootNode,
|
|
37
|
+
'LinkButton',
|
|
38
|
+
LINKBUTTON_IMPORT_DESTINATION,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
const visit = (node: ts.Node): ts.Node => {
|
|
42
|
+
if (ts.isJsxSelfClosingElement(node)) {
|
|
43
|
+
const tagName = node.tagName.getText()
|
|
44
|
+
const tagImportAttributes = tagsMap.get(tagName)
|
|
45
|
+
|
|
46
|
+
if (!tagImportAttributes) return node
|
|
47
|
+
|
|
48
|
+
if (!V1_BUTTONS.includes(tagImportAttributes.originalName)) return node
|
|
49
|
+
if (!V1_BUTTONS_IMPORT_SOURCE.includes(tagImportAttributes.importModuleName)) return node
|
|
50
|
+
|
|
51
|
+
const { targetComponentName, newAttributes, childrenValue } = transformV1ButtonAttributes(
|
|
52
|
+
node,
|
|
53
|
+
tagImportAttributes.originalName,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
const targetTagName =
|
|
57
|
+
targetComponentName === 'Button'
|
|
58
|
+
? (importedTargetButtonTagName ?? 'Button')
|
|
59
|
+
: (importedTargetLinkButtonTagName ?? 'LinkButton')
|
|
60
|
+
|
|
61
|
+
setImportToRemove(
|
|
62
|
+
importsToRemove,
|
|
63
|
+
tagImportAttributes.importModuleName,
|
|
64
|
+
tagImportAttributes.originalName,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
if (targetComponentName === 'Button' && !importedTargetButtonTagName) {
|
|
68
|
+
setImportToAdd(importsToAdd, BUTTON_IMPORT_DESTINATION, {
|
|
69
|
+
componentName: 'Button',
|
|
70
|
+
alias:
|
|
71
|
+
importedTargetButtonTagName !== 'Button' ? importedTargetButtonTagName : undefined,
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (targetComponentName === 'LinkButton' && !importedTargetLinkButtonTagName) {
|
|
76
|
+
setImportToAdd(importsToAdd, LINKBUTTON_IMPORT_DESTINATION, {
|
|
77
|
+
componentName: 'LinkButton',
|
|
78
|
+
alias:
|
|
79
|
+
importedTargetLinkButtonTagName !== 'LinkButton'
|
|
80
|
+
? importedTargetLinkButtonTagName
|
|
81
|
+
: undefined,
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return createJsxElementWithChildren(targetTagName, newAttributes, childrenValue)
|
|
86
|
+
}
|
|
87
|
+
return ts.visitEachChild(node, visit, context)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const node = ts.visitNode(rootNode, visit)
|
|
91
|
+
|
|
92
|
+
return updateKaioImports({ importsToRemove, importsToAdd })(context)(node as ts.SourceFile)
|
|
93
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import ts from 'typescript'
|
|
2
|
+
import { parseJsx } from '../__tests__/utils'
|
|
3
|
+
import { createJsxElementWithChildren } from './createJsxElementWithChildren'
|
|
4
|
+
import { printAst } from './printAst'
|
|
5
|
+
import { transformSource, type TransformSourceArgs } from './transformSource'
|
|
6
|
+
|
|
7
|
+
export const mockedTransformer: ts.TransformerFactory<ts.SourceFile> = (context) => (rootNode) => {
|
|
8
|
+
const visit = (node: ts.Node): ts.Node => {
|
|
9
|
+
let childrenValue: ts.JsxAttributeValue | undefined
|
|
10
|
+
|
|
11
|
+
if (ts.isJsxSelfClosingElement(node)) {
|
|
12
|
+
const tagName = node.tagName.getText()
|
|
13
|
+
const attributes = node.attributes.properties.reduce<ts.JsxAttributeLike[]>((acc, attr) => {
|
|
14
|
+
if (ts.isJsxAttribute(attr) && attr.name.getText() === 'toChildren') {
|
|
15
|
+
childrenValue = attr.initializer
|
|
16
|
+
return acc
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
acc.push(attr)
|
|
20
|
+
return acc
|
|
21
|
+
}, [])
|
|
22
|
+
|
|
23
|
+
return createJsxElementWithChildren(tagName, attributes, childrenValue)
|
|
24
|
+
}
|
|
25
|
+
return ts.visitEachChild(node, visit, context)
|
|
26
|
+
}
|
|
27
|
+
return ts.visitNode(rootNode, visit) as ts.SourceFile
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const testCreateJsxElementWithChildren = (sourceFile: TransformSourceArgs['sourceFile']): string =>
|
|
31
|
+
transformSource({ sourceFile, transformers: [mockedTransformer] })
|
|
32
|
+
|
|
33
|
+
describe('createJsxElementWithChildren()', () => {
|
|
34
|
+
it('transforms a string value', () => {
|
|
35
|
+
const inputAst = parseJsx('<Button toChildren="Hello" variant="primary" />')
|
|
36
|
+
const outputAst = parseJsx('<Button variant="primary">Hello</Button>')
|
|
37
|
+
expect(testCreateJsxElementWithChildren(inputAst)).toEqual(printAst(outputAst))
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('transforms a string in brackets', () => {
|
|
41
|
+
const inputAst = parseJsx(`
|
|
42
|
+
<>
|
|
43
|
+
<Button toChildren={"Double quotes"} variant="primary" />
|
|
44
|
+
<Button toChildren={'Single quotes'} variant="primary" />
|
|
45
|
+
</>
|
|
46
|
+
`)
|
|
47
|
+
const outputAst = parseJsx(`
|
|
48
|
+
<>
|
|
49
|
+
<Button variant="primary">Double quotes</Button>
|
|
50
|
+
<Button variant="primary">Single quotes</Button>
|
|
51
|
+
</>
|
|
52
|
+
`)
|
|
53
|
+
// const outputAst = parseJsx('<Button variant="primary">Hello</Button>')
|
|
54
|
+
expect(testCreateJsxElementWithChildren(inputAst)).toEqual(printAst(outputAst))
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('transforms a string with comments in brackets', () => {
|
|
58
|
+
const inputAst = parseJsx(`<Button
|
|
59
|
+
toChildren={
|
|
60
|
+
"Hello" // comment
|
|
61
|
+
}
|
|
62
|
+
variant="primary" />
|
|
63
|
+
`)
|
|
64
|
+
const outputAst = parseJsx(`<Button variant="primary">{
|
|
65
|
+
"Hello" // comment
|
|
66
|
+
}</Button>`)
|
|
67
|
+
expect(testCreateJsxElementWithChildren(inputAst)).toEqual(printAst(outputAst))
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
it('transforms a template literal with variables', () => {
|
|
71
|
+
/* eslint-disable no-template-curly-in-string */
|
|
72
|
+
const inputAst = parseJsx('<Button toChildren={`Hello ${name}`} variant="primary" />')
|
|
73
|
+
const outputAst = parseJsx('<Button variant="primary">{`Hello ${name}`}</Button>')
|
|
74
|
+
/* eslint-enable no-template-curly-in-string */
|
|
75
|
+
expect(testCreateJsxElementWithChildren(inputAst)).toEqual(printAst(outputAst))
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
it('transforms a variable', () => {
|
|
79
|
+
const inputAst = parseJsx('<Button toChildren={childrenVar} variant="primary" />')
|
|
80
|
+
const outputAst = parseJsx('<Button variant="primary">{childrenVar}</Button>')
|
|
81
|
+
expect(testCreateJsxElementWithChildren(inputAst)).toEqual(printAst(outputAst))
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
it('transforms a ternary', () => {
|
|
85
|
+
const inputAst = parseJsx(
|
|
86
|
+
'<Button toChildren={isPancake ? "Pancake" : "Waffle"} variant="primary" />',
|
|
87
|
+
)
|
|
88
|
+
const outputAst = parseJsx(
|
|
89
|
+
'<Button variant="primary">{isPancake ? "Pancake" : "Waffle"}</Button>',
|
|
90
|
+
)
|
|
91
|
+
expect(testCreateJsxElementWithChildren(inputAst)).toEqual(printAst(outputAst))
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
it('transforms a JSX element', () => {
|
|
95
|
+
const inputAst = parseJsx('<Button toChildren={<span>Hello</span>} variant="primary" />')
|
|
96
|
+
const outputAst = parseJsx('<Button variant="primary"><span>Hello</span></Button>')
|
|
97
|
+
expect(testCreateJsxElementWithChildren(inputAst)).toEqual(printAst(outputAst))
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
it('transforms a JSX self-closing element', () => {
|
|
101
|
+
const inputAst = parseJsx('<Button toChildren={<Icon />} variant="primary" />')
|
|
102
|
+
const outputAst = parseJsx('<Button variant="primary"><Icon /></Button>')
|
|
103
|
+
expect(testCreateJsxElementWithChildren(inputAst)).toEqual(printAst(outputAst))
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
it('transforms a JSX fragment', () => {
|
|
107
|
+
const inputAst = parseJsx('<Button toChildren={<>Hello</>} variant="primary" />')
|
|
108
|
+
const outputAst = parseJsx('<Button variant="primary"><>Hello</></Button>')
|
|
109
|
+
expect(testCreateJsxElementWithChildren(inputAst)).toEqual(printAst(outputAst))
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
it('adds a comment if no value for children has been passed in', () => {
|
|
113
|
+
const inputAst = parseJsx('<Button variant="primary" />')
|
|
114
|
+
const outputAst = parseJsx(`<Button variant="primary">
|
|
115
|
+
/* @todo Children required but a value was not found during the codemod */
|
|
116
|
+
</Button>`)
|
|
117
|
+
expect(testCreateJsxElementWithChildren(inputAst)).toEqual(printAst(outputAst))
|
|
118
|
+
})
|
|
119
|
+
})
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import ts from 'typescript'
|
|
2
|
+
|
|
3
|
+
const createJsxChildren = (childrenValue: ts.JsxAttributeValue): ts.JsxChild => {
|
|
4
|
+
if (ts.isStringLiteral(childrenValue)) {
|
|
5
|
+
return ts.factory.createJsxText(childrenValue.text)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (ts.isJsxExpression(childrenValue)) {
|
|
9
|
+
const value = childrenValue.expression
|
|
10
|
+
|
|
11
|
+
if (value) {
|
|
12
|
+
if (ts.isStringLiteral(value)) {
|
|
13
|
+
// Tests for {"string"}, {'string'}
|
|
14
|
+
const regexExpContainsOnlyQuotedString = new RegExp(/^\{(["']).*(\1)\}$/g)
|
|
15
|
+
|
|
16
|
+
if (regexExpContainsOnlyQuotedString.test(childrenValue.getFullText())) {
|
|
17
|
+
return ts.factory.createJsxText(value.text)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (ts.isJsxElement(value) || ts.isJsxSelfClosingElement(value) || ts.isJsxFragment(value)) {
|
|
22
|
+
return value
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return childrenValue
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return childrenValue
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Use this to replace a self-closing JSX element to a JSX element with children
|
|
34
|
+
*/
|
|
35
|
+
export const createJsxElementWithChildren = (
|
|
36
|
+
tagName: string,
|
|
37
|
+
attributes: ts.JsxAttributeLike[],
|
|
38
|
+
childrenValue: ts.JsxAttributeValue | undefined,
|
|
39
|
+
): ts.JsxElement => {
|
|
40
|
+
const tagNameId = ts.factory.createIdentifier(tagName)
|
|
41
|
+
const fallbackChildren = [
|
|
42
|
+
ts.factory.createJsxText('\n'),
|
|
43
|
+
ts.factory.createJsxText(
|
|
44
|
+
'/* @todo Children required but a value was not found during the codemod */',
|
|
45
|
+
),
|
|
46
|
+
ts.factory.createJsxText('\n'),
|
|
47
|
+
]
|
|
48
|
+
const children = childrenValue ? [createJsxChildren(childrenValue)] : fallbackChildren
|
|
49
|
+
|
|
50
|
+
return ts.factory.createJsxElement(
|
|
51
|
+
ts.factory.createJsxOpeningElement(tagNameId, [], ts.factory.createJsxAttributes(attributes)),
|
|
52
|
+
children,
|
|
53
|
+
ts.factory.createJsxClosingElement(tagNameId),
|
|
54
|
+
)
|
|
55
|
+
}
|
|
@@ -1,32 +1,88 @@
|
|
|
1
1
|
import ts from 'typescript'
|
|
2
2
|
import { parseJsx } from '../__tests__/utils/parseJsx'
|
|
3
|
-
import { createStyleProp } from './createProp'
|
|
3
|
+
import { createProp, createStyleProp } from './createProp'
|
|
4
4
|
import { printAst } from './printAst'
|
|
5
5
|
import { transformSource, type TransformSourceArgs } from './transformSource'
|
|
6
6
|
import { updateJsxElementWithNewProps } from './updateJsxElementWithNewProps'
|
|
7
7
|
|
|
8
|
-
export const
|
|
8
|
+
export const mockTransformer: ts.TransformerFactory<ts.SourceFile> = (context) => (rootNode) => {
|
|
9
9
|
const visit = (node: ts.Node): ts.Node => {
|
|
10
10
|
if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
const newAttributes = node.attributes.properties.map((attr) => {
|
|
12
|
+
if (ts.isJsxAttribute(attr)) {
|
|
13
|
+
return createProp(`${attr.name.getText()}New`, attr.initializer)
|
|
14
|
+
}
|
|
15
|
+
return attr
|
|
16
|
+
})
|
|
17
|
+
return updateJsxElementWithNewProps(node, newAttributes)
|
|
18
|
+
}
|
|
19
|
+
return ts.visitEachChild(node, visit, context)
|
|
20
|
+
}
|
|
21
|
+
return ts.visitNode(rootNode, visit) as ts.SourceFile
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const testCreateProp = (sourceFile: TransformSourceArgs['sourceFile']): string =>
|
|
25
|
+
transformSource({
|
|
26
|
+
sourceFile,
|
|
27
|
+
transformers: [mockTransformer],
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
describe('createProp()', () => {
|
|
31
|
+
it('creates a prop with the pre-existing value', () => {
|
|
32
|
+
const inputAst = parseJsx('<Pancakes isBoolean={false} />')
|
|
33
|
+
const outputAst = parseJsx('<Pancakes isBooleanNew={false} />')
|
|
34
|
+
expect(testCreateProp(inputAst)).toEqual(printAst(outputAst))
|
|
35
|
+
})
|
|
17
36
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
37
|
+
it('creates a prop and transforms true to undefined', () => {
|
|
38
|
+
const inputAst = parseJsx(`
|
|
39
|
+
export const TestComponent = () => (
|
|
40
|
+
<>
|
|
41
|
+
<Pancakes isBoolean />
|
|
42
|
+
<Pancakes isBoolean={false} />
|
|
43
|
+
<Pancakes stringProp="Hello" />
|
|
44
|
+
<Pancakes stringVarProp={stringVar} />
|
|
45
|
+
<Pancakes numberProp={3} />
|
|
46
|
+
<Pancakes objProp={{ key: 'value' }} />
|
|
47
|
+
</>
|
|
48
|
+
)
|
|
49
|
+
`)
|
|
50
|
+
const outputAst = parseJsx(`
|
|
51
|
+
export const TestComponent = () => (
|
|
52
|
+
<>
|
|
53
|
+
<Pancakes isBooleanNew />
|
|
54
|
+
<Pancakes isBooleanNew={false} />
|
|
55
|
+
<Pancakes stringPropNew="Hello" />
|
|
56
|
+
<Pancakes stringVarPropNew={stringVar} />
|
|
57
|
+
<Pancakes numberPropNew={3} />
|
|
58
|
+
<Pancakes objPropNew={{ key: 'value' }} />
|
|
59
|
+
</>
|
|
60
|
+
)
|
|
61
|
+
`)
|
|
62
|
+
expect(testCreateProp(inputAst)).toEqual(printAst(outputAst))
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
export const styleTransformer: ts.TransformerFactory<ts.SourceFile> = (context) => (rootNode) => {
|
|
67
|
+
const visit = (node: ts.Node): ts.Node => {
|
|
68
|
+
if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
|
|
69
|
+
const newAttributes = node.attributes.properties.map((attr) => {
|
|
70
|
+
if (ts.isJsxAttribute(attr)) {
|
|
71
|
+
if (attr.name.getText() === 'replaceWithExistingValue') {
|
|
72
|
+
return createStyleProp({ width: attr.initializer! })
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (attr.name.getText() === 'replaceWithStringValue') {
|
|
76
|
+
return createStyleProp({ width: '100px' })
|
|
77
|
+
}
|
|
21
78
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
79
|
+
if (attr.name.getText() === 'replaceWithNumberValue') {
|
|
80
|
+
return createStyleProp({ width: 100 })
|
|
25
81
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
82
|
+
}
|
|
83
|
+
return attr
|
|
84
|
+
})
|
|
85
|
+
return updateJsxElementWithNewProps(node, newAttributes)
|
|
30
86
|
}
|
|
31
87
|
return ts.visitEachChild(node, visit, context)
|
|
32
88
|
}
|
|
@@ -36,7 +92,7 @@ export const mockedTransformer: ts.TransformerFactory<ts.SourceFile> = (context)
|
|
|
36
92
|
const testCreateStyleProp = (sourceFile: TransformSourceArgs['sourceFile']): string =>
|
|
37
93
|
transformSource({
|
|
38
94
|
sourceFile,
|
|
39
|
-
transformers: [
|
|
95
|
+
transformers: [styleTransformer],
|
|
40
96
|
})
|
|
41
97
|
|
|
42
98
|
describe('createStyleProp()', () => {
|
|
@@ -3,7 +3,14 @@ import ts from 'typescript'
|
|
|
3
3
|
export const createProp = (
|
|
4
4
|
name: string,
|
|
5
5
|
value?: ts.JsxAttributeValue | undefined,
|
|
6
|
-
): ts.JsxAttribute =>
|
|
6
|
+
): ts.JsxAttribute => {
|
|
7
|
+
// Transforms `propName={true}` to `propName`
|
|
8
|
+
if (value && ts.isJsxExpression(value) && value.expression?.kind === ts.SyntaxKind.TrueKeyword) {
|
|
9
|
+
return ts.factory.createJsxAttribute(ts.factory.createIdentifier(name), undefined)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return ts.factory.createJsxAttribute(ts.factory.createIdentifier(name), value)
|
|
13
|
+
}
|
|
7
14
|
|
|
8
15
|
export const createStringProp = (name: string, value: string): ts.JsxAttribute =>
|
|
9
16
|
createProp(name, ts.factory.createStringLiteral(value))
|
|
@@ -5,10 +5,17 @@ type ImportModuleNamedImports = {
|
|
|
5
5
|
namedImports: ts.NodeArray<ts.ImportSpecifier>
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
const getKaioNamedImports = (
|
|
8
|
+
const getKaioNamedImports = (
|
|
9
|
+
visitedNode: ts.Node,
|
|
10
|
+
importSource?: string,
|
|
11
|
+
): ImportModuleNamedImports | undefined => {
|
|
9
12
|
if (ts.isImportDeclaration(visitedNode)) {
|
|
10
13
|
const moduleSpecifier = (visitedNode.moduleSpecifier as ts.StringLiteral).text
|
|
11
|
-
|
|
14
|
+
const hasMatch = importSource
|
|
15
|
+
? moduleSpecifier === importSource
|
|
16
|
+
: moduleSpecifier.includes('@kaizen/components')
|
|
17
|
+
|
|
18
|
+
if (hasMatch) {
|
|
12
19
|
const namedBindings = visitedNode.importClause?.namedBindings
|
|
13
20
|
if (namedBindings && ts.isNamedImports(namedBindings)) {
|
|
14
21
|
return {
|
|
@@ -42,12 +49,13 @@ const getNamesFromSpecifier = (importSpecifier: ts.ImportSpecifier): ImportSpeci
|
|
|
42
49
|
*/
|
|
43
50
|
export const getKaioTagName = (
|
|
44
51
|
node: ts.Node,
|
|
45
|
-
|
|
52
|
+
componentName: string,
|
|
53
|
+
importSource?: string,
|
|
46
54
|
): string | undefined => {
|
|
47
55
|
let alias: string | undefined
|
|
48
56
|
|
|
49
57
|
const visitNode = (visitedNode: ts.Node): string | undefined => {
|
|
50
|
-
const kaioNamedImports = getKaioNamedImports(visitedNode)
|
|
58
|
+
const kaioNamedImports = getKaioNamedImports(visitedNode, importSource)
|
|
51
59
|
|
|
52
60
|
if (!kaioNamedImports) {
|
|
53
61
|
return ts.forEachChild(visitedNode, visitNode)
|
|
@@ -56,7 +64,7 @@ export const getKaioTagName = (
|
|
|
56
64
|
kaioNamedImports.namedImports.find((importSpecifier) => {
|
|
57
65
|
const { tagName, originalName } = getNamesFromSpecifier(importSpecifier)
|
|
58
66
|
|
|
59
|
-
if (originalName ===
|
|
67
|
+
if (originalName === componentName) {
|
|
60
68
|
alias = tagName
|
|
61
69
|
return true
|
|
62
70
|
}
|
package/codemods/utils/index.ts
CHANGED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var tslib = require('tslib');
|
|
4
|
+
var React = require('react');
|
|
5
|
+
var reactAriaComponents = require('react-aria-components');
|
|
6
|
+
var mergeClassNames = require('../utils/mergeClassNames.cjs');
|
|
7
|
+
var LinkContent = require('./subcomponents/LinkContent.cjs');
|
|
8
|
+
var Link_module = require('./Link.module.css.cjs');
|
|
9
|
+
function _interopDefault(e) {
|
|
10
|
+
return e && e.__esModule ? e : {
|
|
11
|
+
default: e
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
15
|
+
var Link = React.forwardRef(function (_a, ref) {
|
|
16
|
+
var children = _a.children,
|
|
17
|
+
_b = _a.variant,
|
|
18
|
+
variant = _b === undefined ? 'primary' : _b,
|
|
19
|
+
_c = _a.size,
|
|
20
|
+
size = _c === undefined ? 'body' : _c,
|
|
21
|
+
icon = _a.icon,
|
|
22
|
+
_d = _a.iconPosition,
|
|
23
|
+
iconPosition = _d === undefined ? 'end' : _d,
|
|
24
|
+
_e = _a.isInline,
|
|
25
|
+
isInline = _e === undefined ? false : _e,
|
|
26
|
+
isDisabled = _a.isDisabled,
|
|
27
|
+
className = _a.className,
|
|
28
|
+
_f = _a.isUnderlined,
|
|
29
|
+
isUnderlined = _f === undefined ? true : _f,
|
|
30
|
+
otherProps = tslib.__rest(_a, ["children", "variant", "size", "icon", "iconPosition", "isInline", "isDisabled", "className", "isUnderlined"]);
|
|
31
|
+
var childIsFunction = typeof children === 'function';
|
|
32
|
+
return React__default.default.createElement(reactAriaComponents.Link, tslib.__assign({
|
|
33
|
+
ref: ref,
|
|
34
|
+
className: mergeClassNames.mergeClassNames(Link_module.link, isDisabled && Link_module.isDisabled, isInline ? Link_module.isInline : Link_module[size], Link_module[variant], className),
|
|
35
|
+
isDisabled: isDisabled
|
|
36
|
+
}, otherProps), function (racStateProps) {
|
|
37
|
+
return React__default.default.createElement(LinkContent.LinkContent, {
|
|
38
|
+
icon: icon,
|
|
39
|
+
iconPosition: iconPosition,
|
|
40
|
+
isUnderlined: isUnderlined
|
|
41
|
+
}, childIsFunction ? children(racStateProps) : children);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
Link.displayName = 'Link';
|
|
45
|
+
exports.Link = Link;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var styles = {
|
|
4
|
+
"link": "Link-module_link__8oxip",
|
|
5
|
+
"isUnderlined": "Link-module_isUnderlined__qvbtS",
|
|
6
|
+
"icon": "Link-module_icon__CXh2J",
|
|
7
|
+
"iconStart": "Link-module_iconStart__ZysGR",
|
|
8
|
+
"iconEnd": "Link-module_iconEnd__-DTiD",
|
|
9
|
+
"primary": "Link-module_primary__bmhX0",
|
|
10
|
+
"secondary": "Link-module_secondary__pyYIV",
|
|
11
|
+
"isInline": "Link-module_isInline__sznAm",
|
|
12
|
+
"extra-small": "Link-module_extra-small__nScM0",
|
|
13
|
+
"body": "Link-module_body__H4Jgj",
|
|
14
|
+
"intro-lede": "Link-module_intro-lede__38Y6J",
|
|
15
|
+
"small": "Link-module_small__4kJcR",
|
|
16
|
+
"white": "Link-module_white__qQr6q",
|
|
17
|
+
"isDisabled": "Link-module_isDisabled__gvLNv",
|
|
18
|
+
"reversed": "Link-module_reversed__IqX8B"
|
|
19
|
+
};
|
|
20
|
+
module.exports = styles;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var mergeClassNames = require('../../utils/mergeClassNames.cjs');
|
|
5
|
+
var Link_module = require('../Link.module.css.cjs');
|
|
6
|
+
function _interopDefault(e) {
|
|
7
|
+
return e && e.__esModule ? e : {
|
|
8
|
+
default: e
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
12
|
+
var LinkIcon = function (_a) {
|
|
13
|
+
var icon = _a.icon;
|
|
14
|
+
return React__default.default.createElement("span", {
|
|
15
|
+
className: Link_module.icon
|
|
16
|
+
}, icon);
|
|
17
|
+
};
|
|
18
|
+
var LinkContent = function (_a) {
|
|
19
|
+
var children = _a.children,
|
|
20
|
+
icon = _a.icon,
|
|
21
|
+
iconPosition = _a.iconPosition,
|
|
22
|
+
isUnderlined = _a.isUnderlined;
|
|
23
|
+
var iconPositionStyling = iconPosition === 'start' ? Link_module.iconStart : Link_module.iconEnd;
|
|
24
|
+
return React__default.default.createElement("span", {
|
|
25
|
+
className: mergeClassNames.mergeClassNames(Link_module.linkContent, isUnderlined && Link_module.isUnderlined)
|
|
26
|
+
}, icon && iconPosition === 'start' && React__default.default.createElement(LinkIcon, {
|
|
27
|
+
icon: icon
|
|
28
|
+
}), React__default.default.createElement("span", {
|
|
29
|
+
className: mergeClassNames.mergeClassNames(icon && iconPositionStyling)
|
|
30
|
+
}, children), icon && iconPosition === 'end' && React__default.default.createElement(LinkIcon, {
|
|
31
|
+
icon: icon
|
|
32
|
+
}));
|
|
33
|
+
};
|
|
34
|
+
exports.LinkContent = LinkContent;
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -318,6 +318,7 @@ var InputSearch = require('./Input/InputSearch/InputSearch.cjs');
|
|
|
318
318
|
var KaizenProvider = require('./KaizenProvider/KaizenProvider.cjs');
|
|
319
319
|
var Label = require('./Label/Label.cjs');
|
|
320
320
|
var LabelledMessage = require('./LabelledMessage/LabelledMessage.cjs');
|
|
321
|
+
var Link = require('./Link/Link.cjs');
|
|
321
322
|
var LikertScaleLegacy = require('./LikertScaleLegacy/LikertScaleLegacy.cjs');
|
|
322
323
|
var LinkButton = require('./LinkButton/LinkButton.cjs');
|
|
323
324
|
var LoadingGraphic = require('./Loading/LoadingGraphic/LoadingGraphic.cjs');
|
|
@@ -941,6 +942,7 @@ exports.InputSearch = InputSearch.InputSearch;
|
|
|
941
942
|
exports.KaizenProvider = KaizenProvider.KaizenProvider;
|
|
942
943
|
exports.Label = Label.Label;
|
|
943
944
|
exports.LabelledMessage = LabelledMessage.LabelledMessage;
|
|
945
|
+
exports.Link = Link.Link;
|
|
944
946
|
exports.LikertScaleLegacy = LikertScaleLegacy.LikertScaleLegacy;
|
|
945
947
|
exports.LinkButton = LinkButton.LinkButton;
|
|
946
948
|
exports.LoadingGraphic = LoadingGraphic.LoadingGraphic;
|
package/dist/cjs/utilitiesV3.cjs
CHANGED
|
@@ -318,6 +318,7 @@ var InputSearch = require('./Input/InputSearch/InputSearch.cjs');
|
|
|
318
318
|
var KaizenProvider = require('./KaizenProvider/KaizenProvider.cjs');
|
|
319
319
|
var Label = require('./Label/Label.cjs');
|
|
320
320
|
var LabelledMessage = require('./LabelledMessage/LabelledMessage.cjs');
|
|
321
|
+
var Link = require('./Link/Link.cjs');
|
|
321
322
|
var LikertScaleLegacy = require('./LikertScaleLegacy/LikertScaleLegacy.cjs');
|
|
322
323
|
var LinkButton = require('./LinkButton/LinkButton.cjs');
|
|
323
324
|
var LoadingGraphic = require('./Loading/LoadingGraphic/LoadingGraphic.cjs');
|
|
@@ -941,6 +942,7 @@ exports.InputSearch = InputSearch.InputSearch;
|
|
|
941
942
|
exports.KaizenProvider = KaizenProvider.KaizenProvider;
|
|
942
943
|
exports.Label = Label.Label;
|
|
943
944
|
exports.LabelledMessage = LabelledMessage.LabelledMessage;
|
|
945
|
+
exports.Link = Link.Link;
|
|
944
946
|
exports.LikertScaleLegacy = LikertScaleLegacy.LikertScaleLegacy;
|
|
945
947
|
exports.LinkButton = LinkButton.LinkButton;
|
|
946
948
|
exports.LoadingGraphic = LoadingGraphic.LoadingGraphic;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { __rest, __assign } from 'tslib';
|
|
2
|
+
import React, { forwardRef } from 'react';
|
|
3
|
+
import { Link as Link$1 } from 'react-aria-components';
|
|
4
|
+
import { mergeClassNames } from '../utils/mergeClassNames.mjs';
|
|
5
|
+
import { LinkContent } from './subcomponents/LinkContent.mjs';
|
|
6
|
+
import styles from './Link.module.css.mjs';
|
|
7
|
+
const Link = /*#__PURE__*/function () {
|
|
8
|
+
const Link = /*#__PURE__*/forwardRef(function (_a, ref) {
|
|
9
|
+
var children = _a.children,
|
|
10
|
+
_b = _a.variant,
|
|
11
|
+
variant = _b === undefined ? 'primary' : _b,
|
|
12
|
+
_c = _a.size,
|
|
13
|
+
size = _c === undefined ? 'body' : _c,
|
|
14
|
+
icon = _a.icon,
|
|
15
|
+
_d = _a.iconPosition,
|
|
16
|
+
iconPosition = _d === undefined ? 'end' : _d,
|
|
17
|
+
_e = _a.isInline,
|
|
18
|
+
isInline = _e === undefined ? false : _e,
|
|
19
|
+
isDisabled = _a.isDisabled,
|
|
20
|
+
className = _a.className,
|
|
21
|
+
_f = _a.isUnderlined,
|
|
22
|
+
isUnderlined = _f === undefined ? true : _f,
|
|
23
|
+
otherProps = __rest(_a, ["children", "variant", "size", "icon", "iconPosition", "isInline", "isDisabled", "className", "isUnderlined"]);
|
|
24
|
+
var childIsFunction = typeof children === 'function';
|
|
25
|
+
return /*#__PURE__*/React.createElement(Link$1, __assign({
|
|
26
|
+
ref: ref,
|
|
27
|
+
className: mergeClassNames(styles.link, isDisabled && styles.isDisabled, isInline ? styles.isInline : styles[size], styles[variant], className),
|
|
28
|
+
isDisabled: isDisabled
|
|
29
|
+
}, otherProps), function (racStateProps) {
|
|
30
|
+
return /*#__PURE__*/React.createElement(LinkContent, {
|
|
31
|
+
icon: icon,
|
|
32
|
+
iconPosition: iconPosition,
|
|
33
|
+
isUnderlined: isUnderlined
|
|
34
|
+
}, childIsFunction ? children(racStateProps) : children);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
Link.displayName = 'Link';
|
|
38
|
+
return Link;
|
|
39
|
+
}();
|
|
40
|
+
export { Link };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
var styles = {
|
|
2
|
+
"link": "Link-module_link__8oxip",
|
|
3
|
+
"isUnderlined": "Link-module_isUnderlined__qvbtS",
|
|
4
|
+
"icon": "Link-module_icon__CXh2J",
|
|
5
|
+
"iconStart": "Link-module_iconStart__ZysGR",
|
|
6
|
+
"iconEnd": "Link-module_iconEnd__-DTiD",
|
|
7
|
+
"primary": "Link-module_primary__bmhX0",
|
|
8
|
+
"secondary": "Link-module_secondary__pyYIV",
|
|
9
|
+
"isInline": "Link-module_isInline__sznAm",
|
|
10
|
+
"extra-small": "Link-module_extra-small__nScM0",
|
|
11
|
+
"body": "Link-module_body__H4Jgj",
|
|
12
|
+
"intro-lede": "Link-module_intro-lede__38Y6J",
|
|
13
|
+
"small": "Link-module_small__4kJcR",
|
|
14
|
+
"white": "Link-module_white__qQr6q",
|
|
15
|
+
"isDisabled": "Link-module_isDisabled__gvLNv",
|
|
16
|
+
"reversed": "Link-module_reversed__IqX8B"
|
|
17
|
+
};
|
|
18
|
+
export { styles as default };
|