@planningcenter/tapestry-migration-cli 3.1.0-rc.2 → 3.1.0-rc.21

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 (115) hide show
  1. package/dist/tapestry-react-shim.cjs +7 -1
  2. package/package.json +3 -3
  3. package/src/components/button/transforms/convertStyleProps.test.ts +97 -0
  4. package/src/components/button/transforms/removeTypeButton.test.ts +0 -1
  5. package/src/components/checkbox/transforms/moveCheckboxImport.test.ts +3 -0
  6. package/src/components/input/index.ts +66 -0
  7. package/src/components/input/transformableInput.ts +49 -0
  8. package/src/components/input/transforms/auditSpreadProps.test.ts +192 -0
  9. package/src/components/input/transforms/auditSpreadProps.ts +26 -0
  10. package/src/components/input/transforms/autoWidthTransform.test.ts +172 -0
  11. package/src/components/input/transforms/autoWidthTransform.ts +41 -0
  12. package/src/components/input/transforms/convertStyleProps.test.ts +128 -0
  13. package/src/components/input/transforms/convertStyleProps.ts +12 -0
  14. package/src/components/input/transforms/highlightOnInteractionToSelectTextOnFocus.test.ts +186 -0
  15. package/src/components/input/transforms/highlightOnInteractionToSelectTextOnFocus.ts +27 -0
  16. package/src/components/input/transforms/inputLabelToLabelProp.test.ts +319 -0
  17. package/src/components/input/transforms/inputLabelToLabelProp.ts +203 -0
  18. package/src/components/input/transforms/mergeFieldIntoInput.test.ts +469 -0
  19. package/src/components/input/transforms/mergeFieldIntoInput.ts +7 -0
  20. package/src/components/input/transforms/mergeInputLabel.test.ts +458 -0
  21. package/src/components/input/transforms/mergeInputLabel.ts +204 -0
  22. package/src/components/input/transforms/moveInputImport.test.ts +166 -0
  23. package/src/components/input/transforms/moveInputImport.ts +14 -0
  24. package/src/components/input/transforms/numberFieldAddTypeNumber.test.ts +92 -0
  25. package/src/components/input/transforms/numberFieldAddTypeNumber.ts +14 -0
  26. package/src/components/input/transforms/numberFieldRenameToInput.test.ts +126 -0
  27. package/src/components/input/transforms/numberFieldRenameToInput.ts +9 -0
  28. package/src/components/input/transforms/removeAsInput.test.ts +139 -0
  29. package/src/components/input/transforms/removeAsInput.ts +20 -0
  30. package/src/components/input/transforms/removeDuplicateKeys.test.ts +302 -0
  31. package/src/components/input/transforms/removeDuplicateKeys.ts +10 -0
  32. package/src/components/input/transforms/removeInputBox.test.ts +352 -0
  33. package/src/components/input/transforms/removeInputBox.ts +109 -0
  34. package/src/components/input/transforms/removeRedundantAriaLabel.test.ts +128 -0
  35. package/src/components/input/transforms/removeRedundantAriaLabel.ts +21 -0
  36. package/src/components/input/transforms/removeTypeInput.test.ts +212 -0
  37. package/src/components/input/transforms/removeTypeInput.ts +22 -0
  38. package/src/components/input/transforms/removeTypeText.test.ts +160 -0
  39. package/src/components/input/transforms/removeTypeText.ts +17 -0
  40. package/src/components/input/transforms/sizeMapping.test.ts +198 -0
  41. package/src/components/input/transforms/sizeMapping.ts +17 -0
  42. package/src/components/input/transforms/skipRenderSideProps.test.ts +236 -0
  43. package/src/components/input/transforms/skipRenderSideProps.ts +27 -0
  44. package/src/components/input/transforms/stateToInvalid.test.ts +208 -0
  45. package/src/components/input/transforms/stateToInvalid.ts +59 -0
  46. package/src/components/input/transforms/stateToInvalidTernary.test.ts +159 -0
  47. package/src/components/input/transforms/stateToInvalidTernary.ts +13 -0
  48. package/src/components/input/transforms/unsupportedProps.test.ts +566 -0
  49. package/src/components/input/transforms/unsupportedProps.ts +84 -0
  50. package/src/components/link/transforms/reviewStyles.test.ts +0 -1
  51. package/src/components/select/index.ts +58 -0
  52. package/src/components/select/transformableSelect.ts +7 -0
  53. package/src/components/select/transforms/auditSpreadProps.test.ts +103 -0
  54. package/src/components/select/transforms/auditSpreadProps.ts +26 -0
  55. package/src/components/select/transforms/childrenToOptions.test.ts +367 -0
  56. package/src/components/select/transforms/childrenToOptions.ts +295 -0
  57. package/src/components/select/transforms/convertLegacyOptions.test.ts +150 -0
  58. package/src/components/select/transforms/convertLegacyOptions.ts +105 -0
  59. package/src/components/select/transforms/convertStyleProps.test.ts +73 -0
  60. package/src/components/select/transforms/convertStyleProps.ts +12 -0
  61. package/src/components/select/transforms/emptyValueToPlaceholder.test.ts +122 -0
  62. package/src/components/select/transforms/emptyValueToPlaceholder.ts +22 -0
  63. package/src/components/select/transforms/innerRefToRef.test.ts +89 -0
  64. package/src/components/select/transforms/innerRefToRef.ts +18 -0
  65. package/src/components/select/transforms/mapChildrenToOptions.test.ts +521 -0
  66. package/src/components/select/transforms/mapChildrenToOptions.ts +312 -0
  67. package/src/components/select/transforms/mergeFieldIntoSelect.test.ts +506 -0
  68. package/src/components/select/transforms/mergeFieldIntoSelect.ts +7 -0
  69. package/src/components/select/transforms/mergeSelectLabel.test.ts +458 -0
  70. package/src/components/select/transforms/mergeSelectLabel.ts +225 -0
  71. package/src/components/select/transforms/moveSelectImport.test.ts +148 -0
  72. package/src/components/select/transforms/moveSelectImport.ts +14 -0
  73. package/src/components/select/transforms/removeDefaultProps.test.ts +249 -0
  74. package/src/components/select/transforms/removeDefaultProps.ts +112 -0
  75. package/src/components/select/transforms/sizeMapping.test.ts +188 -0
  76. package/src/components/select/transforms/sizeMapping.ts +17 -0
  77. package/src/components/select/transforms/skipMultipleSelect.test.ts +148 -0
  78. package/src/components/select/transforms/skipMultipleSelect.ts +23 -0
  79. package/src/components/select/transforms/stateToInvalid.test.ts +217 -0
  80. package/src/components/select/transforms/stateToInvalid.ts +59 -0
  81. package/src/components/select/transforms/stateToInvalidTernary.test.ts +146 -0
  82. package/src/components/select/transforms/stateToInvalidTernary.ts +13 -0
  83. package/src/components/select/transforms/unsupportedProps.test.ts +252 -0
  84. package/src/components/select/transforms/unsupportedProps.ts +44 -0
  85. package/src/components/shared/helpers/getAttributeExpression.ts +26 -0
  86. package/src/components/shared/helpers/unsupportedPropsHelpers.ts +102 -0
  87. package/src/components/shared/transformFactories/helpers/manageImports.ts +14 -12
  88. package/src/components/shared/transformFactories/mergeFieldFactory.ts +244 -0
  89. package/src/components/shared/transformFactories/sizeMappingFactory.ts +9 -2
  90. package/src/components/shared/transformFactories/stylePropTransformFactory.ts +56 -17
  91. package/src/components/shared/transformFactories/ternaryConditionalToPropFactory.ts +65 -0
  92. package/src/components/text-area/index.ts +48 -0
  93. package/src/components/text-area/transforms/auditSpreadProps.test.ts +139 -0
  94. package/src/components/text-area/transforms/auditSpreadProps.ts +10 -0
  95. package/src/components/text-area/transforms/convertStyleProps.test.ts +158 -0
  96. package/src/components/text-area/transforms/convertStyleProps.ts +10 -0
  97. package/src/components/text-area/transforms/innerRefToRef.test.ts +206 -0
  98. package/src/components/text-area/transforms/innerRefToRef.ts +14 -0
  99. package/src/components/text-area/transforms/mergeFieldIntoTextArea.test.ts +477 -0
  100. package/src/components/text-area/transforms/mergeFieldIntoTextArea.ts +5 -0
  101. package/src/components/text-area/transforms/moveTextAreaImport.test.ts +168 -0
  102. package/src/components/text-area/transforms/moveTextAreaImport.ts +13 -0
  103. package/src/components/text-area/transforms/removeDuplicateKeys.test.ts +129 -0
  104. package/src/components/text-area/transforms/removeDuplicateKeys.ts +8 -0
  105. package/src/components/text-area/transforms/removeRedundantAriaLabel.test.ts +183 -0
  106. package/src/components/text-area/transforms/removeRedundantAriaLabel.ts +59 -0
  107. package/src/components/text-area/transforms/sizeMapping.test.ts +199 -0
  108. package/src/components/text-area/transforms/sizeMapping.ts +15 -0
  109. package/src/components/text-area/transforms/stateToInvalid.test.ts +204 -0
  110. package/src/components/text-area/transforms/stateToInvalid.ts +57 -0
  111. package/src/components/text-area/transforms/stateToInvalidTernary.test.ts +133 -0
  112. package/src/components/text-area/transforms/stateToInvalidTernary.ts +11 -0
  113. package/src/components/text-area/transforms/unsupportedProps.test.ts +275 -0
  114. package/src/components/text-area/transforms/unsupportedProps.ts +35 -0
  115. package/src/index.ts +2 -1
