@planningcenter/tapestry-migration-cli 2.3.0-rc.6 → 2.3.0-rc.8
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/dist/tapestry-react-shim.cjs +5064 -0
- package/package.json +9 -5
- package/src/components/button/index.ts +45 -3
- package/src/components/button/transforms/auditSpreadProps.test.ts +352 -0
- package/src/components/button/transforms/auditSpreadProps.ts +24 -0
- package/src/components/button/transforms/childrenToLabel.test.ts +363 -0
- package/src/components/button/transforms/childrenToLabel.ts +84 -0
- package/src/components/button/transforms/commentOnVisualKindDifference.ts +24 -0
- package/src/components/button/transforms/convertStyleProps.test.ts +464 -0
- package/src/components/button/transforms/convertStyleProps.ts +16 -0
- package/src/components/button/transforms/iconToIconButton.test.ts +377 -0
- package/src/components/button/transforms/iconToIconButton.ts +53 -0
- package/src/components/button/transforms/removeAsButton.ts +15 -0
- package/src/components/button/transforms/removeDuplicateKeys.test.ts +302 -0
- package/src/components/button/transforms/removeDuplicateKeys.ts +8 -0
- package/src/components/button/transforms/reviewStyles.ts +17 -0
- package/src/components/button/transforms/spinnerToLoadingButton.test.ts +165 -0
- package/src/components/button/transforms/spinnerToLoadingButton.ts +14 -0
- package/src/components/button/transforms/unsupportedProps.ts +73 -0
- package/src/components/shared/actions/addCommentToAttribute.test.ts +45 -0
- package/src/components/shared/actions/addCommentToAttribute.ts +28 -0
- package/src/components/shared/actions/addCommentToUnsupportedProps.ts +29 -0
- package/src/components/shared/actions/getSpreadProps.ts +7 -0
- package/src/components/shared/actions/hasSpreadProps.ts +7 -0
- package/src/components/shared/actions/removeChildren.ts +7 -0
- package/src/components/shared/actions/removeDuplicateKeys.test.ts +280 -0
- package/src/components/shared/actions/removeDuplicateKeys.ts +45 -0
- package/src/components/shared/actions/removeUnusedImport.test.ts +302 -0
- package/src/components/shared/actions/removeUnusedImport.ts +81 -0
- package/src/components/shared/actions/transformElementName.test.ts +9 -9
- package/src/components/shared/actions/transformElementName.ts +13 -16
- package/src/components/shared/conditions/hasChildren.ts +5 -0
- package/src/components/shared/getJavaScriptTheme.ts +68 -0
- package/src/components/shared/jsThemeLoader.ts +85 -0
- package/src/components/shared/transformFactories/attributeTransformFactory.ts +14 -6
- package/src/components/shared/transformFactories/componentTransformFactory.ts +1 -1
- package/src/components/shared/transformFactories/stylePropTransformFactory.ts +362 -0
- package/src/index.ts +4 -0
- package/src/stubs/stackViewPlugin.ts +33 -0
- package/src/stubs/tapestry-stub.ts +16 -0
- package/src/tapestry-react-shim.ts +7 -0
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Collection,
|
|
3
|
+
JSCodeshift,
|
|
4
|
+
JSXAttribute,
|
|
5
|
+
JSXElement,
|
|
6
|
+
Options,
|
|
7
|
+
Transform,
|
|
8
|
+
} from "jscodeshift"
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
defaultTheme,
|
|
12
|
+
splitStyles,
|
|
13
|
+
stylePropNames,
|
|
14
|
+
} from "../../../../dist/tapestry-react-shim.cjs"
|
|
15
|
+
import { addComment } from "../../shared/actions/addComment"
|
|
16
|
+
import { getAttribute } from "../../shared/actions/getAttribute"
|
|
17
|
+
import { removeAttribute } from "../../shared/actions/removeAttribute"
|
|
18
|
+
import { attributeTransformFactory } from "./attributeTransformFactory"
|
|
19
|
+
|
|
20
|
+
type StylePropMapping = Record<
|
|
21
|
+
string,
|
|
22
|
+
{
|
|
23
|
+
defaultMapping: string
|
|
24
|
+
specialValues?: Record<string, string>
|
|
25
|
+
}
|
|
26
|
+
>
|
|
27
|
+
|
|
28
|
+
// Helper function to extract prop value from JSX attribute
|
|
29
|
+
function extractPropValue(attr: JSXAttribute, j: JSCodeshift) {
|
|
30
|
+
if (!attr.value) {
|
|
31
|
+
// Boolean prop like <Button disabled />
|
|
32
|
+
return true
|
|
33
|
+
} else if (attr.value.type === "StringLiteral") {
|
|
34
|
+
// String literal like color="blue"
|
|
35
|
+
return attr.value.value
|
|
36
|
+
} else if (attr.value.type === "JSXExpressionContainer") {
|
|
37
|
+
// Expression like color={someVar} or color={5}
|
|
38
|
+
const expression = attr.value.expression
|
|
39
|
+
if (expression.type === "StringLiteral") {
|
|
40
|
+
return expression.value
|
|
41
|
+
} else if (expression.type === "NumericLiteral") {
|
|
42
|
+
return expression.value
|
|
43
|
+
} else if (expression.type === "BooleanLiteral") {
|
|
44
|
+
return expression.value
|
|
45
|
+
} else if (expression.type === "Identifier") {
|
|
46
|
+
// Variable reference - we'll use the variable name as a placeholder
|
|
47
|
+
return `{${expression.name}}`
|
|
48
|
+
} else {
|
|
49
|
+
// Complex expression - convert back to string representation
|
|
50
|
+
return `{${j(expression).toSource()}}`
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
// Fallback for other types
|
|
54
|
+
return j(attr.value).toSource()
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function processKeepStyleProps({
|
|
59
|
+
attributes,
|
|
60
|
+
j,
|
|
61
|
+
element,
|
|
62
|
+
source,
|
|
63
|
+
}: {
|
|
64
|
+
attributes: JSXAttribute[]
|
|
65
|
+
element: JSXElement
|
|
66
|
+
j: JSCodeshift
|
|
67
|
+
source: Collection
|
|
68
|
+
}): {
|
|
69
|
+
directProps: Record<string, unknown>
|
|
70
|
+
themeProps: Record<string, unknown>
|
|
71
|
+
} {
|
|
72
|
+
const themeProps: Record<string, unknown> = {}
|
|
73
|
+
const directProps: Record<string, unknown> = {}
|
|
74
|
+
|
|
75
|
+
attributes.forEach((attr) => {
|
|
76
|
+
const propName = attr.name.name as string
|
|
77
|
+
const propValue = extractPropValue(attr, j)
|
|
78
|
+
|
|
79
|
+
// If it's a complex expression (starts and ends with braces), handle it directly
|
|
80
|
+
if (
|
|
81
|
+
typeof propValue === "string" &&
|
|
82
|
+
propValue.startsWith("{") &&
|
|
83
|
+
propValue.endsWith("}")
|
|
84
|
+
) {
|
|
85
|
+
directProps[propName] = propValue
|
|
86
|
+
} else {
|
|
87
|
+
themeProps[propName] = propValue
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
removeAttribute(propName, { element, j, source })
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
return { directProps, themeProps }
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function processRemoveStyleProps({
|
|
97
|
+
j,
|
|
98
|
+
attributes,
|
|
99
|
+
source,
|
|
100
|
+
element,
|
|
101
|
+
}: {
|
|
102
|
+
attributes: JSXAttribute[]
|
|
103
|
+
element: JSXElement
|
|
104
|
+
j: JSCodeshift
|
|
105
|
+
source: Collection
|
|
106
|
+
}) {
|
|
107
|
+
attributes.forEach((attr) => {
|
|
108
|
+
const propName = attr.name.name as string
|
|
109
|
+
removeAttribute(propName, {
|
|
110
|
+
buildComment: (name, value) =>
|
|
111
|
+
`${name} has been removed as this is covered by default styling: ${name}: ${value}`,
|
|
112
|
+
element,
|
|
113
|
+
j,
|
|
114
|
+
source,
|
|
115
|
+
})
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Process props that need style property mappings
|
|
120
|
+
function processStylePropMappings({
|
|
121
|
+
attributes,
|
|
122
|
+
j,
|
|
123
|
+
element,
|
|
124
|
+
source,
|
|
125
|
+
stylePropMapping,
|
|
126
|
+
}: {
|
|
127
|
+
attributes: JSXAttribute[]
|
|
128
|
+
element: JSXElement
|
|
129
|
+
j: JSCodeshift
|
|
130
|
+
source: Collection
|
|
131
|
+
stylePropMapping: StylePropMapping
|
|
132
|
+
}): Record<string, unknown> {
|
|
133
|
+
const styleProps: Record<string, unknown> = {}
|
|
134
|
+
|
|
135
|
+
attributes.forEach((attr) => {
|
|
136
|
+
const propName = attr.name.name as string
|
|
137
|
+
if (propName in stylePropMapping) {
|
|
138
|
+
const propValue = extractPropValue(attr, j)
|
|
139
|
+
const mappingConfig =
|
|
140
|
+
stylePropMapping[propName as keyof typeof stylePropMapping]
|
|
141
|
+
|
|
142
|
+
if (
|
|
143
|
+
mappingConfig.specialValues &&
|
|
144
|
+
typeof propValue === "string" &&
|
|
145
|
+
propValue in mappingConfig.specialValues
|
|
146
|
+
) {
|
|
147
|
+
const specialAction =
|
|
148
|
+
mappingConfig.specialValues[
|
|
149
|
+
propValue as keyof typeof mappingConfig.specialValues
|
|
150
|
+
]
|
|
151
|
+
|
|
152
|
+
if (specialAction === "AUDIT") {
|
|
153
|
+
const text = `${propName}="${propValue}" needs manual review for replacement`
|
|
154
|
+
addComment({ element, j, scope: "styleProp", source, text })
|
|
155
|
+
}
|
|
156
|
+
// Future: could support other special actions here
|
|
157
|
+
} else {
|
|
158
|
+
const mappedPropName = mappingConfig.defaultMapping
|
|
159
|
+
styleProps[mappedPropName] = propValue
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
removeAttribute(propName, { element, j, source })
|
|
163
|
+
}
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
return styleProps
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function applyStylesToComponent({
|
|
170
|
+
j,
|
|
171
|
+
element,
|
|
172
|
+
styles,
|
|
173
|
+
}: {
|
|
174
|
+
element: JSXElement
|
|
175
|
+
j: JSCodeshift
|
|
176
|
+
styles: Record<string, unknown>
|
|
177
|
+
}) {
|
|
178
|
+
const styleAttr = getAttribute({ element, name: "style" })
|
|
179
|
+
const styleValue = j.jsxExpressionContainer(
|
|
180
|
+
j.objectExpression(
|
|
181
|
+
Object.entries(styles).map(([key, value]) => {
|
|
182
|
+
let valueNode
|
|
183
|
+
if (
|
|
184
|
+
typeof value === "string" &&
|
|
185
|
+
value.startsWith("{") &&
|
|
186
|
+
value.endsWith("}")
|
|
187
|
+
) {
|
|
188
|
+
// This is a complex expression wrapped in braces - parse it as JS
|
|
189
|
+
const expressionCode = value.slice(1, -1) // Remove surrounding braces
|
|
190
|
+
try {
|
|
191
|
+
const parsed = j(expressionCode)
|
|
192
|
+
// Get the first expression from the program body
|
|
193
|
+
const firstStatement = parsed.find(j.Program).get("body", 0).value
|
|
194
|
+
if (firstStatement?.type === "ExpressionStatement") {
|
|
195
|
+
valueNode = firstStatement.expression
|
|
196
|
+
} else {
|
|
197
|
+
valueNode = j.stringLiteral(value)
|
|
198
|
+
}
|
|
199
|
+
} catch {
|
|
200
|
+
// If parsing fails, fall back to string literal
|
|
201
|
+
valueNode = j.stringLiteral(value)
|
|
202
|
+
}
|
|
203
|
+
} else if (typeof value === "string") {
|
|
204
|
+
valueNode = j.stringLiteral(value)
|
|
205
|
+
} else {
|
|
206
|
+
valueNode = j.literal(value as string | number | boolean | null)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return j.objectProperty(j.identifier(key), valueNode)
|
|
210
|
+
})
|
|
211
|
+
)
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
if (styleAttr && styleAttr.type === "JSXAttribute") {
|
|
215
|
+
// TODO: ensure this adds to exisiting style object rather than replacing
|
|
216
|
+
styleAttr.value = styleValue
|
|
217
|
+
} else {
|
|
218
|
+
const styleAttr = j.jsxAttribute(j.jsxIdentifier("style"), styleValue)
|
|
219
|
+
|
|
220
|
+
element.openingElement.attributes = element.openingElement.attributes || []
|
|
221
|
+
element.openingElement.attributes.push(styleAttr)
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export function stylePropTransformFactory(config: {
|
|
226
|
+
plugin?: {
|
|
227
|
+
getStyles: (props: Record<string, unknown>) => Record<string, unknown>
|
|
228
|
+
styleProps: string[]
|
|
229
|
+
}
|
|
230
|
+
stylePropMapping?: StylePropMapping
|
|
231
|
+
stylesToKeep?: string[]
|
|
232
|
+
stylesToRemove: string[]
|
|
233
|
+
targetComponent: string
|
|
234
|
+
targetPackage: string
|
|
235
|
+
}): Transform {
|
|
236
|
+
const {
|
|
237
|
+
stylePropMapping = {} as StylePropMapping,
|
|
238
|
+
stylesToKeep = [],
|
|
239
|
+
stylesToRemove,
|
|
240
|
+
} = config
|
|
241
|
+
const transform: (
|
|
242
|
+
element: JSXElement,
|
|
243
|
+
resources: { j: JSCodeshift; options: Options; source: Collection }
|
|
244
|
+
) => boolean = (element, { j, options, source }) => {
|
|
245
|
+
const allAttributes = element.openingElement.attributes || []
|
|
246
|
+
let allStyleProps: Record<string, unknown> = {}
|
|
247
|
+
let directStyleProps: Record<string, unknown> = {}
|
|
248
|
+
const attributes = allAttributes.filter((attr) => {
|
|
249
|
+
if (attr.type !== "JSXAttribute") return false
|
|
250
|
+
const name = attr.name?.name as string
|
|
251
|
+
return (
|
|
252
|
+
name &&
|
|
253
|
+
(stylePropNames.includes(name) ||
|
|
254
|
+
name in stylePropMapping ||
|
|
255
|
+
stylesToKeep.includes(name) ||
|
|
256
|
+
stylesToRemove.includes(name) ||
|
|
257
|
+
(config.plugin?.styleProps.includes(name) ?? false))
|
|
258
|
+
)
|
|
259
|
+
}) as JSXAttribute[]
|
|
260
|
+
|
|
261
|
+
const keepAttributes = attributes.filter(
|
|
262
|
+
(attr) =>
|
|
263
|
+
!stylesToRemove.includes(attr.name.name as string) &&
|
|
264
|
+
!((attr.name.name as string) in stylePropMapping)
|
|
265
|
+
)
|
|
266
|
+
const keepResult = processKeepStyleProps({
|
|
267
|
+
attributes: keepAttributes,
|
|
268
|
+
element,
|
|
269
|
+
j,
|
|
270
|
+
source,
|
|
271
|
+
})
|
|
272
|
+
allStyleProps = {
|
|
273
|
+
...allStyleProps,
|
|
274
|
+
...keepResult.themeProps,
|
|
275
|
+
}
|
|
276
|
+
directStyleProps = {
|
|
277
|
+
...directStyleProps,
|
|
278
|
+
...keepResult.directProps,
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
allStyleProps = {
|
|
282
|
+
...allStyleProps,
|
|
283
|
+
...processStylePropMappings({
|
|
284
|
+
attributes,
|
|
285
|
+
element,
|
|
286
|
+
j,
|
|
287
|
+
source,
|
|
288
|
+
stylePropMapping,
|
|
289
|
+
}),
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const removeAttributes = attributes.filter((attr) =>
|
|
293
|
+
stylesToRemove.includes(attr.name.name as string)
|
|
294
|
+
)
|
|
295
|
+
processRemoveStyleProps({
|
|
296
|
+
attributes: removeAttributes,
|
|
297
|
+
element,
|
|
298
|
+
j,
|
|
299
|
+
source,
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
// Convert collected style props to CSS if any exist
|
|
303
|
+
if (
|
|
304
|
+
Object.keys(allStyleProps).length > 0 ||
|
|
305
|
+
Object.keys(directStyleProps).length > 0
|
|
306
|
+
) {
|
|
307
|
+
try {
|
|
308
|
+
let styles: Record<string, unknown> = {}
|
|
309
|
+
|
|
310
|
+
// Process theme props through the theme system
|
|
311
|
+
if (Object.keys(allStyleProps).length > 0) {
|
|
312
|
+
const result = splitStyles({
|
|
313
|
+
...allStyleProps,
|
|
314
|
+
plugin: config.plugin,
|
|
315
|
+
})
|
|
316
|
+
const cssObject = result.css(defaultTheme)
|
|
317
|
+
styles = { ...styles, ...(cssObject[0] || {}) }
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Add direct props without theme processing
|
|
321
|
+
styles = { ...styles, ...directStyleProps }
|
|
322
|
+
if (options.verbose) console.log("Final generated styles:", styles)
|
|
323
|
+
|
|
324
|
+
// Apply the styles to the component
|
|
325
|
+
applyStylesToComponent({ element, j, styles })
|
|
326
|
+
} catch (error) {
|
|
327
|
+
console.log("Error processing style props:", error)
|
|
328
|
+
console.log("Style props that caused error:", allStyleProps)
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Add new attributes from replacements and mappings
|
|
333
|
+
// const allNewAttributes = [...mappingResult.newAttributes]
|
|
334
|
+
// if (allNewAttributes.length > 0) {
|
|
335
|
+
// path.value.attributes = path.value.attributes || []
|
|
336
|
+
// path.value.attributes.push(...allNewAttributes)
|
|
337
|
+
// hasChanges = true
|
|
338
|
+
// }
|
|
339
|
+
|
|
340
|
+
// Check for unhandled style props before removing processed attributes
|
|
341
|
+
// const mappingPropNames = Object.keys(STYLE_PROP_MAPPINGS)
|
|
342
|
+
// processUnhandledProps(
|
|
343
|
+
// j,
|
|
344
|
+
// path,
|
|
345
|
+
// attributes,
|
|
346
|
+
// KEEP_STYLE_PROPS,
|
|
347
|
+
// REMOVE_STYLE_PROPS,
|
|
348
|
+
// mappingPropNames,
|
|
349
|
+
// stylePropNames,
|
|
350
|
+
// options,
|
|
351
|
+
// fileInfo
|
|
352
|
+
// )
|
|
353
|
+
|
|
354
|
+
return attributes.length + removeAttributes.length > 0
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return attributeTransformFactory({
|
|
358
|
+
targetComponent: config.targetComponent,
|
|
359
|
+
targetPackage: config.targetPackage,
|
|
360
|
+
transform,
|
|
361
|
+
})
|
|
362
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -19,6 +19,10 @@ program
|
|
|
19
19
|
.option("-f, --fix", "Write the changes")
|
|
20
20
|
.option("-p, --path <path>", "The path to the folder/file to migrate")
|
|
21
21
|
.option("-v, --verbose", "Verbose output")
|
|
22
|
+
.option(
|
|
23
|
+
"-j, --js-theme <path>",
|
|
24
|
+
"Path to JavaScript theme file containing design tokens"
|
|
25
|
+
)
|
|
22
26
|
.action((componentName, options) => {
|
|
23
27
|
console.log("Hello from Tapestry Migration CLI! 🎨")
|
|
24
28
|
console.log(`Component: ${componentName}`)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// copied from packages/tapestry-react/src/StackView/StackView.tsx in tapestry-react
|
|
2
|
+
|
|
3
|
+
function spacingValue(value: string | number): string {
|
|
4
|
+
return typeof value === "number" ? value * 8 + "px" : value
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const stackViewPlugin = {
|
|
8
|
+
getStyles({
|
|
9
|
+
inline,
|
|
10
|
+
alignment,
|
|
11
|
+
axis,
|
|
12
|
+
distribution,
|
|
13
|
+
spacing,
|
|
14
|
+
...styles
|
|
15
|
+
}: Record<string, unknown>) {
|
|
16
|
+
if (axis && styles.flexDirection === undefined) {
|
|
17
|
+
styles.flexDirection = axis === "horizontal" ? "row" : "column"
|
|
18
|
+
}
|
|
19
|
+
if (alignment && styles.alignItems === undefined) {
|
|
20
|
+
styles.alignItems = alignment
|
|
21
|
+
}
|
|
22
|
+
if (distribution === "fill") {
|
|
23
|
+
styles["& > *"] = { flex: "1 0 0px" }
|
|
24
|
+
} else if (styles.justifyContent === undefined) {
|
|
25
|
+
styles.justifyContent = distribution
|
|
26
|
+
}
|
|
27
|
+
if (typeof spacing === "number" || typeof spacing === "string") {
|
|
28
|
+
styles.gap = spacingValue(spacing)
|
|
29
|
+
}
|
|
30
|
+
return styles
|
|
31
|
+
},
|
|
32
|
+
styleProps: ["alignment", "axis", "distribution", "spacing"],
|
|
33
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { Button } from "../../../../node_modules/@planningcenter/tapestry/dist/components/button/Button"
|
|
2
|
+
export { DropdownButton } from "../../../../node_modules/@planningcenter/tapestry/dist/components/button/DropdownButton"
|
|
3
|
+
export { DropdownIconButton } from "../../../../node_modules/@planningcenter/tapestry/dist/components/button/DropdownIconButton"
|
|
4
|
+
export { IconButton } from "../../../../node_modules/@planningcenter/tapestry/dist/components/button/IconButton"
|
|
5
|
+
export { LoadingButton } from "../../../../node_modules/@planningcenter/tapestry/dist/components/button/LoadingButton"
|
|
6
|
+
export { PageHeaderActionsDropdownButton } from "../../../../node_modules/@planningcenter/tapestry/dist/components/button/PageHeaderActionsDropdownButton"
|
|
7
|
+
export { IconLink } from "../../../../node_modules/@planningcenter/tapestry/dist/components/link/IconLink"
|
|
8
|
+
export { Link } from "../../../../node_modules/@planningcenter/tapestry/dist/components/link/Link"
|
|
9
|
+
export { PageHeader } from "../../../../node_modules/@planningcenter/tapestry/dist/components/page-header/PageHeader"
|
|
10
|
+
export { Sidenav } from "../../../../node_modules/@planningcenter/tapestry/dist/components/sidenav/Sidenav"
|
|
11
|
+
export { SidenavItem } from "../../../../node_modules/@planningcenter/tapestry/dist/components/sidenav/SidenavItem"
|
|
12
|
+
export { SidenavSection } from "../../../../node_modules/@planningcenter/tapestry/dist/components/sidenav/SidenavSection"
|
|
13
|
+
export {
|
|
14
|
+
computedToken,
|
|
15
|
+
token,
|
|
16
|
+
} from "../../../../node_modules/@planningcenter/tapestry/dist/jsTokens"
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Import the real utilities from tapestry-react (Stencil parts will be stubbed by Vite aliases)
|
|
2
|
+
// Use absolute file paths since the package doesn't export subpaths
|
|
3
|
+
import defaultTheme from "../../../node_modules/@planningcenter/tapestry-react/dist/system/default-theme.js"
|
|
4
|
+
import splitStyles from "../../../node_modules/@planningcenter/tapestry-react/dist/system/split-styles.js"
|
|
5
|
+
import { stylePropNames } from "../../../node_modules/@planningcenter/tapestry-react/dist/system/style-names.js"
|
|
6
|
+
|
|
7
|
+
export { defaultTheme, splitStyles, stylePropNames }
|