@planningcenter/tapestry-migration-cli 3.4.1-rc.9 → 3.5.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.
- package/README.md +22 -0
- package/dist/tapestry-react-shim.cjs +5 -1
- package/package.json +3 -3
- package/src/availableComponents.ts +13 -0
- package/src/components/dropdown/index.test.ts +244 -4
- package/src/components/dropdown/index.ts +28 -2
- package/src/components/dropdown/transforms/auditSpreadProps.test.ts +110 -0
- package/src/components/dropdown/transforms/auditSpreadProps.ts +10 -0
- package/src/components/dropdown/transforms/dividerToSeparator.test.ts +134 -0
- package/src/components/dropdown/transforms/dividerToSeparator.ts +67 -0
- package/src/components/dropdown/transforms/itemToAction.test.ts +19 -1
- package/src/components/dropdown/transforms/itemToAction.ts +14 -2
- package/src/components/dropdown/transforms/linkToLink.test.ts +19 -1
- package/src/components/dropdown/transforms/linkToLink.ts +13 -2
- package/src/components/dropdown/transforms/moveDropdownImport.test.ts +93 -0
- package/src/components/dropdown/transforms/moveDropdownImport.ts +13 -0
- package/src/components/dropdown/transforms/placementIdToMenu.test.ts +140 -0
- package/src/components/dropdown/transforms/placementIdToMenu.ts +96 -0
- package/src/components/dropdown/transforms/unsupportedProps.test.ts +145 -0
- package/src/components/dropdown/transforms/unsupportedProps.ts +12 -0
- package/src/components/dropdown/transforms/unsupportedPropsDivider.test.ts +143 -0
- package/src/components/dropdown/transforms/unsupportedPropsDivider.ts +26 -0
- package/src/components/dropdown/transforms/unsupportedPropsItem.test.ts +123 -0
- package/src/components/dropdown/transforms/unsupportedPropsItem.ts +12 -0
- package/src/components/dropdown/transforms/unsupportedPropsLink.test.ts +107 -0
- package/src/components/dropdown/transforms/unsupportedPropsLink.ts +12 -0
- package/src/components/dropdown/transforms/variantToKind.test.ts +292 -0
- package/src/components/dropdown/transforms/variantToKind.ts +138 -0
- package/src/components/dropdown/transforms/wrapIconTrigger.test.ts +336 -0
- package/src/components/dropdown/transforms/wrapIconTrigger.ts +233 -0
- package/src/components/dropdown/transforms/wrapMenu.test.ts +153 -0
- package/src/components/dropdown/transforms/wrapMenu.ts +54 -0
- package/src/components/dropdown/transforms/wrapTrigger.test.ts +283 -0
- package/src/components/dropdown/transforms/wrapTrigger.ts +98 -0
- package/src/components/input/transforms/unsupportedProps.test.ts +14 -13
- package/src/components/shared/conditions/isChildOf.test.ts +89 -0
- package/src/components/shared/conditions/isChildOf.ts +43 -0
- package/src/components/shared/helpers/unsupportedPropsHelpers.ts +36 -0
- package/src/index.ts +5 -18
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import jscodeshift from "jscodeshift"
|
|
2
|
+
import { describe, expect, it } from "vitest"
|
|
3
|
+
|
|
4
|
+
import transform from "./variantToKind"
|
|
5
|
+
|
|
6
|
+
const j = jscodeshift.withParser("tsx")
|
|
7
|
+
|
|
8
|
+
function applyTransform(source: string): string | null {
|
|
9
|
+
const fileInfo = { path: "test.tsx", source }
|
|
10
|
+
return transform(
|
|
11
|
+
fileInfo,
|
|
12
|
+
{ j, jscodeshift: j, report: () => {}, stats: () => {} },
|
|
13
|
+
{}
|
|
14
|
+
) as string | null
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function wrappedInput(
|
|
18
|
+
attrs: string,
|
|
19
|
+
buttonElement = '<DropdownButton label="Actions" />'
|
|
20
|
+
) {
|
|
21
|
+
return `
|
|
22
|
+
import { Dropdown } from "@planningcenter/tapestry-react"
|
|
23
|
+
import { DropdownButton, DropdownMenu, DropdownTrigger } from "@planningcenter/tapestry"
|
|
24
|
+
|
|
25
|
+
export default function Test() {
|
|
26
|
+
return (
|
|
27
|
+
<Dropdown ${attrs} onClose={fn}>
|
|
28
|
+
<DropdownTrigger>
|
|
29
|
+
${buttonElement}
|
|
30
|
+
</DropdownTrigger>
|
|
31
|
+
<DropdownMenu>
|
|
32
|
+
<DropdownAction id="edit" onAction={fn}>Edit</DropdownAction>
|
|
33
|
+
</DropdownMenu>
|
|
34
|
+
</Dropdown>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
`.trim()
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
describe("variantToKind transform", () => {
|
|
41
|
+
describe("variant-only mappings (default theme)", () => {
|
|
42
|
+
it('maps variant="outline" to kind="secondary"', () => {
|
|
43
|
+
const result = applyTransform(wrappedInput('variant="outline"'))
|
|
44
|
+
expect(result).toContain('kind="secondary"')
|
|
45
|
+
expect(result).not.toContain('variant="outline"')
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('maps variant="fill" to kind="neutral"', () => {
|
|
49
|
+
const result = applyTransform(wrappedInput('variant="fill"'))
|
|
50
|
+
expect(result).toContain('kind="neutral"')
|
|
51
|
+
expect(result).not.toContain('variant="fill"')
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('maps variant="naked" to kind="ghost"', () => {
|
|
55
|
+
const result = applyTransform(wrappedInput('variant="naked"'))
|
|
56
|
+
expect(result).toContain('kind="ghost"')
|
|
57
|
+
expect(result).not.toContain('variant="naked"')
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('normalizes variant="ghost" to kind="ghost"', () => {
|
|
61
|
+
const result = applyTransform(wrappedInput('variant="ghost"'))
|
|
62
|
+
expect(result).toContain('kind="ghost"')
|
|
63
|
+
expect(result).not.toContain('variant="ghost"')
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it('normalizes variant="solid" to kind="neutral" (solid→fill→neutral)', () => {
|
|
67
|
+
const result = applyTransform(wrappedInput('variant="solid"'))
|
|
68
|
+
expect(result).toContain('kind="neutral"')
|
|
69
|
+
expect(result).not.toContain('variant="solid"')
|
|
70
|
+
})
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
describe("theme-only mappings (default variant)", () => {
|
|
74
|
+
it('maps theme="error" to kind="delete"', () => {
|
|
75
|
+
const result = applyTransform(wrappedInput('theme="error"'))
|
|
76
|
+
expect(result).toContain('kind="delete"')
|
|
77
|
+
expect(result).not.toContain('theme="error"')
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('maps theme="primary" to kind="primary"', () => {
|
|
81
|
+
const result = applyTransform(wrappedInput('theme="primary"'))
|
|
82
|
+
expect(result).toContain('kind="primary"')
|
|
83
|
+
expect(result).not.toContain('theme="primary"')
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
it('normalizes theme="destroy" to kind="delete"', () => {
|
|
87
|
+
const result = applyTransform(wrappedInput('theme="destroy"'))
|
|
88
|
+
expect(result).toContain('kind="delete"')
|
|
89
|
+
expect(result).not.toContain('theme="destroy"')
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
it('normalizes theme="interaction" to kind="primary"', () => {
|
|
93
|
+
const result = applyTransform(wrappedInput('theme="interaction"'))
|
|
94
|
+
expect(result).toContain('kind="primary"')
|
|
95
|
+
expect(result).not.toContain('theme="interaction"')
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
describe("theme + variant combined", () => {
|
|
100
|
+
it('maps theme="error" variant="outline" to kind="secondary-delete"', () => {
|
|
101
|
+
const result = applyTransform(
|
|
102
|
+
wrappedInput('theme="error" variant="outline"')
|
|
103
|
+
)
|
|
104
|
+
expect(result).toContain('kind="secondary-delete"')
|
|
105
|
+
expect(result).not.toContain('theme="error"')
|
|
106
|
+
expect(result).not.toContain('variant="outline"')
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
it('maps theme="error" variant="naked" to kind="ghost-delete"', () => {
|
|
110
|
+
const result = applyTransform(
|
|
111
|
+
wrappedInput('theme="error" variant="naked"')
|
|
112
|
+
)
|
|
113
|
+
expect(result).toContain('kind="ghost-delete"')
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
it('maps theme="primary" variant="outline" to kind="secondary-interaction"', () => {
|
|
117
|
+
const result = applyTransform(
|
|
118
|
+
wrappedInput('theme="primary" variant="outline"')
|
|
119
|
+
)
|
|
120
|
+
expect(result).toContain('kind="secondary-interaction"')
|
|
121
|
+
})
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
describe("kind placement", () => {
|
|
125
|
+
it("adds kind to the DropdownButton, not to Dropdown", () => {
|
|
126
|
+
const result = applyTransform(wrappedInput('variant="outline"'))
|
|
127
|
+
const dropdownButtonLine = result
|
|
128
|
+
?.split("\n")
|
|
129
|
+
.find((l) => l.includes("<DropdownButton"))
|
|
130
|
+
expect(dropdownButtonLine).toContain("kind")
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
it("emits TODO and does not duplicate kind when button already has kind", () => {
|
|
134
|
+
const result = applyTransform(
|
|
135
|
+
wrappedInput(
|
|
136
|
+
'variant="outline"',
|
|
137
|
+
'<DropdownButton label="Actions" kind="primary" />'
|
|
138
|
+
)
|
|
139
|
+
)
|
|
140
|
+
expect(result).not.toContain('variant="outline"')
|
|
141
|
+
expect(result).toContain("TODO: tapestry-migration (variant):")
|
|
142
|
+
expect(result).toContain("secondary")
|
|
143
|
+
const buttonLine = result
|
|
144
|
+
?.split("\n")
|
|
145
|
+
.find((l) => l.includes("<DropdownButton"))
|
|
146
|
+
expect(buttonLine).toContain('kind="primary"')
|
|
147
|
+
expect(buttonLine).not.toContain('kind="secondary"')
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
it('maps variant="outline" to kind="secondary" on DropdownIconButton', () => {
|
|
151
|
+
const result = applyTransform(
|
|
152
|
+
wrappedInput(
|
|
153
|
+
'variant="outline"',
|
|
154
|
+
'<DropdownIconButton aria-label="Edit" icon={icon} />'
|
|
155
|
+
)
|
|
156
|
+
)
|
|
157
|
+
expect(result).toContain('kind="secondary"')
|
|
158
|
+
expect(result).not.toContain('variant="outline"')
|
|
159
|
+
})
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
describe("complex/custom trigger child", () => {
|
|
163
|
+
it("removes variant and emits TODO for unknown trigger button", () => {
|
|
164
|
+
const input = `
|
|
165
|
+
import { Dropdown } from "@planningcenter/tapestry-react"
|
|
166
|
+
import { DropdownMenu, DropdownTrigger } from "@planningcenter/tapestry"
|
|
167
|
+
|
|
168
|
+
export default function Test() {
|
|
169
|
+
return (
|
|
170
|
+
<Dropdown variant="outline" onClose={fn}>
|
|
171
|
+
<DropdownTrigger>
|
|
172
|
+
<MyCustomButton label="Actions" />
|
|
173
|
+
</DropdownTrigger>
|
|
174
|
+
<DropdownMenu />
|
|
175
|
+
</Dropdown>
|
|
176
|
+
)
|
|
177
|
+
}
|
|
178
|
+
`.trim()
|
|
179
|
+
|
|
180
|
+
const result = applyTransform(input)
|
|
181
|
+
expect(result).not.toContain('variant="outline"')
|
|
182
|
+
expect(result).toContain("TODO: tapestry-migration (variant):")
|
|
183
|
+
expect(result).toContain("secondary")
|
|
184
|
+
const customButtonLine = result
|
|
185
|
+
?.split("\n")
|
|
186
|
+
.find((l) => l.includes("<MyCustomButton"))
|
|
187
|
+
expect(customButtonLine).not.toContain("kind")
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
it("uses scope=theme when only theme is present on custom trigger", () => {
|
|
191
|
+
const input = `
|
|
192
|
+
import { Dropdown } from "@planningcenter/tapestry-react"
|
|
193
|
+
import { DropdownMenu, DropdownTrigger } from "@planningcenter/tapestry"
|
|
194
|
+
|
|
195
|
+
export default function Test() {
|
|
196
|
+
return (
|
|
197
|
+
<Dropdown theme="error" onClose={fn}>
|
|
198
|
+
<DropdownTrigger>
|
|
199
|
+
<MyCustomButton label="Actions" />
|
|
200
|
+
</DropdownTrigger>
|
|
201
|
+
<DropdownMenu />
|
|
202
|
+
</Dropdown>
|
|
203
|
+
)
|
|
204
|
+
}
|
|
205
|
+
`.trim()
|
|
206
|
+
|
|
207
|
+
const result = applyTransform(input)
|
|
208
|
+
expect(result).toContain("TODO: tapestry-migration (theme):")
|
|
209
|
+
expect(result).not.toContain("TODO: tapestry-migration (variant):")
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
it("uses scope=variant/theme when both are present on custom trigger", () => {
|
|
213
|
+
const input = `
|
|
214
|
+
import { Dropdown } from "@planningcenter/tapestry-react"
|
|
215
|
+
import { DropdownMenu, DropdownTrigger } from "@planningcenter/tapestry"
|
|
216
|
+
|
|
217
|
+
export default function Test() {
|
|
218
|
+
return (
|
|
219
|
+
<Dropdown theme="error" variant="outline" onClose={fn}>
|
|
220
|
+
<DropdownTrigger>
|
|
221
|
+
<MyCustomButton label="Actions" />
|
|
222
|
+
</DropdownTrigger>
|
|
223
|
+
<DropdownMenu />
|
|
224
|
+
</Dropdown>
|
|
225
|
+
)
|
|
226
|
+
}
|
|
227
|
+
`.trim()
|
|
228
|
+
|
|
229
|
+
const result = applyTransform(input)
|
|
230
|
+
expect(result).toContain("TODO: tapestry-migration (variant/theme):")
|
|
231
|
+
})
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
describe("no changes scenarios", () => {
|
|
235
|
+
it("returns null for dynamic variant expression", () => {
|
|
236
|
+
expect(applyTransform(wrappedInput("variant={buttonVariant}"))).toBe(null)
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
it("returns null for dynamic theme expression", () => {
|
|
240
|
+
expect(applyTransform(wrappedInput("theme={buttonTheme}"))).toBe(null)
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
it("returns null for an unmapped variant value", () => {
|
|
244
|
+
expect(applyTransform(wrappedInput('variant="extra-large"'))).toBe(null)
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
it("returns null for an unmapped theme value", () => {
|
|
248
|
+
expect(applyTransform(wrappedInput('theme="unknown-theme"'))).toBe(null)
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
it("returns null when no DropdownTrigger child exists", () => {
|
|
252
|
+
const input = `
|
|
253
|
+
import { Dropdown } from "@planningcenter/tapestry-react"
|
|
254
|
+
|
|
255
|
+
export default function Test() {
|
|
256
|
+
return (
|
|
257
|
+
<Dropdown variant="outline" onClose={fn}>
|
|
258
|
+
<DropdownMenu />
|
|
259
|
+
</Dropdown>
|
|
260
|
+
)
|
|
261
|
+
}
|
|
262
|
+
`.trim()
|
|
263
|
+
|
|
264
|
+
expect(applyTransform(input)).toBe(null)
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
it("returns null when neither variant nor theme is present", () => {
|
|
268
|
+
expect(applyTransform(wrappedInput(""))).toBe(null)
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
it("returns null when Dropdown is not imported from tapestry-react", () => {
|
|
272
|
+
const input = `
|
|
273
|
+
import { Dropdown } from "@planningcenter/tapestry"
|
|
274
|
+
|
|
275
|
+
export default function Test() {
|
|
276
|
+
return (
|
|
277
|
+
<Dropdown variant="outline">
|
|
278
|
+
<DropdownTrigger><DropdownButton label="Actions" /></DropdownTrigger>
|
|
279
|
+
<DropdownMenu />
|
|
280
|
+
</Dropdown>
|
|
281
|
+
)
|
|
282
|
+
}
|
|
283
|
+
`.trim()
|
|
284
|
+
|
|
285
|
+
expect(applyTransform(input)).toBe(null)
|
|
286
|
+
})
|
|
287
|
+
|
|
288
|
+
it("returns null for empty file", () => {
|
|
289
|
+
expect(applyTransform("")).toBe(null)
|
|
290
|
+
})
|
|
291
|
+
})
|
|
292
|
+
})
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { JSXAttribute, JSXElement, Transform } from "jscodeshift"
|
|
2
|
+
|
|
3
|
+
import { addAttribute } from "../../shared/actions/addAttribute"
|
|
4
|
+
import { addComment } from "../../shared/actions/addComment"
|
|
5
|
+
import { getAttribute } from "../../shared/actions/getAttribute"
|
|
6
|
+
import { removeAttribute } from "../../shared/actions/removeAttribute"
|
|
7
|
+
import { hasAttribute } from "../../shared/conditions/hasAttribute"
|
|
8
|
+
import { orConditions } from "../../shared/conditions/orConditions"
|
|
9
|
+
import { attributeTransformFactory } from "../../shared/transformFactories/attributeTransformFactory"
|
|
10
|
+
|
|
11
|
+
const THEME_KIND_MAP: Record<string, Record<string, string>> = {
|
|
12
|
+
default: {
|
|
13
|
+
default: "neutral",
|
|
14
|
+
fill: "neutral",
|
|
15
|
+
naked: "ghost",
|
|
16
|
+
outline: "secondary",
|
|
17
|
+
},
|
|
18
|
+
error: {
|
|
19
|
+
default: "delete",
|
|
20
|
+
fill: "delete",
|
|
21
|
+
naked: "ghost-delete",
|
|
22
|
+
outline: "secondary-delete",
|
|
23
|
+
},
|
|
24
|
+
neutral: {
|
|
25
|
+
default: "neutral",
|
|
26
|
+
fill: "neutral",
|
|
27
|
+
naked: "ghost",
|
|
28
|
+
outline: "secondary",
|
|
29
|
+
},
|
|
30
|
+
primary: {
|
|
31
|
+
default: "primary",
|
|
32
|
+
fill: "primary",
|
|
33
|
+
naked: "ghost-interaction",
|
|
34
|
+
outline: "secondary-interaction",
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const KNOWN_TRIGGER_BUTTONS = new Set(["DropdownButton", "DropdownIconButton"])
|
|
39
|
+
|
|
40
|
+
function normalizeTheme(value: string): string {
|
|
41
|
+
if (value === "destroy" || value === "delete") return "error"
|
|
42
|
+
if (value === "info" || value === "success" || value === "interaction")
|
|
43
|
+
return "primary"
|
|
44
|
+
return value
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function normalizeVariant(value: string): string {
|
|
48
|
+
if (value === "ghost") return "naked"
|
|
49
|
+
if (value === "solid") return "fill"
|
|
50
|
+
return value
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function getStaticStringValue(
|
|
54
|
+
attr: JSXAttribute | undefined,
|
|
55
|
+
defaultValue: string
|
|
56
|
+
): string | null {
|
|
57
|
+
if (!attr || !attr.value) return defaultValue
|
|
58
|
+
if (attr.value.type === "StringLiteral") return attr.value.value
|
|
59
|
+
return null
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function mapToKind(theme: string, variant: string): string | null {
|
|
63
|
+
return (
|
|
64
|
+
THEME_KIND_MAP[normalizeTheme(theme)]?.[normalizeVariant(variant)] ?? null
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function findDropdownTrigger(element: JSXElement): JSXElement | undefined {
|
|
69
|
+
return (element.children ?? []).find(
|
|
70
|
+
(child): child is JSXElement =>
|
|
71
|
+
child.type === "JSXElement" &&
|
|
72
|
+
child.openingElement.name.type === "JSXIdentifier" &&
|
|
73
|
+
child.openingElement.name.name === "DropdownTrigger"
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function findFirstJSXElementChild(element: JSXElement): JSXElement | undefined {
|
|
78
|
+
return (element.children ?? []).find(
|
|
79
|
+
(child): child is JSXElement => child.type === "JSXElement"
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const transform: Transform = attributeTransformFactory({
|
|
84
|
+
condition: orConditions(hasAttribute("variant"), hasAttribute("theme")),
|
|
85
|
+
targetComponent: "Dropdown",
|
|
86
|
+
targetPackage: "@planningcenter/tapestry-react",
|
|
87
|
+
transform: (element, { j, source }) => {
|
|
88
|
+
const variantAttr = getAttribute({ element, name: "variant" })
|
|
89
|
+
const themeAttr = getAttribute({ element, name: "theme" })
|
|
90
|
+
|
|
91
|
+
const variantValue = getStaticStringValue(variantAttr, "fill")
|
|
92
|
+
const themeValue = getStaticStringValue(themeAttr, "default")
|
|
93
|
+
|
|
94
|
+
if (variantValue === null || themeValue === null) return false
|
|
95
|
+
|
|
96
|
+
const mappedKind = mapToKind(themeValue, variantValue)
|
|
97
|
+
if (!mappedKind) return false
|
|
98
|
+
|
|
99
|
+
const triggerChild = findDropdownTrigger(element)
|
|
100
|
+
if (!triggerChild) return false
|
|
101
|
+
|
|
102
|
+
const buttonChild = findFirstJSXElementChild(triggerChild)
|
|
103
|
+
if (!buttonChild) return false
|
|
104
|
+
|
|
105
|
+
const buttonName =
|
|
106
|
+
buttonChild.openingElement.name.type === "JSXIdentifier"
|
|
107
|
+
? buttonChild.openingElement.name.name
|
|
108
|
+
: null
|
|
109
|
+
|
|
110
|
+
if (variantAttr) removeAttribute("variant", { element, j, source })
|
|
111
|
+
if (themeAttr) removeAttribute("theme", { element, j, source })
|
|
112
|
+
|
|
113
|
+
const scope =
|
|
114
|
+
variantAttr && themeAttr
|
|
115
|
+
? "variant/theme"
|
|
116
|
+
: themeAttr
|
|
117
|
+
? "theme"
|
|
118
|
+
: "variant"
|
|
119
|
+
|
|
120
|
+
const existingKind = getAttribute({ element: buttonChild, name: "kind" })
|
|
121
|
+
|
|
122
|
+
if (buttonName && KNOWN_TRIGGER_BUTTONS.has(buttonName) && !existingKind) {
|
|
123
|
+
addAttribute({ element: buttonChild, j, name: "kind", value: mappedKind })
|
|
124
|
+
} else {
|
|
125
|
+
addComment({
|
|
126
|
+
element,
|
|
127
|
+
j,
|
|
128
|
+
scope,
|
|
129
|
+
source,
|
|
130
|
+
text: `add kind="${mappedKind}" to the trigger button manually`,
|
|
131
|
+
})
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return true
|
|
135
|
+
},
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
export default transform
|