@@ -0,0 +1,41 @@
1
+ import { Transform } from "jscodeshift"
2
+
3
+ import { addComment } from "../../shared/actions/addComment"
4
+ import { getAttribute } from "../../shared/actions/getAttribute"
5
+ import { andConditions } from "../../shared/conditions/andConditions"
6
+ import { hasAttribute } from "../../shared/conditions/hasAttribute"
7
+ import { attributeTransformFactory } from "../../shared/transformFactories/attributeTransformFactory"
8
+ import { transformableInput } from "../transformableInput"
9
+
10
+ const transform: Transform = attributeTransformFactory({
11
+ condition: andConditions(hasAttribute("autoWidth"), transformableInput),
12
+ targetComponent: "Input",
13
+ targetPackage: "@planningcenter/tapestry-react",
14
+ transform: (element, { j, source }) => {
15
+ const attr = getAttribute({ element, name: "autoWidth" })
16
+ if (!attr) return false
17
+
18
+ // Shorthand boolean (<Input autoWidth />) — pass through
19
+ if (attr.value === null) return false
20
+
21
+ // Explicit boolean ({true} or {false}) — pass through
22
+ if (
23
+ attr.value.type === "JSXExpressionContainer" &&
24
+ attr.value.expression.type === "BooleanLiteral"
25
+ ) {
26
+ return false
27
+ }
28
+
29
+ // Non-boolean value — add comment
30
+ addComment({
31
+ element,
32
+ j,
33
+ scope: "autoWidth",
34
+ source,
35
+ text: "'autoWidth' no longer accepts measurement values. Use autoWidth={true} to grow to content width, or remove the prop.",
36
+ })
37
+ return true
38
+ },
39
+ })
40
+
41
+ export default transform
@@ -0,0 +1,128 @@
1
+ import jscodeshift from "jscodeshift"
2
+ import { describe, expect, it } from "vitest"
3
+
4
+ import transform from "./convertStyleProps"
5
+
6
+ const j = jscodeshift.withParser("tsx")
7
+
8
+ function applyTransform(source: string, options = {}) {
9
+ const fileInfo = { path: "test.tsx", source }
10
+ const result = transform(
11
+ fileInfo,
12
+ { j, jscodeshift: j, report: () => {}, stats: () => {} },
13
+ options
14
+ ) as string | null
15
+ return result || source
16
+ }
17
+
18
+ describe("convertStyleProps transform", () => {
19
+ describe("visible prop", () => {
20
+ it("should convert visible={false} to display: none", () => {
21
+ const source = `
22
+ import { Input } from "@planningcenter/tapestry-react"
23
+
24
+ export function TestComponent() {
25
+ return <Input visible={false} label="Name" />
26
+ }
27
+ `
28
+
29
+ const result = applyTransform(source)
30
+ expect(result).toContain("style={{")
31
+ expect(result).toContain('display: "none"')
32
+ expect(result).not.toContain("visible={false}")
33
+ })
34
+
35
+ it("should remove visible={true} with no style changes", () => {
36
+ const source = `
37
+ import { Input } from "@planningcenter/tapestry-react"
38
+
39
+ export function TestComponent() {
40
+ return <Input visible={true} label="Name" />
41
+ }
42
+ `
43
+
44
+ const result = applyTransform(source)
45
+ expect(result).not.toContain("visible={true}")
46
+ expect(result).not.toContain("style={{")
47
+ })
48
+ })
49
+
50
+ describe("style prop removal", () => {
51
+ it("should remove marginTop prop", () => {
52
+ const source = `
53
+ import { Input } from "@planningcenter/tapestry-react"
54
+
55
+ export function TestComponent() {
56
+ return <Input marginTop={16} label="Name" />
57
+ }
58
+ `
59
+
60
+ const result = applyTransform(source)
61
+ expect(result).not.toContain("marginTop=")
62
+ })
63
+
64
+ it("should remove alignItems prop", () => {
65
+ const source = `
66
+ import { Input } from "@planningcenter/tapestry-react"
67
+
68
+ export function TestComponent() {
69
+ return <Input alignItems="center" label="Name" />
70
+ }
71
+ `
72
+
73
+ const result = applyTransform(source)
74
+ expect(result).not.toContain("alignItems=")
75
+ })
76
+ })
77
+
78
+ describe("import handling", () => {
79
+ it("should not affect imports", () => {
80
+ const source = `
81
+ import { Input } from "@planningcenter/tapestry-react"
82
+
83
+ export function TestComponent() {
84
+ return <Input visible={false} label="Name" />
85
+ }
86
+ `
87
+
88
+ const result = applyTransform(source)
89
+ expect(result).toContain(
90
+ 'import { Input } from "@planningcenter/tapestry-react"'
91
+ )
92
+ })
93
+ })
94
+
95
+ describe("edge cases", () => {
96
+ it("should not affect Input with no style props", () => {
97
+ const source = `
98
+ import { Input } from "@planningcenter/tapestry-react"
99
+
100
+ export function TestComponent() {
101
+ return <Input label="Name" placeholder="Enter name" />
102
+ }
103
+ `
104
+
105
+ const result = applyTransform(source)
106
+ expect(result).toBe(source)
107
+ })
108
+
109
+ it("should not affect other components", () => {
110
+ const source = `
111
+ import { Input, Button } from "@planningcenter/tapestry-react"
112
+
113
+ export function TestComponent() {
114
+ return (
115
+ <div>
116
+ <Button visible={false}>Hidden</Button>
117
+ <Input visible={false} label="Name" />
118
+ </div>
119
+ )
120
+ }
121
+ `
122
+
123
+ const result = applyTransform(source)
124
+ expect(result).toContain("visible={false}")
125
+ expect(result).toContain('display: "none"')
126
+ })
127
+ })
128
+ })
@@ -0,0 +1,12 @@
1
+ import { stackViewPlugin } from "../../../stubs/stackViewPlugin"
2
+ import { stylePropTransformFactory } from "../../shared/transformFactories/stylePropTransformFactory"
3
+ import { transformableInput } from "../transformableInput"
4
+
5
+ export default stylePropTransformFactory({
6
+ condition: transformableInput,
7
+ plugin: stackViewPlugin,
8
+ stylesToKeep: ["visible"],
9
+ stylesToRemove: [],
10
+ targetComponent: "Input",
11
+ targetPackage: "@planningcenter/tapestry-react",
12
+ })
@@ -0,0 +1,186 @@
1
+ import jscodeshift from "jscodeshift"
2
+ import { describe, expect, it } from "vitest"
3
+
4
+ import transform from "./highlightOnInteractionToSelectTextOnFocus"
5
+
6
+ const j = jscodeshift.withParser("tsx")
7
+
8
+ function applyTransform(source: string, verbose = false): string {
9
+ const fileInfo = { path: "test.tsx", source }
10
+ const result = transform(
11
+ fileInfo,
12
+ { j, jscodeshift: j, report: () => {}, stats: () => {} },
13
+ { verbose }
14
+ ) as string | null
15
+ return result || source
16
+ }
17
+
18
+ describe("highlightOnInteractionToSelectTextOnFocus transform", () => {
19
+ describe("basic rename", () => {
20
+ it("should rename highlightOnInteraction to selectTextOnFocus", () => {
21
+ const input = `
22
+ import { Input } from "@planningcenter/tapestry-react"
23
+
24
+ function Test() {
25
+ return <Input highlightOnInteraction label="Name" />
26
+ }
27
+ `.trim()
28
+
29
+ const result = applyTransform(input)
30
+ expect(result).toContain("selectTextOnFocus")
31
+ expect(result).not.toContain("highlightOnInteraction")
32
+ })
33
+
34
+ it("should rename highlightOnInteraction={true}", () => {
35
+ const input = `
36
+ import { Input } from "@planningcenter/tapestry-react"
37
+
38
+ function Test() {
39
+ return <Input highlightOnInteraction={true} label="Name" />
40
+ }
41
+ `.trim()
42
+
43
+ const result = applyTransform(input)
44
+ expect(result).toContain("selectTextOnFocus={true}")
45
+ expect(result).not.toContain("highlightOnInteraction")
46
+ })
47
+
48
+ it("should rename highlightOnInteraction={false}", () => {
49
+ const input = `
50
+ import { Input } from "@planningcenter/tapestry-react"
51
+
52
+ function Test() {
53
+ return <Input highlightOnInteraction={false} label="Name" />
54
+ }
55
+ `.trim()
56
+
57
+ const result = applyTransform(input)
58
+ expect(result).toContain("selectTextOnFocus={false}")
59
+ expect(result).not.toContain("highlightOnInteraction")
60
+ })
61
+
62
+ it("should rename highlightOnInteraction with variable expression", () => {
63
+ const input = `
64
+ import { Input } from "@planningcenter/tapestry-react"
65
+
66
+ function Test() {
67
+ return <Input highlightOnInteraction={shouldHighlight} label="Name" />
68
+ }
69
+ `.trim()
70
+
71
+ const result = applyTransform(input)
72
+ expect(result).toContain("selectTextOnFocus={shouldHighlight}")
73
+ expect(result).not.toContain("highlightOnInteraction")
74
+ })
75
+
76
+ it("should preserve other props", () => {
77
+ const input = `
78
+ import { Input } from "@planningcenter/tapestry-react"
79
+
80
+ function Test() {
81
+ return (
82
+ <Input
83
+ highlightOnInteraction
84
+ label="Name"
85
+ placeholder="Enter name"
86
+ disabled
87
+ onChange={handleChange}
88
+ />
89
+ )
90
+ }
91
+ `.trim()
92
+
93
+ const result = applyTransform(input)
94
+ expect(result).toContain("selectTextOnFocus")
95
+ expect(result).not.toContain("highlightOnInteraction")
96
+ expect(result).toContain('label="Name"')
97
+ expect(result).toContain('placeholder="Enter name"')
98
+ expect(result).toContain("disabled")
99
+ expect(result).toContain("onChange={handleChange}")
100
+ })
101
+ })
102
+
103
+ describe("edge cases", () => {
104
+ it("should not affect Input without highlightOnInteraction prop", () => {
105
+ const input = `
106
+ import { Input } from "@planningcenter/tapestry-react"
107
+
108
+ function Test() {
109
+ return <Input label="Name" />
110
+ }
111
+ `.trim()
112
+
113
+ const result = applyTransform(input)
114
+ expect(result).toBe(input)
115
+ })
116
+
117
+ it("should not affect other components", () => {
118
+ const input = `
119
+ import { Input, Button } from "@planningcenter/tapestry-react"
120
+
121
+ function Test() {
122
+ return (
123
+ <div>
124
+ <Button highlightOnInteraction>Click</Button>
125
+ <Input highlightOnInteraction label="Name" />
126
+ </div>
127
+ )
128
+ }
129
+ `.trim()
130
+
131
+ const result = applyTransform(input)
132
+ expect(result).toContain("<Button highlightOnInteraction>Click</Button>")
133
+ expect(result).toContain("selectTextOnFocus")
134
+ })
135
+
136
+ it("should handle multiple Input components", () => {
137
+ const input = `
138
+ import { Input } from "@planningcenter/tapestry-react"
139
+
140
+ function Test() {
141
+ return (
142
+ <div>
143
+ <Input highlightOnInteraction label="First" />
144
+ <Input highlightOnInteraction={true} label="Second" />
145
+ </div>
146
+ )
147
+ }
148
+ `.trim()
149
+
150
+ const result = applyTransform(input)
151
+ expect(result).not.toContain("highlightOnInteraction")
152
+ const matches = result.match(/selectTextOnFocus/g)
153
+ expect(matches).toHaveLength(2)
154
+ })
155
+
156
+ it("should add CHANGED comment when verbose is enabled", () => {
157
+ const input = `
158
+ import { Input } from "@planningcenter/tapestry-react"
159
+
160
+ function Test() {
161
+ return <Input highlightOnInteraction label="Name" />
162
+ }
163
+ `.trim()
164
+
165
+ const result = applyTransform(input, true)
166
+ expect(result).toContain("selectTextOnFocus")
167
+ expect(result).not.toContain("highlightOnInteraction=")
168
+ expect(result).toContain(
169
+ "CHANGED: tapestry-migration (selectTextOnFocus): renamed from highlightOnInteraction"
170
+ )
171
+ })
172
+
173
+ it("should not transform if not imported from @planningcenter/tapestry-react", () => {
174
+ const input = `
175
+ import { Input } from "other-library"
176
+
177
+ function Test() {
178
+ return <Input highlightOnInteraction label="Name" />
179
+ }
180
+ `.trim()
181
+
182
+ const result = applyTransform(input)
183
+ expect(result).toBe(input)
184
+ })
185
+ })
186
+ })
@@ -0,0 +1,27 @@
1
+ import { transformAttributeName } from "../../shared/actions/transformAttributeName"
2
+ import { andConditions } from "../../shared/conditions/andConditions"
3
+ import { hasAttribute } from "../../shared/conditions/hasAttribute"
4
+ import { attributeTransformFactory } from "../../shared/transformFactories/attributeTransformFactory"
5
+ import { transformableInput } from "../transformableInput"
6
+
7
+ const transform = attributeTransformFactory({
8
+ condition: andConditions(
9
+ hasAttribute("highlightOnInteraction"),
10
+ transformableInput
11
+ ),
12
+ targetComponent: "Input",
13
+ targetPackage: "@planningcenter/tapestry-react",
14
+ transform: (element, { j, options }) => {
15
+ return transformAttributeName(
16
+ "highlightOnInteraction",
17
+ "selectTextOnFocus",
18
+ {
19
+ element,
20
+ j,
21
+ options,
22
+ }
23
+ )
24
+ },
25
+ })
26
+
27
+ export default transform