@builder.io/mitosis 0.8.0 → 0.9.1
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/{blocks.d.ts → classic/blocks.d.ts} +3 -3
- package/dist/src/generators/angular/{blocks.js → classic/blocks.js} +14 -14
- package/dist/src/generators/angular/classic/component.d.ts +3 -0
- package/dist/src/generators/angular/classic/component.js +356 -0
- package/dist/src/generators/angular/classic/plugins/get-class-properties-plugin.d.ts +2 -0
- package/dist/src/generators/angular/classic/plugins/get-class-properties-plugin.js +138 -0
- package/dist/src/generators/angular/classic/plugins/get-code-processor-plugins.d.ts +8 -0
- package/dist/src/generators/angular/classic/plugins/get-code-processor-plugins.js +60 -0
- package/dist/src/generators/angular/component.d.ts +3 -0
- package/dist/src/generators/angular/component.js +27 -0
- package/dist/src/generators/angular/helpers/format.d.ts +1 -0
- package/dist/src/generators/angular/helpers/format.js +24 -0
- package/dist/src/generators/angular/helpers/get-inputs.d.ts +7 -0
- package/dist/src/generators/angular/helpers/get-inputs.js +18 -0
- package/dist/src/generators/angular/helpers/get-outputs.d.ts +7 -0
- package/dist/src/generators/angular/helpers/get-outputs.js +23 -0
- package/dist/src/generators/angular/helpers/get-refs.d.ts +8 -0
- package/dist/src/generators/angular/helpers/get-refs.js +40 -0
- package/dist/src/generators/angular/helpers/get-styles.d.ts +6 -0
- package/dist/src/generators/angular/helpers/get-styles.js +17 -0
- package/dist/src/generators/angular/helpers/index.d.ts +15 -0
- package/dist/src/generators/angular/helpers/index.js +126 -2
- package/dist/src/generators/angular/{parse-selector.d.ts → helpers/parse-selector.d.ts} +1 -1
- package/dist/src/generators/angular/{parse-selector.js → helpers/parse-selector.js} +3 -3
- package/dist/src/generators/angular/index.d.ts +1 -3
- package/dist/src/generators/angular/index.js +1 -692
- package/dist/src/generators/angular/signals/blocks.d.ts +10 -0
- package/dist/src/generators/angular/signals/blocks.js +242 -0
- package/dist/src/generators/angular/signals/component.d.ts +3 -0
- package/dist/src/generators/angular/signals/component.js +279 -0
- package/dist/src/generators/angular/signals/helpers/get-inputs.d.ts +7 -0
- package/dist/src/generators/angular/signals/helpers/get-inputs.js +15 -0
- package/dist/src/generators/angular/signals/helpers/index.d.ts +9 -0
- package/dist/src/generators/angular/signals/helpers/index.js +22 -0
- package/dist/src/generators/angular/signals/plugins/get-code-processor-plugins.d.ts +4 -0
- package/dist/src/generators/angular/signals/plugins/get-code-processor-plugins.js +194 -0
- package/dist/src/generators/angular/types.d.ts +23 -2
- package/dist/src/generators/angular/types.js +1 -0
- package/dist/src/generators/builder/generator.js +6 -0
- package/dist/src/generators/mitosis/generator.js +11 -27
- package/dist/src/generators/qwik/component-generator.js +1 -0
- package/dist/src/generators/solid/index.js +1 -0
- package/dist/src/generators/stencil/blocks.js +2 -1
- package/dist/src/generators/stencil/component.js +3 -2
- package/dist/src/generators/stencil/helpers/index.d.ts +0 -5
- package/dist/src/generators/stencil/helpers/index.js +2 -33
- package/dist/src/generators/stencil/plugins/get-code-processor-plugins.d.ts +1 -1
- package/dist/src/generators/stencil/plugins/get-code-processor-plugins.js +3 -2
- package/dist/src/generators/svelte/svelte.js +2 -0
- package/dist/src/generators/vue/vue.js +2 -0
- package/dist/src/helpers/babel-transform.js +1 -1
- package/dist/src/helpers/class-components.d.ts +13 -0
- package/dist/src/helpers/class-components.js +51 -0
- package/dist/src/helpers/get-state-object-string.d.ts +4 -0
- package/dist/src/helpers/get-state-object-string.js +22 -5
- package/dist/src/helpers/is-children.js +1 -1
- package/dist/src/helpers/map-refs.d.ts +7 -1
- package/dist/src/helpers/map-refs.js +21 -21
- package/dist/src/helpers/plugins/process-code/index.d.ts +1 -1
- package/dist/src/helpers/plugins/process-code/index.js +16 -2
- package/dist/src/helpers/plugins/process-code/types.d.ts +3 -2
- package/dist/src/helpers/render-imports.d.ts +5 -0
- package/dist/src/helpers/replace-identifiers.js +1 -4
- package/dist/src/helpers/traverse-nodes.d.ts +1 -1
- package/dist/src/parsers/jsx/function-parser.js +15 -0
- package/dist/src/parsers/svelte/html/text.d.ts +18 -0
- package/dist/src/types/mitosis-component.d.ts +2 -0
- package/dist/src/types/mitosis-node.d.ts +7 -2
- package/dist/src/types/mitosis-node.js +8 -3
- package/package.json +1 -1
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { AngularBlockOptions, ToAngularOptions } from '../../../generators/angular/types';
|
|
2
|
+
import { MitosisComponent } from '../../../types/mitosis-component';
|
|
3
|
+
import { MitosisNode } from '../../../types/mitosis-node';
|
|
4
|
+
export declare const blockToAngularSignals: ({ root, json, options, blockOptions, rootRef, }: {
|
|
5
|
+
root: MitosisComponent;
|
|
6
|
+
json: MitosisNode;
|
|
7
|
+
options?: ToAngularOptions | undefined;
|
|
8
|
+
rootRef?: string | undefined;
|
|
9
|
+
blockOptions?: AngularBlockOptions | undefined;
|
|
10
|
+
}) => string;
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.blockToAngularSignals = void 0;
|
|
7
|
+
const html_tags_1 = require("../../../constants/html_tags");
|
|
8
|
+
const helpers_1 = require("../../../generators/angular/helpers");
|
|
9
|
+
const parse_selector_1 = require("../../../generators/angular/helpers/parse-selector");
|
|
10
|
+
const babel_transform_1 = require("../../../helpers/babel-transform");
|
|
11
|
+
const event_handlers_1 = require("../../../helpers/event-handlers");
|
|
12
|
+
const is_children_1 = __importDefault(require("../../../helpers/is-children"));
|
|
13
|
+
const is_mitosis_node_1 = require("../../../helpers/is-mitosis-node");
|
|
14
|
+
const slots_1 = require("../../../helpers/slots");
|
|
15
|
+
const types_1 = require("@babel/types");
|
|
16
|
+
const function_1 = require("fp-ts/function");
|
|
17
|
+
const lodash_1 = require("lodash");
|
|
18
|
+
const getChildren = (root, json, options, blockOptions) => {
|
|
19
|
+
var _a;
|
|
20
|
+
return (_a = json.children) === null || _a === void 0 ? void 0 : _a.map((item) => (0, exports.blockToAngularSignals)({ root, json: item, options, blockOptions })).join('\n');
|
|
21
|
+
};
|
|
22
|
+
const MAPPERS = {
|
|
23
|
+
Fragment: (root, json, options, blockOptions) => {
|
|
24
|
+
const children = getChildren(root, json, options, blockOptions);
|
|
25
|
+
// TODO: Handle `key`?
|
|
26
|
+
return `<ng-container>${children}</ng-container>`;
|
|
27
|
+
},
|
|
28
|
+
Slot: (root, json, options, blockOptions) => {
|
|
29
|
+
const children = getChildren(root, json, options, blockOptions);
|
|
30
|
+
const namedSlotTransform = Object.entries({ ...json.bindings, ...json.properties })
|
|
31
|
+
.map(([binding, value]) => {
|
|
32
|
+
if (value && binding === 'name') {
|
|
33
|
+
const selector = (0, function_1.pipe)((0, lodash_1.isString)(value) ? value : value.code, slots_1.stripSlotPrefix, lodash_1.kebabCase);
|
|
34
|
+
return `select="[${selector}]"`;
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
.join('\n');
|
|
38
|
+
return `<ng-content ${namedSlotTransform}>
|
|
39
|
+
${children}
|
|
40
|
+
</ng-content>`;
|
|
41
|
+
},
|
|
42
|
+
For: (root, json, options, blockOptions) => {
|
|
43
|
+
var _a, _b, _c;
|
|
44
|
+
const forNode = json;
|
|
45
|
+
const indexName = forNode.scope.indexName;
|
|
46
|
+
const forName = forNode.scope.forName;
|
|
47
|
+
let trackByFnName;
|
|
48
|
+
// Check if "key" is present for the first child of the for loop
|
|
49
|
+
if ((0, helpers_1.hasFirstChildKeyAttribute)(forNode)) {
|
|
50
|
+
const fnIndex = ((_a = root.meta) === null || _a === void 0 ? void 0 : _a._trackByForIndex) || 0;
|
|
51
|
+
trackByFnName = `trackBy${forName ? forName.charAt(0).toUpperCase() + forName.slice(1) : ''}${fnIndex}`;
|
|
52
|
+
root.meta._trackByForIndex = fnIndex + 1;
|
|
53
|
+
let code = (_b = forNode.children[0].bindings.key) === null || _b === void 0 ? void 0 : _b.code;
|
|
54
|
+
root.state[trackByFnName] = {
|
|
55
|
+
code: `${trackByFnName}(${indexName !== null && indexName !== void 0 ? indexName : '_'}: number, ${forName}: any) { return ${code}; }`,
|
|
56
|
+
type: 'method',
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const children = getChildren(root, json, options, blockOptions);
|
|
60
|
+
const item = forName !== null && forName !== void 0 ? forName : '_';
|
|
61
|
+
const of = (_c = forNode.bindings.each) === null || _c === void 0 ? void 0 : _c.code;
|
|
62
|
+
const track = `track ${trackByFnName ? trackByFnName : indexName ? indexName : 'i'};`;
|
|
63
|
+
const index = indexName ? `let ${indexName} = $index` : 'let i = $index';
|
|
64
|
+
return `
|
|
65
|
+
@for (${item} of ${of};${track}${index}) {
|
|
66
|
+
${children}
|
|
67
|
+
}
|
|
68
|
+
`;
|
|
69
|
+
},
|
|
70
|
+
Show: (root, json, options, blockOptions) => {
|
|
71
|
+
var _a, _b;
|
|
72
|
+
let condition = (_a = json.bindings.when) === null || _a === void 0 ? void 0 : _a.code;
|
|
73
|
+
const children = getChildren(root, json, options, blockOptions);
|
|
74
|
+
let elseBlock = '';
|
|
75
|
+
// else condition
|
|
76
|
+
if ((0, is_mitosis_node_1.isMitosisNode)((_b = json.meta) === null || _b === void 0 ? void 0 : _b.else)) {
|
|
77
|
+
elseBlock = `@else{
|
|
78
|
+
${(0, exports.blockToAngularSignals)({ root, json: json.meta.else, options, blockOptions })}
|
|
79
|
+
}`;
|
|
80
|
+
}
|
|
81
|
+
if (condition === null || condition === void 0 ? void 0 : condition.includes('children()')) {
|
|
82
|
+
console.error(`
|
|
83
|
+
${json.name}: You can't use children() in a Show block for \`when\` targeting angular.
|
|
84
|
+
Try to invert it like this:
|
|
85
|
+
"<Show when={props.label} else={props.children}>{props.label}</Show>"
|
|
86
|
+
`);
|
|
87
|
+
}
|
|
88
|
+
return `@if(${condition}){
|
|
89
|
+
${children}
|
|
90
|
+
}${elseBlock}`;
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
// TODO: Maybe in the future allow defining `string | function` as values
|
|
94
|
+
const BINDINGS_MAPPER = {
|
|
95
|
+
innerHTML: 'innerHTML',
|
|
96
|
+
style: 'ngStyle',
|
|
97
|
+
};
|
|
98
|
+
const stringifyBinding = (node, blockOptions) => ([key, binding]) => {
|
|
99
|
+
var _a, _b;
|
|
100
|
+
if (key.startsWith('$') || key.startsWith('"') || key === 'key') {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if ((binding === null || binding === void 0 ? void 0 : binding.type) === 'spread') {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const keyToUse = BINDINGS_MAPPER[key] || key;
|
|
107
|
+
if (!binding)
|
|
108
|
+
return '';
|
|
109
|
+
const { code } = binding;
|
|
110
|
+
if ((0, event_handlers_1.checkIsEvent)(keyToUse)) {
|
|
111
|
+
const args = binding.arguments || [];
|
|
112
|
+
const event = (0, event_handlers_1.getEventNameWithoutOn)(keyToUse);
|
|
113
|
+
if (code.includes('event.target.')) {
|
|
114
|
+
console.error(`
|
|
115
|
+
Component ${node.name} has an event ${event} that uses 'event.target.xxx'.
|
|
116
|
+
This will cause an error in Angular.
|
|
117
|
+
Please create a new function with the EventTarget and use e.g:
|
|
118
|
+
'(event.target as HTMLInputElement).value'`);
|
|
119
|
+
}
|
|
120
|
+
const value = (0, babel_transform_1.babelTransformExpression)(code, {
|
|
121
|
+
Identifier(path) {
|
|
122
|
+
// Only change arguments inside a call expression or event
|
|
123
|
+
if (((0, types_1.isCallExpression)(path.parent) && args.includes(path.node.name)) ||
|
|
124
|
+
path.node.name === 'event') {
|
|
125
|
+
path.node.name = '$event';
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
// native events are all lowerCased
|
|
130
|
+
const lowerCaseEvent = event.toLowerCase();
|
|
131
|
+
const eventKey = (0, event_handlers_1.checkIsBindingNativeEvent)(event) ||
|
|
132
|
+
((_a = blockOptions.nativeEvents) === null || _a === void 0 ? void 0 : _a.find((nativeEvent) => nativeEvent === keyToUse || nativeEvent === event || nativeEvent === lowerCaseEvent))
|
|
133
|
+
? lowerCaseEvent
|
|
134
|
+
: event;
|
|
135
|
+
return ` (${eventKey})="${value}"`;
|
|
136
|
+
}
|
|
137
|
+
else if (keyToUse === 'class') {
|
|
138
|
+
return ` [class]="${code}" `;
|
|
139
|
+
}
|
|
140
|
+
else if (keyToUse === 'ref' || keyToUse === 'spreadRef') {
|
|
141
|
+
return ` #${code} `;
|
|
142
|
+
}
|
|
143
|
+
else if ((html_tags_1.VALID_HTML_TAGS.includes(node.name.trim()) || keyToUse.includes('-')) &&
|
|
144
|
+
!((_b = blockOptions.nativeAttributes) === null || _b === void 0 ? void 0 : _b.includes(keyToUse)) &&
|
|
145
|
+
!Object.values(BINDINGS_MAPPER).includes(keyToUse)) {
|
|
146
|
+
// standard html elements need the attr to satisfy the compiler in many cases: eg: svg elements and [fill]
|
|
147
|
+
return ` [attr.${keyToUse}]="${code}" `;
|
|
148
|
+
}
|
|
149
|
+
else if (keyToUse === 'innerHTML') {
|
|
150
|
+
return blockOptions.sanitizeInnerHTML
|
|
151
|
+
? ` [innerHTML]="${code}" `
|
|
152
|
+
: ` [innerHTML]="sanitizer.bypassSecurityTrustHtml(${code})" `;
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
return `[${keyToUse}]="${code}"`;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
const getElementTag = (json, blockOptions) => {
|
|
159
|
+
const childComponents = (blockOptions === null || blockOptions === void 0 ? void 0 : blockOptions.childComponents) || [];
|
|
160
|
+
let element, classNames = [], attributes;
|
|
161
|
+
const isComponent = childComponents.find((impName) => impName === json.name);
|
|
162
|
+
if (isComponent) {
|
|
163
|
+
const selector = json.meta.selector;
|
|
164
|
+
if (selector) {
|
|
165
|
+
try {
|
|
166
|
+
({ element, classNames, attributes } = (0, parse_selector_1.parseSelector)(`${selector}`));
|
|
167
|
+
}
|
|
168
|
+
catch (_a) {
|
|
169
|
+
element = (0, lodash_1.kebabCase)(json.name);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
element = (0, lodash_1.kebabCase)(json.name);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
element = json.name;
|
|
178
|
+
}
|
|
179
|
+
let additionalString = '';
|
|
180
|
+
// TODO: merge with existing classes/bindings
|
|
181
|
+
if (classNames.length) {
|
|
182
|
+
additionalString += `class="${classNames.join(' ')}" `;
|
|
183
|
+
}
|
|
184
|
+
// TODO: Merge with existing properties
|
|
185
|
+
if (attributes) {
|
|
186
|
+
Object.entries(attributes).forEach(([key, value]) => {
|
|
187
|
+
if (value) {
|
|
188
|
+
additionalString += `${key}=${JSON.stringify(value)} `;
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
additionalString += `${key} `;
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
return { element, additionalString };
|
|
196
|
+
};
|
|
197
|
+
const blockToAngularSignals = ({ root, json, options = {}, blockOptions = {
|
|
198
|
+
nativeAttributes: [],
|
|
199
|
+
nativeEvents: [],
|
|
200
|
+
}, rootRef, }) => {
|
|
201
|
+
var _a;
|
|
202
|
+
if (MAPPERS[json.name]) {
|
|
203
|
+
return MAPPERS[json.name](root, json, options, blockOptions);
|
|
204
|
+
}
|
|
205
|
+
if ((0, is_children_1.default)({ node: json })) {
|
|
206
|
+
return `<ng-content></ng-content>`;
|
|
207
|
+
}
|
|
208
|
+
if (json.properties._text) {
|
|
209
|
+
return json.properties._text;
|
|
210
|
+
}
|
|
211
|
+
const textCode = (_a = json.bindings._text) === null || _a === void 0 ? void 0 : _a.code;
|
|
212
|
+
if (textCode) {
|
|
213
|
+
return `{{${textCode}}}`;
|
|
214
|
+
}
|
|
215
|
+
let str = '';
|
|
216
|
+
const { element, additionalString } = getElementTag(json, blockOptions);
|
|
217
|
+
str += `<${element} ${additionalString}`;
|
|
218
|
+
for (const key in json.properties) {
|
|
219
|
+
const value = json.properties[key];
|
|
220
|
+
str += ` ${key}="${value}" `;
|
|
221
|
+
}
|
|
222
|
+
const stringifiedBindings = Object.entries(json.bindings)
|
|
223
|
+
.map(stringifyBinding(json, blockOptions))
|
|
224
|
+
.join('');
|
|
225
|
+
str += stringifiedBindings;
|
|
226
|
+
if (rootRef && !str.includes(`#${rootRef}`)) {
|
|
227
|
+
// Add ref for passing attributes
|
|
228
|
+
str += `#${rootRef}`;
|
|
229
|
+
}
|
|
230
|
+
if (html_tags_1.SELF_CLOSING_HTML_TAGS.has(json.name)) {
|
|
231
|
+
return str + ' />';
|
|
232
|
+
}
|
|
233
|
+
str += '>';
|
|
234
|
+
if (json.children) {
|
|
235
|
+
str += json.children
|
|
236
|
+
.map((item) => (0, exports.blockToAngularSignals)({ root, json: item, options, blockOptions }))
|
|
237
|
+
.join('\n');
|
|
238
|
+
}
|
|
239
|
+
str += `</${element}>`;
|
|
240
|
+
return str;
|
|
241
|
+
};
|
|
242
|
+
exports.blockToAngularSignals = blockToAngularSignals;
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.componentToAngularSignals = void 0;
|
|
4
|
+
const helpers_1 = require("../../../generators/angular/helpers");
|
|
5
|
+
const format_1 = require("../../../generators/angular/helpers/format");
|
|
6
|
+
const get_outputs_1 = require("../../../generators/angular/helpers/get-outputs");
|
|
7
|
+
const get_refs_1 = require("../../../generators/angular/helpers/get-refs");
|
|
8
|
+
const get_styles_1 = require("../../../generators/angular/helpers/get-styles");
|
|
9
|
+
const blocks_1 = require("../../../generators/angular/signals/blocks");
|
|
10
|
+
const helpers_2 = require("../../../generators/angular/signals/helpers");
|
|
11
|
+
const get_inputs_1 = require("../../../generators/angular/signals/helpers/get-inputs");
|
|
12
|
+
const get_code_processor_plugins_1 = require("../../../generators/angular/signals/plugins/get-code-processor-plugins");
|
|
13
|
+
const types_1 = require("../../../generators/angular/types");
|
|
14
|
+
const on_mount_1 = require("../../../generators/helpers/on-mount");
|
|
15
|
+
const dedent_1 = require("../../../helpers/dedent");
|
|
16
|
+
const event_handlers_1 = require("../../../helpers/event-handlers");
|
|
17
|
+
const fast_clone_1 = require("../../../helpers/fast-clone");
|
|
18
|
+
const get_child_components_1 = require("../../../helpers/get-child-components");
|
|
19
|
+
const get_components_used_1 = require("../../../helpers/get-components-used");
|
|
20
|
+
const get_props_1 = require("../../../helpers/get-props");
|
|
21
|
+
const get_state_object_string_1 = require("../../../helpers/get-state-object-string");
|
|
22
|
+
const is_upper_case_1 = require("../../../helpers/is-upper-case");
|
|
23
|
+
const merge_options_1 = require("../../../helpers/merge-options");
|
|
24
|
+
const render_imports_1 = require("../../../helpers/render-imports");
|
|
25
|
+
const strip_meta_properties_1 = require("../../../helpers/strip-meta-properties");
|
|
26
|
+
const attribute_passing_1 = require("../../../helpers/web-components/attribute-passing");
|
|
27
|
+
const plugins_1 = require("../../../modules/plugins");
|
|
28
|
+
const lodash_1 = require("lodash");
|
|
29
|
+
const componentToAngularSignals = (userOptions = {}) => {
|
|
30
|
+
return ({ component }) => {
|
|
31
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
|
|
32
|
+
// Make a copy we can safely mutate, similar to babel's toolchain
|
|
33
|
+
let json = (0, fast_clone_1.fastClone)(component);
|
|
34
|
+
// Init compileContext
|
|
35
|
+
json.compileContext = {
|
|
36
|
+
angular: {
|
|
37
|
+
hooks: {
|
|
38
|
+
ngAfterViewInit: {
|
|
39
|
+
code: '',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
extra: {
|
|
43
|
+
importCalls: [],
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
const options = (0, merge_options_1.initializeOptions)({
|
|
48
|
+
target: 'angular',
|
|
49
|
+
component,
|
|
50
|
+
defaults: types_1.DEFAULT_ANGULAR_OPTIONS,
|
|
51
|
+
userOptions,
|
|
52
|
+
});
|
|
53
|
+
options.typescript = true; // Angular uses ts all the time
|
|
54
|
+
options.api = 'signals';
|
|
55
|
+
if (options.plugins) {
|
|
56
|
+
json = (0, plugins_1.runPreJsonPlugins)({ json, plugins: options.plugins });
|
|
57
|
+
}
|
|
58
|
+
const withAttributePassing = true; // We always want to pass attributes
|
|
59
|
+
const rootRef = (0, attribute_passing_1.getAddAttributePassingRef)(json, options);
|
|
60
|
+
const domRefs = (0, get_refs_1.getDomRefs)({ json, options, rootRef, withAttributePassing });
|
|
61
|
+
let props = Array.from((0, get_props_1.getProps)(json));
|
|
62
|
+
const events = props.filter((prop) => (0, event_handlers_1.checkIsEvent)(prop));
|
|
63
|
+
const childComponents = (0, get_child_components_1.getChildComponents)(json);
|
|
64
|
+
props = props.filter((prop) => {
|
|
65
|
+
// Best practise for Angular is to use Events without "on"
|
|
66
|
+
// Stencil doesn't need children as a prop
|
|
67
|
+
return prop !== 'children' && !(0, event_handlers_1.checkIsEvent)(prop);
|
|
68
|
+
});
|
|
69
|
+
const processBindingOptions = {
|
|
70
|
+
events,
|
|
71
|
+
props,
|
|
72
|
+
target: 'angular',
|
|
73
|
+
skipAppendEmit: true,
|
|
74
|
+
};
|
|
75
|
+
options.plugins = (0, get_code_processor_plugins_1.getCodeProcessorPlugins)(json, options, processBindingOptions);
|
|
76
|
+
if (options.plugins) {
|
|
77
|
+
json = (0, plugins_1.runPostJsonPlugins)({ json, plugins: options.plugins });
|
|
78
|
+
}
|
|
79
|
+
// CSS
|
|
80
|
+
const styles = (0, get_styles_1.getAngularStyles)({ json, options });
|
|
81
|
+
// Mitosis Metadata
|
|
82
|
+
const useMetadata = (_a = json.meta) === null || _a === void 0 ? void 0 : _a.useMetadata;
|
|
83
|
+
const onPush = ((_b = useMetadata === null || useMetadata === void 0 ? void 0 : useMetadata.angular) === null || _b === void 0 ? void 0 : _b.changeDetection) == 'OnPush';
|
|
84
|
+
const writeableSignals = ((_d = (_c = useMetadata === null || useMetadata === void 0 ? void 0 : useMetadata.angular) === null || _c === void 0 ? void 0 : _c.signals) === null || _d === void 0 ? void 0 : _d.writeable) || [];
|
|
85
|
+
const requiredSignals = ((_f = (_e = useMetadata === null || useMetadata === void 0 ? void 0 : useMetadata.angular) === null || _e === void 0 ? void 0 : _e.signals) === null || _f === void 0 ? void 0 : _f.required) || [];
|
|
86
|
+
// Context & Injectables
|
|
87
|
+
const injectables = Object.entries(((_g = json === null || json === void 0 ? void 0 : json.context) === null || _g === void 0 ? void 0 : _g.get) || {}).map(([variableName, { name }]) => {
|
|
88
|
+
return `public ${variableName} : ${name}`;
|
|
89
|
+
});
|
|
90
|
+
const shouldUseSanitizer = !((_h = useMetadata === null || useMetadata === void 0 ? void 0 : useMetadata.angular) === null || _h === void 0 ? void 0 : _h.sanitizeInnerHTML) && (0, helpers_1.traverseAndCheckIfInnerHTMLIsUsed)(json);
|
|
91
|
+
if (shouldUseSanitizer) {
|
|
92
|
+
injectables.push('protected sanitizer: DomSanitizer');
|
|
93
|
+
}
|
|
94
|
+
// HTML
|
|
95
|
+
let template = json.children
|
|
96
|
+
.map((item) => {
|
|
97
|
+
var _a, _b, _c, _d;
|
|
98
|
+
return (0, blocks_1.blockToAngularSignals)({
|
|
99
|
+
root: json,
|
|
100
|
+
json: item,
|
|
101
|
+
options,
|
|
102
|
+
rootRef: withAttributePassing && rootRef === attribute_passing_1.ROOT_REF ? rootRef : undefined, // only pass rootRef if it's not the default
|
|
103
|
+
blockOptions: {
|
|
104
|
+
childComponents,
|
|
105
|
+
nativeAttributes: (_b = (_a = useMetadata === null || useMetadata === void 0 ? void 0 : useMetadata.angular) === null || _a === void 0 ? void 0 : _a.nativeAttributes) !== null && _b !== void 0 ? _b : [],
|
|
106
|
+
nativeEvents: (_d = (_c = useMetadata === null || useMetadata === void 0 ? void 0 : useMetadata.angular) === null || _c === void 0 ? void 0 : _c.nativeEvents) !== null && _d !== void 0 ? _d : [],
|
|
107
|
+
sanitizeInnerHTML: !shouldUseSanitizer,
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
})
|
|
111
|
+
.join('\n');
|
|
112
|
+
if (options.prettier !== false) {
|
|
113
|
+
template = (0, format_1.tryFormat)(template, 'html');
|
|
114
|
+
}
|
|
115
|
+
// Angular component settings
|
|
116
|
+
const componentsUsed = Array.from((0, get_components_used_1.getComponentsUsed)(json)).filter((item) => item.length && (0, is_upper_case_1.isUpperCase)(item[0]) && !types_1.BUILT_IN_COMPONENTS.has(item));
|
|
117
|
+
const componentSettings = {
|
|
118
|
+
selector: `'${(0, lodash_1.kebabCase)(json.name)}'`,
|
|
119
|
+
standalone: 'true',
|
|
120
|
+
imports: `[${['CommonModule', ...componentsUsed].join(', ')}]`,
|
|
121
|
+
template: `\`${(0, helpers_1.getTemplateFormat)(template)}\``,
|
|
122
|
+
};
|
|
123
|
+
if (onPush) {
|
|
124
|
+
componentSettings.changeDetection = `'ChangeDetectionStrategy.OnPush'`;
|
|
125
|
+
}
|
|
126
|
+
if (styles) {
|
|
127
|
+
componentSettings.styles = `\`${styles}\``;
|
|
128
|
+
}
|
|
129
|
+
(0, strip_meta_properties_1.stripMetaProperties)(json);
|
|
130
|
+
const dataString = (0, get_state_object_string_1.getStateObjectStringFromComponent)(json, {
|
|
131
|
+
format: 'class',
|
|
132
|
+
data: true,
|
|
133
|
+
functions: false,
|
|
134
|
+
getters: false,
|
|
135
|
+
valueMapper: (code, _, typeParameter) => {
|
|
136
|
+
if (typeParameter && !code.length) {
|
|
137
|
+
console.error(`
|
|
138
|
+
Component ${json.name} has state property without an initial value'.
|
|
139
|
+
This will cause an error in Angular.
|
|
140
|
+
Please add a initial value for every state property even if it's \`undefined\`.`);
|
|
141
|
+
}
|
|
142
|
+
return `signal${typeParameter ? `<${typeParameter}>` : ''}(${code})`;
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
const methodsString = (0, get_state_object_string_1.getStateObjectStringFromComponent)(json, {
|
|
146
|
+
format: 'class',
|
|
147
|
+
data: false,
|
|
148
|
+
functions: true,
|
|
149
|
+
getters: true,
|
|
150
|
+
onlyValueMapper: true,
|
|
151
|
+
valueMapper: (code, type, _, key) => {
|
|
152
|
+
return code.startsWith('function') ? code.replace('function', '').trim() : code;
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
// Imports
|
|
156
|
+
const coreImports = (0, helpers_2.getAngularCoreImportsAsString)({
|
|
157
|
+
refs: domRefs.size !== 0,
|
|
158
|
+
input: props.length !== 0,
|
|
159
|
+
output: events.length !== 0,
|
|
160
|
+
model: writeableSignals.length !== 0,
|
|
161
|
+
effect: ((_j = json.hooks.onUpdate) === null || _j === void 0 ? void 0 : _j.length) !== 0,
|
|
162
|
+
signal: dataString.length !== 0,
|
|
163
|
+
onPush,
|
|
164
|
+
});
|
|
165
|
+
let str = (0, dedent_1.dedent) `
|
|
166
|
+
import { ${coreImports} } from '@angular/core';
|
|
167
|
+
import { CommonModule } from '@angular/common';
|
|
168
|
+
${shouldUseSanitizer ? `import { DomSanitizer } from '@angular/platform-browser';` : ''}
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
${json.types ? json.types.join('\n') : ''}
|
|
172
|
+
${(0, helpers_1.getDefaultProps)(json)}
|
|
173
|
+
|
|
174
|
+
${(0, render_imports_1.renderPreComponent)({
|
|
175
|
+
explicitImportFileExtension: options.explicitImportFileExtension,
|
|
176
|
+
component: json,
|
|
177
|
+
target: 'angular',
|
|
178
|
+
preserveFileExtensions: options.preserveFileExtensions,
|
|
179
|
+
importMapper: (_, theImport, importedValues) => {
|
|
180
|
+
const { defaultImport } = importedValues;
|
|
181
|
+
const { path } = theImport;
|
|
182
|
+
if (defaultImport && componentsUsed.includes(defaultImport)) {
|
|
183
|
+
return `import { ${defaultImport} } from '${path}';`;
|
|
184
|
+
}
|
|
185
|
+
return undefined;
|
|
186
|
+
},
|
|
187
|
+
})}
|
|
188
|
+
|
|
189
|
+
@Component({
|
|
190
|
+
${Object.entries(componentSettings)
|
|
191
|
+
.map(([k, v]) => `${k}: ${v}`)
|
|
192
|
+
.join(',')}
|
|
193
|
+
})
|
|
194
|
+
export class ${json.name} implements AfterViewInit {
|
|
195
|
+
${(0, lodash_1.uniq)(json.compileContext.angular.extra.importCalls)
|
|
196
|
+
.map((importCall) => `protected readonly ${importCall} = ${importCall};`)
|
|
197
|
+
.join('\n')}
|
|
198
|
+
|
|
199
|
+
${(0, get_inputs_1.getSignalInputs)({
|
|
200
|
+
json,
|
|
201
|
+
writeableSignals,
|
|
202
|
+
requiredSignals,
|
|
203
|
+
props: Array.from(props),
|
|
204
|
+
})}
|
|
205
|
+
${(0, get_outputs_1.getOutputs)({ json, outputVars: events, api: options.api })}
|
|
206
|
+
|
|
207
|
+
${Array.from(domRefs)
|
|
208
|
+
.map((refName) => `${refName} = viewChild<ElementRef>("${refName}")`)
|
|
209
|
+
.join('\n')}
|
|
210
|
+
|
|
211
|
+
${dataString}
|
|
212
|
+
${methodsString}
|
|
213
|
+
|
|
214
|
+
constructor(${injectables.join(',\n')}) {
|
|
215
|
+
${((_k = json.hooks.onUpdate) === null || _k === void 0 ? void 0 : _k.length)
|
|
216
|
+
? (_l = json.hooks.onUpdate) === null || _l === void 0 ? void 0 : _l.map(({ code, depsArray }) =>
|
|
217
|
+
/**
|
|
218
|
+
* We need allowSignalWrites only for Angular 17 https://angular.dev/api/core/CreateEffectOptions#allowSignalWrites
|
|
219
|
+
* TODO: remove on 2025-05-15 https://angular.dev/reference/releases#actively-supported-versions
|
|
220
|
+
*/
|
|
221
|
+
`effect(() => {
|
|
222
|
+
${(depsArray === null || depsArray === void 0 ? void 0 : depsArray.length)
|
|
223
|
+
? `
|
|
224
|
+
// --- Mitosis: Workaround to make sure the effect() is triggered ---
|
|
225
|
+
${depsArray.join('\n')}
|
|
226
|
+
// ---
|
|
227
|
+
`
|
|
228
|
+
: ''}
|
|
229
|
+
${code}
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
allowSignalWrites: true, // Enable writing to signals inside effects
|
|
233
|
+
}
|
|
234
|
+
);`).join('\n')
|
|
235
|
+
: ''}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
${withAttributePassing ? (0, attribute_passing_1.getAttributePassingString)(options.typescript) : ''}
|
|
239
|
+
|
|
240
|
+
${!json.hooks.onMount.length && !((_m = json.hooks.onInit) === null || _m === void 0 ? void 0 : _m.code)
|
|
241
|
+
? ''
|
|
242
|
+
: `ngOnInit() {
|
|
243
|
+
${!((_o = json.hooks) === null || _o === void 0 ? void 0 : _o.onInit) ? '' : (_p = json.hooks.onInit) === null || _p === void 0 ? void 0 : _p.code}
|
|
244
|
+
${json.hooks.onMount.length > 0 ? (0, on_mount_1.stringifySingleScopeOnMount)(json) : ''}
|
|
245
|
+
}`}
|
|
246
|
+
|
|
247
|
+
${
|
|
248
|
+
// hooks specific to Angular
|
|
249
|
+
((_r = (_q = json.compileContext) === null || _q === void 0 ? void 0 : _q.angular) === null || _r === void 0 ? void 0 : _r.hooks)
|
|
250
|
+
? Object.entries((_t = (_s = json.compileContext) === null || _s === void 0 ? void 0 : _s.angular) === null || _t === void 0 ? void 0 : _t.hooks)
|
|
251
|
+
.map(([key, value]) => {
|
|
252
|
+
return `${key}() {
|
|
253
|
+
${value.code}
|
|
254
|
+
}`;
|
|
255
|
+
})
|
|
256
|
+
.join('\n')
|
|
257
|
+
: ''}
|
|
258
|
+
|
|
259
|
+
${json.hooks.onUnMount
|
|
260
|
+
? `ngOnDestroy() {
|
|
261
|
+
${((_u = json.hooks.onUnMount) === null || _u === void 0 ? void 0 : _u.code) || ''}
|
|
262
|
+
}`
|
|
263
|
+
: ''}
|
|
264
|
+
|
|
265
|
+
}
|
|
266
|
+
`;
|
|
267
|
+
if (options.plugins) {
|
|
268
|
+
str = (0, plugins_1.runPreCodePlugins)({ json, code: str, plugins: options.plugins });
|
|
269
|
+
}
|
|
270
|
+
if (options.prettier !== false) {
|
|
271
|
+
str = (0, format_1.tryFormat)(str, 'typescript');
|
|
272
|
+
}
|
|
273
|
+
if (options.plugins) {
|
|
274
|
+
str = (0, plugins_1.runPostCodePlugins)({ json, code: str, plugins: options.plugins });
|
|
275
|
+
}
|
|
276
|
+
return str;
|
|
277
|
+
};
|
|
278
|
+
};
|
|
279
|
+
exports.componentToAngularSignals = componentToAngularSignals;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MitosisComponent } from '../../../../types/mitosis-component';
|
|
2
|
+
export declare const getSignalInputs: ({ props, json, writeableSignals, requiredSignals, }: {
|
|
3
|
+
props: string[];
|
|
4
|
+
json: MitosisComponent;
|
|
5
|
+
writeableSignals: string[];
|
|
6
|
+
requiredSignals: string[];
|
|
7
|
+
}) => string;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSignalInputs = void 0;
|
|
4
|
+
const getSignalInputs = ({ props, json, writeableSignals, requiredSignals, }) => {
|
|
5
|
+
const propsTypeRef = json.propsTypeRef !== 'any' ? json.propsTypeRef : undefined;
|
|
6
|
+
return props
|
|
7
|
+
.map((prop) => {
|
|
8
|
+
const hasDefaultProp = json.defaultProps && json.defaultProps.hasOwnProperty(prop);
|
|
9
|
+
const propType = propsTypeRef ? `${propsTypeRef}["${prop}"]` : 'any';
|
|
10
|
+
const defaultProp = hasDefaultProp ? `defaultProps["${prop}"]` : '';
|
|
11
|
+
return `${prop} = ${writeableSignals.includes(prop) ? 'model' : 'input'}${requiredSignals.includes(prop) ? '.required' : ''}<${propType}>(${defaultProp})`;
|
|
12
|
+
})
|
|
13
|
+
.join('\n');
|
|
14
|
+
};
|
|
15
|
+
exports.getSignalInputs = getSignalInputs;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getAngularCoreImportsAsString = void 0;
|
|
4
|
+
const getAngularCoreImportsAsString = ({ refs, output, input, model, onPush, effect, signal, }) => {
|
|
5
|
+
const angularCoreImports = {
|
|
6
|
+
Component: true,
|
|
7
|
+
AfterViewInit: true,
|
|
8
|
+
viewChild: refs,
|
|
9
|
+
ElementRef: refs,
|
|
10
|
+
model,
|
|
11
|
+
output,
|
|
12
|
+
input,
|
|
13
|
+
effect,
|
|
14
|
+
signal,
|
|
15
|
+
ChangeDetectionStrategy: onPush,
|
|
16
|
+
};
|
|
17
|
+
return Object.entries(angularCoreImports)
|
|
18
|
+
.map(([key, bool]) => (bool ? key : ''))
|
|
19
|
+
.filter((key) => !!key)
|
|
20
|
+
.join(', ');
|
|
21
|
+
};
|
|
22
|
+
exports.getAngularCoreImportsAsString = getAngularCoreImportsAsString;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ToAngularOptions } from '../../../../generators/angular/types';
|
|
2
|
+
import { ProcessBindingOptions } from '../../../../helpers/class-components';
|
|
3
|
+
import { MitosisComponent } from '../../../../types/mitosis-component';
|
|
4
|
+
export declare const getCodeProcessorPlugins: (json: MitosisComponent, options: ToAngularOptions, processBindingOptions: ProcessBindingOptions) => import("../../../..").MitosisPlugin[];
|