@builder.io/mitosis 0.9.3 → 0.9.5
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/swift/blocks.d.ts +8 -0
- package/dist/src/generators/swift/blocks.js +304 -0
- package/dist/src/generators/swift/generator.d.ts +1 -1
- package/dist/src/generators/swift/generator.js +256 -303
- package/dist/src/generators/swift/helpers.d.ts +42 -0
- package/dist/src/generators/swift/helpers.js +412 -0
- package/dist/src/generators/swift/types.d.ts +25 -0
- package/package.json +1 -1
|
@@ -1,334 +1,287 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.componentToSwift = void 0;
|
|
7
|
-
const event_handlers_1 = require("../../helpers/event-handlers");
|
|
8
|
-
const legacy_1 = __importDefault(require("neotraverse/legacy"));
|
|
9
4
|
const dedent_1 = require("../../helpers/dedent");
|
|
10
5
|
const fast_clone_1 = require("../../helpers/fast-clone");
|
|
11
|
-
const filter_empty_text_nodes_1 = require("../../helpers/filter-empty-text-nodes");
|
|
12
6
|
const generic_format_1 = require("../../helpers/generic-format");
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return (`Image(${processBinding((_a = json.bindings.image) === null || _a === void 0 ? void 0 : _a.code, options) || `"${json.properties.image}"`})` +
|
|
32
|
-
getStyleString(json, options) +
|
|
33
|
-
getActionsString(json, options));
|
|
34
|
-
},
|
|
35
|
-
input: (json, options) => {
|
|
36
|
-
var _a, _b;
|
|
37
|
-
const name = json.properties.$name;
|
|
38
|
-
let str = `TextField(${json.bindings.placeholder
|
|
39
|
-
? processBinding((_a = json.bindings.placeholder) === null || _a === void 0 ? void 0 : _a.code, options)
|
|
40
|
-
: json.properties.placeholder
|
|
41
|
-
? JSON.stringify(json.bindings.placeholder.code)
|
|
42
|
-
: '""'}, text: $${name})` +
|
|
43
|
-
getStyleString(json, options) +
|
|
44
|
-
getActionsString(json, options);
|
|
45
|
-
if (json.bindings.onChange) {
|
|
46
|
-
str += `
|
|
47
|
-
.onChange(of: ${name}) { ${name} in
|
|
48
|
-
${processBinding(wrapAction(`var event = { target: { value: "\\(${name})" } };
|
|
49
|
-
${(_b = json.bindings.onChange) === null || _b === void 0 ? void 0 : _b.code}`), options)}
|
|
50
|
-
}`;
|
|
51
|
-
}
|
|
52
|
-
return str;
|
|
53
|
-
},
|
|
7
|
+
const get_props_1 = require("../../helpers/get-props");
|
|
8
|
+
const get_refs_1 = require("../../helpers/get-refs");
|
|
9
|
+
const getters_to_functions_1 = require("../../helpers/getters-to-functions");
|
|
10
|
+
const merge_options_1 = require("../../helpers/merge-options");
|
|
11
|
+
const on_event_1 = require("../../helpers/on-event");
|
|
12
|
+
const patterns_1 = require("../../helpers/patterns");
|
|
13
|
+
const process_code_1 = require("../../helpers/plugins/process-code");
|
|
14
|
+
const slots_1 = require("../../helpers/slots");
|
|
15
|
+
const strip_meta_properties_1 = require("../../helpers/strip-meta-properties");
|
|
16
|
+
const plugins_1 = require("../../modules/plugins");
|
|
17
|
+
const blocks_1 = require("./blocks");
|
|
18
|
+
const helpers_1 = require("./helpers");
|
|
19
|
+
const DEFAULT_OPTIONS = {
|
|
20
|
+
stateType: 'state',
|
|
21
|
+
formatCode: true,
|
|
22
|
+
includeTypes: true,
|
|
23
|
+
includePreview: true,
|
|
24
|
+
classPrefix: '',
|
|
54
25
|
};
|
|
55
|
-
const
|
|
26
|
+
const componentToSwift = (userProvidedOptions) => ({ component }) => {
|
|
56
27
|
var _a, _b;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
if ((0, mitosis_node_1.checkIsForNode)(json)) {
|
|
97
|
-
str += `ForEach(${processBinding((_a = json.bindings.each) === null || _a === void 0 ? void 0 : _a.code, options)}, id: \\.self) { ${json.scope.forName} in ${children
|
|
98
|
-
.map((item) => blockToSwift(item, options))
|
|
99
|
-
.join('\n')} }`;
|
|
100
|
-
}
|
|
101
|
-
else if (json.name === 'Show') {
|
|
102
|
-
str += `if ${processBinding((_b = json.bindings.when) === null || _b === void 0 ? void 0 : _b.code, options)} {
|
|
103
|
-
${children.map((item) => blockToSwift(item, options)).join('\n')}
|
|
104
|
-
}`;
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
str += `${name}(`;
|
|
108
|
-
for (const key in json.properties) {
|
|
109
|
-
if (key === 'class' || key === 'className') {
|
|
110
|
-
continue;
|
|
28
|
+
const options = (0, merge_options_1.initializeOptions)({
|
|
29
|
+
target: 'swift',
|
|
30
|
+
component,
|
|
31
|
+
defaults: DEFAULT_OPTIONS,
|
|
32
|
+
userOptions: userProvidedOptions,
|
|
33
|
+
});
|
|
34
|
+
options.plugins = [
|
|
35
|
+
...(options.plugins || []),
|
|
36
|
+
(0, on_event_1.processOnEventHooksPlugin)(),
|
|
37
|
+
(0, process_code_1.CODE_PROCESSOR_PLUGIN)((codeType) => {
|
|
38
|
+
switch (codeType) {
|
|
39
|
+
case 'bindings':
|
|
40
|
+
case 'properties':
|
|
41
|
+
case 'hooks':
|
|
42
|
+
case 'hooks-deps':
|
|
43
|
+
case 'hooks-deps-array':
|
|
44
|
+
case 'state':
|
|
45
|
+
case 'context-set':
|
|
46
|
+
case 'dynamic-jsx-elements':
|
|
47
|
+
case 'types':
|
|
48
|
+
return (x) => (0, helpers_1.convertConsoleLogToPrint)(x);
|
|
49
|
+
}
|
|
50
|
+
}),
|
|
51
|
+
(0, process_code_1.CODE_PROCESSOR_PLUGIN)((codeType) => {
|
|
52
|
+
switch (codeType) {
|
|
53
|
+
case 'hooks':
|
|
54
|
+
return (code) => (0, helpers_1.stripStateAndProps)({ json, options })(code);
|
|
55
|
+
case 'bindings':
|
|
56
|
+
case 'hooks-deps':
|
|
57
|
+
case 'state':
|
|
58
|
+
return (code) => (0, patterns_1.stripGetter)((0, helpers_1.stripStateAndProps)({ json, options })(code));
|
|
59
|
+
case 'properties':
|
|
60
|
+
case 'context-set':
|
|
61
|
+
return (code) => (0, helpers_1.stripStateAndProps)({ json, options })(code);
|
|
62
|
+
case 'dynamic-jsx-elements':
|
|
63
|
+
case 'hooks-deps-array':
|
|
64
|
+
case 'types':
|
|
65
|
+
return (x) => (0, helpers_1.convertConsoleLogToPrint)(x);
|
|
111
66
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
67
|
+
}),
|
|
68
|
+
];
|
|
69
|
+
// Make a copy we can safely mutate
|
|
70
|
+
let json = (0, fast_clone_1.fastClone)(component);
|
|
71
|
+
json = (0, plugins_1.runPreJsonPlugins)({ json, plugins: options.plugins });
|
|
72
|
+
(0, getters_to_functions_1.gettersToFunctions)(json);
|
|
73
|
+
const componentName = options.classPrefix + (json.name || ((_a = json.meta.useMetadata) === null || _a === void 0 ? void 0 : _a.name) || 'MitosisComponent');
|
|
74
|
+
// Process props
|
|
75
|
+
const filteredProps = Array.from((0, get_props_1.getProps)(json)).filter((prop) => !(0, slots_1.isSlotProperty)(prop));
|
|
76
|
+
const props = Array.from(new Set(filteredProps));
|
|
77
|
+
// Process refs (not directly applicable in SwiftUI, will be converted to @State)
|
|
78
|
+
const refs = Array.from((0, get_refs_1.getRefs)(json))
|
|
79
|
+
.map((0, helpers_1.stripStateAndProps)({ json, options }))
|
|
80
|
+
.filter((x) => !props.includes(x));
|
|
81
|
+
json = (0, plugins_1.runPostJsonPlugins)({ json, plugins: options.plugins });
|
|
82
|
+
(0, strip_meta_properties_1.stripMetaProperties)(json);
|
|
83
|
+
// Generate state variables
|
|
84
|
+
const stateProperties = Object.entries(json.state)
|
|
85
|
+
.filter(([_, value]) => {
|
|
86
|
+
// Skip methods - they'll be handled separately
|
|
87
|
+
return !((value === null || value === void 0 ? void 0 : value.type) === 'method' ||
|
|
88
|
+
((value === null || value === void 0 ? void 0 : value.code) && (value.code.includes('function') || value.code.includes('=>'))));
|
|
89
|
+
})
|
|
90
|
+
.map(([key, value]) => {
|
|
91
|
+
var _a, _b, _c, _d, _e;
|
|
92
|
+
// Check for value properties safely
|
|
93
|
+
const propertyType = value === null || value === void 0 ? void 0 : value.propertyType;
|
|
94
|
+
// Determine Swift type - handle missing type property
|
|
95
|
+
let valueType = 'Any';
|
|
96
|
+
if (value === null || value === void 0 ? void 0 : value.typeParameter) {
|
|
97
|
+
valueType = value.typeParameter;
|
|
116
98
|
}
|
|
117
|
-
|
|
118
|
-
if
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
key === 'className') {
|
|
125
|
-
continue;
|
|
99
|
+
else {
|
|
100
|
+
// Try to infer type from code if possible
|
|
101
|
+
if (((_a = value === null || value === void 0 ? void 0 : value.code) === null || _a === void 0 ? void 0 : _a.includes('"')) || ((_b = value === null || value === void 0 ? void 0 : value.code) === null || _b === void 0 ? void 0 : _b.includes("'"))) {
|
|
102
|
+
valueType = 'string';
|
|
103
|
+
}
|
|
104
|
+
else if ((_c = value === null || value === void 0 ? void 0 : value.code) === null || _c === void 0 ? void 0 : _c.match(/^[0-9]+(\.[0-9]+)?$/)) {
|
|
105
|
+
valueType = 'number';
|
|
126
106
|
}
|
|
127
|
-
if ((0
|
|
128
|
-
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
// TODO: other event mappings
|
|
133
|
-
console.warn(`Unsupported event binding "${key}"`);
|
|
134
|
-
}
|
|
107
|
+
else if ((value === null || value === void 0 ? void 0 : value.code) === 'true' || (value === null || value === void 0 ? void 0 : value.code) === 'false') {
|
|
108
|
+
valueType = 'boolean';
|
|
135
109
|
}
|
|
136
|
-
else {
|
|
137
|
-
|
|
138
|
-
// TODO: need binding mappings
|
|
139
|
-
// str += ` ${key}: ${processBinding(value, options)}, `;
|
|
110
|
+
else if (((_d = value === null || value === void 0 ? void 0 : value.code) === null || _d === void 0 ? void 0 : _d.startsWith('[')) || ((_e = value === null || value === void 0 ? void 0 : value.code) === null || _e === void 0 ? void 0 : _e.startsWith('Array'))) {
|
|
111
|
+
valueType = 'Array<Any>';
|
|
140
112
|
}
|
|
141
113
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
114
|
+
const typeAnnotation = (0, helpers_1.getStatePropertyTypeAnnotation)(propertyType, valueType);
|
|
115
|
+
const swiftType = (0, helpers_1.getSwiftType)(valueType);
|
|
116
|
+
let stateDeclaration = `${typeAnnotation} ${key}: ${swiftType}`;
|
|
117
|
+
// Add default value if present
|
|
118
|
+
if (value === null || value === void 0 ? void 0 : value.code) {
|
|
119
|
+
stateDeclaration += ` = ${value.code}`;
|
|
146
120
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
value = parseFloat(rawValue);
|
|
173
|
-
str += `\n.${useKey}(${value})`;
|
|
121
|
+
else {
|
|
122
|
+
// Add default initialization based on type
|
|
123
|
+
switch (swiftType) {
|
|
124
|
+
case 'String':
|
|
125
|
+
stateDeclaration += ' = ""';
|
|
126
|
+
break;
|
|
127
|
+
case 'Bool':
|
|
128
|
+
stateDeclaration += ' = false';
|
|
129
|
+
break;
|
|
130
|
+
case 'Double':
|
|
131
|
+
case 'Int':
|
|
132
|
+
stateDeclaration += ' = 0';
|
|
133
|
+
break;
|
|
134
|
+
case 'Array<String>':
|
|
135
|
+
case '[String]':
|
|
136
|
+
stateDeclaration += ' = []';
|
|
137
|
+
break;
|
|
138
|
+
default:
|
|
139
|
+
if (swiftType.includes('Array') || swiftType.includes('[')) {
|
|
140
|
+
stateDeclaration += ' = []';
|
|
141
|
+
}
|
|
142
|
+
else if (swiftType !== 'Any' && swiftType !== 'Void') {
|
|
143
|
+
stateDeclaration += '/* initialize with appropriate default */';
|
|
144
|
+
}
|
|
145
|
+
}
|
|
174
146
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
147
|
+
return stateDeclaration;
|
|
148
|
+
})
|
|
149
|
+
.join('\n ');
|
|
150
|
+
// Generate state function variables with inline closure assignment
|
|
151
|
+
const functionStateProperties = [];
|
|
152
|
+
Object.entries(json.state)
|
|
153
|
+
.filter(([_, value]) => {
|
|
154
|
+
return ((value === null || value === void 0 ? void 0 : value.type) === 'method' ||
|
|
155
|
+
((value === null || value === void 0 ? void 0 : value.code) && (value.code.includes('function') || value.code.includes('=>'))));
|
|
156
|
+
})
|
|
157
|
+
.forEach(([key, value]) => {
|
|
158
|
+
if (!(value === null || value === void 0 ? void 0 : value.code)) {
|
|
159
|
+
// Handle empty function with inline closure
|
|
160
|
+
functionStateProperties.push(`private var ${key}: () -> Void = { () in /* Empty function */ }`);
|
|
161
|
+
return;
|
|
178
162
|
}
|
|
179
|
-
|
|
180
|
-
|
|
163
|
+
// Convert the JS function to Swift
|
|
164
|
+
const processedCode = (0, helpers_1.stripStateAndProps)({ json, options })(value.code);
|
|
165
|
+
const { swiftCode, signature } = (0, helpers_1.convertJsFunctionToSwift)(processedCode, `_${key}`);
|
|
166
|
+
// Parse signature to get parameter list and return type
|
|
167
|
+
const signatureMatch = signature.match(/func _([^(]+)\(([^)]*)\) -> ([^{]+)/);
|
|
168
|
+
if (signatureMatch) {
|
|
169
|
+
const [, funcName, params, returnType] = signatureMatch;
|
|
170
|
+
// Create the function type for the state variable
|
|
171
|
+
const paramTypes = params
|
|
172
|
+
? params
|
|
173
|
+
.split(',')
|
|
174
|
+
.map((p) => { var _a; return ((_a = p.trim().split(':')[1]) === null || _a === void 0 ? void 0 : _a.trim()) || 'Any'; })
|
|
175
|
+
.join(', ')
|
|
176
|
+
: '';
|
|
177
|
+
const functionType = params
|
|
178
|
+
? `(${paramTypes}) -> ${returnType.trim()}`
|
|
179
|
+
: `() -> ${returnType.trim()}`;
|
|
180
|
+
// Extract function body from swiftCode
|
|
181
|
+
const bodyMatch = swiftCode.match(/{\s*([\s\S]*?)\s*}/);
|
|
182
|
+
const functionBody = bodyMatch ? bodyMatch[1].trim() : '/* Empty function body */';
|
|
183
|
+
// Build closure syntax for inline assignment
|
|
184
|
+
const closureSyntax = params
|
|
185
|
+
? `{ (${params}) -> ${returnType.trim()} in\n ${functionBody}\n }`
|
|
186
|
+
: `{ () -> ${returnType.trim()} in\n ${functionBody}\n }`;
|
|
187
|
+
// Add the state variable declaration with inline closure assignment
|
|
188
|
+
functionStateProperties.push(`var ${key}: ${functionType} = ${closureSyntax}`);
|
|
181
189
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}
|
|
185
|
-
function getJsSource(json, options) {
|
|
186
|
-
const str = `const state = new Proxy(${(0, get_state_object_string_1.getStateObjectStringFromComponent)(json)}, {
|
|
187
|
-
set: (target, key, value) => {
|
|
188
|
-
const returnVal = Reflect.set(target, key, value);
|
|
189
|
-
update();
|
|
190
|
-
return returnVal;
|
|
191
|
-
}
|
|
192
|
-
});`;
|
|
193
|
-
if (options.prettier === false) {
|
|
194
|
-
return str.trim();
|
|
195
|
-
}
|
|
196
|
-
else {
|
|
197
|
-
return (0, try_prettier_format_1.tryPrettierFormat)(str, 'typescript').trim();
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
const processBinding = (str, options) => {
|
|
201
|
-
// Use triple quotes for multiline strings or strings including '"'
|
|
202
|
-
if (str.includes('\n') || str.includes('"')) {
|
|
203
|
-
return `eval(code: """
|
|
204
|
-
${str}
|
|
205
|
-
""")`;
|
|
206
|
-
}
|
|
207
|
-
// Use double quotes for simple strings
|
|
208
|
-
return `eval(code: "${str}")`;
|
|
209
|
-
};
|
|
210
|
-
function componentHasDynamicData(json) {
|
|
211
|
-
const hasState = (0, state_1.checkHasState)(json);
|
|
212
|
-
if (hasState) {
|
|
213
|
-
return true;
|
|
214
|
-
}
|
|
215
|
-
let found = false;
|
|
216
|
-
(0, legacy_1.default)(json).forEach(function (node) {
|
|
217
|
-
if ((0, is_mitosis_node_1.isMitosisNode)(node)) {
|
|
218
|
-
if (Object.keys(node.bindings).filter((item) => item !== 'css').length) {
|
|
219
|
-
found = true;
|
|
220
|
-
this.stop();
|
|
221
|
-
}
|
|
190
|
+
else {
|
|
191
|
+
// Fallback if signature parsing fails
|
|
192
|
+
functionStateProperties.push(`var ${key}: () -> Void = { () in /* Could not parse function */ }`);
|
|
222
193
|
}
|
|
223
194
|
});
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
function
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
if (node.name === 'input') {
|
|
233
|
-
if (!Object.keys(node.bindings).filter((item) => item !== 'css').length) {
|
|
234
|
-
return;
|
|
235
|
-
}
|
|
236
|
-
if (!node.properties.$name) {
|
|
237
|
-
node.properties.$name = `input${++inputIndex}`;
|
|
238
|
-
}
|
|
239
|
-
json.meta.inputNames[node.properties.$name] =
|
|
240
|
-
((_a = node.bindings.value) === null || _a === void 0 ? void 0 : _a.code) || '';
|
|
241
|
-
}
|
|
195
|
+
// Process lifecycle methods
|
|
196
|
+
const lifecycleMethods = [];
|
|
197
|
+
// Only add onInit if needed and if there are no function state properties
|
|
198
|
+
// (to avoid duplicate initializers)
|
|
199
|
+
if ((_b = json.hooks.onInit) === null || _b === void 0 ? void 0 : _b.code) {
|
|
200
|
+
lifecycleMethods.push((0, dedent_1.dedent) `
|
|
201
|
+
init() {
|
|
202
|
+
${json.hooks.onInit.code}
|
|
242
203
|
}
|
|
243
|
-
|
|
244
|
-
}
|
|
245
|
-
function getInputBindings(json, options) {
|
|
246
|
-
let str = '';
|
|
247
|
-
const inputNames = json.meta.inputNames;
|
|
248
|
-
if (!inputNames) {
|
|
249
|
-
return str;
|
|
204
|
+
`);
|
|
250
205
|
}
|
|
251
|
-
|
|
252
|
-
str += `\n@State private var ${item}: String = ""`;
|
|
253
|
-
}
|
|
254
|
-
return str;
|
|
255
|
-
}
|
|
256
|
-
const componentToSwift = (options = {}) => ({ component }) => {
|
|
257
|
-
const json = (0, fast_clone_1.fastClone)(component);
|
|
258
|
-
mapDataForSwiftCompatability(json);
|
|
259
|
-
const hasDyanmicData = componentHasDynamicData(json);
|
|
260
|
-
let children = json.children.map((item) => blockToSwift(item, options)).join('\n');
|
|
261
|
-
const hasInputNames = Object.keys(json.meta.inputNames || {}).length > 0;
|
|
206
|
+
// Generate SwiftUI component
|
|
262
207
|
let str = (0, dedent_1.dedent) `
|
|
263
|
-
|
|
264
|
-
${!hasDyanmicData
|
|
265
|
-
? ''
|
|
266
|
-
: `import JavaScriptCore
|
|
267
|
-
|
|
268
|
-
final class UpdateTracker: ObservableObject {
|
|
269
|
-
@Published var value = 0;
|
|
270
|
-
|
|
271
|
-
func update() {
|
|
272
|
-
value += 1
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
`}
|
|
276
|
-
|
|
277
|
-
struct ${component.name}: View {
|
|
278
|
-
${!hasDyanmicData
|
|
279
|
-
? ''
|
|
280
|
-
: `
|
|
281
|
-
@ObservedObject var updateTracker = UpdateTracker()
|
|
282
|
-
private var jsContext = JSContext()
|
|
283
|
-
${getInputBindings(json, options)}
|
|
208
|
+
import SwiftUI
|
|
284
209
|
|
|
285
|
-
|
|
286
|
-
|
|
210
|
+
struct ${componentName}: View {
|
|
211
|
+
${props
|
|
212
|
+
.map((prop) => {
|
|
213
|
+
var _a, _b, _c, _d;
|
|
214
|
+
const propType = ((_b = (_a = json.props) === null || _a === void 0 ? void 0 : _a[prop]) === null || _b === void 0 ? void 0 : _b.propertyType) || 'Any';
|
|
215
|
+
const swiftType = (0, helpers_1.getSwiftType)(propType);
|
|
216
|
+
return `let ${prop}: ${swiftType}${((_d = (_c = json.props) === null || _c === void 0 ? void 0 : _c[prop]) === null || _d === void 0 ? void 0 : _d.optional) ? '?' : ''}`;
|
|
217
|
+
})
|
|
218
|
+
.join('\n ')}
|
|
219
|
+
|
|
220
|
+
${stateProperties}
|
|
221
|
+
${functionStateProperties.length > 0
|
|
222
|
+
? '\n // Function state variables\n ' + functionStateProperties.join('\n ')
|
|
223
|
+
: ''}
|
|
224
|
+
|
|
225
|
+
var body: some View {
|
|
226
|
+
${json.children
|
|
227
|
+
.map((item) => (0, blocks_1.blockToSwift)({
|
|
228
|
+
json: item,
|
|
229
|
+
options: options,
|
|
230
|
+
parentComponent: json,
|
|
231
|
+
}))
|
|
232
|
+
.join('\n')}
|
|
233
|
+
${lifecycleMethods.filter((method) => method.startsWith('.')).join('\n ')}
|
|
287
234
|
}
|
|
288
|
-
|
|
289
|
-
${!
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
235
|
+
|
|
236
|
+
${lifecycleMethods.filter((method) => !method.startsWith('.')).join('\n ')}
|
|
237
|
+
}
|
|
238
|
+
`;
|
|
239
|
+
// Add preview if enabled
|
|
240
|
+
if (options.includePreview) {
|
|
241
|
+
str += (0, dedent_1.dedent) `
|
|
242
|
+
\n
|
|
243
|
+
#if DEBUG
|
|
244
|
+
struct ${componentName}_Previews: PreviewProvider {
|
|
245
|
+
static var previews: some View {
|
|
246
|
+
${componentName}(
|
|
247
|
+
${props
|
|
248
|
+
.map((prop) => {
|
|
249
|
+
var _a, _b, _c, _d;
|
|
250
|
+
const propType = ((_b = (_a = json.props) === null || _a === void 0 ? void 0 : _a[prop]) === null || _b === void 0 ? void 0 : _b.propertyType) || 'Any';
|
|
251
|
+
const swiftType = (0, helpers_1.getSwiftType)(propType);
|
|
252
|
+
// Generate appropriate preview values based on type
|
|
253
|
+
let previewValue = '';
|
|
254
|
+
switch (swiftType) {
|
|
255
|
+
case 'String':
|
|
256
|
+
previewValue = '"Preview"';
|
|
257
|
+
break;
|
|
258
|
+
case 'Bool':
|
|
259
|
+
previewValue = 'false';
|
|
260
|
+
break;
|
|
261
|
+
case 'Double':
|
|
262
|
+
case 'Int':
|
|
263
|
+
previewValue = '0';
|
|
264
|
+
break;
|
|
265
|
+
default:
|
|
266
|
+
if ((_d = (_c = json.props) === null || _c === void 0 ? void 0 : _c[prop]) === null || _d === void 0 ? void 0 : _d.optional) {
|
|
267
|
+
previewValue = 'nil';
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
previewValue = '/* provide preview value */';
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return `${prop}: ${previewValue}`;
|
|
274
|
+
})
|
|
275
|
+
.join(',\n ')}
|
|
276
|
+
)
|
|
306
277
|
}
|
|
307
|
-
|
|
308
|
-
let updateRef = updateTracker.update
|
|
309
|
-
let updateFn : @convention(block) () -> Void = { updateRef() }
|
|
310
|
-
jsContext?.setObject(updateFn, forKeyedSubscript: "update" as NSString)
|
|
311
|
-
|
|
312
|
-
jsContext?.evaluateScript(jsSource)
|
|
313
|
-
}
|
|
314
|
-
`.trim()}
|
|
315
|
-
|
|
316
|
-
var body: some View {
|
|
317
|
-
VStack {
|
|
318
|
-
${children}
|
|
319
|
-
}${!hasInputNames
|
|
320
|
-
? ''
|
|
321
|
-
: `
|
|
322
|
-
.onAppear {
|
|
323
|
-
setComputedState()
|
|
324
278
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
}
|
|
328
|
-
`;
|
|
329
|
-
if (options.prettier !== false) {
|
|
330
|
-
str = (0, generic_format_1.format)(str);
|
|
279
|
+
#endif
|
|
280
|
+
`;
|
|
331
281
|
}
|
|
282
|
+
str = (0, plugins_1.runPreCodePlugins)({ json, code: str, plugins: options.plugins });
|
|
283
|
+
str = (0, generic_format_1.format)(str);
|
|
284
|
+
str = (0, plugins_1.runPostCodePlugins)({ json, code: str, plugins: options.plugins });
|
|
332
285
|
return str;
|
|
333
286
|
};
|
|
334
287
|
exports.componentToSwift = componentToSwift;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { MitosisComponent } from '../../types/mitosis-component';
|
|
2
|
+
import { MitosisNode } from '../../types/mitosis-node';
|
|
3
|
+
import { ToSwiftOptions } from './types';
|
|
4
|
+
export declare const convertConsoleLogToPrint: (code: string) => string;
|
|
5
|
+
export declare const ensureSwiftStringFormat: (code: string) => string;
|
|
6
|
+
export declare const stripStateAndProps: ({ json, options, }: {
|
|
7
|
+
json: MitosisComponent;
|
|
8
|
+
options: ToSwiftOptions;
|
|
9
|
+
}) => (code: string) => string;
|
|
10
|
+
export declare const getSwiftType: (type: string | undefined) => string;
|
|
11
|
+
export declare const jsxElementToSwiftUIView: (tagName: string) => string;
|
|
12
|
+
export declare const cssToSwiftUIModifiers: (style: Record<string, string>) => string[];
|
|
13
|
+
export declare const getStatePropertyTypeAnnotation: (propertyType: string | undefined, type: string | undefined) => string;
|
|
14
|
+
export declare const getEventHandlerName: (eventName: string) => string;
|
|
15
|
+
export declare const needsScrollView: (json: MitosisNode) => boolean;
|
|
16
|
+
export declare const isForEachBlock: (json: MitosisNode) => boolean;
|
|
17
|
+
export declare const getForEachParams: (json: MitosisNode, processCode: (code: string) => string) => {
|
|
18
|
+
collection: string;
|
|
19
|
+
itemName: string;
|
|
20
|
+
indexName: string | null;
|
|
21
|
+
};
|
|
22
|
+
export declare const camelToSnakeCase: (str: string) => string;
|
|
23
|
+
export declare const getBindingType: (key: string) => string;
|
|
24
|
+
/**
|
|
25
|
+
* Extract function signature information from JavaScript function code
|
|
26
|
+
*/
|
|
27
|
+
export declare const extractFunctionSignature: (code: string) => {
|
|
28
|
+
name: string;
|
|
29
|
+
params: {
|
|
30
|
+
name: string;
|
|
31
|
+
type: string;
|
|
32
|
+
}[];
|
|
33
|
+
returnType: string;
|
|
34
|
+
body: string;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Convert JavaScript function code to Swift function syntax
|
|
38
|
+
*/
|
|
39
|
+
export declare const convertJsFunctionToSwift: (code: string, functionName?: string) => {
|
|
40
|
+
swiftCode: string;
|
|
41
|
+
signature: string;
|
|
42
|
+
};
|