@builder.io/mitosis 0.9.5 → 0.11.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/dist/src/generators/angular/helpers/index.d.ts +1 -1
- package/dist/src/generators/angular/helpers/index.js +6 -3
- package/dist/src/generators/angular/signals/blocks.js +141 -6
- package/dist/src/generators/angular/signals/component.js +109 -23
- package/dist/src/generators/angular/signals/helpers/get-computed.d.ts +6 -0
- package/dist/src/generators/angular/signals/helpers/get-computed.js +79 -0
- package/dist/src/generators/angular/signals/helpers/get-dynamic-template-refs.d.ts +2 -0
- package/dist/src/generators/angular/signals/helpers/get-dynamic-template-refs.js +25 -0
- package/dist/src/generators/angular/signals/helpers/get-inputs.js +1 -1
- package/dist/src/generators/angular/signals/helpers/index.d.ts +6 -1
- package/dist/src/generators/angular/signals/helpers/index.js +9 -4
- package/dist/src/generators/angular/signals/plugins/get-code-processor-plugins.js +364 -11
- package/dist/src/generators/angular/types.d.ts +6 -1
- package/dist/src/generators/angular/types.js +1 -0
- package/dist/src/generators/builder/generator.js +9 -0
- package/dist/src/generators/mitosis/generator.js +39 -1
- package/dist/src/generators/react/generator.js +1 -1
- package/dist/src/generators/react/helpers/state.d.ts +1 -1
- package/dist/src/generators/react/helpers/state.js +47 -4
- package/dist/src/helpers/event-handlers.js +1 -1
- package/dist/src/helpers/is-hook-empty.d.ts +2 -0
- package/dist/src/helpers/is-hook-empty.js +14 -0
- package/dist/src/parsers/builder/builder.d.ts +7 -0
- package/dist/src/parsers/builder/builder.js +38 -7
- package/dist/src/parsers/jsx/element-parser.d.ts +2 -1
- package/dist/src/parsers/jsx/element-parser.js +92 -14
- package/dist/src/parsers/jsx/function-parser.d.ts +2 -2
- package/dist/src/parsers/jsx/function-parser.js +2 -2
- package/dist/src/parsers/jsx/jsx.js +2 -2
- package/dist/src/parsers/jsx/types.d.ts +7 -0
- package/dist/src/parsers/svelte/html/text.d.ts +3 -0
- package/dist/src/types/config.d.ts +4 -3
- package/dist/src/types/mitosis-node.d.ts +8 -0
- package/package.json +1 -1
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getAngularCoreImportsAsString = void 0;
|
|
4
|
-
const getAngularCoreImportsAsString = ({ refs, output, input, model, onPush, effect, signal, }) => {
|
|
4
|
+
const getAngularCoreImportsAsString = ({ refs, output, input, model, onPush, effect, signal, computed, viewChild, viewContainerRef, templateRef, renderer, }) => {
|
|
5
5
|
const angularCoreImports = {
|
|
6
6
|
Component: true,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
viewChild: refs || viewChild,
|
|
8
|
+
ElementRef: refs || viewChild,
|
|
9
|
+
ViewContainerRef: viewContainerRef,
|
|
10
|
+
TemplateRef: templateRef,
|
|
11
|
+
Renderer2: !!renderer,
|
|
10
12
|
model,
|
|
11
13
|
output,
|
|
12
14
|
input,
|
|
13
15
|
effect,
|
|
14
16
|
signal,
|
|
17
|
+
computed,
|
|
15
18
|
ChangeDetectionStrategy: onPush,
|
|
19
|
+
InputSignal: input,
|
|
20
|
+
ModelSignal: model,
|
|
16
21
|
};
|
|
17
22
|
return Object.entries(angularCoreImports)
|
|
18
23
|
.map(([key, bool]) => (bool ? key : ''))
|
|
@@ -1,18 +1,81 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getCodeProcessorPlugins = void 0;
|
|
4
|
+
const get_computed_1 = require("../../../../generators/angular/signals/helpers/get-computed");
|
|
4
5
|
const babel_transform_1 = require("../../../../helpers/babel-transform");
|
|
5
6
|
const class_components_1 = require("../../../../helpers/class-components");
|
|
6
7
|
const event_handlers_1 = require("../../../../helpers/event-handlers");
|
|
7
8
|
const process_code_1 = require("../../../../helpers/plugins/process-code");
|
|
9
|
+
const symbol_processor_1 = require("../../../../symbols/symbol-processor");
|
|
8
10
|
const mitosis_node_1 = require("../../../../types/mitosis-node");
|
|
9
11
|
const types_1 = require("@babel/types");
|
|
12
|
+
// Helper functions for handling nested state updates
|
|
13
|
+
const getBaseObject = (node) => {
|
|
14
|
+
if (!node)
|
|
15
|
+
return null;
|
|
16
|
+
if (!(0, types_1.isMemberExpression)(node))
|
|
17
|
+
return node;
|
|
18
|
+
return getBaseObject(node.object);
|
|
19
|
+
};
|
|
20
|
+
const getPropertyFromStateChain = (node) => {
|
|
21
|
+
// Start at the leftmost object and traverse up to find the first property after 'state'
|
|
22
|
+
let current = node;
|
|
23
|
+
while ((0, types_1.isMemberExpression)(current)) {
|
|
24
|
+
if ((0, types_1.isMemberExpression)(current.object) &&
|
|
25
|
+
(0, types_1.isIdentifier)(current.object.object) &&
|
|
26
|
+
current.object.object.name === 'state' &&
|
|
27
|
+
(0, types_1.isIdentifier)(current.object.property)) {
|
|
28
|
+
return current.object.property.name;
|
|
29
|
+
}
|
|
30
|
+
current = current.object;
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
};
|
|
34
|
+
const getNestedPath = (node, topLevelProp) => {
|
|
35
|
+
const path = [];
|
|
36
|
+
let current = node;
|
|
37
|
+
// Collect all property names starting after the top-level property
|
|
38
|
+
let foundTopLevel = false;
|
|
39
|
+
while ((0, types_1.isMemberExpression)(current)) {
|
|
40
|
+
if ((0, types_1.isIdentifier)(current.property)) {
|
|
41
|
+
path.unshift(current.property.name);
|
|
42
|
+
}
|
|
43
|
+
if ((0, types_1.isMemberExpression)(current.object) &&
|
|
44
|
+
(0, types_1.isIdentifier)(current.object.object) &&
|
|
45
|
+
current.object.object.name === 'state' &&
|
|
46
|
+
(0, types_1.isIdentifier)(current.object.property) &&
|
|
47
|
+
current.object.property.name === topLevelProp) {
|
|
48
|
+
foundTopLevel = true;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
current = current.object;
|
|
52
|
+
}
|
|
53
|
+
return foundTopLevel ? path : [];
|
|
54
|
+
};
|
|
55
|
+
const buildPathAccess = (baseParam, propertyPath) => {
|
|
56
|
+
return propertyPath.reduce((acc, prop) => {
|
|
57
|
+
return (0, types_1.memberExpression)(acc, (0, types_1.identifier)(prop));
|
|
58
|
+
}, baseParam);
|
|
59
|
+
};
|
|
10
60
|
const isStateOrPropsExpression = (path) => {
|
|
11
61
|
return ((0, types_1.isMemberExpression)(path.node) &&
|
|
12
62
|
(0, types_1.isIdentifier)(path.node.object) &&
|
|
13
63
|
(0, types_1.isIdentifier)(path.node.property) &&
|
|
14
64
|
(path.node.object.name === 'props' || path.node.object.name === 'state'));
|
|
15
65
|
};
|
|
66
|
+
const isAFunctionOrMethod = (json, path) => {
|
|
67
|
+
var _a, _b, _c;
|
|
68
|
+
return (json &&
|
|
69
|
+
(0, types_1.isIdentifier)(path.node.object) &&
|
|
70
|
+
(0, types_1.isIdentifier)(path.node.property) &&
|
|
71
|
+
path.node.object.name === 'state' &&
|
|
72
|
+
json.state &&
|
|
73
|
+
typeof path.node.property.name === 'string' &&
|
|
74
|
+
json.state[path.node.property.name] &&
|
|
75
|
+
((_a = json.state[path.node.property.name]) === null || _a === void 0 ? void 0 : _a.type) &&
|
|
76
|
+
(((_b = json.state[path.node.property.name]) === null || _b === void 0 ? void 0 : _b.type) === 'method' ||
|
|
77
|
+
((_c = json.state[path.node.property.name]) === null || _c === void 0 ? void 0 : _c.type) === 'function'));
|
|
78
|
+
};
|
|
16
79
|
const handleAssignmentExpression = (path) => {
|
|
17
80
|
if ((0, types_1.isMemberExpression)(path.node.left) &&
|
|
18
81
|
(0, types_1.isIdentifier)(path.node.left.object) &&
|
|
@@ -23,8 +86,96 @@ const handleAssignmentExpression = (path) => {
|
|
|
23
86
|
const call = (0, types_1.callExpression)(root, [path.node.right]);
|
|
24
87
|
path.replaceWith(call);
|
|
25
88
|
}
|
|
89
|
+
else if ((0, types_1.isMemberExpression)(path.node.left) &&
|
|
90
|
+
path.node.left.computed &&
|
|
91
|
+
(((0, types_1.isMemberExpression)(path.node.left.object) &&
|
|
92
|
+
(0, types_1.isIdentifier)(path.node.left.object.object) &&
|
|
93
|
+
path.node.left.object.object.name === 'state') ||
|
|
94
|
+
((0, types_1.isIdentifier)(path.node.left.object) && path.node.left.object.name === 'state'))) {
|
|
95
|
+
/**
|
|
96
|
+
* Handle array element assignments like: state.arr[0] = '123'
|
|
97
|
+
* Example:
|
|
98
|
+
* Input: state.arr[0] = '123'
|
|
99
|
+
* Output: state.arr.update(arr => {
|
|
100
|
+
* arr[0] = '123';
|
|
101
|
+
* return arr;
|
|
102
|
+
* })
|
|
103
|
+
*/
|
|
104
|
+
let stateProp;
|
|
105
|
+
let baseObject;
|
|
106
|
+
if ((0, types_1.isIdentifier)(path.node.left.object) && path.node.left.object.name === 'state') {
|
|
107
|
+
stateProp = path.node.left.property;
|
|
108
|
+
baseObject = path.node.left.object;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
stateProp = getPropertyFromStateChain(path.node.left);
|
|
112
|
+
if (!stateProp)
|
|
113
|
+
return;
|
|
114
|
+
baseObject = (0, types_1.memberExpression)((0, types_1.identifier)('state'), (0, types_1.identifier)(stateProp));
|
|
115
|
+
}
|
|
116
|
+
const root = (0, types_1.memberExpression)(baseObject, (0, types_1.identifier)('update'));
|
|
117
|
+
root.extra = { ...root.extra, updateExpression: true };
|
|
118
|
+
const paramName = typeof stateProp === 'string' ? stateProp : (0, types_1.isIdentifier)(stateProp) ? stateProp.name : 'item';
|
|
119
|
+
const param = (0, types_1.identifier)(paramName);
|
|
120
|
+
let assignTarget;
|
|
121
|
+
if ((0, types_1.isIdentifier)(path.node.left.object) && path.node.left.object.name === 'state') {
|
|
122
|
+
// Direct state array: state[index] = value
|
|
123
|
+
assignTarget = (0, types_1.memberExpression)(param, path.node.left.property, true);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
// Property array: state.arr[index] = value
|
|
127
|
+
assignTarget = (0, types_1.memberExpression)(param, path.node.left.property, true);
|
|
128
|
+
}
|
|
129
|
+
const block = (0, types_1.blockStatement)([
|
|
130
|
+
(0, types_1.expressionStatement)((0, types_1.assignmentExpression)('=', assignTarget, path.node.right)),
|
|
131
|
+
(0, types_1.returnStatement)(param),
|
|
132
|
+
]);
|
|
133
|
+
const arrowFunction = (0, types_1.arrowFunctionExpression)([param], block);
|
|
134
|
+
const call = (0, types_1.callExpression)(root, [arrowFunction]);
|
|
135
|
+
path.replaceWith(call);
|
|
136
|
+
}
|
|
137
|
+
else if ((0, types_1.isMemberExpression)(path.node.left) &&
|
|
138
|
+
(0, types_1.isMemberExpression)(path.node.left.object) &&
|
|
139
|
+
(0, types_1.isIdentifier)(getBaseObject(path.node.left)) &&
|
|
140
|
+
getBaseObject(path.node.left).name === 'state') {
|
|
141
|
+
/**
|
|
142
|
+
* Handle any level of nested updates like state.store.something.nested = newVal
|
|
143
|
+
* Example:
|
|
144
|
+
* Input: state.store.something.nested = newVal
|
|
145
|
+
* Output: state.store.update(obj => ({
|
|
146
|
+
* ...obj,
|
|
147
|
+
* store: {
|
|
148
|
+
* ...obj.store,
|
|
149
|
+
* something: {
|
|
150
|
+
* ...obj.store.something,
|
|
151
|
+
* nested: newVal
|
|
152
|
+
* }
|
|
153
|
+
* }
|
|
154
|
+
* }))
|
|
155
|
+
*/
|
|
156
|
+
const stateProp = getPropertyFromStateChain(path.node.left);
|
|
157
|
+
if (!stateProp)
|
|
158
|
+
return;
|
|
159
|
+
const topLevelProp = (0, types_1.memberExpression)((0, types_1.identifier)('state'), (0, types_1.identifier)(stateProp));
|
|
160
|
+
const nestedPaths = getNestedPath(path.node.left, stateProp);
|
|
161
|
+
const root = (0, types_1.memberExpression)(topLevelProp, (0, types_1.identifier)('update'));
|
|
162
|
+
root.extra = { ...root.extra, updateExpression: true };
|
|
163
|
+
const paramName = stateProp;
|
|
164
|
+
const param = (0, types_1.identifier)(paramName);
|
|
165
|
+
let innerValue = path.node.right;
|
|
166
|
+
for (let i = nestedPaths.length - 1; i >= 0; i--) {
|
|
167
|
+
const spreadTarget = i === 0 ? param : buildPathAccess(param, nestedPaths.slice(0, i));
|
|
168
|
+
innerValue = (0, types_1.objectExpression)([
|
|
169
|
+
(0, types_1.spreadElement)(spreadTarget),
|
|
170
|
+
(0, types_1.objectProperty)((0, types_1.identifier)(nestedPaths[i]), innerValue, false, false),
|
|
171
|
+
]);
|
|
172
|
+
}
|
|
173
|
+
const arrowFunction = (0, types_1.arrowFunctionExpression)([param], innerValue, false);
|
|
174
|
+
const call = (0, types_1.callExpression)(root, [arrowFunction]);
|
|
175
|
+
path.replaceWith(call);
|
|
176
|
+
}
|
|
26
177
|
};
|
|
27
|
-
const handleMemberExpression = (path) => {
|
|
178
|
+
const handleMemberExpression = (path, json) => {
|
|
28
179
|
var _a, _b, _c, _d;
|
|
29
180
|
if (((_a = path.node.extra) === null || _a === void 0 ? void 0 : _a.makeCallExpressionDone) || ((_c = (_b = path.parentPath) === null || _b === void 0 ? void 0 : _b.node.extra) === null || _c === void 0 ? void 0 : _c.updateExpression)) {
|
|
30
181
|
// Don't add a function if we've done it already
|
|
@@ -39,6 +190,12 @@ const handleMemberExpression = (path) => {
|
|
|
39
190
|
return;
|
|
40
191
|
}
|
|
41
192
|
if (isStateOrPropsExpression(path)) {
|
|
193
|
+
// Check if the state property is a method or function type, and if so, bind it to 'this'
|
|
194
|
+
if (isAFunctionOrMethod(json, path)) {
|
|
195
|
+
const bindExpr = `${path.toString()}.bind(this)`;
|
|
196
|
+
path.replaceWith((0, types_1.identifier)(bindExpr));
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
42
199
|
path.node.extra = { ...path.node.extra, makeCallExpressionDone: true };
|
|
43
200
|
path.replaceWith((0, types_1.callExpression)(path.node, []));
|
|
44
201
|
}
|
|
@@ -66,7 +223,74 @@ const handleHookAndStateOnEvents = (path, isHookDepArray) => {
|
|
|
66
223
|
}
|
|
67
224
|
return false;
|
|
68
225
|
};
|
|
69
|
-
const
|
|
226
|
+
const handleTemplateLiteral = (path, json, context) => {
|
|
227
|
+
var _a;
|
|
228
|
+
const fnName = `templateStr_${(0, symbol_processor_1.hashCodeAsString)(path.toString())}`;
|
|
229
|
+
const extraParams = new Set();
|
|
230
|
+
// Collect loop variables from context
|
|
231
|
+
let currentContext = context;
|
|
232
|
+
while (currentContext === null || currentContext === void 0 ? void 0 : currentContext.parent) {
|
|
233
|
+
if (((_a = currentContext.parent.node) === null || _a === void 0 ? void 0 : _a.name) === mitosis_node_1.ForNodeName) {
|
|
234
|
+
const forNode = currentContext.parent.node;
|
|
235
|
+
if (forNode.scope.forName)
|
|
236
|
+
extraParams.add(forNode.scope.forName);
|
|
237
|
+
if (forNode.scope.indexName)
|
|
238
|
+
extraParams.add(forNode.scope.indexName);
|
|
239
|
+
}
|
|
240
|
+
currentContext = currentContext.parent;
|
|
241
|
+
}
|
|
242
|
+
const processedExpressions = path.node.expressions.map((expr) => {
|
|
243
|
+
let exprCode = '';
|
|
244
|
+
try {
|
|
245
|
+
const { code } = require('@babel/generator').default(expr);
|
|
246
|
+
exprCode = code;
|
|
247
|
+
}
|
|
248
|
+
catch (e) {
|
|
249
|
+
exprCode = expr.toString();
|
|
250
|
+
}
|
|
251
|
+
// Replace state.x with this.x() for signals
|
|
252
|
+
return exprCode
|
|
253
|
+
.replace(/\bstate\.(\w+)(?!\()/g, 'this.$1()')
|
|
254
|
+
.replace(/\bprops\.(\w+)(?!\()/g, 'this.$1()');
|
|
255
|
+
});
|
|
256
|
+
// Convert Set to Array for final usage
|
|
257
|
+
const paramsList = Array.from(extraParams);
|
|
258
|
+
json.state[fnName] = {
|
|
259
|
+
code: `${fnName}(${paramsList.join(', ')}) {
|
|
260
|
+
return \`${path.node.quasis
|
|
261
|
+
.map((quasi, i) => {
|
|
262
|
+
const escapedRaw = quasi.value.raw.replace(/\\/g, '\\\\').replace(/\$/g, '\\$');
|
|
263
|
+
return (escapedRaw +
|
|
264
|
+
(i < processedExpressions.length ? '${' + processedExpressions[i] + '}' : ''));
|
|
265
|
+
})
|
|
266
|
+
.join('')}\`;
|
|
267
|
+
}`,
|
|
268
|
+
type: 'method',
|
|
269
|
+
};
|
|
270
|
+
// Return the function call with any needed parameters
|
|
271
|
+
return `${fnName}(${paramsList.join(', ')})`;
|
|
272
|
+
};
|
|
273
|
+
const handleCallExpressionArgument = (json, arg) => {
|
|
274
|
+
var _a;
|
|
275
|
+
if ((0, types_1.isMemberExpression)(arg) &&
|
|
276
|
+
(0, types_1.isIdentifier)(arg.object) &&
|
|
277
|
+
(0, types_1.isIdentifier)(arg.property) &&
|
|
278
|
+
(arg.object.name === 'state' || arg.object.name === 'props') &&
|
|
279
|
+
!((_a = arg.extra) === null || _a === void 0 ? void 0 : _a.makeCallExpressionDone)) {
|
|
280
|
+
if (arg.object.name === 'state' && json) {
|
|
281
|
+
const argPath = { node: arg };
|
|
282
|
+
if (isAFunctionOrMethod(json, argPath)) {
|
|
283
|
+
const argStr = arg.object.name + '.' + arg.property.name;
|
|
284
|
+
return (0, types_1.identifier)(`${argStr}.bind(this)`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
const newArg = (0, types_1.callExpression)(arg, []);
|
|
288
|
+
newArg.extra = { makeCallExpressionDone: true };
|
|
289
|
+
return newArg;
|
|
290
|
+
}
|
|
291
|
+
return arg;
|
|
292
|
+
};
|
|
293
|
+
const transformHooksAndState = (code, isHookDepArray, json) => {
|
|
70
294
|
return (0, babel_transform_1.babelTransformExpression)(code, {
|
|
71
295
|
AssignmentExpression(path) {
|
|
72
296
|
handleAssignmentExpression(path);
|
|
@@ -95,24 +319,87 @@ const transformHooksAndState = (code, isHookDepArray) => {
|
|
|
95
319
|
const call = (0, types_1.callExpression)(root, [arrowFunction]);
|
|
96
320
|
path.replaceWith(call);
|
|
97
321
|
}
|
|
322
|
+
else if ((0, types_1.isMemberExpression)(path.node.argument) &&
|
|
323
|
+
(0, types_1.isMemberExpression)(path.node.argument.object) &&
|
|
324
|
+
(0, types_1.isIdentifier)(getBaseObject(path.node.argument)) &&
|
|
325
|
+
getBaseObject(path.node.argument).name === 'state') {
|
|
326
|
+
// Handle nested update expressions like: state.obj.counter++
|
|
327
|
+
// Example:
|
|
328
|
+
// Input: state.obj.counter++
|
|
329
|
+
// Output: state.obj.update(obj => {
|
|
330
|
+
// Object.assign(obj, {
|
|
331
|
+
// counter: obj.counter + 1
|
|
332
|
+
// });
|
|
333
|
+
// return obj;
|
|
334
|
+
// });
|
|
335
|
+
//
|
|
336
|
+
const stateProp = getPropertyFromStateChain(path.node.argument);
|
|
337
|
+
if (!stateProp)
|
|
338
|
+
return;
|
|
339
|
+
const topLevelProp = (0, types_1.memberExpression)((0, types_1.identifier)('state'), (0, types_1.identifier)(stateProp));
|
|
340
|
+
const nestedPaths = getNestedPath(path.node.argument, stateProp);
|
|
341
|
+
const root = (0, types_1.memberExpression)(topLevelProp, (0, types_1.identifier)('update'));
|
|
342
|
+
root.extra = { ...root.extra, updateExpression: true };
|
|
343
|
+
const paramName = stateProp;
|
|
344
|
+
const param = (0, types_1.identifier)(paramName);
|
|
345
|
+
const lastPropName = nestedPaths[nestedPaths.length - 1];
|
|
346
|
+
const innerParamName = lastPropName + '_value';
|
|
347
|
+
const nestedPathAccess = buildPathAccess(param, nestedPaths.slice(0, -1));
|
|
348
|
+
let innerValue = (0, types_1.objectExpression)([
|
|
349
|
+
(0, types_1.spreadElement)(nestedPathAccess),
|
|
350
|
+
(0, types_1.objectProperty)((0, types_1.identifier)(lastPropName), (0, types_1.updateExpression)(path.node.operator, (0, types_1.identifier)(innerParamName), path.node.prefix), false, false),
|
|
351
|
+
]);
|
|
352
|
+
for (let i = nestedPaths.length - 2; i >= 0; i--) {
|
|
353
|
+
const spreadTarget = i === 0 ? param : buildPathAccess(param, nestedPaths.slice(0, i));
|
|
354
|
+
innerValue = (0, types_1.objectExpression)([
|
|
355
|
+
(0, types_1.spreadElement)(spreadTarget),
|
|
356
|
+
(0, types_1.objectProperty)((0, types_1.identifier)(nestedPaths[i]), innerValue, false, false),
|
|
357
|
+
]);
|
|
358
|
+
}
|
|
359
|
+
const block = (0, types_1.blockStatement)([
|
|
360
|
+
(0, types_1.expressionStatement)((0, types_1.callExpression)((0, types_1.memberExpression)((0, types_1.identifier)('Object'), (0, types_1.identifier)('assign')), [
|
|
361
|
+
param,
|
|
362
|
+
innerValue,
|
|
363
|
+
])),
|
|
364
|
+
(0, types_1.returnStatement)(param),
|
|
365
|
+
]);
|
|
366
|
+
const arrowFunction = (0, types_1.arrowFunctionExpression)([param], block);
|
|
367
|
+
const call = (0, types_1.callExpression)(root, [arrowFunction]);
|
|
368
|
+
path.replaceWith(call);
|
|
369
|
+
}
|
|
98
370
|
},
|
|
99
371
|
MemberExpression(path) {
|
|
100
372
|
const skip = handleHookAndStateOnEvents(path, isHookDepArray);
|
|
101
373
|
if (skip) {
|
|
102
374
|
return;
|
|
103
375
|
}
|
|
104
|
-
handleMemberExpression(path);
|
|
376
|
+
handleMemberExpression(path, json);
|
|
377
|
+
},
|
|
378
|
+
CallExpression(path) {
|
|
379
|
+
// if args has a state.x or props.x, we need to add this.x() to the args
|
|
380
|
+
if (path.node.arguments.length > 0) {
|
|
381
|
+
const newArgs = path.node.arguments.map((arg) => handleCallExpressionArgument(json, arg));
|
|
382
|
+
// Only replace arguments if we made any changes
|
|
383
|
+
if (newArgs.some((arg, i) => arg !== path.node.arguments[i])) {
|
|
384
|
+
path.node.arguments = newArgs;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
105
387
|
},
|
|
106
388
|
});
|
|
107
389
|
};
|
|
108
390
|
const addToImportCall = (json, importName) => {
|
|
109
|
-
const
|
|
391
|
+
const importInstance = json.imports.find((imp) => imp.imports[importName]);
|
|
392
|
+
// Check if this is a type import - if it is, don't add it to importCalls
|
|
393
|
+
if ((importInstance === null || importInstance === void 0 ? void 0 : importInstance.importKind) === 'type') {
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
const isImportCall = !!importInstance;
|
|
110
397
|
const isExportCall = json.exports ? !!json.exports[importName] : false;
|
|
111
398
|
if (isImportCall || isExportCall) {
|
|
112
399
|
json.compileContext.angular.extra.importCalls.push(importName);
|
|
113
400
|
}
|
|
114
401
|
};
|
|
115
|
-
const transformBindings = (json, code) => {
|
|
402
|
+
const transformBindings = (json, code, key, context) => {
|
|
116
403
|
return (0, babel_transform_1.babelTransformExpression)(code, {
|
|
117
404
|
BlockStatement() {
|
|
118
405
|
console.error(`
|
|
@@ -126,6 +413,13 @@ ${code}`);
|
|
|
126
413
|
if ((0, types_1.isIdentifier)(path.node.callee)) {
|
|
127
414
|
addToImportCall(json, path.node.callee.name);
|
|
128
415
|
}
|
|
416
|
+
if (path.node.arguments.length > 0) {
|
|
417
|
+
const newArgs = path.node.arguments.map((arg) => handleCallExpressionArgument(json, arg));
|
|
418
|
+
// Only replace arguments if we made any changes
|
|
419
|
+
if (newArgs.some((arg, i) => arg !== path.node.arguments[i])) {
|
|
420
|
+
path.node.arguments = newArgs;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
129
423
|
},
|
|
130
424
|
Identifier(path) {
|
|
131
425
|
// If we use a constant from an import we need to add it to the Component as well
|
|
@@ -137,14 +431,28 @@ ${code}`);
|
|
|
137
431
|
var _a;
|
|
138
432
|
// We cannot use " for string literal in template
|
|
139
433
|
if ((_a = path.node.extra) === null || _a === void 0 ? void 0 : _a.raw) {
|
|
140
|
-
path.node.extra.raw = path.node.extra.raw.replaceAll('"',
|
|
434
|
+
path.node.extra.raw = path.node.extra.raw.replaceAll('"', '"');
|
|
141
435
|
}
|
|
142
436
|
},
|
|
143
437
|
AssignmentExpression(path) {
|
|
144
438
|
handleAssignmentExpression(path);
|
|
145
439
|
},
|
|
146
440
|
MemberExpression(path) {
|
|
147
|
-
handleMemberExpression(path);
|
|
441
|
+
handleMemberExpression(path, json);
|
|
442
|
+
},
|
|
443
|
+
TemplateLiteral(path) {
|
|
444
|
+
var _a, _b, _c;
|
|
445
|
+
// they are already created as trackBy functions
|
|
446
|
+
if (key === 'key') {
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
// skip template literals in spread bindings
|
|
450
|
+
if (key && ((_c = (_b = (_a = context === null || context === void 0 ? void 0 : context.node) === null || _a === void 0 ? void 0 : _a.bindings) === null || _b === void 0 ? void 0 : _b[key]) === null || _c === void 0 ? void 0 : _c.code.includes('...'))) {
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
// When we encounter a template literal, convert it to a function
|
|
454
|
+
const fnCall = handleTemplateLiteral(path, json, context);
|
|
455
|
+
path.replaceWith((0, types_1.identifier)(fnCall));
|
|
148
456
|
},
|
|
149
457
|
});
|
|
150
458
|
};
|
|
@@ -155,7 +463,49 @@ const getCodeProcessorPlugins = (json, options, processBindingOptions) => {
|
|
|
155
463
|
switch (codeType) {
|
|
156
464
|
case 'bindings':
|
|
157
465
|
return (code, key, context) => {
|
|
158
|
-
var _a, _b, _c;
|
|
466
|
+
var _a, _b, _c, _d, _e, _f;
|
|
467
|
+
// Handle object spread expressions or TypeScript type assertions
|
|
468
|
+
if ((code.startsWith('{') && code.includes('...')) || code.includes(' as ')) {
|
|
469
|
+
if (((_a = context === null || context === void 0 ? void 0 : context.node) === null || _a === void 0 ? void 0 : _a.bindings) && key) {
|
|
470
|
+
const binding = context.node.bindings[key];
|
|
471
|
+
let isForContext = false;
|
|
472
|
+
let forName = '';
|
|
473
|
+
let indexName = '';
|
|
474
|
+
let currentContext = context;
|
|
475
|
+
while (currentContext === null || currentContext === void 0 ? void 0 : currentContext.parent) {
|
|
476
|
+
if (((_b = currentContext.parent.node) === null || _b === void 0 ? void 0 : _b.name) === mitosis_node_1.ForNodeName) {
|
|
477
|
+
isForContext = true;
|
|
478
|
+
const forNode = currentContext.parent.node;
|
|
479
|
+
forName = forNode.scope.forName || '_';
|
|
480
|
+
indexName = forNode.scope.indexName || '_';
|
|
481
|
+
break;
|
|
482
|
+
}
|
|
483
|
+
currentContext = currentContext.parent;
|
|
484
|
+
}
|
|
485
|
+
const computedName = (0, get_computed_1.createObjectSpreadComputed)(json, binding, key, isForContext, forName, indexName);
|
|
486
|
+
if (isForContext) {
|
|
487
|
+
const params = [];
|
|
488
|
+
if (forName)
|
|
489
|
+
params.push(forName);
|
|
490
|
+
if (indexName)
|
|
491
|
+
params.push(indexName);
|
|
492
|
+
if (params.length > 0) {
|
|
493
|
+
return (0, class_components_1.processClassComponentBinding)(json, `${computedName}(${params.join(', ')})`, {
|
|
494
|
+
...processBindingOptions,
|
|
495
|
+
replaceWith: 'this.',
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
return (0, class_components_1.processClassComponentBinding)(json, `${computedName}()`, {
|
|
500
|
+
...processBindingOptions,
|
|
501
|
+
replaceWith: 'this.',
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
const needsToReplaceWithThis = (code.startsWith('{') && code.includes('...')) ||
|
|
506
|
+
code.includes(' as ') ||
|
|
507
|
+
(context === null || context === void 0 ? void 0 : context.node.name.includes('.')) ||
|
|
508
|
+
((_c = context === null || context === void 0 ? void 0 : context.node.bindings[key]) === null || _c === void 0 ? void 0 : _c.type) === 'spread';
|
|
159
509
|
let replaceWith = '';
|
|
160
510
|
if (key === 'key') {
|
|
161
511
|
/**
|
|
@@ -163,12 +513,15 @@ const getCodeProcessorPlugins = (json, options, processBindingOptions) => {
|
|
|
163
513
|
* We will create a new function for the key attribute.
|
|
164
514
|
* Therefore, we need to add "this" to state and props.
|
|
165
515
|
*/
|
|
166
|
-
const isForParent = ((
|
|
516
|
+
const isForParent = ((_f = (_e = (_d = context === null || context === void 0 ? void 0 : context.parent) === null || _d === void 0 ? void 0 : _d.parent) === null || _e === void 0 ? void 0 : _e.node) === null || _f === void 0 ? void 0 : _f.name) === mitosis_node_1.ForNodeName;
|
|
167
517
|
if (isForParent) {
|
|
168
518
|
replaceWith = 'this.';
|
|
169
519
|
}
|
|
170
520
|
}
|
|
171
|
-
|
|
521
|
+
if (needsToReplaceWithThis) {
|
|
522
|
+
replaceWith = 'this.';
|
|
523
|
+
}
|
|
524
|
+
return (0, class_components_1.processClassComponentBinding)(json, transformBindings(json, code, key, context), {
|
|
172
525
|
...processBindingOptions,
|
|
173
526
|
replaceWith,
|
|
174
527
|
});
|
|
@@ -177,7 +530,7 @@ const getCodeProcessorPlugins = (json, options, processBindingOptions) => {
|
|
|
177
530
|
case 'hooks':
|
|
178
531
|
case 'state':
|
|
179
532
|
return (code) => {
|
|
180
|
-
return (0, class_components_1.processClassComponentBinding)(json, transformHooksAndState(code, codeType === 'hooks-deps-array'), processBindingOptions);
|
|
533
|
+
return (0, class_components_1.processClassComponentBinding)(json, transformHooksAndState(code, codeType === 'hooks-deps-array', json), processBindingOptions);
|
|
181
534
|
};
|
|
182
535
|
case 'properties':
|
|
183
536
|
case 'hooks-deps':
|
|
@@ -10,6 +10,7 @@ export interface ToAngularOptions extends BaseTranspilerOptions {
|
|
|
10
10
|
importMapper?: Function;
|
|
11
11
|
bootstrapMapper?: Function;
|
|
12
12
|
visuallyIgnoreHostElement?: boolean;
|
|
13
|
+
defaultExportComponents?: boolean;
|
|
13
14
|
experimental?: {
|
|
14
15
|
injectables?: (variableName: string, variableType: string) => string;
|
|
15
16
|
inject?: boolean;
|
|
@@ -28,7 +29,6 @@ export type AngularMetadata = {
|
|
|
28
29
|
*/
|
|
29
30
|
nativeEvents?: string[];
|
|
30
31
|
/**
|
|
31
|
-
* @deprecated Rename component in *.lite.tsx
|
|
32
32
|
* Overwrite default selector for component. Default will be kebab case (MyComponent -> my-component)
|
|
33
33
|
*/
|
|
34
34
|
selector?: string;
|
|
@@ -47,6 +47,11 @@ export type AngularMetadata = {
|
|
|
47
47
|
* Can be used with `useTarget({angular: ()=> ...})` if needed.
|
|
48
48
|
*/
|
|
49
49
|
outputs?: string[];
|
|
50
|
+
/**
|
|
51
|
+
* Skip hydration for the component.
|
|
52
|
+
* Adds `host: { ngSkipHydration: "true" }` to the component decorator.
|
|
53
|
+
*/
|
|
54
|
+
skipHydration?: boolean;
|
|
50
55
|
/**
|
|
51
56
|
* Only for api=signals
|
|
52
57
|
*/
|
|
@@ -541,6 +541,15 @@ const blockToBuilder = (json, options = {}, _internalOptions = {}) => {
|
|
|
541
541
|
for (const key in json.slots) {
|
|
542
542
|
componentOptions[key] = json.slots[key].map((node) => (0, exports.blockToBuilder)(node, options));
|
|
543
543
|
}
|
|
544
|
+
for (const key in json.blocksSlots) {
|
|
545
|
+
const value = json.blocksSlots[key];
|
|
546
|
+
(0, legacy_1.default)(value).forEach(function (v) {
|
|
547
|
+
if ((0, is_mitosis_node_1.isMitosisNode)(v)) {
|
|
548
|
+
this.update((0, exports.blockToBuilder)(v, options, _internalOptions));
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
componentOptions[key] = value;
|
|
552
|
+
}
|
|
544
553
|
const hasCss = !!((_l = bindings.css) === null || _l === void 0 ? void 0 : _l.code);
|
|
545
554
|
let responsiveStyles = {
|
|
546
555
|
large: {},
|
|
@@ -20,6 +20,7 @@ const state_1 = require("../../helpers/state");
|
|
|
20
20
|
const plugins_1 = require("../../modules/plugins");
|
|
21
21
|
const mitosis_node_1 = require("../../types/mitosis-node");
|
|
22
22
|
const json5_1 = __importDefault(require("json5"));
|
|
23
|
+
const legacy_1 = __importDefault(require("neotraverse/legacy"));
|
|
23
24
|
const standalone_1 = require("prettier/standalone");
|
|
24
25
|
const react_1 = require("../react");
|
|
25
26
|
exports.DEFAULT_FORMAT = 'legacy';
|
|
@@ -186,7 +187,14 @@ const blockToMitosis = (json, toMitosisOptions = {}, component, insideJsx) => {
|
|
|
186
187
|
for (const key in json.slots) {
|
|
187
188
|
const value = json.slots[key];
|
|
188
189
|
str += ` ${key}={`;
|
|
189
|
-
|
|
190
|
+
/**
|
|
191
|
+
* Pass the empty array as foo={[]} could be treated differently than not
|
|
192
|
+
* passing the prop at all.
|
|
193
|
+
*/
|
|
194
|
+
if (value.length === 0) {
|
|
195
|
+
str += '[]';
|
|
196
|
+
}
|
|
197
|
+
else if (value.length > 1) {
|
|
190
198
|
str += '<>';
|
|
191
199
|
}
|
|
192
200
|
str += json.slots[key]
|
|
@@ -197,6 +205,15 @@ const blockToMitosis = (json, toMitosisOptions = {}, component, insideJsx) => {
|
|
|
197
205
|
}
|
|
198
206
|
str += `}`;
|
|
199
207
|
}
|
|
208
|
+
for (const key in json.blocksSlots) {
|
|
209
|
+
const value = json.blocksSlots[key];
|
|
210
|
+
(0, legacy_1.default)(value).forEach(function (v) {
|
|
211
|
+
if ((0, is_mitosis_node_1.isMitosisNode)(v)) {
|
|
212
|
+
this.update((0, exports.blockToMitosis)(v, toMitosisOptions, component, insideJsx));
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
str += `${key}={${generateBlockSlotsCode(value)}}`;
|
|
216
|
+
}
|
|
200
217
|
if (html_tags_1.SELF_CLOSING_HTML_TAGS.has(json.name)) {
|
|
201
218
|
return str + ' />';
|
|
202
219
|
}
|
|
@@ -213,6 +230,27 @@ const blockToMitosis = (json, toMitosisOptions = {}, component, insideJsx) => {
|
|
|
213
230
|
return str;
|
|
214
231
|
};
|
|
215
232
|
exports.blockToMitosis = blockToMitosis;
|
|
233
|
+
const generateBlockSlotsCode = (blockSlot) => {
|
|
234
|
+
let code = '';
|
|
235
|
+
// generate array props (foo=[...])
|
|
236
|
+
if (Array.isArray(blockSlot)) {
|
|
237
|
+
code += `[${blockSlot.map(generateBlockSlotsCode).join(',')}]`;
|
|
238
|
+
// generate object props (foo={{ ... }})
|
|
239
|
+
}
|
|
240
|
+
else if (typeof blockSlot === 'object' && blockSlot !== null) {
|
|
241
|
+
code += '{';
|
|
242
|
+
for (const key in blockSlot) {
|
|
243
|
+
if (blockSlot.hasOwnProperty(key)) {
|
|
244
|
+
code += `${key}: ${generateBlockSlotsCode(blockSlot[key])},`;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
code += '}';
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
code += blockSlot;
|
|
251
|
+
}
|
|
252
|
+
return code;
|
|
253
|
+
};
|
|
216
254
|
const getRefsString = (json, refs = Array.from((0, get_refs_1.getRefs)(json))) => {
|
|
217
255
|
var _a, _b;
|
|
218
256
|
let str = '';
|
|
@@ -358,7 +358,7 @@ const _componentToReact = (json, options, isSubComponent = false) => {
|
|
|
358
358
|
`;
|
|
359
359
|
const str = (0, dedent_1.dedent) `
|
|
360
360
|
${shouldAddUseClientDirective ? `'use client';` : ''}
|
|
361
|
-
${(0, state_2.getDefaultImport)(options)}
|
|
361
|
+
${(0, state_2.getDefaultImport)(options, json)}
|
|
362
362
|
${styledComponentsCode ? `import styled from 'styled-components';\n` : ''}
|
|
363
363
|
${reactLibImports.size
|
|
364
364
|
? `import { ${Array.from(reactLibImports).join(', ')} } from '${options.preact ? 'preact/hooks' : 'react'}'`
|
|
@@ -14,4 +14,4 @@ export declare const getReactVariantStateString: ({ hasState, options, json, use
|
|
|
14
14
|
json: MitosisComponent;
|
|
15
15
|
options: ToReactOptions;
|
|
16
16
|
}) => string;
|
|
17
|
-
export declare const getDefaultImport: (options: ToReactOptions) => string;
|
|
17
|
+
export declare const getDefaultImport: (options: ToReactOptions, json: MitosisComponent) => string;
|