@litsx/babel-preset-litsx 0.2.1 → 0.4.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.
@@ -8,7 +8,7 @@ function createThisMemberExpression(propName) {
8
8
  return t.memberExpression(t.thisExpression(), t.identifier(propName));
9
9
  }
10
10
 
11
- export function transformJSXExpressions(jsxPath, bindings) {
11
+ export function transformJSXExpressions(jsxPath, bindings, state = null) {
12
12
  const localNames = Array.from(bindings.keys());
13
13
 
14
14
  jsxPath.traverse({
@@ -22,6 +22,15 @@ function createLitsxInfrastructureImport(importedName) {
22
22
  );
23
23
  }
24
24
 
25
+ function createLitsxInternalRuntimeImport(importedName) {
26
+ return t.importDeclaration(
27
+ [
28
+ t.importSpecifier(t.identifier(importedName), t.identifier(importedName)),
29
+ ],
30
+ t.stringLiteral("@litsx/litsx/internal/runtime-render-context")
31
+ );
32
+ }
33
+
25
34
  function createLitsxImport(importedName) {
26
35
  return t.importDeclaration(
27
36
  [
@@ -225,5 +234,28 @@ export function finalizeProgram(programPath, state) {
225
234
  }
226
235
  }
227
236
 
237
+ if (state.__litsxNeedsRendererCallImport) {
238
+ const bodyPathsWithInternalRuntime = programPath.get("body");
239
+ const internalRuntimeImports = bodyPathsWithInternalRuntime.filter(
240
+ (n) =>
241
+ n.isImportDeclaration() &&
242
+ n.node.source.value === "@litsx/litsx/internal/runtime-render-context"
243
+ );
244
+
245
+ let internalRuntimeImported = false;
246
+ internalRuntimeImports.some((importPath) => {
247
+ if (ensureNamedImport(importPath, "renderRendererCall")) {
248
+ internalRuntimeImported = true;
249
+ return true;
250
+ }
251
+
252
+ return false;
253
+ });
254
+
255
+ if (!internalRuntimeImported) {
256
+ programPath.unshiftContainer("body", createLitsxInternalRuntimeImport("renderRendererCall"));
257
+ }
258
+ }
259
+
228
260
  pruneUnusedLitsxStaticImports(programPath);
229
261
  }
@@ -0,0 +1,113 @@
1
+ import {
2
+ createComponentInstanceRefSyncStatement,
3
+ hasRefProp,
4
+ lowerForwardedElementRefs,
5
+ } from "./transform-litsx-refs.js";
6
+ import {
7
+ replaceParamReferences,
8
+ transformJSXExpressions,
9
+ } from "./transform-litsx-param-rewrites.js";
10
+ import { transformJSXRendererCalls } from "./transform-litsx-renderer-calls.js";
11
+
12
+ let t;
13
+
14
+ export function setRenderBodyBabelTypes(nextTypes) {
15
+ t = nextTypes;
16
+ }
17
+
18
+ function createThisMemberExpression(propName) {
19
+ return t.memberExpression(t.thisExpression(), t.identifier(propName));
20
+ }
21
+
22
+ function createNestedInitializerStatement(pattern, root, defaultValue) {
23
+ const rootAccess = createThisMemberExpression(root);
24
+ let sourceExpression = rootAccess;
25
+
26
+ if (defaultValue) {
27
+ sourceExpression = t.logicalExpression(
28
+ "??",
29
+ t.cloneNode(rootAccess),
30
+ t.cloneNode(defaultValue)
31
+ );
32
+ }
33
+
34
+ return t.variableDeclaration("const", [
35
+ t.variableDeclarator(t.cloneNode(pattern), sourceExpression),
36
+ ]);
37
+ }
38
+
39
+ function collectReturnStatement(functionPath, bindings, state) {
40
+ let returnStatement = null;
41
+
42
+ functionPath.traverse({
43
+ ReturnStatement(returnPath) {
44
+ if (t.isJSXElement(returnPath.node.argument)) {
45
+ returnStatement = returnPath.node;
46
+ transformJSXRendererCalls(returnPath, bindings, state);
47
+ transformJSXExpressions(returnPath, bindings, state);
48
+ }
49
+ },
50
+ });
51
+
52
+ return returnStatement;
53
+ }
54
+
55
+ export function prepareComponentRender(functionPath, node, propertyNames, bindings, nestedInitializers, options = {}) {
56
+ const returnStatement = collectReturnStatement(
57
+ functionPath,
58
+ bindings,
59
+ options.state ?? null
60
+ );
61
+
62
+ if (!returnStatement) {
63
+ return null;
64
+ }
65
+
66
+ const capturedPropAliasStatements = replaceParamReferences(
67
+ functionPath,
68
+ bindings,
69
+ propertyNames
70
+ );
71
+ const prefixStatements = [];
72
+
73
+ const forwardRefOptions = options.forwardRef || null;
74
+ const resolvedRefPropName =
75
+ forwardRefOptions?.propName ||
76
+ (propertyNames.has("ref") || hasRefProp(functionPath) ? "ref" : null);
77
+ let needsCallbackRef = false;
78
+
79
+ if (resolvedRefPropName) {
80
+ prefixStatements.push(
81
+ ...lowerForwardedElementRefs(functionPath, resolvedRefPropName)
82
+ );
83
+ needsCallbackRef =
84
+ prefixStatements.some(
85
+ (statement) =>
86
+ t.isExpressionStatement(statement) &&
87
+ t.isCallExpression(statement.expression) &&
88
+ t.isIdentifier(statement.expression.callee, { name: "useCallbackRef" })
89
+ ) || needsCallbackRef;
90
+ }
91
+
92
+ if (resolvedRefPropName && !forwardRefOptions) {
93
+ prefixStatements.push(createComponentInstanceRefSyncStatement());
94
+ needsCallbackRef = true;
95
+ }
96
+
97
+ if (capturedPropAliasStatements.length > 0) {
98
+ prefixStatements.push(...capturedPropAliasStatements);
99
+ }
100
+
101
+ if (nestedInitializers.length > 0) {
102
+ const initializerStatements = nestedInitializers.map(({ pattern, root, defaultValue }) =>
103
+ createNestedInitializerStatement(pattern, root, defaultValue)
104
+ );
105
+ prefixStatements.push(...initializerStatements);
106
+ }
107
+
108
+ return {
109
+ needsCallbackRef,
110
+ prefixStatements,
111
+ returnStatement,
112
+ };
113
+ }
@@ -0,0 +1,92 @@
1
+ let t;
2
+
3
+ export function setRendererCallsBabelTypes(nextTypes) {
4
+ t = nextTypes;
5
+ }
6
+
7
+ function createThisMemberExpression(propName) {
8
+ return t.memberExpression(t.thisExpression(), t.identifier(propName));
9
+ }
10
+
11
+ function getBoundPropName(bindingInfo) {
12
+ if (typeof bindingInfo === "string") {
13
+ return bindingInfo;
14
+ }
15
+
16
+ if (bindingInfo && typeof bindingInfo === "object") {
17
+ return bindingInfo.bindKey ?? null;
18
+ }
19
+
20
+ return null;
21
+ }
22
+
23
+ function isPropBackedCallee(node, localNames) {
24
+ if (t.isIdentifier(node)) {
25
+ return localNames.includes(node.name);
26
+ }
27
+
28
+ if (
29
+ t.isMemberExpression(node) &&
30
+ !node.computed &&
31
+ t.isIdentifier(node.object)
32
+ ) {
33
+ return localNames.includes(node.object.name) && node.object.name === "props";
34
+ }
35
+
36
+ return false;
37
+ }
38
+
39
+ function getPropBackedCalleeReplacement(node, bindings) {
40
+ if (t.isIdentifier(node)) {
41
+ const propName = getBoundPropName(bindings.get(node.name));
42
+ return propName ? createThisMemberExpression(propName) : node;
43
+ }
44
+
45
+ if (
46
+ t.isMemberExpression(node) &&
47
+ !node.computed &&
48
+ t.isIdentifier(node.object)
49
+ ) {
50
+ const propName = getBoundPropName(bindings.get(node.object.name));
51
+ if (!propName) {
52
+ return node;
53
+ }
54
+
55
+ return t.memberExpression(
56
+ createThisMemberExpression(propName),
57
+ t.cloneNode(node.property),
58
+ false
59
+ );
60
+ }
61
+
62
+ return node;
63
+ }
64
+
65
+ export function transformJSXRendererCalls(jsxPath, bindings, state = null) {
66
+ const localNames = Array.from(bindings.keys());
67
+
68
+ jsxPath.traverse({
69
+ JSXExpressionContainer(expressionPath) {
70
+ if (!t.isCallExpression(expressionPath.node.expression)) {
71
+ return;
72
+ }
73
+
74
+ const { callee, arguments: args } = expressionPath.node.expression;
75
+ if (!isPropBackedCallee(callee, localNames)) {
76
+ return;
77
+ }
78
+
79
+ if (state) {
80
+ state.__litsxNeedsRendererCallImport = true;
81
+ }
82
+
83
+ expressionPath.node.expression = t.callExpression(
84
+ t.identifier("renderRendererCall"),
85
+ [
86
+ getPropBackedCalleeReplacement(callee, bindings),
87
+ ...args,
88
+ ]
89
+ );
90
+ },
91
+ });
92
+ }
@@ -0,0 +1,368 @@
1
+ import jsxSyntaxPlugin from "@babel/plugin-syntax-jsx";
2
+ import { decodeVirtualAttributeName } from "@litsx/jsx-authoring";
3
+ import { importedBindingNeedsRendererContext } from "./transform-litsx-element-candidates.js";
4
+
5
+ let t;
6
+
7
+ function createHostReferenceExpression() {
8
+ return t.conditionalExpression(
9
+ t.binaryExpression(
10
+ "===",
11
+ t.unaryExpression("typeof", t.thisExpression(), true),
12
+ t.stringLiteral("undefined")
13
+ ),
14
+ t.nullLiteral(),
15
+ t.thisExpression()
16
+ );
17
+ }
18
+
19
+ function stringifyJsxName(nameNode) {
20
+ if (t.isJSXIdentifier(nameNode)) {
21
+ return nameNode.name;
22
+ }
23
+
24
+ if (t.isJSXMemberExpression(nameNode)) {
25
+ return `${stringifyJsxName(nameNode.object)}.${nameNode.property.name}`;
26
+ }
27
+
28
+ if (t.isJSXNamespacedName(nameNode)) {
29
+ return `${nameNode.namespace.name}:${nameNode.name.name}`;
30
+ }
31
+
32
+ return "unknown";
33
+ }
34
+
35
+ function getTag(node) {
36
+ const name = stringifyJsxName(node.name);
37
+ const isCapitalized =
38
+ name.charAt(0) === name.charAt(0).toUpperCase() &&
39
+ name.charAt(0) !== name.charAt(0).toLowerCase();
40
+ const isComponent =
41
+ node.name.type !== "JSXIdentifier" || isCapitalized || name.includes("-");
42
+ return { name, isComponent };
43
+ }
44
+
45
+ function unwrapExpression(node) {
46
+ let current = node;
47
+
48
+ while (current) {
49
+ if (t.isParenthesizedExpression?.(current)) {
50
+ current = current.expression;
51
+ continue;
52
+ }
53
+
54
+ if (
55
+ t.isTSAsExpression?.(current) ||
56
+ t.isTSSatisfiesExpression?.(current) ||
57
+ t.isTypeCastExpression?.(current) ||
58
+ t.isTSNonNullExpression?.(current)
59
+ ) {
60
+ current = current.expression;
61
+ continue;
62
+ }
63
+
64
+ break;
65
+ }
66
+
67
+ return current;
68
+ }
69
+
70
+ function getFunctionNodeFromBinding(binding) {
71
+ if (!binding?.path) {
72
+ return null;
73
+ }
74
+
75
+ if (binding.path.isFunctionDeclaration()) {
76
+ return binding.path.node;
77
+ }
78
+
79
+ if (binding.path.isVariableDeclarator()) {
80
+ const init = unwrapExpression(binding.path.node.init);
81
+ if (t.isArrowFunctionExpression(init) || t.isFunctionExpression(init)) {
82
+ return init;
83
+ }
84
+ }
85
+
86
+ return null;
87
+ }
88
+
89
+ function mergeBooleanResults(results) {
90
+ return results.some(Boolean);
91
+ }
92
+
93
+ function jsxTreeNeedsRendererContext(node, scope, seenBindings = new Set()) {
94
+ if (!node) {
95
+ return false;
96
+ }
97
+
98
+ if (t.isJSXFragment(node)) {
99
+ return mergeBooleanResults(
100
+ node.children.map((child) => jsxChildNeedsRendererContext(child, scope, seenBindings))
101
+ );
102
+ }
103
+
104
+ if (!t.isJSXElement(node)) {
105
+ return false;
106
+ }
107
+
108
+ const { isComponent } = getTag(node.openingElement);
109
+ if (isComponent) {
110
+ return true;
111
+ }
112
+
113
+ const childNeedsContext = mergeBooleanResults(
114
+ node.children.map((child) => jsxChildNeedsRendererContext(child, scope, seenBindings))
115
+ );
116
+
117
+ if (childNeedsContext) {
118
+ return true;
119
+ }
120
+
121
+ return mergeBooleanResults(
122
+ node.openingElement.attributes.map((attr) => {
123
+ if (!t.isJSXAttribute(attr) || !t.isJSXExpressionContainer(attr.value)) {
124
+ return false;
125
+ }
126
+ return expressionNeedsRendererContext(attr.value.expression, scope, seenBindings);
127
+ })
128
+ );
129
+ }
130
+
131
+ function jsxChildNeedsRendererContext(child, scope, seenBindings) {
132
+ if (t.isJSXElement(child) || t.isJSXFragment(child)) {
133
+ return jsxTreeNeedsRendererContext(child, scope, seenBindings);
134
+ }
135
+
136
+ if (t.isJSXExpressionContainer(child)) {
137
+ return expressionNeedsRendererContext(child.expression, scope, seenBindings);
138
+ }
139
+
140
+ return false;
141
+ }
142
+
143
+ function functionBodyNeedsRendererContext(body, scope, seenBindings = new Set()) {
144
+ if (!body) {
145
+ return false;
146
+ }
147
+
148
+ if (t.isBlockStatement(body)) {
149
+ return mergeBooleanResults(
150
+ body.body.map((statement) => statementNeedsRendererContext(statement, scope, seenBindings))
151
+ );
152
+ }
153
+
154
+ return expressionNeedsRendererContext(body, scope, seenBindings);
155
+ }
156
+
157
+ function statementNeedsRendererContext(statement, scope, seenBindings) {
158
+ if (t.isReturnStatement(statement)) {
159
+ return expressionNeedsRendererContext(statement.argument, scope, seenBindings);
160
+ }
161
+
162
+ if (t.isIfStatement(statement)) {
163
+ return mergeBooleanResults([
164
+ statementNeedsRendererContext(statement.consequent, scope, seenBindings),
165
+ statement.alternate
166
+ ? statementNeedsRendererContext(statement.alternate, scope, seenBindings)
167
+ : false,
168
+ ]);
169
+ }
170
+
171
+ if (t.isBlockStatement(statement)) {
172
+ return functionBodyNeedsRendererContext(statement, scope, seenBindings);
173
+ }
174
+
175
+ return false;
176
+ }
177
+
178
+ function callExpressionNeedsRendererContext(node, scope, seenBindings) {
179
+ const callee = unwrapExpression(node.callee);
180
+ if (!t.isIdentifier(callee)) {
181
+ return false;
182
+ }
183
+
184
+ const binding = scope.getBinding(callee.name);
185
+ const functionNode = getFunctionNodeFromBinding(binding);
186
+ if (!functionNode) {
187
+ return false;
188
+ }
189
+
190
+ if (seenBindings.has(binding)) {
191
+ return false;
192
+ }
193
+
194
+ const nextSeenBindings = new Set(seenBindings);
195
+ nextSeenBindings.add(binding);
196
+ return functionBodyNeedsRendererContext(functionNode.body, binding.path.scope, nextSeenBindings);
197
+ }
198
+
199
+ function expressionNeedsRendererContext(node, scope, seenBindings = new Set()) {
200
+ const expression = unwrapExpression(node);
201
+ if (!expression) {
202
+ return false;
203
+ }
204
+
205
+ if (t.isJSXElement(expression) || t.isJSXFragment(expression)) {
206
+ return jsxTreeNeedsRendererContext(expression, scope, seenBindings);
207
+ }
208
+
209
+ if (t.isConditionalExpression(expression)) {
210
+ return mergeBooleanResults([
211
+ expressionNeedsRendererContext(expression.consequent, scope, seenBindings),
212
+ expressionNeedsRendererContext(expression.alternate, scope, seenBindings),
213
+ ]);
214
+ }
215
+
216
+ if (t.isLogicalExpression(expression)) {
217
+ return mergeBooleanResults([
218
+ expressionNeedsRendererContext(expression.left, scope, seenBindings),
219
+ expressionNeedsRendererContext(expression.right, scope, seenBindings),
220
+ ]);
221
+ }
222
+
223
+ if (t.isSequenceExpression(expression)) {
224
+ return mergeBooleanResults(
225
+ expression.expressions.map((part) => expressionNeedsRendererContext(part, scope, seenBindings))
226
+ );
227
+ }
228
+
229
+ if (t.isArrayExpression(expression)) {
230
+ return mergeBooleanResults(
231
+ expression.elements.filter(Boolean).map((part) => expressionNeedsRendererContext(part, scope, seenBindings))
232
+ );
233
+ }
234
+
235
+ if (t.isCallExpression(expression)) {
236
+ return callExpressionNeedsRendererContext(expression, scope, seenBindings);
237
+ }
238
+
239
+ return false;
240
+ }
241
+
242
+ function isBindableFunctionReference(expressionPath, options = {}) {
243
+ const expression = unwrapExpression(expressionPath.node);
244
+ if (
245
+ t.isArrowFunctionExpression(expression) ||
246
+ t.isFunctionExpression(expression)
247
+ ) {
248
+ return functionBodyNeedsRendererContext(expression.body, expressionPath.scope);
249
+ }
250
+
251
+ if (t.isIdentifier(expression)) {
252
+ const binding = expressionPath.scope.getBinding(expression.name);
253
+ const functionNode = getFunctionNodeFromBinding(binding);
254
+ if (!functionNode) {
255
+ const programPath = expressionPath.findParent((entry) => entry.isProgram?.());
256
+ return importedBindingNeedsRendererContext(
257
+ programPath,
258
+ expression.name,
259
+ options
260
+ );
261
+ }
262
+ return functionBodyNeedsRendererContext(functionNode.body, binding.path.scope, new Set([binding]));
263
+ }
264
+
265
+ return false;
266
+ }
267
+
268
+ function shouldBindRendererContext(attributePath, rawName, expressionPath, options = {}) {
269
+ if (typeof rawName !== "string" || rawName[0] !== ".") {
270
+ return false;
271
+ }
272
+
273
+ const openingElement = attributePath.parentPath;
274
+ if (!openingElement?.isJSXOpeningElement()) {
275
+ return false;
276
+ }
277
+
278
+ const { isComponent } = getTag(openingElement.node);
279
+ if (!isComponent) {
280
+ return false;
281
+ }
282
+
283
+ return isBindableFunctionReference(expressionPath, options);
284
+ }
285
+
286
+ function ensureRendererBindingImport(programPath) {
287
+ const bodyPaths = programPath.get("body");
288
+ const runtimeImports = bodyPaths.filter(
289
+ (path) =>
290
+ path.isImportDeclaration() &&
291
+ path.node.source.value === "@litsx/litsx/internal/runtime-render-context"
292
+ );
293
+
294
+ const importSpecifier = t.importSpecifier(
295
+ t.identifier("bindRendererContext"),
296
+ t.identifier("bindRendererContext")
297
+ );
298
+
299
+ for (const importPath of runtimeImports) {
300
+ const { specifiers } = importPath.node;
301
+ const hasImport = specifiers.some(
302
+ (specifier) =>
303
+ t.isImportSpecifier(specifier) &&
304
+ t.isIdentifier(specifier.imported, { name: "bindRendererContext" })
305
+ );
306
+
307
+ if (hasImport) {
308
+ return;
309
+ }
310
+
311
+ specifiers.push(importSpecifier);
312
+ return;
313
+ }
314
+
315
+ programPath.unshiftContainer("body", t.importDeclaration(
316
+ [importSpecifier],
317
+ t.stringLiteral("@litsx/litsx/internal/runtime-render-context")
318
+ ));
319
+ }
320
+
321
+ export default function transformLitsxRendererProps(api) {
322
+ api.assertVersion?.(7);
323
+ t = api.types;
324
+
325
+ return {
326
+ name: "transform-litsx-renderer-props",
327
+ inherits: jsxSyntaxPlugin.default || jsxSyntaxPlugin,
328
+ visitor: {
329
+ Program: {
330
+ enter(_, state) {
331
+ state.__litsxNeedsRendererBindingImport = false;
332
+ },
333
+ exit(programPath, state) {
334
+ if (state.__litsxNeedsRendererBindingImport) {
335
+ ensureRendererBindingImport(programPath);
336
+ }
337
+ },
338
+ },
339
+ JSXAttribute(path, state) {
340
+ const { node } = path;
341
+ if (node.value?.type !== "JSXExpressionContainer") {
342
+ return;
343
+ }
344
+
345
+ const rawName = decodeVirtualAttributeName(node.name.name) ?? node.name.name;
346
+ const expressionPath = path.get("value.expression");
347
+ if (!expressionPath?.node) {
348
+ return;
349
+ }
350
+
351
+ if (!shouldBindRendererContext(path, rawName, expressionPath, {
352
+ filename: state.file?.opts?.filename || "",
353
+ })) {
354
+ return;
355
+ }
356
+
357
+ state.__litsxNeedsRendererBindingImport = true;
358
+ node.value.expression = t.callExpression(
359
+ t.identifier("bindRendererContext"),
360
+ [
361
+ createHostReferenceExpression(),
362
+ expressionPath.node,
363
+ ]
364
+ );
365
+ },
366
+ },
367
+ };
368
+ }
@@ -1,5 +1,14 @@
1
1
  let t;
2
2
 
3
+ function isCapitalizedComponentName(name) {
4
+ if (typeof name !== "string" || name.length === 0) {
5
+ return false;
6
+ }
7
+
8
+ const first = name[0];
9
+ return first === first.toUpperCase() && first !== first.toLowerCase();
10
+ }
11
+
3
12
  export function setWrapperUtilsBabelTypes(nextTypes) {
4
13
  t = nextTypes;
5
14
  }
@@ -67,6 +76,7 @@ export function maybeTransformWrappedVariableDeclarator({
67
76
  {
68
77
  ...resolvedPluginOptions,
69
78
  ...wrapperMeta.options,
79
+ state,
70
80
  typeResolver: state?.__litsxTypeResolver,
71
81
  warn: (warning) => {
72
82
  state?.__litsxWarnings?.push(warning);
@@ -129,12 +139,17 @@ export function handlePotentialComponentExport({
129
139
  exportName = declaration.declarations[0].id.name;
130
140
  }
131
141
 
142
+ if (exportName && !isCapitalizedComponentName(exportName)) {
143
+ return false;
144
+ }
145
+
132
146
  const classNode = transformFunction(
133
147
  declarationPath,
134
148
  exportPath.findParent((p) => p.isProgram()),
135
149
  exportName,
136
150
  {
137
151
  ...state?.__litsxResolvedPluginOptions,
152
+ state,
138
153
  typeResolver,
139
154
  warn: (warning) => {
140
155
  state?.__litsxWarnings?.push(warning);
@@ -170,6 +185,10 @@ export function handlePotentialComponentExport({
170
185
  : undefined;
171
186
  const programPath = exportPath.findParent((p) => p.isProgram());
172
187
 
188
+ if (exportName && !isCapitalizedComponentName(exportName)) {
189
+ return false;
190
+ }
191
+
173
192
  if (initPath.isCallExpression()) {
174
193
  const wrapperMeta = getWrapperMetadata(initPath);
175
194
  if (!wrapperMeta) return false;
@@ -184,6 +203,7 @@ export function handlePotentialComponentExport({
184
203
  {
185
204
  ...state?.__litsxResolvedPluginOptions,
186
205
  ...wrapperMeta.options,
206
+ state,
187
207
  typeResolver,
188
208
  warn: (warning) => {
189
209
  state?.__litsxWarnings?.push(warning);
@@ -196,7 +216,11 @@ export function handlePotentialComponentExport({
196
216
  exportPath.scope.removeBinding(exportName);
197
217
  }
198
218
 
199
- exportPath.replaceWith(t.exportNamedDeclaration(classNode, []));
219
+ exportPath.replaceWith(
220
+ isDefault
221
+ ? t.exportDefaultDeclaration(classNode)
222
+ : t.exportNamedDeclaration(classNode, [])
223
+ );
200
224
  exportPath.requeue();
201
225
  pruneWrapperImports(wrapperMeta);
202
226
  updateTransformState?.(state, classNode);
@@ -217,6 +241,10 @@ export function handlePotentialComponentExport({
217
241
  ? wrapperMeta.functionPath.node.id.name
218
242
  : undefined;
219
243
 
244
+ if (!inferredName || !isCapitalizedComponentName(inferredName)) {
245
+ return false;
246
+ }
247
+
220
248
  const classNode = transformFunction(
221
249
  wrapperMeta.functionPath,
222
250
  programPath,
@@ -224,6 +252,7 @@ export function handlePotentialComponentExport({
224
252
  {
225
253
  ...state?.__litsxResolvedPluginOptions,
226
254
  ...wrapperMeta.options,
255
+ state,
227
256
  typeResolver,
228
257
  warn: (warning) => {
229
258
  state?.__litsxWarnings?.push(warning);